From ca38770256bd1a9efc9df9ccd2142073bdffe766 Mon Sep 17 00:00:00 2001 From: Packit Service Date: Dec 09 2020 20:29:13 +0000 Subject: libsoup-2.62.3 base --- diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..89ad10c --- /dev/null +++ b/AUTHORS @@ -0,0 +1,13 @@ +SOUP Authors +============ + +Original SOUP 0.0 - 0.7: + Alex Graveley + Dick Porter + Miguel De Icaza + +libsoup 1.99.x - 2.2: + Joe Shaw + Dan Winship + +See MAINTAINERS for the current maintainers. diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..5bc8fb2 --- /dev/null +++ b/COPYING @@ -0,0 +1,481 @@ + GNU LIBRARY GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1991 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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! diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..38d2872 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,28 @@ +## Process this file with automake to produce Makefile.in +ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS} + +SUBDIRS = libsoup po tests examples docs win32 + +EXTRA_DIST = \ + data/effective_tld_names.dat \ + libsoup-2.4.pc.in \ + libsoup-gnome-2.4.pc.in \ + gtk-doc.make \ + libsoup-zip.in \ + glib-tap.mk \ + tap-driver.sh \ + tap-test \ + Makefile.glib \ + config.h.win32 + +DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc --enable-introspection --disable-vala + +pkgconfigdir = $(libdir)/pkgconfig + +pkgconfig_DATA = libsoup-2.4.pc + +if BUILD_LIBSOUP_GNOME +pkgconfig_DATA += libsoup-gnome-2.4.pc +endif + +@CODE_COVERAGE_RULES@ diff --git a/Makefile.glib b/Makefile.glib new file mode 100644 index 0000000..97e94b0 --- /dev/null +++ b/Makefile.glib @@ -0,0 +1,303 @@ +# -*- Mode: makefile -*- +# +# To use: +# +# In configure.ac: +# add -Wno-portability to AM_INIT_AUTOMAKE +# add GLIB_CONFIG([min-version[, required-modules]]) +# (remove AM_PATH_GLIB_2_0 and GLIB_GSETTINGS) +# +# Add to Makefile.am where your library/program is built: +# include $(GLIB_MAKEFILE) +# +# BUILT_SOURCES = $(GLIB_GENERATED) +# +# Add *.stamp to .gitignore +# +# Add a GLIB_GENERATED variable with the files you want to generate, +# as described below. (The examples below use filenames with hyphens, +# eg foo-marshal.h, but you can omit the hyphens if that matches your +# file naming scheme better.) +# +# You do not need to modify CLEANFILES or EXTRA_DIST for any of these +# macros. + + +# glib-genmarshal +# +# To generate signal marshallers, add files with names ending in +# "marshal.h" and "marshal.c" to GLIB_GENERATED: +# +# GLIB_GENERATED += foo-marshal.h foo-marshal.c +# foo_marshal_sources = aaa.c bbb.c ccc.c ddd.c +# +# Makefile.glib will then generate a foo-marshal.list file containing +# all _foo_marshal_* functions referenced by $(foo_marshal_sources), +# and will rebuild foo-marshal.c/foo-marshal.h whenever the list +# changes. +# +# For your convenience, any .h files or $(GLIB_GENERATED) files in +# $(foo_marshal_sources) will be ignored. This means you can usually just +# set foo_marshal_sources to the value of your library/program's +# _SOURCES variable, even if that variable contains foo-marshal.c. +# +# You can set GLIB_GENMARSHAL_H_FLAGS and GLIB_GENMARSHAL_C_FLAGS (or +# an appropriate file-specific variable, eg +# foo_marshal_GENMARSHAL_H_FLAGS) to set/override glib-genmarshal +# options. + + +# glib-mkenums +# +# To generate enum type registrations, add files with names ending +# in "-enum-types.[ch]" or "enumtypes.[ch]" to GLIB_GENERATED: +# +# GLIB_GENERATED += foo-enum-types.h foo-enum-types.c +# foo_enum_types_sources = aaa.h bbb.h ccc.h ddd.h +# +# Makefile.glib will create a list all of the enum/flags types +# declared in $(foo_enum_type_sources), and will rebuild +# foo-enum-types.c/foo-enum-types.h whenever that list changes. (No +# template files are required.) +# +# For your convenience, any .c files or $(GLIB_GENERATED) files in +# $(foo_enum_types_sources) will be ignored. This means you can +# usually set foo_enum_types_sources to the value of your +# library/program's _HEADERS and/or _SOURCES variables, even if that +# contains foo-enum-types.h. +# +# You can set GLIB_MKENUMS_H_FLAGS and GLIB_MKENUMS_C_FLAGS (or an +# appropriate file-specific variable, eg +# foo_enum_types_MKENUMS_H_FLAGS) to set/override glib-mkenums +# options. In particular, you can do: +# +# GLIB_MKENUMS_C_FLAGS = --fhead "\#define FOO_I_KNOW_THIS_IS_UNSTABLE" +# +# (The backslash is necessary to keep make from thinking the "#" is +# the start of a comment.) + + +# glib-compile-schemas +# +# Any foo.gschemas.xml files listed in gsettingsschema_DATA will be +# validated before installation, and (if --disable-schemas-compile was +# not passed) compiled after installation. +# +# To build an enums file, add it to GLIB_GENERATED (in addition to +# gsettingsschema_DATA): +# +# GLIB_GENERATED += org.gnome.foo.enums.xml +# org_gnome_foo_enums_xml_sources = aaa.h bbb.h ccc.h ddd.h +# +# All enums files will be built before any schema files are validated. + + +######## + +# Notes on Makefile.glib hacking: +# +# - The exact rules that automake generates for a Makefile vary +# depending on what sorts of things were done in the Makefile.am, +# so we have to be careful with what rules we assume are there. +# In particular, (a) the glue to handle BUILT_SOURCES and the +# various hooks won't be output unless those things were +# referenced in the Makefile.am, and (b) a Makefile.am with +# SUBDIRS will get different rules than one without. +# +# - Build rules should always refer to their dependencies via $^, +# not by reusing a variable that is listed in the rule's +# dependencies. This is needed to make srcdir!=builddir builds +# work. You can use $(filter)/$(filter-out) if $^ has things +# you don't want in it. +# +# - When using a filename as something other than a filename, +# consider whether you need to wrap it in $(notdir) to get the +# right result when that file is being pulled out of a +# subdirectory. +# +# - All private variables should be prefixed with _glib or _GLIB +# +# - "make -qp > makefile.out" will give you a copy of the +# Makefile after all macros are expanded. +# +# The genmarshal code is commented; the mkenums and schema code is +# generally similar. + +_GLIB_CLEANFILES = +_GLIB_DISTCLEANFILES = + +_GLIB_V_GEN = $(_glib_v_gen_$(V)) +_glib_v_gen_ = $(_glib_v_gen_$(AM_DEFAULT_VERBOSITY)) +_glib_v_gen_0 = @echo " GEN " $(subst .stamp,,$@); + + +### glib-genmarshal + +# _GLIB_MARSHAL_GENERATED contains the basenames (eg, "foo-marshal") +# of all the marshal-related files to be generated. +_GLIB_MARSHAL_GENERATED = $(subst .h,,$(filter %marshal.h,$(GLIB_GENERATED))) + +# These are used as macros (with the value of $(1) inherited from the "caller") +# _glib_marshal_prefix("foo-marshal") = "foo" (used in the C marshal names) +# _glib_marshal_sources_var("foo-marshal") = "foo_marshal_sources" +# _glib_marshal_sources = the filtered value of $(foo_marshal_sources) +_glib_marshal_prefix = $(subst marshal,,$(subst _marshal,,$(subst -,_,$(notdir $(1)))))_marshal +_glib_marshal_sources_var = $(subst -,_,$(notdir $(1)))_sources +_glib_marshal_sources = $(filter-out %.h,$(filter-out $(GLIB_GENERATED),$($(_glib_marshal_sources_var)))) + +# This is a multi-line macro (ending with the "endef" below) that +# outputs a set of rules for a single .h/.c pair (whose basename is +# $(1)). The initial $(if) line makes make error out if +# foo_marshal_sources wasn't set. Note that single-$ variables are +# expanded when the macro is called, and double-$ variables are +# expanded when the rule is invoked. +define _glib_make_genmarshal_rules +$(if $(_glib_marshal_sources),,$(error Need to define $(_glib_marshal_sources_var) for $(1).[ch])) + +$(1).list.stamp: $(_glib_marshal_sources) Makefile + $$(_GLIB_V_GEN) LC_ALL=C sed -ne 's/.*_$(_glib_marshal_prefix)_\([_A-Z]*\).*/\1/p' $$(filter-out Makefile, $$^) | sort -u | sed -e 's/__/:/' -e 's/_/,/g' > $(1).list.tmp && \ + (cmp -s $(1).list.tmp $(1).list || cp $(1).list.tmp $(1).list) && \ + rm -f $(1).list.tmp && \ + echo timestamp > $$@ + +$(1).list: $(1).list.stamp + @true + +$(1).h: $(1).list + $$(_GLIB_V_GEN) $$(GLIB_GENMARSHAL) \ + --prefix=_$(_glib_marshal_prefix) --header \ + $$(GLIB_GENMARSHAL_H_FLAGS) \ + $$($(_glib_marshal_prefix)_GENMARSHAL_H_FLAGS) \ + $$< > $$@.tmp && \ + mv $$@.tmp $$@ + +$(1).c: $(1).list + $$(_GLIB_V_GEN) (echo "#include \"$$(subst .c,.h,$$(@F))\""; $$(GLIB_GENMARSHAL) \ + --prefix=_$(_glib_marshal_prefix) --body \ + $$(GLIB_GENMARSHAL_C_FLAGS) \ + $$($(_glib_marshal_prefix)_GENMARSHAL_C_FLAGS) \ + $$< ) > $$@.tmp && \ + mv $$@.tmp $$@ + +_GLIB_CLEANFILES += $(1).list.stamp $(1).list +_GLIB_DISTCLEANFILES += $(1).h $(1).c +endef + +# Run _glib_make_genmarshal_rules for each set of generated files +$(foreach f,$(_GLIB_MARSHAL_GENERATED),$(eval $(call _glib_make_genmarshal_rules,$f))) + + +### glib-mkenums + +_GLIB_ENUM_TYPES_GENERATED = $(subst .h,,$(filter %enum-types.h %enumtypes.h,$(GLIB_GENERATED))) + +_glib_enum_types_prefix = $(subst -,_,$(notdir $(1))) +_glib_enum_types_guard = __$(shell LC_ALL=C echo $(_glib_enum_types_prefix) | tr 'a-z' 'A-Z')_H__ +_glib_enum_types_sources_var = $(_glib_enum_types_prefix)_sources +_glib_enum_types_sources = $(filter-out $(GLIB_GENERATED),$($(_glib_enum_types_sources_var))) +_glib_enum_types_h_sources = $(filter %.h,$(_glib_enum_types_sources)) + +define _glib_make_mkenums_rules +$(if $(_glib_enum_types_sources),,$(error Need to define $(_glib_enum_types_sources_var) for $(1).[ch])) + +$(1).h.stamp: $(_glib_enum_types_h_sources) Makefile + $$(_GLIB_V_GEN) $$(GLIB_MKENUMS) \ + --fhead "/* Generated by glib-mkenums. Do not edit */\n\n#ifndef $(_glib_enum_types_guard)\n#define $(_glib_enum_types_guard)\n\n" \ + $$(GLIB_MKENUMS_H_FLAGS) \ + $$($(_glib_enum_types_prefix)_MKENUMS_H_FLAGS) \ + --fhead "#include \n\nG_BEGIN_DECLS\n" \ + --fhead "#ifndef GLIB_MKENUMS_EXTERN\n#define GLIB_MKENUMS_EXTERN\n#endif\n" \ + --vhead "GLIB_MKENUMS_EXTERN GType @enum_name@_get_type (void) G_GNUC_CONST;\n#define @ENUMPREFIX@_TYPE_@ENUMSHORT@ (@enum_name@_get_type ())\n" \ + --ftail "G_END_DECLS\n\n#endif /* $(_glib_enum_types_guard) */" \ + $$(filter-out Makefile, $$^) > $(1).h.tmp && \ + (cmp -s $(1).h.tmp $(1).h || cp $(1).h.tmp $(1).h) && \ + rm -f $(1).h.tmp && \ + echo timestamp > $$@ + +$(1).h: $(1).h.stamp + @true + +$(1).c.stamp: $(_glib_enum_types_h_sources) Makefile + $$(_GLIB_V_GEN) $$(GLIB_MKENUMS) \ + --fhead "/* Generated by glib-mkenums. Do not edit */\n\n#ifdef HAVE_CONFIG_H\n#include \n#endif\n\n#include \"$(notdir $(1)).h\"\n\n" \ + $$(GLIB_MKENUMS_C_FLAGS) \ + $$($(_glib_enum_types_prefix)_MKENUMS_C_FLAGS) \ + --fhead "$$(foreach f,$$(filter-out Makefile,$$(^F)),\n#include \"$$(f)\")\n\n" \ + --vhead "GType\n@enum_name@_get_type (void)\n{\n static volatile gsize g_define_type_id__volatile = 0;\n\n if (g_once_init_enter (&g_define_type_id__volatile))\n {\n static const G@Type@Value values[] = {\n" \ + --vprod " { @VALUENAME@, \"@VALUENAME@\", \"@valuenick@\" },\n" \ + --vtail " { 0, NULL, NULL }\n };\n GType g_define_type_id =\n g_@type@_register_static (g_intern_static_string (\"@EnumName@\"), values);\n g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);\n }\n\n return g_define_type_id__volatile;\n}\n" \ + $$(filter-out Makefile, $$^) > $(1).c.tmp && \ + (cmp -s $(1).c.tmp $(1).c || cp $(1).c.tmp $(1).c) && \ + rm -f $(1).c.tmp && \ + echo timestamp > $$@ + +$(1).c: $(1).c.stamp + @true + +_GLIB_CLEANFILES += $(1).h.stamp $(1).c.stamp +_GLIB_DISTCLEANFILES += $(1).h $(1).c $(1).h.stamp $(1).c.stamp +endef + +$(foreach f,$(_GLIB_ENUM_TYPES_GENERATED),$(eval $(call _glib_make_mkenums_rules,$f))) + + +### glib-compile-schemas + +_GLIB_ENUMS_XML_GENERATED = $(filter %.enums.xml,$(GLIB_GENERATED)) +_GLIB_GSETTINGS_SCHEMA_FILES = $(filter %.gschema.xml,$(gsettingsschema_DATA)) +_GLIB_GSETTINGS_VALID_FILES = $(subst .xml,.valid,$(_GLIB_GSETTINGS_SCHEMA_FILES)) + +_glib_enums_xml_prefix = $(subst .,_,$(notdir $(1))) +_glib_enums_xml_sources_var = $(_glib_enums_xml_prefix)_sources +_glib_enums_xml_sources = $(filter-out $(GLIB_GENERATED),$($(_glib_enums_xml_sources_var))) +_glib_enums_xml_namespace = $(subst .enums.xml,,$(notdir $(1))) + +define _glib_make_enums_xml_rule +$(if $(_glib_enums_xml_sources),,$(error Need to define $(_glib_enums_xml_sources_var) for $(1))) + +$(1): $(_glib_enums_xml_sources) Makefile + $$(_GLIB_V_GEN) $$(GLIB_MKENUMS) --comments '' --fhead "" --vhead " <@type@ id='$(_glib_enums_xml_namespace).@EnumName@'>" --vprod " " --vtail " " --ftail "" $$(filter-out Makefile, $$^) > $$@.tmp && mv $$@.tmp $$@ +endef + +_GLIB_V_CHECK = $(_glib_v_check_$(V)) +_glib_v_check_ = $(_glib_v_check_$(AM_DEFAULT_VERBOSITY)) +_glib_v_check_0 = @echo " CHECK " $(subst .valid,.xml,$@); + +define _glib_make_schema_validate_rule +$(subst .xml,.valid,$(1)): $(_GLIB_ENUMS_XML_GENERATED) $(1) + $$(_GLIB_V_CHECK) $$(GLIB_COMPILE_SCHEMAS) --strict --dry-run $$(addprefix --schema-file=,$$^) && touch $$@ +endef + +define _glib_make_schema_rules +all-am: $(_GLIB_GSETTINGS_VALID_FILES) + +install-data-am: glib-install-schemas-hook + +glib-install-schemas-hook: install-gsettingsschemaDATA + @test -n "$(GSETTINGS_DISABLE_SCHEMAS_COMPILE)$(DESTDIR)" || (echo $(GLIB_COMPILE_SCHEMAS) $(gsettingsschemadir); $(GLIB_COMPILE_SCHEMAS) $(gsettingsschemadir)) + +uninstall-am: glib-uninstall-schemas-hook + +glib-uninstall-schemas-hook: uninstall-gsettingsschemaDATA + @test -n "$(GSETTINGS_DISABLE_SCHEMAS_COMPILE)$(DESTDIR)" || (echo $(GLIB_COMPILE_SCHEMAS) $(gsettingsschemadir); $(GLIB_COMPILE_SCHEMAS) $(gsettingsschemadir)) + +.PHONY: glib-install-schemas-hook glib-uninstall-schemas-hook +endef + +_GLIB_CLEANFILES += $(_GLIB_ENUMS_XML_GENERATED) $(_GLIB_GSETTINGS_VALID_FILES) + +$(foreach f,$(_GLIB_ENUMS_XML_GENERATED),$(eval $(call _glib_make_enums_xml_rule,$f))) +$(foreach f,$(_GLIB_GSETTINGS_SCHEMA_FILES),$(eval $(call _glib_make_schema_validate_rule,$f))) +$(if $(_GLIB_GSETTINGS_SCHEMA_FILES),$(eval $(_glib_make_schema_rules))) + + +### Cleanup +.PHONY: clean-glib distclean-glib + +clean-am: clean-glib +clean-glib: + $(if $(strip $(_GLIB_CLEANFILES)),-rm -f $(_GLIB_CLEANFILES)) + +distclean-am: distclean-glib +distclean-glib: + $(if $(strip $(_GLIB_DISTCLEANFILES)),-rm -f $(_GLIB_DISTCLEANFILES)) diff --git a/Makefile.in b/Makefile.in new file mode 100644 index 0000000..db59833 --- /dev/null +++ b/Makefile.in @@ -0,0 +1,988 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +@BUILD_LIBSOUP_GNOME_TRUE@am__append_1 = libsoup-gnome-2.4.pc +subdir = . +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_code_coverage.m4 \ + $(top_srcdir)/m4/glibtests.m4 $(top_srcdir)/m4/gtk-doc.m4 \ + $(top_srcdir)/m4/intltool.m4 $(top_srcdir)/m4/introspection.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/vapigen.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \ + $(am__configure_deps) $(am__DIST_COMMON) +am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ + configure.lineno config.status.lineno +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = config.h +CONFIG_CLEAN_FILES = libsoup-2.4.pc libsoup-gnome-2.4.pc libsoup-zip \ + config.h.win32 +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(pkgconfigdir)" +DATA = $(pkgconfig_DATA) +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + cscope distdir dist dist-all distcheck +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \ + $(LISP)config.h.in +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +CSCOPE = cscope +DIST_SUBDIRS = $(SUBDIRS) +am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/config.h.in \ + $(srcdir)/config.h.win32.in $(srcdir)/libsoup-2.4.pc.in \ + $(srcdir)/libsoup-gnome-2.4.pc.in $(srcdir)/libsoup-zip.in \ + $(top_srcdir)/build-aux/compile \ + $(top_srcdir)/build-aux/config.guess \ + $(top_srcdir)/build-aux/config.sub \ + $(top_srcdir)/build-aux/install-sh \ + $(top_srcdir)/build-aux/ltmain.sh \ + $(top_srcdir)/build-aux/missing AUTHORS COPYING NEWS README \ + build-aux/compile build-aux/config.guess build-aux/config.sub \ + build-aux/install-sh build-aux/ltmain.sh build-aux/missing \ + compile config.guess config.sub depcomp install-sh ltmain.sh \ + missing +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +distdir = $(PACKAGE)-$(VERSION) +top_distdir = $(distdir) +am__remove_distdir = \ + if test -d "$(distdir)"; then \ + find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ + && rm -rf "$(distdir)" \ + || { sleep 5 && rm -rf "$(distdir)"; }; \ + else :; fi +am__post_remove_distdir = $(am__remove_distdir) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +GZIP_ENV = --best +DIST_ARCHIVES = $(distdir).tar.xz +DIST_TARGETS = dist-xz +distuninstallcheck_listfiles = find . -type f -print +am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ + | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' +distcleancheck_listfiles = find . -type f -print +ACLOCAL = @ACLOCAL@ +ALL_LINGUAS = @ALL_LINGUAS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +APACHE_HTTPD = @APACHE_HTTPD@ +APACHE_MODULE_DIR = @APACHE_MODULE_DIR@ +APACHE_PHP_MODULE_DIR = @APACHE_PHP_MODULE_DIR@ +APACHE_SSL_MODULE_DIR = @APACHE_SSL_MODULE_DIR@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CODE_COVERAGE_CFLAGS = @CODE_COVERAGE_CFLAGS@ +CODE_COVERAGE_CPPFLAGS = @CODE_COVERAGE_CPPFLAGS@ +CODE_COVERAGE_CXXFLAGS = @CODE_COVERAGE_CXXFLAGS@ +CODE_COVERAGE_ENABLED = @CODE_COVERAGE_ENABLED@ +CODE_COVERAGE_LDFLAGS = @CODE_COVERAGE_LDFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CURL = @CURL@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GCOV = @GCOV@ +GENHTML = @GENHTML@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_COMPILE_RESOURCES = @GLIB_COMPILE_RESOURCES@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MAKEFILE = @GLIB_MAKEFILE@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GMSGFMT = @GMSGFMT@ +GOBJECT_QUERY = @GOBJECT_QUERY@ +GREP = @GREP@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +HAVE_GNOME = @HAVE_GNOME@ +HTML_DIR = @HTML_DIR@ +IF_HAVE_MOD_UNIXD = @IF_HAVE_MOD_UNIXD@ +IF_HAVE_PHP = @IF_HAVE_PHP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ +INTLTOOL_MERGE = @INTLTOOL_MERGE@ +INTLTOOL_PERL = @INTLTOOL_PERL@ +INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ +INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@ +INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@ +INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@ +INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LCOV = @LCOV@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PHP = @PHP@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOUP_AGE = @SOUP_AGE@ +SOUP_API_VERSION = @SOUP_API_VERSION@ +SOUP_CURRENT = @SOUP_CURRENT@ +SOUP_DEBUG_FLAGS = @SOUP_DEBUG_FLAGS@ +SOUP_HIDDEN_VISIBILITY_CFLAGS = @SOUP_HIDDEN_VISIBILITY_CFLAGS@ +SOUP_MAJOR_VERSION = @SOUP_MAJOR_VERSION@ +SOUP_MICRO_VERSION = @SOUP_MICRO_VERSION@ +SOUP_MINOR_VERSION = @SOUP_MINOR_VERSION@ +SOUP_REVISION = @SOUP_REVISION@ +SQLITE_CFLAGS = @SQLITE_CFLAGS@ +SQLITE_LIBS = @SQLITE_LIBS@ +STRIP = @STRIP@ +USE_NLS = @USE_NLS@ +VALAC = @VALAC@ +VAPIDIR = @VAPIDIR@ +VAPIGEN = @VAPIGEN@ +VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@ +VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@ +VERSION = @VERSION@ +XGETTEXT = @XGETTEXT@ +XML_CFLAGS = @XML_CFLAGS@ +XML_LIBS = @XML_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +installed_test_metadir = @installed_test_metadir@ +installed_testdir = @installed_testdir@ +intltool__v_merge_options_ = @intltool__v_merge_options_@ +intltool__v_merge_options_0 = @intltool__v_merge_options_0@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +ntlm_auth = @ntlm_auth@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS} +SUBDIRS = libsoup po tests examples docs win32 +EXTRA_DIST = \ + data/effective_tld_names.dat \ + libsoup-2.4.pc.in \ + libsoup-gnome-2.4.pc.in \ + gtk-doc.make \ + libsoup-zip.in \ + glib-tap.mk \ + tap-driver.sh \ + tap-test \ + Makefile.glib \ + config.h.win32 + +DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc --enable-introspection --disable-vala +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = libsoup-2.4.pc $(am__append_1) +all: config.h + $(MAKE) $(AM_MAKEFLAGS) all-recursive + +.SUFFIXES: +am--refresh: Makefile + @: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \ + $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + echo ' $(SHELL) ./config.status'; \ + $(SHELL) ./config.status;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + $(SHELL) ./config.status --recheck + +$(top_srcdir)/configure: $(am__configure_deps) + $(am__cd) $(srcdir) && $(AUTOCONF) +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) +$(am__aclocal_m4_deps): + +config.h: stamp-h1 + @test -f $@ || rm -f stamp-h1 + @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1 + +stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status + @rm -f stamp-h1 + cd $(top_builddir) && $(SHELL) ./config.status config.h +$(srcdir)/config.h.in: $(am__configure_deps) + ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) + rm -f stamp-h1 + touch $@ + +distclean-hdr: + -rm -f config.h stamp-h1 +libsoup-2.4.pc: $(top_builddir)/config.status $(srcdir)/libsoup-2.4.pc.in + cd $(top_builddir) && $(SHELL) ./config.status $@ +libsoup-gnome-2.4.pc: $(top_builddir)/config.status $(srcdir)/libsoup-gnome-2.4.pc.in + cd $(top_builddir) && $(SHELL) ./config.status $@ +libsoup-zip: $(top_builddir)/config.status $(srcdir)/libsoup-zip.in + cd $(top_builddir) && $(SHELL) ./config.status $@ +config.h.win32: $(top_builddir)/config.status $(srcdir)/config.h.win32.in + cd $(top_builddir) && $(SHELL) ./config.status $@ + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool config.lt +install-pkgconfigDATA: $(pkgconfig_DATA) + @$(NORMAL_INSTALL) + @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkgconfigdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgconfigdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgconfigdir)" || exit $$?; \ + done + +uninstall-pkgconfigDATA: + @$(NORMAL_UNINSTALL) + @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(pkgconfigdir)'; $(am__uninstall_files_from_dir) + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscope: cscope.files + test ! -s cscope.files \ + || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS) +clean-cscope: + -rm -f cscope.files +cscope.files: clean-cscope cscopelist +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + -rm -f cscope.out cscope.in.out cscope.po.out cscope.files + +distdir: $(DISTFILES) + $(am__remove_distdir) + test -d "$(distdir)" || mkdir "$(distdir)" + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done + -test -n "$(am__skip_mode_fix)" \ + || find "$(distdir)" -type d ! -perm -755 \ + -exec chmod u+rwx,go+rx {} \; -o \ + ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ + || chmod -R a+r "$(distdir)" +dist-gzip: distdir + tardir=$(distdir) && $(am__tar) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).tar.gz + $(am__post_remove_distdir) + +dist-bzip2: distdir + tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 + $(am__post_remove_distdir) + +dist-lzip: distdir + tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz + $(am__post_remove_distdir) +dist-xz: distdir + tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz + $(am__post_remove_distdir) + +dist-tarZ: distdir + @echo WARNING: "Support for distribution archives compressed with" \ + "legacy program 'compress' is deprecated." >&2 + @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 + tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z + $(am__post_remove_distdir) + +dist-shar: distdir + @echo WARNING: "Support for shar distribution archives is" \ + "deprecated." >&2 + @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 + shar $(distdir) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).shar.gz + $(am__post_remove_distdir) + +dist-zip: distdir + -rm -f $(distdir).zip + zip -rq $(distdir).zip $(distdir) + $(am__post_remove_distdir) + +dist dist-all: + $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:' + $(am__post_remove_distdir) + +# This target untars the dist file and tries a VPATH configuration. Then +# it guarantees that the distribution is self-contained by making another +# tarfile. +distcheck: dist + case '$(DIST_ARCHIVES)' in \ + *.tar.gz*) \ + eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).tar.gz | $(am__untar) ;;\ + *.tar.bz2*) \ + bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ + *.tar.lz*) \ + lzip -dc $(distdir).tar.lz | $(am__untar) ;;\ + *.tar.xz*) \ + xz -dc $(distdir).tar.xz | $(am__untar) ;;\ + *.tar.Z*) \ + uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ + *.shar.gz*) \ + eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\ + *.zip*) \ + unzip $(distdir).zip ;;\ + esac + chmod -R a-w $(distdir) + chmod u+w $(distdir) + mkdir $(distdir)/_build $(distdir)/_build/sub $(distdir)/_inst + chmod a-w $(distdir) + test -d $(distdir)/_build || exit 0; \ + dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ + && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ + && am__cwd=`pwd` \ + && $(am__cd) $(distdir)/_build/sub \ + && ../../configure \ + $(AM_DISTCHECK_CONFIGURE_FLAGS) \ + $(DISTCHECK_CONFIGURE_FLAGS) \ + --srcdir=../.. --prefix="$$dc_install_base" \ + && $(MAKE) $(AM_MAKEFLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) dvi \ + && $(MAKE) $(AM_MAKEFLAGS) check \ + && $(MAKE) $(AM_MAKEFLAGS) install \ + && $(MAKE) $(AM_MAKEFLAGS) installcheck \ + && $(MAKE) $(AM_MAKEFLAGS) uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ + distuninstallcheck \ + && chmod -R a-w "$$dc_install_base" \ + && ({ \ + (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ + distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ + } || { rm -rf "$$dc_destdir"; exit 1; }) \ + && rm -rf "$$dc_destdir" \ + && $(MAKE) $(AM_MAKEFLAGS) dist \ + && rm -rf $(DIST_ARCHIVES) \ + && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ + && cd "$$am__cwd" \ + || exit 1 + $(am__post_remove_distdir) + @(echo "$(distdir) archives ready for distribution: "; \ + list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ + sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' +distuninstallcheck: + @test -n '$(distuninstallcheck_dir)' || { \ + echo 'ERROR: trying to run $@ with an empty' \ + '$$(distuninstallcheck_dir)' >&2; \ + exit 1; \ + }; \ + $(am__cd) '$(distuninstallcheck_dir)' || { \ + echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \ + exit 1; \ + }; \ + test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left after uninstall:" ; \ + if test -n "$(DESTDIR)"; then \ + echo " (check DESTDIR support)"; \ + fi ; \ + $(distuninstallcheck_listfiles) ; \ + exit 1; } >&2 +distcleancheck: distclean + @if test '$(srcdir)' = . ; then \ + echo "ERROR: distcleancheck can only run from a VPATH build" ; \ + exit 1 ; \ + fi + @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left in build directory after distclean:" ; \ + $(distcleancheck_listfiles) ; \ + exit 1; } >&2 +check-am: all-am +check: check-recursive +all-am: Makefile $(DATA) config.h +installdirs: installdirs-recursive +installdirs-am: + for dir in "$(DESTDIR)$(pkgconfigdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-hdr \ + distclean-libtool distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: install-pkgconfigDATA + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -rf $(top_srcdir)/autom4te.cache + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: uninstall-pkgconfigDATA + +.MAKE: $(am__recursive_targets) all install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \ + am--refresh check check-am clean clean-cscope clean-generic \ + clean-libtool cscope cscopelist-am ctags ctags-am dist \ + dist-all dist-bzip2 dist-gzip dist-lzip dist-shar dist-tarZ \ + dist-xz dist-zip distcheck distclean distclean-generic \ + distclean-hdr distclean-libtool distclean-tags distcleancheck \ + distdir distuninstallcheck dvi dvi-am html html-am info \ + info-am install install-am install-data install-data-am \ + install-dvi install-dvi-am install-exec install-exec-am \ + install-html install-html-am install-info install-info-am \ + install-man install-pdf install-pdf-am install-pkgconfigDATA \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs installdirs-am maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ + uninstall-am uninstall-pkgconfigDATA + +.PRECIOUS: Makefile + + +@CODE_COVERAGE_RULES@ + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/NEWS b/NEWS new file mode 100644 index 0000000..a9a1942 --- /dev/null +++ b/NEWS @@ -0,0 +1,3611 @@ +Changes in libsoup from 2.62.2 to 2.62.3: + + * Check for trailing dots in domains [#5, Claudio Saavedra] + * Set default cookie path for NULL origins [#1, Adrian Perez de Castro] + * Use atomic-refcounting in classes that are not using GObject-refcounting + [bgo#785110, Edward Hervey] + * Many Coverity-found code fixes [bgo#781771, Milan Crha] + * Bail out on cookie-jar calls with empty hostnames [#3, Michael Catanzaro] + + Note: from now onwards bgo# references bugs in GNOME Bugzilla + and # issues in GNOME gitlab. + +Changes in libsoup from 2.62.1 to 2.62.2: + + * Fixes to instrospection annotation [#795135, + Claudio Saavedra] + + * Fixes to the test suite with PHP version >= 7.2 + [#795111, Jan Alexander Steffens] + + * Critical warning fixes to SoupSocket [Carlos Garcia Campos] + + * Updated Romanian translation. + +Changes in libsoup from 2.62.0 to 2.62.1: + + * Fix digest authentication with encoded URIs + [#794208, Claudio Saavedra] + * Avoid unaligned memory accesses in WebSocket implementation + [#794421, Rolf Eike Beer] + * Use base domain to decide if cookies are third-party + [#792130, Michael Catanzaro] + * Fix crash under soup_socket_new() + [#762138, Milan Crha] + +Changes in libsoup from 2.61.91 to 2.62.0: + + * Updated translations. + +Changes in libsoup from 2.61.90 to 2.61.91: + + * Add limit to header length to avoid DOS attacks + [#792173, Michele Dionisio] + + * Update the public-suffix list. + [Claudio Saavedra] + + * Revert "cookie-jar: use base domain to decide if cookie is third party" + [#792130, Claudio Saavedra] + +Changes in libsoup from 2.61.2 to 2.61.90: + + * Various improvements to the WebSocket implementation + [#792113, Italo Guerrieri] + + * cookie-jar: use base domain to decide if cookie is third party + [#792130, Michael Catanzaro] + + * Add new API to create a new connection from a SoupSession + [#792212, Carlos Garcia Campos] + + * soup-headers: accept any 3 digit number as message status code + [#792124, Carlos Garcia Campos] + +Changes in libsoup from 2.61.1 to 2.61.2: + + * session: don't request Keep-Alive for upgraded connections + [#788723, Lionel Landwerlin] + +Changes in libsoup from 2.60.2 to 2.61.1: + + * tld-parser: use Python 3 [#785735, Ross Burton] + + * Fix heap-buffer-overflow in soup_ntlm_parse_challenge() + [#788037, Milan Crha] + + * Fix possibly uninitialized value in ssl-test + [Tomas Popela] + + * SoupCache: fix the timestamp for responses [#791031, + Claudio Saavedra] + +Changes in libsoup from 2.60.1 to 2.60.2: + + * Fix documentation typos [#788920, Nirbheek Chauhan] + + * format-zero-length warning triggered in soup-logger.c + [#789096, Tomas Popela] + + * Warnings while generating inrospection files + [#789099, Tomas Popela] + + * Visual Studio builds: Enhance security of x64 binaries + [Chun-wei Fan] + + * Updated translation: Nepali. + +Changes in libsoup from 2.60.0 to 2.60.1: + + * Fallback to another authentication type if the current + failed [#788238, Tomas Popela] + + * Fix unbalanced G_GNUC_BEGIN_IGNORE_DEPRECATIONS use in + soup-session.c [#787166, Zan Dobersek] + + * SoupCache: fix setting default value for cache dir + [#788452, Cosimo Cecchi] + + * Updated translations: Catalan (Valencian). + +Changes in libsoup from 2.59.90.1 to 2.60.0: + + * New/updated translations: Catalan, Danish, Dutch, Nepali + +Changes in libsoup from 2.59.90 to 2.59.90.1: + + * CVE-2017-2885: Fixed a chunked decoding buffer overrun that + could be exploited against either clients or servers. + [#785774] + +Changes in libsoup from 2.58.0 to 2.59.90: + + * Several SoupAuthNegotiate compatibility fixes [#783780, + #783781, Tomas Popela] + + * Include a payload in SoupWebsocketConnection's "ping" + messages (to avoid problems with certain buggy server + implementations), and emit a signal when receiving a "pong" + (to allow apps to notice when the remote peer has + disconnected them). [#785660, David Woodhouse] + + * Fix the interpretation of wss:// URIs, which previously + mostly didn't work. [#784766, Nirbheek Chauhan]. + + * Fixed SoupContentSniffer behavior on XML files with no + Content-Type + [https://bugs.webkit.org/show_bug.cgi?id=173923] + + * Fixed a bug with cancelling async requests [#773257, Carlos + Garcia Campos] + + * Reverted the (undocumented) change in 2.58.0 to call + soup_session_abort() after changing + SoupSession:proxy-resolver; while this made its behavior + more consistent with :proxy-uri, it ended up breaking + things. [#781590] + + * Allow HTTP responses that have no trailing CRLF after the + response headers (and no body) [#780352, Carlos Garcia + Campos] + + * Fixed an out-of-bounds read in SoupURI parsing [#785042] + + * Fixed a spurious (debug-level) error message in + SoupWebsocketConnection [#784935, Ignacio Casal Quinteiro] + + * Fixed introspection annotations on + soup_message_headers_get_content_range() [Philip Withnall] + + * Fixed a flake in tests/header-parsing [#777258] + + * Update tests/test-cert.pem to use stronger algorithms to + avoid problems with newer gnutls. [#784949, Jan Alexander + Steffens] + + * Fixed examples/get to not accidentally break https + certificate validation [#784259, Sebatian Dröge] + + * Misc updates to apache/php stuff in unit tests: + * Dropped support for Apache 2.2 + * Deal with mod_unixd being compiled-in [#776478] + * Switched PHP support from PHP 5 to PHP 7 + + * Updated translations: + Esperanto, Turkish + +Changes in libsoup from 2.2.57.1 to 2.58.0: + + * Fix authentication issues when the SOUP_MESSAGE_DO_NOT_USE_AUTH_CACHE + flag is used. [#778497, #777936, Carlos Garcia Campos] + + * MSVC build improvements (Chun-wei Fan) + + * Updated translations: + Basque, Belarusian, Brazilian Portuguese, Chinese (Taiwan), Danish, + French, Galician, Greek, Indonesian, Italian, Korean, Latvian, + Lithuanian, Norwegian bokmål, Russian, Serbian, Slovak, Slovenian, + Spanish, zh_CN + +Changes in libsoup from 2.56.0 to 2.57.1: + + * Added SoupWebsocketConnection:keepalive-interval, to make a + connection send regular pings. [#773253, Ignacio Casal + Quinteiro] + + * Added soup_auth_manager_clear_cached_credentials() and + SOUP_MESSAGE_DO_NOT_USE_AUTH_CACHE, to allow greater control + over the use of cached HTTP auth credentials. [#774031, + #774033, Carlos Garcia Campos] + + * Fixed the use of SoupSession:proxy-uri values containing + passwords. [#772932, Jonathan Lebon] + + * Various minor WebSocket fixes [Ignacio Casal Quinteiro]: + * Avoid sending data after we start closing the + connection [#774957] + * Do not log a critical if the peer sends an invalid + close status code + * Log a debug message when a "pong" is received + + * Fixed introspection of + soup_message_headers_get_content_range() [Jasper St. Pierre] + + * Replaced Vala [Deprecated] annotations with [Version] to + avoid build warnings [#773177, Evan Nemerson] + + * MSVC build improvements (Chun-wei Fan) + + * Updated error/message strings to use Unicode punctuation. + [#772217, Piotr Drąg] + + * Updated translations: + Czech, Friulian, German, Hebrew, Hungarian, + Norwegian bokmål, Polish, Swedish + +Changes in libsoup from 2.55.90 to 2.56.0: + + * Added SoupWebsocketConnection:max-incoming-payload-size + property, to override the default maximum incoming payload + size. [#770022, Ignacio Casal Quinteiro] + + * Added soup-version.h symbols (in particular + soup_check_version()) to introspection. [#771439, Rico + Tzschichholz] + + * Updated the copy of the public suffix list used by SoupTLD + [#769650, Michael Catanzaro] + + * Updated translations: + British English, Greek, Polish + +Changes in libsoup from 2.54.1 to 2.55.90: + + * Removed support for SSLv3 fallback; sites that reject TLS + 1.x handshakes will now just fail with an error. (Firefox + and Chrome have both already switched to this behavior.) + [#765940, Dan Winship] + + * Fixed the parsing of s in the new GVariant-based + XMLRPC code. [#767707, Dan Winship] + + * Fixed soup_server_set_ssl_cert_file(), which was added in + 2.48 but didn't actually work... [patch on libsoup-list from + Sean DuBois] + + * Added GObject properties to SoupLogger to make it + bindings-friendly. [#768053, Jonh Wendell] + + * Fixed build error on FreeBSD [#765376, Ting-Wei Lan] + + * Fixed build with certain new versions of glibc that define + "EOF" as a macro. [#768731, Philip Withnall] + + * Updated m4/ax_code_coverage.m4 with support for lcov 1.12 + [Philip Withnall] + + * Updated po files for future gettext versions [Piotr Drąg] + + * New/updated translations: + Occitan, Scottish Gaelic + +Changes in libsoup from 2.54.0.1 to 2.54.1: + + * *** IMPORTANT *** + Fixed an ABI break in 2.54.0 caused by adding a member to + SoupAuthClass; 2.54.1 is ABI-compatible with 2.53.92 and + earlier, but NOT with the anomalous 2.54.0. If you built + packages against 2.54.0, you will need to rebuild them + against 2.54.1. + + * Fixed NTLM authentication when ntlm_auth from the latest + version of Samba is present. [#765106, Milan Crha] + + * Updates to MSVC build, including for GSS-API support + [Chun-wei Fan] + + * Updated translations: + Friulian + +Changes in libsoup from 2.53.92 to 2.54.0.1: + + * (2.54.0.1 fixes a build problem with the 2.54.0 tarball, + which would not build if you configured with + "--without-gnome". There are no other changes between 2.54.0 + and 2.54.0.1.) + + * Fixed examples/simple-httpd on Windows [#758759, Chun-wei + Fan] + +Changes in libsoup from 2.53.90 to 2.53.92: + + * libsoup now supports HTTP "Negotiate"/GSSAPI/Kerberos + authentication. It must be enabled specifically by the + application and is also subject to certain other + restrictions, some of which are not yet controllable through + the API. [#587145, Guido Guenther, Tomas Popela, David + Woodhouse, Dan Winship] + + * Added support for building under MSVC [#758759, Chun-wei + Fan] + + * Fixed a problem with the 2.53.90 tarball that caused + translations to be mis-installed. + + * Updated translations: + Occitan + +Changes in libsoup from 2.53.2 to 2.53.90: + + * NUL bytes in headers are now ignored [#760832, Dan Winship] + + * Fixed transfer annotation of soup_form_decode* functions + [#743966, Lionel Landwerlin] + + * Updated translations: + Bulgarian, Latvian, Norwegian bokmål + +Changes in libsoup from 2.53.1 to 2.53.2: + + * Fixed up symbol visibility handling for mingw by copying + GLib's system [Ignacio Casal Quinteiro, #757146] + + * Finally marked the old SoupSessionAsync and SoupSessionSync + methods as deprecated [Ignacio Casal Quinteiro, Dan Winship, + #757146] + + * Added libsoup-2.4.deps for valac [Rico Tzschichholz] + + * Make it possible to build from git without gtk-doc being + installed [Ignacio Casal Quinteiro] + + * Updated translations: + Norwegian bokmål, Occitan + +Changes in libsoup from 2.52.1 to 2.53.1: + + * Really fixed build under MinGW for sure this time [Ignacio + Casal Quinteiro] + + * Fixed SoupServer Web Sockets code so that the + SoupClientContext passed to a SoupServerWebsocketCallback is + fully usable (rather than crashing when you try to do most + things). + +Changes in libsoup from 2.52.0 to 2.52.1: + + * Fixed build under MinGW [Chun-wei Fan] + + * Fixed build with --disable-introspection [#755389, Quentin + Glidic] + + * Fixed HTTP authentication protection space handling for + files directly under the root directory. [#755617, Carlos + Garcia Campos] + + * Fixed a warning when loading data from SoupCache while using + an authenticated proxy. [#756076, Carlos Garcia Campos] + + * Updated translations: + German, Vietnamese + +Changes in libsoup from 2.51.92 to 2.52.0: + + * Removed duplicate test paths from tests/date so it will pass + with glib 2.46.0 + +Changes in libsoup from 2.51.90 to 2.51.92: + + * Added g_autoptr() support for all libsoup types. [#754721, + Kalev Lember] + + * Added a missing (allow-none) annotation to + soup_uri_normalize() [#754776, Jens Georg] + + * Updated translations: + Polish + +Changes in libsoup from 2.51.3 to 2.51.90: + + * Added a new GVariant-based XMLRPC API, and deprecated the + old GValue-based API (along with the associated + GValue-manipulating utilities). [#746495, Xavier Claessens] + + * Multiple build fixes for Visual Studio [#752952, Chun-wei Fan] + + * Added VAPI generation [#750679, Daniel Espinosa] + + * Fixed the mode bits on soup-cookie.c, which was previously + marked executable for some reason. [rh #1247285] + + * Updated translations: + Norwegian bokmål, Portuguese, Thai, Turkish + +Changes in libsoup from 2.50.0 to 2.51.3: + + * Fixed "make check" in non-English locales [rh #1224989, + #749397] + + * Fixed some compiler warnings [#748514, Philip Withnall] + + * New/Updated translations: + Aragonese, Catalan, Occitan, Russian + +Changes in libsoup from 2.49.92 to 2.50: + + * Updated translations: + Basque, Chinese (Taiwan), Danish, Indonesian, + Norwegian bokmål + +Changes in libsoup from 2.49.91.1 to 2.49.92: + + * Fixed an NTLM problem that caused spurious "Authentication + Failed" errors in evolution-ews. [#735197] + + * New/updated translations: + Bosnian, Czech, Greek, Hebrew, Italian, Korean, Lithuanian, + Polish, Serbian, Slovak, Slovenian, Spanish, Swedish + +Changes in libsoup from 2.49.1 to 2.49.91.1: + + * WebSockets! Libsoup now has support for WebSockets in both + SoupSession and SoupServer. [#627738, Dan Winship and Lionel + Landwerlin, based on code from the Cockpit project] + + * The WebSocket code in libsoup 2.49.91 did not build on + 32-bit architectures. 2.49.91.1 was released to fix + this. + + * Added support for NTLMv2 Session Security to SoupAuthNTLM. + (This is transparent to the app/user; if the server supports + it, it will be used.) [#739192, Adam Seering] + + * Added soup_server_accept_iostream() to allow feeding a + non-GSocketConnection GIOStream to SoupServer (eg, when + accepting HTTP requests on some other sort of connection). + [#744186, Marc-André Lureau] + + * Added soup_session_steal_connection() and + soup_client_context_steal_connection(), to allow you to + steal a GIOStream from a SoupSession or SoupServer and then + use it for non-HTTP purposes. [#721343, Dan Winship] + + * Added soup_server_add_early_handler(), for adding SoupServer + handlers to run at :got-headers time rather than :got-body + (eg, to set up a streaming read of the request body). + [#625645, Dan Winship] + + * Added a new SOUP_MESSAGE_IGNORE_CONNECTION_LIMITS flag, + which can be used to bypass SoupSession:max-conns and + SoupSession:max-conns-per-host on a per-message basis. + [#744720, Carlos Garcia Campos] + + * Multiple SoupCache fixes from Carlos Garcia Campos: + + * Leaked resources are now cleaned up when opening the + cache. [#667682] + + * The "Age" header is no longer added to cached + responses. [#741108] + + * Fixed the interpretation of the "must-revalidate" + directive to not be stricter than required. [#744468] + + * Messages retrieved from cache now behave slightly more + like non-cache messages in terms of SoupSession + signals and timing. [#744788] Additionally, there is a + new SoupMessage::starting signal, which is like + SoupSession::request-started, but emitted for cached + resources as well. [#731153] + + * Fixed soup_session_cancel_message() to work reliably on + paused messages. [#745094, Sven Neumann] + + * Added code-coverage support to the build. [#744744, + Marc-André Lureau] + + * Fixed the library symbol check in "make check" to work when + building with linker options that result in slightly + different organization. [#741348, Iain Lane] + + * Added a hack to SoupSessionFeature so that people will stop + re-reporting an old Eclipse bug against libsoup. [#710242] + + * Miscellaneous bug and leak fixes in the test programs, leak + fixes in libsoup, and documentation updates. + + * Updated translations: + Brazilian Portuguese, French, Galician, Hungarian, Slovak, + Slovenian, Spanish, Turkish + +Changes in libsoup from 2.48.0 to 2.49.1: + + * Fixed a bug in the SoupMessage:event signal that broke + evolution's ability to connect to https hosts with "bad" + certificates. [#739951, Dan Winship] + + * Fixed a case where the async codepaths could potentially + block on a synchronous write [#727138, Dan Winship] + + * Fixed the symbol soup_server_set_ssl_cert_file() to get + exported, and added soup_server_get_uris() to the + documentation. [Tristan Van Berkom] + + * Improved a bunch of introspection annotations [#729987, Evan + Nemerson] + + * Clarified some documentation. [Tristan Van Berkom, Dan + Winship] + + * Fixed Windows build, twice [#738003, Kouhei Sutou, and + #738551, Kalev Lember]. + + * Updated translations: + Bengali (Indian), Chinese (Traditional), Italian, Latvian, + Serbian, Telugu, Ukranian + +Changes in libsoup from 2.47.92 to 2.48.0: + + * Updated translations: + Bengali (India), Danish, German, Hindi, Kannada, Punjabi + +Changes in libsoup from 2.47.4 to 2.47.92: + + * Fixed a crash in SoupCache when receiving certain invalid + Cache-Control headers. [#733587, Raveendra Karu] + + * Updated translations: + Assamese, Basque, Catalan (Valencian), Catalan, Chinese + (Traditional), French, Gujarati, Hungarian, Indonesian, + Korean, Marathi, Norwegian bokmål, Oriya, Polish, Swedish, + Tamil + +Changes in libsoup from 2.47.3 to 2.47.4: + + * Fixed two crashes that could occur in multithreaded use + (in particular, with the latest git gvfs). [#732783, + #732925, Ross Lagerwall] + + * Fixed the handling of data: URIs with base64-encoded data + but no explicit MIME type. [#732112, Raveendra Karu]. Added + tests for this and other data: URI cases. [Dan] + + * Fixed a bug in SoupAuthNTLM that affected 28-character-long + passwords. [#732087, David Woodhouse] + + * Fixed tests to pass with GLib git master (which warns if you + use deprecated GObject properties, and which also caught a + mutex-handling bug in test-utils.c) + + * Updated translations: + Galician, Greek, Lithuanian, Russian + +Changes in libsoup from 2.46.0 to 2.47.3: + + * Added new-and-improved SoupServer API, and deprecated much + of the existing API: + + * Servers can now listen on multiple ports, including + listening on both IPv4 and IPv6 (which is the default + behavior when using the new API), or serving both http + and https from a single SoupServer. + + * You can create a SoupServer from an existing listening + socket (either a file descriptor or a GSocket). + + * When using the new APIs, SoupServer now obeys the + thread-default GMainContext rather than using the + :async-context property. + + * soup_server_set_ssl_cert_file() allows setting the + certificate and key files with feedback if it fails + (unlike the old construct-time "ssl-cert-file" and + "ssl-key-file" properties, which fail with a + g_warning() and a NULL return from g_object_new() if + they fail). + + * SoupClientContext has new methods that return GSocket + and GSocketAddress, rather than SoupSocket and + SoupAddress. + + * SoupSession now has a :tls-interaction property, which can + be used to add a GTlsInteraction to a session, allowing it + to provide a client-side certificate if the server requests + one. [#334021, Colin Walters] + + * soup_session_abort() no longer tries to close active + connections, which was causing crashes in evolution + [rh#1093314] + + * Fixed a GMainContext-handling bug that could cause crashes + in gstreamer's souphttpsrc. [#729737, Dmitry Shatrov] + + * Fixed a memory leak when requesting to delete a cookie that + didn't exist [Joseph Artsimovich] + + * Updated translations: + Brazilian Portuguese, Czech, Hebrew, Spanish + +Changes in libsoup from 2.45.92 to 2.46.0: + + * (No changes, just a version bump) + +Changes in libsoup from 2.45.90 to 2.45.92: + + * Fixed problems with using an http proxy on port 80. [patch + from Slava Monich on libsoup-list] + + * Plugged a small per-connection leak. [patch from Slava + Monich on libsoup-list] + + * Belatedly bumped up the glib requirement to 2.38, which is + required for the TAP driver. + + * Fixed up some leftover issues from the test porting to + gtestutils: + + test-utils: change http_debug command-line flag + xmlrpc-test: use g_test_skip() + redirect-test: remove a flaky test + auth-test: remove some erroneous SKIP_IF_NO_APACHEs + tests: split up some test programs into more tests + tests: remove debug_printf()s that are redundant with test names + tests: use g_test_bug() to annotate test cases + +Changes in libsoup from 2.45.3 to 2.45.90: + + * Fixed a problem where libsoup would use the "http" proxy + settings for "https" requests [#724316, Matt Barnes] + + * Updated SoupContentSniffer to match the current version of + the MIME sniffing specification [#648849 / #715126, Gustavo + Noronha Silva] + + * Updated the soup-tld APIs to accept ASCII-encoded hostnames + in addition to UTF-8 ones. + + * Ported the test programs to the gtestutils framework, added + support for installed tests, and made the tests use the TAP + driver. + + Some tests still need to be split up into more pieces, and + the debug output is now somewhat less useful in some cases. + + * Fixed the test programs to not depend on local proxy + settings. + + * Added some more checks to header-tests [#722341, Lionel + Landwerlin] + + * Fixed the "simple-proxy" example program, which had been + broken for a while. + + * Updated translations: + Korean + +Changes in libsoup from 2.44.1 to 2.45.3: + + * The documentation has finally been updated to reflect the + new APIs added in 2.42. + + * Added GBytes-valued :request-body-data and + :response-body-data properties to SoupMessage, which should + help some bindings. + + * We now set TCP_NODELAY on sockets, improving throughput a + bit. In particular, this avoids an unnecessary extra round + trip in the TLS handshake. + + * The SoupSession APIs that return GErrors now return the + actual underlying gio errors in the event of connection + failures and the like. + + * Updated the copy of the Public Suffix list used by soup-tld. + + * Fixed a hang with internet radio streams in Rhythmbox (and + some other places). [#710494, Dan] + + * Fixed a connection leak when cancelling the close of + a message GInputStream. [#711260, Dan] + + * Updated the soup_server_pause_message() / + soup_server_unpause_message() documentation to clarify when + you can and can't call them. [#710602, Philip Withnall] + + * soup_message_set_request() and soup_message_set_response() + now g_warn_if_fail() if you pass an invalid Content-Type. + (And they also have better introspection annotations.) + [#686766, Dan] + + * Plugged a few memory leaks [#711085, Christophe Fergeau] + + * Fixed connection-test to pass with current glib [#711361, + Colin Walters] + + * session-test now passes when run against the dummy TLS + backend (ie, if you don't have glib-networking installed), + as long as you have the latest glib. + + * Fixed build with -Werror=format-nonliteral [#720082, Ryan + Lortie] + + * Fix build with --without-ntlm [#710267, Dan] + + * Fixed a few warnings [Dan, Fabiano Fidêncio] + + * Tests are now more verbose by default under "make check", + since current automake just redirects all the output to a + log file anyway. + + * Updated translations: + Chinese + +Changes in libsoup from 2.44.0 to 2.44.1: + + * If you called g_input_stream_close() on SoupMessage or + SoupRequests's GInputStream before you finished reading it, + it would block until the rest of the response had been read + (which in the case of, eg, an infinite audio stream, meant + that it would block forever). This was an unintended change + from 2.42 and is now fixed. [#695652, Dan] + + * soup_session_queue_message() on a plain SoupSession (not + SoupSessionAsync) was operating synchronously rather than + asynchronously as it should have. [#707711, Dan] + + * soup-form methods now use the HTML5 x-www-form-urlencoded + rules rather than the HTML4 ones. (In particular, they leave + "-", "_", and "." unencoded.) [#708621, Alban Browaeys] + + * The test programs now explicitly request the "memory" + GSettings backend, meaning they won't print a warning if + they get it accidentally, and they won't accidentally use + the dconf proxy settings if the dconf backend is available. + [Dan] + + * Fix SoupSession so that if you override the proxy + configuration at construct time, it doesn't try to resolve + the default GProxyResolver. (This is important in particular + for programs that expect to run outside a user session, + which would otherwise spew errors from the dconf GSettings + backend about not being able to connect to dconf.) Likewise + with TLS settings and the TLS backend. [#708696, Dan] + + * Fix the SoupServer:tls-certificate property; + soup_server_is_https() had not been updated to recognize it, + and so would return FALSE, which in turn meant that the + server would return 400 Bad Request in response to https + requests. [#709647, Fabiano Fidêncio] + + * Fixed a sporadic failure in tests/connection-test. [Dan] + + * Updated translations: + Tajik + +Changes in libsoup from 2.43.92 to 2.44.0: + + * New/updated translations: + Dutch, Indonesian + +Changes in libsoup from 2.43.90 to 2.43.92: + + * Fixed a bug in the connection-pool code, which would in + certain cases accidentally keep using a connection after a + message was cancelled while in progress, causing the next + request on that connection to get the response to the + previous request, etc. [#708006, David Woodhouse] + + * Fixed some problems when falling back from samba + single-sign-on-based NTLM to ordinary ask-for-a-password + NTLM. [#703186, David Woodhouse] + + * When sending a conditional GET request, SoupCache now + preserves the original message's list of disabled features, + ensure that it gets back the same kind of response the + original message would have. [#706338, Andre Moreira + Magalhaes] + + * Fixed a warning when the remote host closes the connection + while we are writing something using chunked encoding. + [#703297, Dan] + + * Added SoupServer:http-aliases and :https-aliases properties, + to specify URI schemes that should be treated as though they + were http (just like SoupSession:http-aliases and + :https-aliases, but on the server side). [#703694, Dan] + + * Fixed race conditions in cache-test and timeout-test that + could case spurious failures. [#698305, #660581, Dan] + +Changes in libsoup from 2.43.5 to 2.43.90: + + * Fixed the handling of unsatisfiable range requests in + SoupServer [pointed out on mailing list, Dan]. Also, added + more documentation clarifying that you don't need to handle + range requests yourself in many cases. + + * Fixed the handling of IPv6 address literals with scope IDs. + (Requires the latest glib as well for the complete fix.) + [#669724, Dan] + +Changes in libsoup from 2.43.4 to 2.43.5: + + * SoupProxyURIResolver is now deprecated in favor of the + SoupSession:proxy-resolver property (which takes a + GProxyResolver). [#680273, Dan] + + * The SoupKnownStatusCode enum is now called SoupStatus. The + old name continues to exist as an alias, but is deprecated. + (This change has no visible effect in C; it is primarily to + help language bindings, so that, eg, SOUP_STATUS_NOT_FOUND + maps to "Soup.Status.NOT_FOUND" rather than + "Soup.KnownStatusCode.NOT_FOUND".) [#684409, Dan] + + * Fixed the parsing of URI schemes in SoupURI (in particular, + to allow scheme names with digits in them). [#703776, Dan] + + * Fixed SoupLogger to print a message's response headers even + if the message gets cancelled before the complete response + body is received. [#703200, Andres Gomez] + + * Fixed a build problem in non-UTF-8 locales [#702534, Ross + Lagerwall] + + * SoupSession now warns if you use + soup_session_pause_message() or + soup_session_unpause_message() on a synchronous message + (which has never worked, though that fact wasn't + documented). [#703461, Philip Withnall] + +Changes in libsoup from 2.43.2 to 2.43.4: + + * Fixed a bug that could cause synchronous sessions to get + stuck in a state where no new messages would ever get + processed. [#703463, Philip Withnall] + + * Fixed another memory leak in SoupSocket (found while + added a test case for #700472) + + * Switched to using g_cclosure_marshal_generic() rather than + using glib-genmarshal. [#686042, Olivier Blin] + + * Changed SoupServer to call unref() on the query hash table + after calling the handler, rather than destroy(), so that + the handler can keep a copy of the query data if it wants. + [#702793, Bernhard Schuster] + + * Fixed a few introspection annotations + + * Updated examples/get to use SoupLogger and to allow + redirecting the output to a file [#703231, #703229, Andres + Gomez] + +Changes in libsoup from 2.43.1 to 2.43.2: + + * Fixed an authentication error when using NTLM when + connecting to an https site over a proxy; the code was + getting confused and thinking that the 200 OK response to + the CONNECT meant that NTLM auth had succeeded. [#698728, + Dan] + + * Fixed a memory leak in SoupSocket. [#700472, Richard + Röjfors] + + * Fixed a missing include error on some platforms [#700003, + Erik van Pienbroek] + + * Fixed warnings when running against the "dummy" TLS backend. + [#700518, Dan] + +Changes in libsoup from 2.42.1 to 2.43.1: + + * Including no longer pulls in the system + networking headers. This may cause some packages to no + longer compile, if they were accidentally depending on this. + Adding "#include " will fix them on both + unix and Windows. (This was done as part of fixing the build + on Windows.) [#692134, Dan] + + * Fixed SoupSession:proxy-resolver [#698163, Dan] + + * Added soup_message_set_priority(), to mark messages as being + high, low, or normal priority, and update the message queue + to prioritize them accordingly. [#696277, Sergio] + + * Fixed several test programs to still work if glib-networking + isn't installed [Dan], and fixed another to still work if + the kernel has no IPv6 support. [#698220, Dan] + +Changes in libsoup from 2.42.0 to 2.42.1: + + * Fixed SoupProxyResolverDefault, which got broken in 2.42.92. + [#697028, Dan] + + * Fixed a gigantic memory leak when using SoupCache. [#696594, + Xan] + + * Fixed a build problem on Windows. [#696354, Kalev Lember] + + * Fixed ntlm-test to pass whether or not Samba ntlm_auth + support was compiled in. [#697510, Dan] + + * New/updated translations: + Basque, Turkish + +Changes in libsoup from 2.41.92 to 2.42.0: + + * Fixed a compiler warning on 32bit in a test program. [Kalev + Lember] + + * New/updated translations: + Hindi, Kannada, Korean, Malayalam, Marathi, Odia, Persian, + Tadjik, Tamil, Telugu + +Changes in libsoup from 2.41.91 to 2.41.92: + + * Fixed a bug that caused libsoup to retry an incorrect + password repeatedly, forever, in a certain case that + affected Google calendars in evolution in particuar. + [Red Hat bug #916224, Dan] + + * Also added code to make such infinite retry loops impossible + in the future. [Dan] + + * Fixed SoupRequestData's handling of URIs with "%00" in them. + [#695246, Žan Doberšek] + + * Added the SoupSession:proxy-resolver property, to override + the GProxyResolver used by a session. (This means there are + now three different ways of controlling proxy resolution in + SoupSession... this will be cleaned up a bit after 2.42.) + [#680273, Dan] + + * Added missing G_BEGIN_DECLS/G_END_DECLS to + soup-message-headers.h, so that its functions can be called + from C++. [Carlos Garcia Campos] + + * Updated translations: + Assamese, Belarusian, Brazilian Portuguese, Catalan + (Valencian), Catalan, Danish, Estonian, French, Greek, + Gujarati, Hungarian, Italian, Latvian, Portuguese, Russian, + Slovenian, Thai + +Changes in libsoup from 2.41.90 to 2.41.91: + + * Fixed a crash that showed up with XMLRPC requests in + WebKitGTK. [#694920, Sergio] + + * Fixed SoupCache to update the cached headers when it + receives a 304 Not Modified response, and added a test for + this. [#695121, Sergio] + + * libsoup now builds under automake 1.13 (and "make check" + works under the parallel test harness which is the default + in 1.13) [#694135] + + * The tests/ directory now contains only actual test programs + that are run by "make check", and the programs that are + intended more as example code are under examples/. + + * New/updated translations: + Aragonese, Chinese (traditional), Czech, Galician, Hebrew, + Lithuanian, Norwegian bokmål, Punjabi, Spanish, Uyghur, + Vietnamese + +Changes in libsoup from 2.41.5 to 2.41.90: + + * Added SoupSession:local-address property, which allows you + to force connections to bind to a particular local address + (eg, to control the interface that is used). [#693215, Jonh + Wendell] + + * Fixed SoupCache to properly handle messages that get + cancelled, and added tests for this. [#692310, Sergio] + + * Fixed a reference leak in SoupCache that resulted in + epiphany hanging for several seconds on exit and then + eventually printing "Cache flush finished despite X pending + requests". And added more tests. [#682527, Sergio] + + * Fixed SoupAuthNTLM so that SoupSession:authenticate gets + emitted with retrying=TRUE if the first attempt fails (ie, + make it work the same way as SoupAuthBasic and + SoupAuthDigest). [#693222, Dan] + + * Fixed the SoupSession:add-feature-by-type property to accept + non-SoupSessionFeature features as well (eg, auth types) + [Dan] + + * Fixed a build bug that would break all the apache-based + tests if you didn't have PHP installed. [#693311, Dan] + + * Updated translations: + Malayalam, Polish, Serbian, Slovak + +Changes in libsoup from 2.41.4 to 2.41.5: + + * Reverted the change to SoupURI's password handling from + 2.41.4, since it turns out to have broken some things. + [#692149, Dan] + + * Avoid a g_return_if_fail() when loading + SoupSession:ssl-ca-file fails. [#691930, Guillaume + Desmottes] + + * Fixed a bug in SoupBodyInputStream that caused redirects in + WebKitGTK to hang. [#692026, Sergio] + + * Updated translations: + Belarusian, Chinese (traditional), German, Italian, + Norwegian bokmål, Serbian, Uyghur + +Changes in libsoup from 2.41.3 to 2.41.4: + + * Lots of docs fixes, including catching up with some (but not + all!) of the API additions and deprecations, and a new + chapter with hints on porting from + SoupSessionAsync/SoupSessionSync to the new-and-improved + plain SoupSession. + + * The plain SoupSession type now supports + soup_session_queue_message() (with SoupSessionAsync + semantics) and soup_session_send_message() (with + SoupSessionSync semantics), and there are now + soup_session_new() and soup_session_new_with_options(). + + * The mirroring of the SoupMessage API onto SoupRequestHTTP, + added in 2.41.3, has been reverted. However, new APIs + soup_session_send() and soup_session_send_async() have been + added that let you use the GInputStream-based API with + SoupMessages rather than SoupRequest, so if you're doing + HTTP-specific stuff, you can just use that instead. + + * soup_message_get_https_status() now returns the certificate + and flags for unsuccessful https connections as well as + successful ones. [#690176] + + * Fixed a deadlock when calling soup_session_abort() on a + SoupSessionSync in some cases. [#691399] + + * Internal SoupCache rewrites/improvements [#682112, Sergio] + + * Plugged a memory leak in SoupCache [#690382, Sudarsana + Nagineni] and one in SoupAuthDigest [#690142] + + * LIBSOUP_DISABLE_DEPRECATED has been renamed to + SOUP_DISABLE_DEPRECATED, but that's just to keep gtk-doc + happy, and you shouldn't use it. You should use + SOUP_VERSION_MIN_REQUIRED instead. + + * Fixed the samba-windbind-based NTLM support, which appears + to have been broken before. + + * SoupAuthManager is now a public class (so you can remove it + as a feature from a session, or disable it for a particular + message). It also has a new method + soup_auto_manager_use_auth(), which can be used to "preload" + authentication for a host so that libsoup will use + authentication on the very first request. + + * SoupURI now treats "http://user@example.com" as having a + password of "" rather than NULL, since a NULL password would + not be valid for any known HTTP auth type. + + * build: libsoup now uses autoreconf instead of + gnome-autogen.sh, and no longer uses AM_GLIB_GNU_GETTEXT + [Javier Jardon]. + + * Updated translations: + Assamese, Bulgarian, Estonian, Friulian, Galician, Hebrew, + Polish, Slovenian, Spanish + +Changes in libsoup from 2.41.2 to 2.41.3 (codename: "I Left My +Deprecated APIs in A Coruña"): + + * BUILD DEPENDENCY CHANGES: libsoup-gnome no longer depends on + libgnome-keyring, and the sqlite3 dependency has been moved + from libsoup-gnome to libsoup proper. (See below). + + + * SoupRequest is now stable API. SoupRequester, however, is + deprecated. Instead you can now call soup_session_request() + or soup_session_request_uri() to create a SoupRequest. + + Some documentation has been updated to reflect this, but + much more still needs to be (in particular the "Client-side + Tutorial"). + + * SoupRequestHTTP now has a number of fields and methods that + mirror the SoupMessage data, so you don't have to use + soup_request_http_get_message() in many cases. On the flip + side, there is also now soup_message_get_request(). And you + can create a SoupRequestHTTP directly (and override its + request method) by using soup_session_request_http() or + soup_session_request_http_uri()). + + * soup_message_set_chunk_allocator() is now deprecated; apps + that want to do streaming reads should just use SoupRequest, + which is vastly more sane. + + + * SoupPasswordManager is now deprecated, and + SoupPasswordManagerGNOME is now a no-op (and libsoup-gnome + no longer links against libgnome-keyring). [#594377, #679866] + + * SoupCookieJarSqlite is now deprecated in favor of + SoupCookieJarDB, which is exactly the same thing except that + it's in libsoup itself rather than being in libsoup-gnome + (something that many people have requested). This means that + libsoup now requires sqlite3... if this offends you horribly + then you have a few months to speak up... + + * SoupProxyResolverGNOME is now deprecated; there hasn't been + any real reason to use it since SoupProxyResolverDefault was + added. + + * As a result of the last three items, libsoup-gnome now + consists entirely of deprecated APIs, and there is no reason + you should use it any more (though packagers need to keep + building it, for backward compatibility). + + + * SoupSession is no longer an abstract class, and you can + create a plain SoupSession, which behaves in a more + traditionally-gio-like way (allowing a mix of sync and async + methods, etc). This "plain" SoupSession also has more sane + default values of certain properties, and has certain + SoupSessionFeatures built in. + + This will eventually replace SoupSessionAsync and + SoupSessionSync completely, but most of the documentation + hasn't yet been updated at this point... + + This change involved merging the majority of the + SoupSessionAsync and SoupSessionSync code into SoupSession, + getting rid of lots of redundancy in the process. There may + be some bug fallout from this (probably on the + SoupSessionSync side, since WebKit's tests tend to shake out + all SoupSessionAsync bugs). However, this should help to + avoid SoupSessionSync-only bugs in the future, since much + more of the code is now shared. + + + * Usernames and passwords passed into SoupSession a URI will + now be cleared after they're used, so that if they are + wrong, the authenticate signal will be emitted on the next + round. [#689673, Martin Robinson] + + * SoupURI now leaves "%00" in URIs as-is, rather than decoding + it to "\0", which was not intended and is never useful. + + * Fixed a bug in SoupBodyOutputStream that could cause libsoup + to sometimes use blocking I/O rather than non-blocking when + writing chunked message bodies. [#688974, Milan Plzik] + + * Fixed a bug in SoupFilterInputStream that could cause some + non-blocking reads to suck up CPU while waiting for the + network. (This was noticed with multipart/x-mixed-replace + processing; it's not clear if it affected anything else.) + [Gustavo] + + * tests: misc small fixes + + + * New/updated translations: + Assamese, Galician, Japanese, Odia, Polish, Spanish + +Changes in libsoup from 2.41.1 to 2.41.2: + + * libsoup-2.4.so and libsoup-gnome-2.4.so now only export the + symbols that are part of the public API. (Plus, temporarily, + one additional symbol, soup_message_io_cleanup, which is + used by gvfs and possibly a few other modules, even though + it shouldn't be. If you copied soup-input-stream.c from + gvfs, you should port your code to use SoupRequest instead.) + [Dan, #595176] + + * Added SOUP_VERSION_MIN_REQUIRED / SOUP_VERSION_MAX_ALLOWED + macros like the corresponding glib ones, to allow libsoup + users to request per-version deprecation/availability + warnings. [Dan] + + * Fixed a crash caused by a race condition in SoupSessionSync, + and reorganized some code to avoid other possible similar + race conditions. [#684238, Dan] + + * Fixed a crash when a DNS resolution failed, caused by a bug + in the GTask porting in 2.41.1. [#688330, Milan Crha] + + * Fixed a problem that would cause g_warning()s in epiphany + when browsing sites that (incorrectly) returned empty + Cache-Control headers. [#683433, Dan] + + * We now add a Host header to HTTP/1.0 requests as well as + HTTP/1.1 ones. [Dan] + + * Fixed a bug in the printing of IPv6 address literals in the + Host header in SoupLogger. (They were being sent across the + wire correctly, they were just printed wrong by SoupLogger.) + [Dan] + + * Belatedly added soup-multipart-input-stream.h to soup.h. + [Dan] + + * Removed an evil hack in the long-deprecated + SoupProxyResolver code (not to be confused with + SoupProxyURIResolver), to avoid warnings with glib master. + If you had previously implemented a custom + SoupProxyResolver, then it will probably (silently) stop + working, but you should have ported it to + SoupProxyURIResolver years ago anyway... [Dan, #687659] + + * Fixed a few race conditions in the test programs that could + cause "make check" to fail on slow or heavily-loaded + machines. [Dan] + + * Further cleaned up and reorganized the internal HTTP I/O + codepaths, in preparation for an improved SoupCache. + [#682112, Sergio] (This change should not actually be + externally noticeable. But if SoupContentDecoder or + SoupContentSniffer turns out to be broken in this release, + this would be why). + + * New/updated translations: + Slovak, Uyghur + +Changes in libsoup from 2.40.1 to 2.41.1: + + * Changed the behavior of NTLM authentication to be more like + what other apps apparently do. Now if the user does not + specify a domain in the username (eg, "MYDOMAIN\username"), + then we will not specify a domain in the NTLM response + (rather than assuming that the user is in the server's + default domain). People who get broken by this change should + be able to fix it by including an explicit domain in their + username, but the theory is that no one should get broken by + this... If this change does turn out to hurt more than it + helps then it may be reverted later. [#624613, Dan, based on + a suggestion from David Woodhouse] + + * Fixed a crash caused by a race condition in SoupSessionSync. + [#684238, Dan] + + * SoupRequest now supports resource:// URIs, for reading from + gresource. [#682721, Carlos] + + * Added new compile-time and runtime APIs for checking the + libsoup version. [#684514, Martin Robinson] + + * Updated to take advantage of (and require) glib 2.35; + removed all g_type_init() calls and ported to GTask. [Dan] + + * Added support for Apache 2.4 to the unit tests. [Dan] + + * New translations: + Uzbek (Cyrillic) + +Changes in libsoup from 2.40.0 to 2.40.1: + + * Improved the parsing of multipart/x-mixed-replace responses. + [#685752, Gustavo] + + * Fixed handling of IPv6 address literals. [#684990, Dan] + + * New/updated translations: + Catalan, Catalan (Valencian), Norwegian bokmål + +Changes in libsoup from 2.39.92 to 2.40.0: + + * New/updated translations: + Bengali (India), Bulgarian, Chinese (Simplified), Estonian, + German, Hebrew, Hindi, Hungarian, Latvian, Malayalam, + Punjabi, Tamil, Telugu, Thai, Ukranian + +Changes in libsoup from 2.39.91 to 2.39.92: + + * Fixed some g_warnings (and a possible crash) with the + soup_request_send_async(). [#683404, Dan] + + * Fixed a hang with SoupSessionSync [#682923, Dan] + + * Handle empty "Cache-Control" headers. [Sergio] + + * New/updated translations: + Assamese, Belarusian, Brazilian Portuguese, British English, + Chinese (Traditional), Czech, Danish, French, Galician, + Greek, Gujarati, Hungarian, Indonesian, Italian, Lithuanian, + Marathi, Persian, Polish, Portuguese, Russian, Serbian, + Slovenian, Spanish + +Changes in libsoup from 2.39.90 to 2.39.91: + + * Added missing (transfer full) annotation to + soup_cookie_jar_add_cookie() and + soup_cookie_jar_add_cookie_with_first_party(), fixing + crashes in bindings. [#682554, Daniel Drake] + + * Fixed a crash [#682569, Alexander Larsson] and a win32 build + problem [#683200, Kalev Lember] introduced by the memory + leak fixes in 2.39.90 + + * Fixed the SoupMessage:network-event signal, which had been + skipping the G_SOCKET_CLIENT_COMPLETE state in tunneled + https connections. And added a test for this. [Dan] + + * New/updated translations: + French, Japanese, Korean, Latvian, Lithuanian, Polish, + Punjabi, Swedish, Tamil + +Changes in libsoup from 2.39.5 to 2.39.90: + + * Added SoupMultipartInputStream, for handling multipart + responses (particularly multipart/x-mixed-replace). + [#656684, Gustavo] + + * Fixed a potential crash in SoupSessionAsync after the + session is finalized. + + * Fixed a regression in soup_tls_is_public_suffix() [#681085, + Sergio] + + * Added a SOUP_MESSAGE_IDEMPOTENT flag, so that apps can + bypass the "POSTs must be sent on new connections" check, + which was causing evolution-ews to have to create a new + connection for every request. [#681493, Milan Crha] + + * Changed SoupSession so that pending SoupMessages now hold a + ref on the session. It is possible that this will break code + that was depending on the old, dumb, behavior (where + unreffing the session with messages pending would cause + those messages to be cancelled), in which case this will be + reverted before 2.40. + + * Fixed memory leaks found by valgrind. + + * Cleaned up some code in SoupCache. [#681509, Sergio] + + * New/updated translations: + Bengali (India), Chinese (Traditional), German, Marathi, + Turkish, Ukranian + +Changes in libsoup from 2.39.4.1 to 2.39.5: + + * Fixed several bugs in the soup-message-io updates that could + cause hangs or I/O errors. [#679527 and other bugs not filed + in bugzilla] + + * Fixed SoupServer:async-context to work properly again + + * Further fixes to soup_uri_normalize() when using the + "unescape_extra" parameter. [#680018] + + * Fixed soup_xmlrpc_parse_method_call() to handle the case + where there is no element (which is legal). + [#671661] + + * Fixed the deprecation warning on soup_message_headers_get() + [#680143] + + * Added warnings to some erroneous SoupSocket usages rather + than returning bogus data. [#673083, Simon McVittie] + + * Fixed build under Windows/MinGW + + * SoupSocket no longer emits the "readable" signal when a + socket is disconnected if that socket is non-blocking. + + * Updated public suffix list to the current version. + + * New/Updated translations: + Assamese, Chinese (simplified), Esperanto, Galician, Greek, Gujarati, + Hebrew, Norwegian bokmål, Russian, Serbian, Slovenian + +Changes in libsoup from 2.39.4 to 2.39.4.1: + + * Fixed indentation problems in tld-parser.py so it will work + under python 3. [#680089, "marduk"] + + * Actually fixed cookies in non-suffixed/private domains, + which still didn't work after the last fix. [#679230, + Carlos] + + * Updated translations: + Spanish + +Changes in libsoup from 2.39.3 to 2.39.4: + + * Fixed the SoupRequest codepaths to properly retry in the + case where the server closes a persistent connection when we + try to use it. [Dan, might be the fix for #679527, but this + is not yet confirmed] + + * Fixed the content-type and content-length of requests + retrieved from SoupCache. [#680029, Carlos Garcia Campos] + + * Fixed the handling of cookies in non-suffixed and private + domains ("localhost", "foo.local", etc) [#679230, Sergio and + Dan] + + * Fixed cookie parsing to allow attribute values on "secure" + and "HttpOnly". (Neither is supposed to have a value, but it + happens in the real world.) [#678753, Dan, based on a patch + from "Basavaraj"] + + * Fixed soup_uri_normalize() to not always run the "fixup" + codepath. [#680018, pointed out by Yann Soubeyrand] + + * Fixed a (rare) crash when closing the stream returned from + SoupRequestHTTP. [Dan] + + * Use G_DEPRECATED on deprecated functions, and then fix up + the warnings this caused due to libsoup using its own + deprecated functions. [#671770, Javier Jardón] + + * Fixed up "make dist" by, among other things, rewriting + tld-parser in python. [#678909, Colin Walters] + + * Removed the "getbug" example program in tests/, which didn't + work any more anyway. [Dan] + + * Various internal code cleanups. [Dan] Fixed one crash + resulting from this [#680055, Alban Browaeys]; hopefully + there won't be any more. + + * New/Updated translations: + Assamese, Belarusian, Bulgarian, Chinese (traditional), Hebrew, + Indonesian, Lithuanian, Norwegian bokmål, Vietnamese + +Changes in libsoup from 2.39.2 to 2.39.3: + + * Added new functions for comparing domains against the + "public suffix" list (http://publicsuffix.org/), and in + particular fixed SoupCookieJar to not allow setting cookies + in "public" domains (eg, ".co.uk"). [#673802, Sergio] + + * Added two new SoupCookieJar APIs + (soup_cookie_jar_get_cookies() and + soup_cookie_jar_set_cookie_with_first_party()) as part of + fixing the handling of HttpOnly cookies in WebKitGTK. + [#677922, Christophe Dumez] + + * Fixed g-i annotation of + soup_message_headers_get_content_type(). [#677002, Dan] + + * Updated translations: + Galician, Greek, Slovenian, Spanish, Telugu + +Changes in libsoup from 2.39.1 to 2.39.2: + + * Fixed several bugs that resulted from the I/O code rewrite + in 2.39.1, and added more test cases to exercise the new + code paths: + + * Problems with cancelling messages from the + got-headers signal [#674747, Dan] + + * Persistent connections were not always being closed + properly after a message was cancelled mid-response. + [Dan] + + * Cancelling a SoupRequest before it started I/O + didn't work. [Dan] + + * Asynchronous HTTP authentication via the SoupRequest + API [#675306, Dan] + + * Memory leak [#676038, Ray Strode] + + * Refcounting bug that manifested as a crash in rygel + [#676038, Ray Strode] + + * Handling failed CONNECT requests via SoupRequest + [#675865, Sergio] + + * Messages with trailing junk following a compressed + message body [#676477, Dan] + + * Fixed three cache-related bugs that affect some sites + (notably Twitter) [Sergio] + + * Fixed a bug in the /usr/bin/ntlm_auth integration when you + don't already have credentials cached, and avoid printing + warning messages when ntlm_auth is present but not usable. + [Dan] + + * Fixed some g-ir-scanner warnings, and included + SoupRequester/SoupRequest in the introspected API [#676742, + Jasper St. Pierre] + + * Added soup_buffer_get_as_bytes() [#676776, Jasper] + + * New/updated translations: + Belarusian, Chinese (simplified), French, Galician, Greek, + Hebrew, Polish, Punjabi, Romanian, Slovenian, Spanish + +Changes in libsoup from 2.38.1 to 2.39.1: + + * Major rewrite of the I/O code to use gio streams more + directly. In particular, when using SoupRequestHTTP now, the + input stream that is returned is actually pulling data from + the socket, rather than just repeatedly pausing and + unpausing the underlying SoupMessage and waiting for data to + be pushed into it. This also means that SoupRequestHTTP now + works with SoupSessionSync as well. [#591739, Dan] + + (The SoupRequest API is still protected by unstable-API + #ifdefs, but will be made public later in this cycle.) + + * Libsoup now finally supports SOCKS proxies again. [#553269, + Dan] + + * Certain error messages returned from the streaming API + (SoupRequest, etc) are now localized; more strings will be + localized later on. + + * New translations: Galician, Hebrew, Indonesian, Norwegian + bokmål, Polish, Russian, Slovenian, Spanish. + + * Added a SoupCookieJar:is-persistent property, to distinguish + memory-only jars from SoupCookieJarText and + SoupCookieJarSqlite. [#672838, Carlos Garcia Campos] + +Changes in libsoup from 2.38.0 to 2.38.1: + + * Fixed a situation where soup_connection_disconnect() could + end up calling g_object_unref(NULL) when an idle connection + was closed. [Sergio, #672178] + + * Fixed two warnings when cancelling an in-progress + soup_socket_connect_async(). [pointed out on the mailing + list by Sven Neumann] + + * Fixed a crash when disposing a SoupServer with open + connections. [#673468, Jonny Lamb] + + * Fixed the SoupSession:ssl-use-system-ca-file property to get + turned off (rather than on) when you set it to FALSE... Also + fixed up the property notifications around the various + certificate-verification properties (ssl-ca-file, + ssl-use-system-ca-file, and tls-database). + + * Fixed SoupSession to not leak paused SoupMessages that + were still in progress when it was unreffed. [#673905] + + * Updated the win32 file: URI code again, to fix regressions + in the WebKit tests. [WebKit bug #82484] + +Changes in libsoup from 2.37.92 to 2.38.0: + + * Minor documentation fixes + +Changes in libsoup from 2.37.91 to 2.37.92: + + * Added soup_session_prefetch_dns() and deprecated + soup_session_prepare_for_uri(). The new method takes a + completion callback, allowing you to know how many DNS + resolutions are currently outstanding, so you don't spam the + resolver. [Sergio, WebKit bug #41630] + +Changes in libsoup from 2.37.90 to 2.37.91: + + * Fixed an out-of-bounds memory read that could occur when + parsing malformed requests/responses. + + * Fixed a build-related bug in Makefile.glib that affected + locales such as Estonian where "Z" is not the last (ASCII) + letter of the alphabet. [#654395, Priit Laes] + + * Fixed the handling of file: URIs with query components, + which got broken in 2.37.90. + + * Fixed SoupAuthManagerNTLM to not fall back to allowing Basic + auth when NTLM failed. + + * Further tweaked the warnings/fallback in SoupURI, so that + soup_uri_to_string() on an http URI with a NULL path would + translate that to "/" like it used to. [#670431] + + * Fixed a warning when cancelling the load of a page with many + subresources. [#667245] + + * Use G_GNUC_BEGIN/END_IGNORE_DEPRECATIONS if GLib is new + enough, to avoid getting warned about the use of + GValueArray. + +Changes in libsoup from 2.37.5 to 2.37.90: + + * libsoup is now beta-testing Makefile.glib from bug 654395. + If 2.37.90 fails to build in some strange way that 2.37.5 + did not, this is probably why. + + * Replaced some of the SoupURI g_return_if_fail()s that were + added in 2.37.5 with g_warn_if_fail()s. Although it had + always been documented that SoupURIs must have a non-NULL + path, most SoupURI functions treated NULL the same as "", + and various apps (eg, rhythmbox, midori) were accidentally + relying on this. [Dan] + + * Added various return-if-fails and other sanity checks to + various functions. [#669479, Robert Swain, Mark Nauwelaerts, + Simon McVittie] + + * Updated docs/annotation of soup_form_decode_multipart() to + note that all of the out parameters are (allow-none). Fixed + the file_control_name parameter to actually allow NULL like + the docs already claimed. [#669479, Simon McVittie] + + * Fixed a minor URI parsing bug. (It was allowing URI schemes + to contain numbers.) [Dan] + + * Fixed a few memory leaks introduced in the 2.37 cycle. [Dan] + + * Fixed SoupServer to be able to correctly respond to HTTP/1.0 + requests over IPv6 (which previously would always have + returned "400 Bad Request"). [#666399, Dan] + + * Changed SoupSessionAsync to make it possible to finalize it + from the "wrong" thread. [#667364, Dan]. + + * Fixed SoupCache to not cache resources whose URIs have query + components (unless they have explicit cache headers); to not + generate broken conditional requests for resources that + cannot be conditionally validated; and to not spew warnings + when receiving invalid Cache-Control headers. [#668865, + Sergio]. + +Changes in libsoup from 2.37.4 to 2.37.5: + + * Fixed a bug in SoupSession:use-thread-context [Dan] + + * Fixed the case of cancelling a message from + SoupSession::request-started [#668098, Raphael Kubo da + Costa] + + * Fixed a crash in epiphany when loading a page with more than + 1000 or so images. [#668508, Dan] + + * Fixed a bunch of cases involving invalid URLs found while + testing SoupServer against an HTTP protocol fuzzer. Also + fixed up some documentation/annotations and added some new + test cases. [#667637, Simon McVittie] + + * Fixed SoupRequestFile to work on Windows. [Paweł Forysiuk] + +Changes in libsoup from 2.37.3 to 2.37.4: + + * SoupMessage now has a "network-event" signal that can be + monitored for information about DNS, proxy lookup, TCP + connections, and TLS handshakes. [Dan] + + * The HTTP header parsing code now avoids hitting + g_return_if_fails() (and returns an error instead) in a few + cases of seriously-invalid headers. [#666316, Simon + McVittie, Dan] + + * POSTs and other non-idempotent requests are now always sent + on newly-created connections. You can also force this + behavior on other messages by setting the + SOUP_MESSAGE_NEW_CONNECTION flag. [#578990, Dan] + + * Server-closed idle connections are now detected ahead of + time on Windows, preventing occasional spurious "Connection + terminated unexpectedly" errors. (This had been fixed on + UNIX since 2.28, but the earlier fix didn't work with + WinSock.) [#578990, Dan] + + * Plugged a leak in SoupRequestHTTP. [#667099, Xan] + +Changes in libsoup from 2.37.2 to 2.37.3: + + * Now requires glib 2.31 + + * Simplified SoupHTTPInputStream and SoupRequestHTTP, allowing + related simplifications in WebKit's ResourceHandleSoup. This + is an ABI-incompatible change, but SoupHTTPInputStream is an + unstable API. [#663451, Dan] + + * Fixed a bug that caused the SOUP_MESSAGE_CERTIFICATE_TRUSTED + flag to always be cleared, causing epiphany to claim all + https pages were untrusted. [#665182, Dan] + + * Fixed some bugs in the handling of SoupSession:http-aliases + and SoupSession:https-aliases. + + * Fixed handling of ACLOCAL_FLAGS [#641470, Craig Keogh] + + * Fixed SoupContentDecoder's "ignore Content-Encoding: gzip + because the server didn't actually mean it" hack to handle + x-gzip too. + + * Clarified the documentation on SoupSession:ssl-strict + [#666280] + +Changes in libsoup from 2.37.1 to 2.37.2: + + * Fixed up the output of SoupDirectoryInputStream, thus + improving the display of local directories in WebKit-based + browsers. [#662266, Sergio] + + * Fixed a bug introduced in 2.37.1 that caused some cancelled + SoupMessages to be leaked. [#662847, Sergio] + + * Added new SoupSession properties "http-aliases" and + "https-aliases" that allow you to configure more explicitly + what URL protocols are treated as aliases for http (eg, + "dav:", "webcal:", etc), and which should be recognized as + meaning something else, (eg, "ftp:") [Dan] + + * Added soup_session_would_redirect() and + soup_session_redirect_message(), to help users that want to + handle some or all redirects themselves. Added + soup_message_set_redirect() to make it easier to return + redirection responses from a SoupServer. [Dan] + + * Added the SoupSession "use-thread-context" property, which + tells it to use GMainContexts in a gio-compliant way (and in + particular, allows having different messages running in + different GMainContexts on the same SoupSession, though only + to a limited extent since SoupSessionAsync is still not + thread-safe). In particular, this was added in order to + address WebKit bug 68238. [Dan] + + * Made SoupURI %-encode non-ASCII characters when parsing + URIs, in particular to fix a problem with certain servers + sending syntactically invalid redirects that they would then + only interpret correctly if you fixed the syntax for them. + (@$!@#! Although the new code is probably more correct than + the old code anyway, so...) [#662806, Dan] + + * Fixed a connection-handling bug that could cause problems + with servers that requested authentication and then timed + out the connection while the application was waiting for the + user to enter a password. [#660057, Dan] + + * Made NTLM and Basic authentication handle some non-ASCII + usernames and passwords. (NTLM should handle most. It's + impossible to fix Basic in the general case.) [#576838, + Joachim Breitner, "sponsored by ITOMIG GmbH and the City of + Böblingen"] + + * Added support for "deflate" Content-Encoding, so that we can + work with broken servers that insisted on using it even + though we explicitly indicated in the request headers that + we didn't support it. (@$#!#) [#661682, Sergio] + +Changes in libsoup from 2.36.0 to 2.37.1: + + * Fixed a problem with connections being assigned to multiple + requests at once after a redirection [#651146, Sergio]. Made + soup_session_pause/unpause_message() work in any state, not + just while the HTTP I/O is occurring, and used this to add a + test case for that bug. [Dan] + + * Ported SoupSession to use GTlsDatabase internally, and added + two new properties, SoupSession:use-system-ca-file (to + specify that the session should use the default system + tlsdb) and SoupSession:tlsdb (to specify a specific tlsdb to + use). [Dan] + + * Likewise, added SoupServer:tls-certificate, for specifying a + certificate/key for an https server to use. + + * Made SoupHTTPInputStream use memory more efficiently. + [#659255, Sergio] + + * Fixed soup_message_get_https_status() to return information + more reliably (with latest glib-networking). + + * Bumped the glib requirement to 2.30.0; although libsoup does + not use any new glib 2.30 APIs, there are several important + bugfixes in glib between 2.28 and 2.30 that libsoup needs. + Currently libsoup builds against either glib 2.30.x or glib + 2.31.x. + +Changes in libsoup from 2.35.92 to 2.36.0: + + * Improvements to gtk-doc documentation. [Dan] + +Changes in libsoup from 2.35.90 to 2.35.92: + + * Fixed a problem where SoupHTTPRequest response bodies could + be truncated. [#659256, Sergio] + + * Fixed a bug in copying TLS information from SoupSocket to + SoupMessage, causing all https connections to be reported as + "untrusted" in epiphany. [Dan] + + * Made SoupSession remove items from its host cache after a + while, so that if a host changes IP address, it will + eventually try to re-resolve it. [#646959, Sergio] + +Changes in libsoup from 2.35.5 to 2.35.90: + + * Added SOUP_MESSAGE_CAN_REBUILD flag, to use with + soup_message_body_set_accumulate(FALSE) on a request body, + to indicate that the caller will recreate the request body + after it has been discarded if the message needs to be + re-sent. [#656650] + + * Fixed the build on mingw-w64 by not using "interface" as + as variable name. [#656402, Erik van Pienbroek] + + * (The multihosted https server regression mentioned in the + 2.35.5 NEWS turned out to be a glib-networking bug, which is + fixed as of 2.29.18.) + +Changes in libsoup from 2.35.4 to 2.35.5: + + * Support NTLM single sign on via samba's /usr/bin/ntlm_auth. + [#650940, Mandy Wu]. This is enabled by default (if NTLM is + enabled for the session and the ntlm_auth binary is + available), but will fall back to the standard + password-based authentication if SSO fails. + + * Default to TLS+extensions for https connections, falling + back to SSLv3-without-extensions (the old default) only if + the server fails to negotiate TLS. [#581342] + + * As a result of this change, some users are currently + seeing problems with sites that serve multiple https + hosts from a single IP address (eg, + *.launchpad.net). There is no known workaround at + this time. + + * Fixed a longstanding problem with https pages sometimes not + loading when using a proxy. [#631368, based on patches from + DongJae Kim and Thierry Reding] + + * SoupContentSniffer: don't use gio's sniffing rules, since + the spec now recommends that browsers not do any additional + sniffing beyond what's in the spec. [#648846, "arno"] + + * Fixed SoupRequestHTTP to work properly with alternate + GMainContexts. [#653707] + + * Added some annotations from Vala's vapi files. [#655397, + Evan Nemerson]. Also, removed SoupProxyResolver from the + gir/typelib, since it had been deprecated since before + introspection was available, and it was being scanned wrong + anyway. + +Changes in libsoup from 2.35.3 to 2.35.4: + + * CVE-2011-2524: Fixed a security hole that caused some + SoupServer users to unintentionally allow accessing the + entire local filesystem when they thought they were only + providing access to a single directory. [#653258] + + * Plugged another SoupCache memory leak [Xan] + + * Simplified SoupCache keys, and handle collisions. [#649963, + Sergio] + + * Annotate SoupSession:add-feature, etc, as (skip), so they + don't conflict with the methods of the same name. [#655150, + Jasper St. Pierre] + +Changes in libsoup from 2.34.1 to 2.35.3: + + * SoupCache fixes [Sergio]: + + * Don't store hop-by-hop headers [#650094] + + * Fix status code and headers of responses returned + from the cache after being revalidated [#649965] + + * Added versioning support to the cache file format + [#652554] and extended it to keep track of the + status code [#649965] + + * Fixed storage of time values in the cache [#653349] + + * Fixed a use-after-free that could result in bogus + data being written to the cache [#650620] + + * Various leaks [#649309] + + * Work around an Apache bug where it tells browsers to + automatically decode .gz files but still keep the .gz in the + name. [#613361, Dan] + + * Fixed an overflow when sending a response larger than 2^31 + bytes (eg, streaming movies in Rygel). [#638468, Jens Georg] + + * Always send the Keep-Alive header, not just to hosts we + already know to be HTTP/1.0 [#648680, Sergio] + + * Fixed various leaks [#652699, Sergio], [#651643, Milan], + [etc, Xan] + + * Minor build fix for Debian/Ubuntu [#648948] + + * Fixed a docs typo + +Changes in libsoup from 2.34.0 to 2.34.1: + + * Two multipart forms/Content-Disposition fixes [Dan]: + + * UTF-8-encoded header encoding/decoding rules updated + to match RFC 5987. In particular, a UTF-8-encoded + filename parameter in Content-Disposition will now + override an ASCII one. + + * When not using UTF-8-encoded filenames in + Content-Disposition, always quote the filename, + since some servers erroneously fail to handle + non-quoted ones. [#641280] + + * Fixed several memory leaks [Dan, Xan] + + * Fixed decoding base64 data: URLs [#646896, Sergio] + + * Simplified the libsoup-gnome build on Windows by dropping + the gnome-keyring dependency. [Fridrich Štrba] + + * Fixed a bug in soup_uri_to_string() in which (invalid) port + numbers could be output as negative numbers (tripping up a + WebKit "sanity checking" test). [#647767, Sergio] + + * Fixed a cache corruption bug in SoupCache. [#648285, Sergio] + + * Fixed a crash in SoupSessionSync when using + soup_session_abort(). + +Changes in libsoup from 2.33.92 to 2.34.0: + + * Fixed the GMainContext handling of the new + SoupProxyResolverDefault (which among other things fixes + gstreamer usage inside epiphany). [#646201, Sebastian Dröge] + + * Tweaked the introspection Makefile rules to fix a problem + building on Debian/Ubuntu. [#645505] + + * Belated bumped the shared library versioning to reflect the + API additions since 2.32.0 + +Changes in libsoup from 2.33.90 to 2.33.92: + + * LIBSOUP NO LONGER DEPENDS ON GCONF OR LIBPROXY. + (see below). + + * Added SoupProxyResolverDefault, which uses uses gio's + GProxyResolver to resolve proxies [#642982, Gustavo Noronha + Silva]. Despite the "default" in the name, it is not used by + default, for compatibility reasons, but it is available in + plain libsoup, not libsoup-gnome. (Of course, it depends on + having glib-networking installed.) + + * Updated SoupProxyResolverGNOME to be based on + SoupProxyResolverDefault, but explicitly requesting the + "gnome" GProxyResolver if it is available [#625898], and + removed the old code that used GConf and libproxy directly. + + * Added soup_server_disconnect(), to explicitly disconnect a + SoupServer, since it is not possible to g_object_unref() it + from memory-managed language bindings. [#638576, Andreas + Rottmann] + + * SoupDate now parses month names case-insensitively [#644048, + Christian Dywan] + + * Avoid a g_return_if_fail() when using + SOUP_COOKIE_JAR_ACCEPT_NO_THIRD_PARTY with non-http URIs + (file:, data:, etc). [#643226] + + * SoupCookieJar now catches overflows when parsing very + distant dates [#643462, based on a patch from Mark + Starovoytov] + + * Fixed a buggy interaction between request body streaming and + restarted requests [David Woodhouse]. Added some new tests + to tests/chunk-test.c to make sure that a specific + (unsupported!) way of using those methods would not get + broken in the future. + + * Fixed soup_socket_get_remote_address(), which had been + broken since 2.33.4 (and which in turn caused + soup_client_context_get_address/_get_host to be broken). + [#645227] + +Changes in libsoup from 2.33.6 to 2.33.90: + + * Attempted to make libsoup's dependency on glib-networking + (for TLS support) more explicit, by requiring that + glib-networking be present at compile time unless the + builder explicitly passes "--disable-tls-check", and noting + that packagers should give libsoup a runtime dependency on + glib-networking. + + * Fixed a bug in talking to servers with virtual hosts with + Unicode names (IDNs) [#642075] + + * Added a "Connection: Keep-Alive" header when talking to + HTTP/1.0 hosts, to improve performance. [#640414, Sergio + Villar Senin] + + * Changed SoupCache to not cache multipart/x-mixed-replace + content. [#642028, Sergio Villar Senin] + +Changes in libsoup from 2.33.5 to 2.33.6: + + * Made SoupSessionAsync do idle-connection cleanup more + sanely, resulting in faster load times for pages with lots + of subresources. [#639768, Sergio Villar Senin] + + * Fixed soup_form_decode()'s behavior (and by extension, + SoupServer query string handling) with datasets that contain + multiple values for the same key, and added a test case. + [#639783, Sven Neumann] + + * Fixed warnings pointed out by gcc 4.6, including a bug in + SoupCache that would cause unnecessary revalidations + [#640556]. + + * Belated copied a fix from the WebKit copy of soup-cache.c + into ours, and fixed a bug in the local copy of + soup-request-data.c [#641022, Sergio Villar Senin], in + preparation for making WebKit use the libsoup versions. + +Changes in libsoup from 2.33.4 to 2.33.5: + + * Fixed certain cases of soup_session_cancel_message() with + SoupSessionSync that could previously cause warnings or + crashes. [#637741] + +Changes in libsoup from 2.32.2 to 2.33.4: + + * SoupSocket now uses GSocketConnection and GTlsConnection + internally rather than making socket calls directly and + using GIOStream, and TLS is handled via glib's APIs rather + than using gnutls directly. + + * The gzip Content-Encoding handler is now implemented using + GZlibDecompressor + + * As a result of the above two changes, libsoup no longer + directly depends on gnutls, libgcrypt, or zlib, though it + still indirectly depends on zlib via glib and libxml2. Also, + although libsoup does not depend on glib-networking as a + build-time dependency, some "make check" tests will be + skipped if it is not installed. + + * The SoupRequest/SoupCache code from WebKit has been + imported, but it is not yet recommended for general use, and + is not necessarily API stable. [#523100, Sergio Villar, with + the SoupRequest parts based on the Summer of Code work by + Gabriel Corvalan and the cache parts based on an earlier + patch by Xan Lopez] + + * Added SoupMessage:tls-certificate and + SoupMessage:tls-errors, which give more information about + the certificate used to authenticate a TLS connection. + + * It is now possible to disable Basic or Digest auth in a + session by using soup_session_remove_feature_by_type() with + SOUP_TYPE_AUTH_BASIC or SOUP_TYPE_AUTH_DIGEST. Likewise, the + right way to enable NTLM support now is to call + soup_session_add_feature_by_type() with SOUP_TYPE_AUTH_NTLM; + SOUP_SESSION_USE_NTLM is now deprecated. + + * Allow setting cookies on file:// URIs, since other browsers + do, and WebKit has a test for it. [#603825] + + * .gir/.typelib files now include C header/library information + (needed by vala and some other bindings) [#635395, Evan + Nemerson] + + * Added annotations on soup_message_headers_get_content_type() + [Lucas Rocha] and SoupHTTPVersion [John Palmieri] + + * Fixed a Set-Cookie processing leak [#636741, Jonathan + Jongsma] + +Changes in libsoup from 2.32.1 to 2.32.2: + + * Fixed a regression in 2.32.0 that caused evolution-exchange + to get stuck and stop updating. [#634422] + + * Fixed a regression in 2.32.0 with apps using asynchronous + sessions from multiple threads (in particular, gupnp) + [#635101] + + * Fixed the regression test for #631525 to not cause spurious + "make check" failures on some machines. + +Changes in libsoup from 2.32.0 to 2.32.1: + + * Fixed a regression in 2.32.0 with the use of persistent + connections that caused spurious "Connection terminated + unexpectedly" errors. [#631525, debugged by Sergio Villar] + + * Fixed a regression in 2.32.0 that caused proxy-related + DNS errors to return SOUP_STATUS_CANT_RESOLVE rather than + SOUP_STATUS_CANT_RESOLVE_PROXY. + + * Usernames/passwords specified explicitly in request URIs now + override existing cached auth info. [#631679, Sergio Villar] + + * Changed soup_uri_decode() and soup_uri_normalize() to just + ignore malformed %-encoding rather than returning NULL, + for consistency with soup_uri_new(). [#630540] + + * Fixed soup_form_decode() to ignore invalid parameters, + and soup_form_encode_hash() to just g_return_if_fail() + rather than crashing if there are NULL values in the + hash. [#620220] + + * Added another workaround for stupid servers that close the + connection before returning the full response (in this case, + when using chunked encoding and failing to include the + final 0-length chunk). [#629160] + + * Fixed a bug in SoupCookieJarText that deleted excess cookies + whenever any cookie expired. [#631641, Michał Kazior] + + * Fixed a small leak in SoupContentDecoder if you were using + it incorrectly. [pointed out in email by Christophe + Gillette] + + * Added regression tests for passwords-in-URIs [#631679, + Sergio Villar] and SOUP_SESSION_IDLE_TIMEOUT. + +Changes in libsoup from 2.31.92 to 2.32.0: + + * (No changes, just a version bump) + +Changes in libsoup from 2.31.90 to 2.31.92: + + * Updated for gobject-introspection 0.9.5. Also added some new + annotations and removed a bunch of private headers from the + scanning process. + + * Percent-encoded characters in URIs are no longer + automatically normalized to uppercase, since apparently some + servers are stupid. [#628728, Sergio Villar Senin] + + * Fixed a crash when resolving a URI containing both spaces + and non-UTF8 8bit characters. [#629449] + +Changes in libsoup from 2.31.2 to 2.31.90: + + * libsoup now tries to connect to each IP address associated + with a hostname, if the first one fails. In particular, if a + host has both IPv4 and IPv6 addresses, and only one of them + is reachable from the current host, libsoup will now try the + other one rather than failing. (libc is supposed to sort the + IP addresses in the right order, such that, eg, if you don't + have IPv6 connectivity, it will put the IPv4 address first. + For some reason though, this seems to be broken on some + distros.) [#526321]. + + * Fixed Accept-Language header generation in locales where "," + is used as the decimal point. + +Changes in libsoup from 2.31.2 to 2.31.6: + + * Disabled TLS 1.2 in addition to the already-disabled 1.1 and + 1.0 [see below, in libsoup 2.27.2], thus making libsoup + usable with gnutls 2.10. [#622857. This commit, 01a43ad9, + can be applied to libsoup 2.30.x as well if you need that + release to work with gnutls 2.10.] + + * When using libproxy 0.3 or newer, libsoup no longer leaks + proxy-related environment variables into child processes + [#603285] + + * Changed the way message/connection binding works in + SoupSession so that (among other things), when there are + multiple requests queued to a host, and one of them gets a + network error, the other requests are still allowed to try + to succeed, rather than all failing immediately. [#619633] + + * SoupSession now limits the number of times a message can be + redirected, to avoid infinite loops [#604383, José Millán + Soto] + + * Fixed handling of certain messages where the response + headers included "Connection: close" but the server did not + actually close the connection at the end. [#611481] + + * Fixed some incorrect g-i annotations [#621021] + + * Fixed an out-of-bounds memory access when processing certain + Set-Cookie headers [#620288] + + * Improved msg->reason_phrase on network errors [#623274] + + * Fixed gir file disting [#621727, Yaakov Selkowitz] + +Changes in libsoup from 2.30.1 to 2.31.2: + + * gobject-introspection has now been merged in. Use + --enable-introspection to build. [#576595, Andreas Rottmann] + Note that the introspected API is not yet stable, and in + particular, there are numerous values annotated as "utf8" + which are actually not guaranteed to be utf8. (Eg, most + header data.) + + * Added some helper functions for bindings: + soup_buffer_new_take(), + soup_message_body_append_take(), and + soup_buffer_get_data(). [#576595, Andreas Rottmann] + + * Also added properties for several SoupMessage public + fields, and getter methods for various boxed types + (SoupCookie, SoupDate, SoupURI). + + * Added some additional hash-table annotations. + [#619086, Gustavo Noronha Silva] + + * Marked SoupSession abstract. [#617216, Lorenzo Gil, the + first bug filed by someone trying to use libsoup via + introspection!] Likewise for SoupAuth and SoupAuthDomain. + + * Fixed a problem with SoupSessionAsync that would cause + messages to get lost if you aborted a previous message while + it was still looking up the hostname. Fixed several other + problems that were discovered while adding a regression test + for that. [#618641, thanks to Claudio Saavedra for a good + test case] + + * Fixed another connecting-to-lame-http-server problem, and a + getting-stuck-in-a-loop-reconnecting bug that it revealed. + [#615535] + +Changes in libsoup from 2.30.0 to 2.30.1: + + * Fix for https through proxies that close the connection when + returning a "407 Proxy Authentication Required" response, + and add a regression test for that case. [#611663] + + * Fixed multiple forms/multipart-related interoperability + problems reported by Egon Andersen: + + * Don't quote the multipart boundary string if it's + not needed, since RFC 2616 recommends that you + don't, and some servers don't handle quotes there + correctly. (Sigh.) [#614176] + + * Don't put an extra blank line before the first + multipart part, since it's unnecessary and some + servers don't handle a multipart preamble correctly. + (Sigh.) [#614183] + + * Don't put Content-Transfer-Encoding headers in the + multipart/form-data parts, even though the HTML 4 + spec says you must, since no other browsers do, and + some servers don't handle them correctly. (Sigh.) + [#614198] + + * Changed SoupCookieJarSqlite to actually erase deleted + cookies from the database. [#615711, Lukasz Slachciak] + + * Fixed SoupLogger to be more robust against getting passed + bad data by the session. [#611663] + + * Fixed SoupAuthDomain to ignore paths when doing proxy auth + + * Fixed a g_warning when hovering over a javascript link in + WebKit. [#613442, Xan Lopez] + +Changes in libsoup from 2.29.91 to 2.30.0: + + * Fixed a crash in the whitespace-stripping code in + soup_uri_new() [#612644, "arnaud.lb"] + + * Update content-sniffing algorithm to match Chrome and the + soon-to-be-updated sniffing spec. [#611502, Gustavo Noronha + Silva] + + * We now handle "Content-Encoding: x-gzip" as well as "gzip" + (even though "x-gzip" has been deprecated for more than 10 + years). [#611476] + + * Fixed leaks found by valgrind + + * Make the "make check" programs only bind to 127.0.0.1, not + any public network interfaces. [#609489, Saleem Absulrasool] + + * Add a test to sniffing-test to make sure that Content-Type + parameters are preserved correctly. [Gustavo Noronha Silva] + +Changes in libsoup from 2.29.90 to 2.29.91: + + * Added SOUP_SESSION_SSL_STRICT and + SOUP_MESSAGE_CERTIFICATE_TRUSTED, to allow callers to + determine if an https response comes from a server with a + recognized/valid or unrecognized/invalid certificate. + [#610374, Gustavo Noronha Silva] + + * Fixed handling of certain badly-formatted URIs [#590524] + +Changes in libsoup from 2.29.6 to 2.29.90: + + * Added soup_cookie_jar_set_accept_policy() and related API + for implementing cookie acceptance policies. [#608353, Xan + Lopez] + + * Fixed the "request-read" signal in SoupServer to actually be + emitted. + +Changes in libsoup from 2.29.5 to 2.29.6: + + * Fixed SoupContentDecoder to ignore trailing junk after the + encoded message body (as other browsers do), rather than + getting stuck in an infinite loop. [#606352] + + * Fixed an invalid read in soup_cookie_applies_to_uri() + [#607024, pointed out by Xan] + + * Fixed linking on OS X [#606959] + + * Removed a harmless warning in SoupServer. [#606645] + +Changes in libsoup from 2.29.3 to 2.29.5: + + * Added SoupContentDecoder, providing support for + Content-Encoding: gzip for WebKitGTK. [#522772] + + * Added "accept-language" and "accept-language-auto" + properties to SoupSession, to support the Accept-Language + header. [#597004, Mario Sanchez Prada] + + * Fixed a bug in SoupPasswordManagerGNOME that could cause + crashes if you typed the wrong password once and then tried + again. [#595554, debugged by Gustavo Noronha Silva] + + * Fixed a crash in SoupAuthDigest if the server claims support + for both qop=auth and qop=auth-int. (This was not noticed + sooner because no one actually supports qop=auth-int, and + the server in question here was probably confused. :) + + * Updated cookie parsing/output to more closely match + draft-ietf-httpstate-cookie-00. [Also fixes #603496 (WebKit + unit test), and #604794 (hang parsing malformed Set-Cookie + header)] + + * Fixed https-via-proxy to not hang if there is an error + communicating with the proxy immediately after the TLS + negotiation. [#587528] + + * Fixed a bug that broke gobject-introspection's introspection + of libsoup. [#603696, Vincent Untz] + + * Handle spurious CR/LFs between responses. [#602863, + Alexander V. Butenko] + + * Fixed soup-message-client-io to not erroneously include URI + fragments on the Request-Line when sending via a proxy. + [Related to WebKit bug #28687] + + * Fixed Digest authentication against certain (buggy?) + clients/servers that require you to use quotes in exactly the + same places where the spec uses them. [#582219] + + * Fix ugly gtype-related hack to work with the latest unstable + glib. [Benjamin Otte] + +Changes in libsoup from 2.28.1 to 2.29.3: + + * Fixed a crash in SoupCookieJarSqlite when using cookie + databases not created by libsoup (eg, upgraded epiphany + installations). [Patch from Emilio Pozuelo Monfort] + + * Fixed SoupCookieJar to handle non-http URIs properly (so + that, eg, JavaScript bookmarklets that try to set/read + cookies won't cause crashes). [#602498] + + * HEAD requests that receive a "303 See Other" response will + now do a HEAD, not a GET, on the redirected-to resource. + Fixes gvfs access to some sites, including certain + youtube.com URIs. [#600830] + + * Fixed a g_warning that would always trigger in the + server-side SoupCookie code. [#602389] + + * Fixed the server-side SoupMultipart code to be able to parse + multiparts containing binary attachments, rather than + rejecting them as malformed. [#601640] + + * Fixed the Request-Line format in the https-over-proxy case. + Among other things, this fixes access to bugzilla.gnome.org + from WebKitGTK-based browsers. [#598277, #600826] + + * Fixed a leak in SoupSession if a message was cancelled while + the initial socket connection was in progress. [#596074, + debugged by Arnout Vandecappelle] + + * Fixed server-side parsing of Digest auth. [#602898, Chris + Head] + + * Fixed WinSock initialization on Windows. [#600689, Tor + Lillqvist] + + * Fixed a sporadic crash in the SSL code on Windows. [#600748, + Tor Lillqvist] + + * Fixed handling of https connections with timeouts on + Windows. [#600749, Tor Lillqvist] + + * Added soup_session_prepare_for_uri(), to allow DNS + prefetching for faster browsing. [#598948, José Millán Soto] + + * SoupSession now avoids redundant DNS lookups again when + first connecting to a new site, resulting in (probably + imperceptibly) faster loads. + + * Added some debugging APIs to SoupConnection and SoupSession + for use by, eg, epiphany's soup-fly extension. [#589163, + José Millán Soto] + +Changes in libsoup from 2.28.0 to 2.28.1: + + * libsoup will now attempt to make multiple connections to a + server at once when there are multiple messages queued to + that server. The previous behavior (only allowing a single + pending connection to each server) resulted in slow load + times on pages with lots of subresources (images, css, js, + etc) on servers that disallow persistent connections. + [#594768] + + * There should now be fewer (no?) "Connection terminated + unexpectedly" errors in WebKitGTK. + + * Fixed a crash in SoupCookieJarSqlite [#596859, patch from + Alexander Sack]. + + * Fixed soup_address_get_physical() and address-to-name + resolution of SoupAddress [patch from Enrico Tröger]. + + * Fixed a bug in SoupContentSniffer that could cause false + negatives [#597545, patch from Alejandro Castro]. + + * Fixed the configure error if you have gnutls-devel but not + gcrypt-devel installed [#587709]. + +Changes in libsoup from 2.27.92 to 2.28.0: + + * Fixed a handful of leaks found with valgrind, including a + large one in SoupContentSniffer [WebKit bug 28148]. + + * Changed the behavior of SoupCookieJarSqlite to improve + performance. [#584522, patch from Gustavo Noronha Silva] + + * Fixed a crash in SoupSocket that affected gupnp. [#594951, + patch from Olivier Crête] + + * Fixed the type of the SOUP_METHOD_* and SOUP_URI_SCHEME_* + macros to be const char * rather than gpointer. [#594508] + +Changes in libsoup from 2.27.91 to 2.27.92: + + * Removed SoupPasswordManager from the public API until its + problems can be addressed. Although it is still present, you + need to #define a special symbol for it to be visible in the + header files; see #594377 for details. + + * Fixed a bug where empty query components were dropped from + URIs. [#594405] + + * Fixed "make check" to work (but warn) when building with + --disable-ssl. + + * Fixed some small documentation bugs pointed out by Dominik + Bylica and Lucian Langa. + +Changes in libsoup from 2.27.90 to 2.27.91: + + * Added SoupPasswordManager, an interface for managing + persistent password storage, and SoupPasswordManagerGNOME + (in libsoup-gnome), which implements it using gnome-keyring. + tests/get.c provides a minimal example of how to use it. + + * libsoup should now notice when the server closes a + persistent connection, and close its side of the connection + sooner. This should hopefully fix the spurious "Connection + terminated unexpectedly" errors in WebKitGTK. [#578990] + + * Fixed some problems with connection management in + SoupSession that could cause a session to eventually "stall" + and be unable to process new requests. [#592084] + + * Fixed an infinite loop that caused 100% CPU usage if the + network went down at exactly the right time while there were + unsent messages in the queue. [#592492] + + * Fixed a crash in SoupLogger. [#591857] + + * Fixed the definition of soup_message_is_keepalive() for + HTTP/1.0 messages, to fix a problem introduced in 2.27.90 + where some messages would load completely but never emit + "finished". + + * Fixed a crash in SoupServer introduced in 2.27.90 when + processing a request with no "Host" header. + +Changes in libsoup from 2.27.5 to 2.27.90: + + * libsoup now uses glib's GResolver rather than its own DNS + code. For 2.27.90, the only visible change should be that + internationalized domain names are now supported. [#548287] + + * Added soup_message_disable_feature(), which allows you to + disable particular features (eg, cookies, proxy, + content-sniffing, etc) on a per-message basis. [#574773] + + * It is now possible to implement "OPTIONS *" in a SoupServer; + you must explicitly register a handler for "*" in order to + do this. [#590751] + + * Ignore Content-Length on EOF-terminated responses, to match + other browsers and therefore cope with broken servers that + send the wrong length. [Patch from Benjamin Otte.] + + * Fixed the status code when trying to fetch an https URI with + a non-gnutls build of libsoup. [#590464] + + * Fixed strict-aliasing warnings introduced in 2.27.4 + [#588771] + + * Fixed some warnings noted by fortify [#591226] and -Wextra. + + * libsoup now uses automake 1.11's silent-rules support by + default (if you are building with automake 1.11). Use + "./configure --disable-silent-rules" or "make V=1" to + disable. + +Changes in libsoup from 2.27.4 to 2.27.5: + + * Fixed a crash when a web server redirected a request to a + non-http URI (eg, "about:blank"). [#528882] + + * Fixed a hang when trying to create an attachment on certain + bugzilla installations from epiphany. [#584645] + + * Fixed verification of V1 TLS certificates [#589323, Patrick + Ohly] + + * Fixed compile problems on Windows (in the ssl code), and on + Linux (when the most recent version of gtk-doc was + installed). + +Changes in libsoup from 2.27.2 to 2.27.4: + + * Added SoupContentSniffer and the "content-sniffed" signal on + SoupMessage, to do Content-Type sniffing per the HTML5 / + draft-abarth-mime-sniff algorithm. [#572589, Gustavo Noronha + Silva] + + * Updated the earlier SoupSession timeout fixes ([#574414], + [#578928]) so that async connect() also times out [#588177, + Mark Nauwelaerts] and SSL works on Windows again [#587910, + Fridrich Strba]. + + * Fixed the behavior on a 301 response to a POST to match + real-world usage rather than what the spec says. (We were + doing the right thing on 302 and 303, but had missed 301.) + [#586692] + + * Changed configure so that if GNUTLS isn't found then it + errors out, rather than silently building an SSL-less + libsoup. Configure with --disable-ssl if you actually don't + want SSL. [#584955] + +Changes in libsoup from 2.27.1 to 2.27.2: + + * Replaced SoupProxyResolver with SoupProxyURIResolver, which + is a bit simpler, works with non-HTTP URIs (and so could be + used by gvfsd-ftp) and supports proxy auth correctly. + [#580051] + + * Fixed SoupSession to not try to resolve http server + hostnames when it's just going to pass the hostname off to a + proxy server anyway. This fixes things on hosts that use a + proxy for everything and have no working DNS config + [#577532] and also makes WebKitGTK behave more like other + browsers in terms of per-host connection limits (we now + limit connections based on hostname rather than on IP + address). + + We also no longer set the AI_CANONNAME flag when calling + getaddrinfo(), which saves us a little bit of unnecessary + network traffic. [Pointed out by Christophe Gillette on the + mailing list.] + + * libsoup now always uses SSL 3.0 (not TLS 1.0 or 1.1) for + https URIs, to work around problems with older servers that + don't implement the (apparently quite confusing) TLS/SSL + compatibility rules correctly. Makes a bunch of + previously-inaccessible sites now accessible in WebKitGTK + (notably PayPal) [#581342]. Will eventually be revisited, to + first try TLS 1.1 and fall back if that fails. + + * Fixed Digest auth to (recent) Apple CalDAV servers. + [#583091] + + * Changed the way the SoupSession "authenticate" signal works + a bit. We now never emit "authenticate" before sending a + request, even if we know for sure that it's going to fail, + because this makes the semantics of the authenticate handler + too complicated (and because we'll only get into this + situation if a previous call to the authenticate handler + failed anyway). Fixes problems in WebKitGTK when you cancel + a password dialog, and then later try to load the page + again. [#583462, mostly figured out by Gustavo Noronha + Silva]. + + * Fixed a bug in the CRLF-vs-LF patch (#571283) that caused + libsoup to fail to parse the response headers (returning + SOUP_STATUS_MALFORMED) if a CR LF got split across two + read()s. [#582002] + + * Allow using PUT in soup_form_request_for_data(), to work + with certain broken web APIs. [#581860, Ross Burton]. Also, + fixed a problem with empty POST bodies that made some parts + of gmail not work in WebKitGTK. + + * Applied some minor bugfixes to configure.in and autogen.sh + [#583911, #583942]. Fixed configure.in to not use gcc + warning options that the installed version of gcc doesn't + recognize [#578851]. + + * Added G_GNUC_NULL_TERMINATED and G_GNUC_PRINTF to a few + methods that should have had them. [#581754, Ross Burton] + +Changes in libsoup from 2.26.1 to 2.27.1: + + * SOUP_SESSION_TIMEOUT now works properly with + SoupSessionAsync [#574414] and SSL [#578928]. Added + tests/timeout-test to test this. + + * SoupDate fixes: + + * soup_date_to_string() now handles SOUP_DATE_RFC2822 + [#579055, Enrico Tröger] + + * soup_date_new_from_string() now accepts 24:00 as a + time in ISO8601 timestamps + + * soup_date_to_string() now coerces the date to UTC + for HTTP and cookie dates, and outputs the UTC + correct offset for the other date types. + + * Added regression tests to tests/date + + * soup_headers_parse() now completely ignores + syntactically-incorrect headers, rather than passing them to + soup_message_headers_append() and causing a g_warning. + soup_message_headers_append() now also rejects 0-length + header names. Updated tests/header-parsing to check this. + [#579318] + + * Fix a crash when cancelling a message from a "restarted" + handler, and updated a regression test to notice the + underlying cause. [#580193] + + * Completing the API updates for #576760 from 2.26.1, + soup_message_headers_get() is now marked deprecated in favor + of soup_message_headers_get_one() and _get_list(). + +Changes in libsoup from 2.26.0 to 2.26.1: + + * libsoup uses libproxy for PAC and WPAD proxy resolution + again. However, it arranges to do all communication with + GConf itself, to ensure that libproxy doesn't call it in + non-thread-safe ways. [#571527] Also, fixed a bug in + SoupSessionSync when proxy resolution failed. [#574957, + patch from Milan Crha]. + + (Also fixed three SoupProxyResolverGNOME bugs since the + 2.26.0.9 preview release. [#578746, #578809]) + + * SoupURI now handles unencoded spaces in URIs. In particular, + redirects via Location headers with spaces in them now work. + [#566530] + + * libsoup can now deal with servers (and clients) that + erroneously use LF LF instead of CR LF CR LF to separate + the headers and body. [#571283] + + * Added soup_message_headers_get_one() and + soup_message_headers_get_list(), which will eventually + deprecate soup_message_headers_get(). This lets applications + deal correctly with implementations that erroneously send + multiple copies of single-valued headers. [#576760] + + * In particular, soup_message_headers_get_content_type() now + ignores duplicate Content-Type headers [#576760] and also + ignores syntactically-incorrect Content-Type headers. + [#577630] + + * SoupCookieJar can now store multiple cookies with the same + domain and name, but different paths. [#577360] + + * Abnormal SSL connection closes are now treated as ordinary + EOFs, for compatibility with certain sites. [#577386] + + * soup_header_g_string_append_param() now allows NULL values. + [#577728] + + * soup_message_headers_append() now rejects header names and + values with newlines or certain other illegal data in them, + rather than generating syntactically invalid headers. + + * Fixed a small bug in soup_date_new_from_string's ISO 8601 + handling [qv #578369 for g_time_val_from_iso8601]. + + * The regression tests now work correctly on machines where + "localhost" resolves to "::1" instead of "127.0.0.1". + [#576583, patch from Andreas Rottmann] + + * Fixed warnings when a message has a network problem when + many other messages are queued. [#578809] + + * Miscellaneous documentation fixes/clarifications. + +Changes in libsoup from 2.25.91 to 2.26.0: + + * Temporarily disable libproxy support to work around a bug in + its gnome plugin that causes gvfsd-http (and probably + eventually other apps) to crash. [#571527]. For now, + SoupProxyResolverGNOME uses only GConf. To be fixed in + 2.26.1 + + * Fixed a bug that showed up in WebKit, where if many messages + were queued all at once to a server that doesn't support + persistent connections, some of the requests will get lost. + #574365, reported by Xan Lopez. + + * Fixed SoupServer to support using SOUP_ENCODING_EOF, so you + can stream responses of unknown length to HTTP/1.0 clients. + [#572153]. Added a regression test for this, and for chunked + and Content-Length-based streaming. + + * Fixed several bugs that prevented SoupCookieJarSqlite from + working. [#572409, patch from Xan Lopez] + + * Added G_{BEGIN,END}_DECLS guards to public headers that were + missing it. (Xan Lopez) + + * Misc gtk-doc improvements + +Changes in libsoup from 2.25.5 to 2.25.91: + + * Fixed a crash in SoupProxyResolverGNOME when the proxy + requires authentication. (This does not make proxy + authentication *work* yet, it just makes it not crash.) + + * Updated documentation + +Changes in libsoup from 2.25.4 to 2.25.5: + + * SoupProxyResolverGConf (which was incomplete) is gone, and + libsoup-gnome now requires libproxy, which is now officially + an external dependency of GNOME. + + * Fixed a bug in SoupCookieJar that was making it send + "Cookie: (null)" when it had no cookies for a site, which + confused some web servers (WebKit bug 23240). + + * Fixed a bug with using SOUP_MEMORY_TEMPORARY buffers and + soup_message_body_set_accumulate(FALSE). (Part of WebKit bug + 18343, noticed by Gustavo Noronha Silva.) + + * Fixed the build with non-gcc compilers + +Changes in libsoup from 2.25.3 to 2.25.4: + + * Added soup_session_get_feature() and + soup_session_get_features(), to query the features currently + available in a session (which is needed by the patch in + https://bugs.webkit.org/show_bug.cgi?id=22624) + +Changes in libsoup from 2.25.2 to 2.25.3: + + * Fixed a crash when using both cookies and a proxy. [#562191, + Mark Lee] + + * Fixed soup_form_decode() to correctly handle forms with + URI-encoded parameter names [#563302, Evan Nemerson] and + added a regression test. + + * Fixed a crash in SoupProxyResolverGConf. [#563145] + +Changes in libsoup from 2.25.1 to 2.25.2: + + * Fixed client behavior when presented with multiple auth + types to choose the *strongest* auth type (eg, Digest) + rather than the *weakest* one [#562339, Pontus Oldberg]. + Added a regression test for this. + + * Moved libsoup-gnome headers to a different directory to make + it easier to split libsoup and libsoup-gnome into separate + packages, and to ensure that things that only want to be + looking at plain libsoup headers (like gir-repository) don't + accidentally see the libsoup-gnome ones. + + * Some minor doc fixes + + * Fixed libsoup-gnome linking with --as-needed. [#559342] + +Changes in libsoup from 2.24.1 to 2.25.1: + + libsoup 2.25.1 introduces a new library, libsoup-gnome, which + will be used for features which are important to GNOME apps, + but which require GNOME-specific libraries that non-GNOME apps + may not want to add dependencies on. + + In 2.25.1, libsoup-gnome contains: + + * SOUP_TYPE_PROXY_RESOLVER_GNOME, a SoupSessionFeature + type that can be added to a SoupSession to provide + automatic proxy handling via the GConf proxy keys. (See + below) The default implementation uses libproxy, which + also handles WPAD, PAC, etc, but if libproxy is not + available it will use GConf directly, supporting only + the basic HTTP proxy functionality. + + * SoupCookieJarSqlite, a SoupSessionFeature that handles + cookies and stores them in a Firefox 3-compatible sqlite + file. (This is not actually a "GNOME-specific" feature, + but I didn't want to make libsoup itself depend on + sqlite, and I didn't want to make the dependency + optional. This might change before 2.26.) + + * SOUP_TYPE_GNOME_FEATURES_2_26: a SoupSessionFeature type + that can be added to a SoupSession to add all + GNOME-integration features that are available for 2.26; + as of 2.25.1, this is just the GNOME proxy resolver, but + by 2.26.0 it may also include gnome-keyring support and + possibly other features. + + Applications/libraries that are currently doing GConf proxy + lookup by hand can be updated as follows: + + * Remove all of the existing code that listens to the + GConf keys and sets SOUP_SESSION_PROXY_URI + + * Change the configure check to require + "libsoup-gnome-2.4 >= 2.25.1" instead of "libsoup-2.4" + + * #include + + * After creating your SoupSession, do: + + soup_session_add_feature_by_type (session, SOUP_TYPE_PROXY_RESOLVER_GNOME); + + (Or alternatively, use SOUP_SESSION_ADD_FEATURE_BY_TYPE + with soup_session_async_new_with_options() or + soup_session_sync_new_with_options().) + + + Other new features and bug fixes in 2.25.1 include: + + * SoupCookieJarText, like SoupCookieJarSqlite, but using the + old-style cookies.txt format, and in the base libsoup rather + than libsoup-gnome. + + * Various bugfixes to SoupCookie and SoupCookieJar to fix the + problems with cookies not working on certain sites. + + * The new SoupMultipart type provides support for multipart + MIME bodies, and soup-form now includes several methods for + generating and parsing multipart form data and file uploads. + + * SoupMessageHeaders now has methods for easy handling of the + Content-Type, Content-Disposition, Range, and Content-Range + headers. The Content-Disposition handling recognizes + RFC2231-encoded UTF-8 filenames. + + * SoupServer now automatically handles partial GET requests; + if your server returns SOUP_STATUS_OK in response to a + partial GET, libsoup will automatically convert it to a + SOUP_STATUS_PARTIAL_CONTENT response with only the requested + portions. + + Thanks to Xan Lopez and Diego Escalante Urrelo for their work + on SoupCookie, SoupCookieJar, SoupCookieJarText, and + SoupCookieJarSqlite. + +Changes in libsoup from 2.24.0.1 to 2.24.1: + + * Fixed a crash when unreffing the session from a + soup_session_queue_message() callback [#533473], and added + regression test. In particular, this fixes a crash in + seahorse when trying to connect to a non-responsive + keyserver. + + * Fixed an infinite loop when giving a bad password to a site + that uses non-standard capitalization in the + WWW-Authenticate header (eg, gmail.com) [#536285]. + + * Fixed a leak in SoupSessionAsync when using a non-default + GMainContext. [addendum to #498509, Arnout Vandecappelle] + Added additional code to the regression tests to make sure + sessions and servers do not get leaked. + + * Fixed a leak in the XML-RPC code + + * Compile fixes for "gcc -pedantic" [#553976, Sander Dijkhuis] + and -DG_DISABLE_DEPRECATED / -DG_DISABLE_SINGLE_INCLUDES + [#557072, Cosimo Cecchi] + + * Patched xmlrpc-test to accept the incorrect response to + test_echo() that php-xmlrpc gives when it's built against + libxml2 >= 2.7.1 (qv http://bugs.php.net/45996), so that + I can "make distcheck"... + + * Updated generated documentation + +Changes in libsoup from 2.23.92 to 2.24.0.1: + + * Reverted part of the fix for #528882, which caused the DAAP + plugin in rhythmbox to crash. [#553466] + +Changes in libsoup from 2.23.91 to 2.23.92: + + * Fixed the handling of a 302 response to a HEAD request, + which should NOT be treated like a 303 response. [#551190, + Jonathan Matthew] + +Changes in libsoup from 2.23.6 to 2.23.91: + + * Fixed a crash in gvfs [#528882], though there is still an + unknown bug there. As part of this fix, libsoup will now + return an error if you try to do an operation on a non-HTTP + URI. (Previously it was just treating any URI scheme except + "https" as HTTP.) + + * Added soup_date_to_timeval() for gvfs. [#549006, patch from + Bastien Nocera] + +Changes in libsoup from 2.23.1 to 2.23.6: + + * Fixed use of g_idle_add() so that heavy I/O won't end up + blocking libsoup callbacks. [#536676, Benjamin Otte] + + * Allow the caller to override the Host header. [#539803, Marc + Maurer] + + * Properly handle responses larger than 4G. [#539861, Peter + Christensen] + + * Fixed the build when using certain LDFLAGS [#541506, Götz + Waschk] + + * Fixed a small bug in Digest auth handling. [#544681, Mads + Chr. Olesen] + + * Fixed multiple Windows bugs [Tor Lillqvist] + +Changes in libsoup from 2.4.1 to 2.23.1: + + * This is the first unstable release leading up to GNOME 2.24. + Bumped the libsoup version number up to 2.23.x to match the + GNOME version; note that the API version is still "2.4", + meaning in particular that you still call it "libsoup-2.4" + when using pkg-config. + + * Added SoupSessionFeature, an interface type that will be + used for several new features. Ported SoupLogger and + SoupAuthManager to use it. + + * Added SoupCookie and SoupCookieJar. This API is already + being used in Epiphany, via WebKit, but it is not yet + complete. + + * Fixed GnuTLS support on Win32. [#528752, Marc Maurer] + +Changes in libsoup from 2.4.0 to 2.4.1: + + * Fixed SoupMessage to not downgrade to HTTP/1.0 for the + second attempt when it receives an HTTP/1.0 redirect or 401. + [#521848, Tommu Komulainen] + + * Fixed Host: header syntax when the host is an IPv6 address + literal. + + * Fixed SoupSession to not emit "authenticate" multiple times + for messages that have been requeued. [#522601, Tommi + Komulainen]. Also added two new signals to SoupSession, + request-queued and request-unqueued, to help simplify + certain session-helpers and avoid bugs like this in the + future. + + * Fixed soup_server_pause_message() to actually work (rather + than *un*pausing the message). + + * Added a property SOUP_SESSION_IDLE_TIMEOUT that can be used + to set a timeout after which idle connections will + automatically be closed. [#518214, Jorn Baayen] + + * Implemented RFC 2069-style Digest auth, and fixed SoupAuth + to compare auth scheme names case-insensitively, to fix + authentication against Apple's calendar server. [#498484] + + * Fixed a crash in SoupAuthDomainDigest if the client provided + an unrecognized username. [pointed out by Curtis Magyar on + IRC] + + * Fixed a few SoupDate bugs. (In particular, it was outputting + the wrong day of the week when stringifying dates.) + + * Improved the cleanup of idle connections, to fix slow load + times with the libsoup backend of WebKit. + + * Added a new SoupMessage signal "wrote-body-data" that can be + used for progress information when sending a large request + body. Also allow providing the request body in multiple + chunks even when using Content-Length encoding. [#525101, + Christian Kellner] + + * libsoup now ignores SIGPIPE globally, instead of + un-thread-safe-ly ignoring it only around network writes. In + particular, this means it is ignored when the SSL code needs + to unexpectedly do a write when we asked it to do a read. + [#524397, Curtis Magyar] + + * The discard-body-chunks-once-they're-no-longer-needed + behavior, confusingly called SOUP_MESSAGE_OVERWRITE_CHUNKS, + is now controlled by a SoupMessageBody method + (soup_message_body_set_accumulate()), and can be applied to + either the request body or the response body. + (OVERWRITE_CHUNKS is still available for backward + compatibility.) [#522146, Christian Kellner] + + * The DNS cache no longer caches "no such host" results, since + some name servers lie to clients outside their firewall, + which could then cause problems for laptops moved between + networks. [#523269, Jörgen Scheibengruber] + + * Added some new regression tests, fixed some small bugs in + the existing ones. + +Changes in libsoup from 2.3.4 to 2.4.0: + + * Fixed a small memory leak in SoupSession. [#518798, Wouter + Cloetens] + + * Minor fixes to redirect behavior; PROPFINDs can now be + automatically redirected (pointed out by Christian Kellner), + and 302 is treated like 307, not 303. Also fixed to make + sure that redirect-test actually gets run by "make check". + + * The SoupSocket I/O methods now set nread/nwrote even on + error. [Benjamin Otte] + +Changes in libsoup from 2.3.2 to 2.3.4: + + * The documentation should be accessible from devhelp again + [#518384, Mart Raudsepp]. (Also fixed another + documentation-generation bug that affected builds from svn, + but not the 2.3.2 tarball for some reason. [#518317, + Benjamin Otte].) + + * Fixed dependencies in libsoup-2.4.pc file [#517631, + Sebastian Dröge] + +Changes in libsoup from 2.3.0.1 to 2.3.2: + + API changes / Behavior changes: + + * soup_server_add_auth_domain() now refs the auth domain when + adding it. (soup_server_remove_auth_domain() already + unreffed it.) This means existing applications using + SoupAuthDomain will now have a small memory leak. Those + applications should update their libsoup-2.4 requirement to + ">= 2.3.2" at some point before the final GNOME 2.22.0 + release, and then fix the code to unref the auth domain + after adding it to the server. + + * SoupSession's automatic redirect-handling behavior now obeys + RFC 2616 more closely. In particular, status codes 300 and + 304 are no longer mistakenly considered redirects; POSTs + that receive 303 are now redirected into GETs; and POSTs + that receive 301, 302, or 307 are now not redirected. + + Applications that were using the SOUP_MESSAGE_NO_REDIRECT + flag to prevent libsoup from redirecting POSTs incorrectly + before should now be able to remove that if they depend on + libsoup-2.4 >= 2.3.2. + + API additions: + + * Added a SOUP_SESSION_USER_AGENT property to SoupSession, and + SOUP_SERVER_SERVER_HEADER to SoupServer, to support + automatically adding "User-Agent" and "Server" headers to + messages. (The default behavior is to do nothing, as + before.) + + * Added several new methods to soup-forms.h. Applications that + are encoding a fixed set of form fields can now just pass + them to soup_form_encode(), rather than needing to construct + a GHashTable or GData list. (Likewise, the new + soup_uri_set_query_from_fields() behaves similarly for + directly updating a URI with form data.) There are also now + soup_form_request_new() and other related methods, to + directly create a GET or POST SoupMessage for submitting a + form query. + + The original soup_form_* methods have all been renamed, + although #defines exist for backward compatibility. + + * Added soup_message_set_chunk_allocator() and + soup_buffer_new_with_owner(), to give applications more + control over memory usage/copying when doing streaming HTTP. + [Wouter Cloetens, #513810]. + + * Added several new methods to soup-value-utils.h for working + with multiple array or hash table values at once: + soup_value_hash_new_with_vals(), + soup_value_hash_insert_vals(), + soup_value_hash_lookup_vals(), + soup_value_array_new_with_vals(), and + soup_value_array_append_vals(). + + This helps to simplify XML-RPC calls that send or receive + structs or arrays. + + * Added soup_date_to_time_t(). + + * Added SoupMessageHeadersIterator, an iterator type for + SoupMessageHeaders that can be used instead of + soup_message_headers_foreach(). + + Bug fixes: + + * Fixed a crash-when-idle in evolution-exchange [#437835] and + rhythmbox [#506552]. + + * Added the API version to the gtk-doc installation dir, to + prevent parallel-installation problems with libsoup 2.2 and + 2.4. [#512810, Daniel Gryniewicz]. + + * Fixed tests/query-test to compile correctly on Solaris. + [#513602, patch from Jeff Cai] + + * Fixed some other minor HTTP conformance issues. + + Python bindings: + + * Although not present in the release tarball, there are now + experimental python bindings for libsoup in GNOME subversion + (in the python/ subdirectory of libsoup trunk). These are + not yet stable (and are not built by default or installed + even when building from svn), but comments on them are + welcome at libsoup-list@gnome.org + +Changes in libsoup from the 2.2 series to 2.3.0.1: + + libsoup 2.3.0 is the first beta release of the libsoup 2.4 + series. It is an API break from the earlier 2.2 series that + fixes various bugs and API warts and lays the groundwork for + language bindings and various new features in upcoming + releases. + + (2.3.0.1 is identical to the 2.3.0 release in terms of code, + but includes this updated NEWS file which was accidentally + left out of the 2.3.0 tarball.) + + http://library.gnome.org/devel/libsoup/unstable/libsoup-porting-2.2-2.4.html + goes over the API changes in detail. If you have questions not + answered by the porting document, please send mail to + libsoup-list@gnome.org. + + Specific user-reported bugs fixed in this release: + + * SoupURI now correctly handles URIs with complex encoded + queries [#266516, Jean-Yves Lefort] + + * It is now possible for a SoupServer to use Digest auth + without needing to have the cleartext password available. + [#347108, Anas Nashif] + + * Digest authentication now properly handles "stale=true" and + "nextnonce=..." [#471380, Jari Urpalainen] + + * SoupServer is now subclassible [#491653, Mathias Hasselmann] + + * soup_server_run_async and soup_server_quit no longer ref and + unref the server, as that doesn't match ordinary GObject + conventions [#494128, Mathias Hasselmann] + + * The test programs no longer use a symbol name that conflicts + with Cygwin [#501631, Cygwin Ports Maintainer] + + * libsoup can now handle the not-quite-HTTP responses returned + by Shoutcast servers [#502325, Wouter Cloetens] + + * If you use libsoup while disconnected from the network, it + no longer caches the failed DNS results [#508593, Bradley + Worley] + + Items from http://live.gnome.org/LibSoup/ToDo fixed: + + * "Expect: 100-continue" processing now works correctly on + both client and server. + + * SoupSessions are no longer leaked + + * The XML-RPC API is improved. The SOAP API is gone... + + * Added utility functions for HTML form handling + + * Improved message header handling + + * SoupServer now automatically adds a "Date" header + +========== + +Changes in libsoup from 2.2.103 to 2.2.104: + + * soup_message_io_pause() and soup_message_io_pause() are now + allowed for client messages (and in particular, they don't + mess up when called from the "got_chunk" callback). + [#452280, Marco Barisione] + + * Fixed some bugs in SOUP_SESSION_ASYNC_CONTEXT support that + would cause parts of an operation to run in the default + context rather than the session's context. Also fixed some + leaks and added a regression test. [#498509, Wouter + Cloetens] + + * There is a new test/sample program, tests/pull-api.c, + showing how to implement a pull API using SoupSessionAsync. + (This depends on the fixes for #452280 and #498509, so it + won't work with older versions of libsoup.) + + * Discovered "valgrind --leak-resolution=med" and fixed some + more memory leaks. + +Changes in libsoup from 2.2.102 to 2.2.103: + + * Fix memory corruption in SoupSessionAsync that caused + rhythmbox to crash. [#484988, patch from Rob Bradford] + + * Fix socket refcounting in SoupServer to fix warnings / + possible crash. [#459896, Emanuele Aina] + +Changes in libsoup from 2.2.101 to 2.2.102: + + * Unbreak the build when building without SSL. Not that you + should be building without SSL anyway, but... (reported by + guenther). + +Changes in libsoup from 2.2.100 to 2.2.101: + + * Fix build on cygwin [384498] + + * Fix SSL rehandshaking on synchronous sockets [415402, Jacob + Berkman] and add a regression test for it. + + * Fix two bugs in https tunnels over proxies that require + authentication (noticed by Varadhan), and add a regression + test for them. + + * Ensure that if you queue multiple messages at once to an + http server that requires authentication but that you + haven't authenticated to yet, that all of the messages get + properly authenticated [271540, James Willcox]. And add a + regression test for it. + + * Fix NTLM authentication, which got broken by the previous + fix. [471389, Varadhan]. Add a basic NTLM regression test + that doesn't really test the crypto/encoding parts, but at + least makes sure that the message flow is correct. + + * Allow trailing whitespace after HTTP version in + Response-Line, for compatibility with broken servers + [475169, Stephane Loeuillet]. Add that case to the + header-parsing regression test. + + * Fix crash when the session's "authenticate" handler returns + a username and no password when using NTLM. [480987, Wendell + MacKenzie] + + * Use "new" glib base64 and iso8601 methods rather than + duplicating them. [337010, patch from Emmanuele Bassi]. + + * Implement soup_session_queue_message() for SoupSessionSync. + + * Add G_BEGIN_DECLS / G_END_DECLS to all headers that were + missing them. [438776, patch from Jonathon Jongsma]. + + * Fix broken definition of SOUP_IS_MESSAGE_FILTER_CLASS. Noted + by "cascardo" on libsoup-list. + + * Remove documentation of non-public MD5 methods [440092, + Jonathon Jongsma]. Removed a mysterious half-sentence in the + SoupMessage docs [458116, Marco Barisione]. + +Changes in libsoup from 2.2.99 to 2.2.100: + + * Fixed soup_headers_parse_status_line() so WebDAV response + parsing will work again. [406997] + + * Fixed a bug in the header-parsing regression test that + caused the test to fail sometimes, even though the actual + header-parsing code was fine. + +Changes in libsoup from 2.2.98 to 2.2.99: + + * Fixed header parsing, including a crash in SoupServer with + certain malformed requests [391970]. + + * Fixed redirection to other hosts with SoupSessionAsync. + [382251] + + * Fixed a small memory leak pointed out by Chris Austin. + +Changes in libsoup from 2.2.97 to 2.2.98: + + * The XML-RPC code now correctly interprets foo + as meaning the same thing as + foo. [364490] Pointed out by + Todd Kulesza. + + * Memory leak fixes from Andrew W. Nosenko. + + * A few symbols that should have been static before now are. + [376387] Patch from Matthias Clasen. + +Changes in libsoup from 2.2.96 to 2.2.97: + + * Fixed SOAP and XML-RPC code to handle whitespace and + comments in the XML better. (Based on a patch from Andrew W. + Nosenko.) + + * Fixed lots of typecasting/constness warnings in the code + (mostly via a patch from Andrew W. Nosenko) + + * Fixed build on Cygwin [321827] + + * Fixed libsoup-2.2.pc fields [343340] and make it get + uninstalled correctly [356809]. (Mikhail Zabaluev and + Matthew Barnes) + + * Fixed some small leaks in SoupServer pointed out by Paolo + Borelli. [351500] + +Changes in libsoup from 2.2.95.1 to 2.2.96: + + * SoupServer now works even if you don't explicitly set an + encoding for the response. (In particular, the automatic 404 + if you request a path with no handlers now works. Problem + pointed out by Dennis Jacobfeuerborn.) + + * WWW-Authenticate and Proxy-Authenticate responses with no + realm parameter are now ignored, as per RFC 2617, fixing a + crash pointed out by Nate Nielsen. + + * Added soup_xmlrpc_message_from_string(), from Fernando + Herrera [348532]. + + * simple-httpd and "get" now support HEAD + +Changes in libsoup from 2.2.94 to 2.2.95.1: + + * Even more fixes to XML-RPC, found by the new XML-RPC + regression test. This includes some API changes that I don't + feel guilty about, because the code totally didn't work at + all before. + + * Fixed a bug in soup_mktime_utc() + + * (2.2.95 was identical to 2.2.95.1. The only difference is + that the shared library version was belatedly bumped from + 8.2.0 to 8.3.0 to reflect the API "additions") + +Changes in libsoup from 2.2.93 to 2.2.94: + + * Various fixes to the XML-RPC code (which apparently had not + actually ever worked before) from Brent Smith. [343973, + 344222, 344458] + + * Added client and server API tutorials to the docs + + * auth-test now uses a local Apache 2.2 install, if possible, + rather than depending on files that used to be on an old + Ximian web server but haven't been anywhere for a long time. + [311825] + +Changes in libsoup from 2.2.92 to 2.2.93: + + * Fixed outgoing data corruption caused when SoupServer + started writing out a response a second time after already + having started once. [334469]. Also fixed 342640 and another + bug caused by the workaround for 334469 in 2.2.92. Based on + patches and analysis from William Jon McCann and Armin + Bauer. + + * Fixed a deadlock when changing a session's proxy URI. + [309867 / bnc 174255, based on a patch by Veerapuram + Varadhan]. + + * Fixed https-via-proxies in the synchronous case. [bnc 174255] + + * Fixed a crash in evolution-exchange [342545, fix based on an + analysis by Wang Xin]. + + * Fixed simple-proxy to not crash at startup. Oops. (Alex + Larsson) + +Changes in libsoup from 2.2.91 to 2.2.92: + + * Fixed server-side digest auth to return a valid "algorithm" + value and client-side to not crash if it sees an invalid one + [328615]. + + * Fixed the Request-Line parsing code to not hardcode a + maximum URI length (to allow very long DAAP requests from + iTunes in Rhythmbox). [335040] + + * Fixed some warnings (signed/unsigned mismatch). + +Changes in libsoup from 2.2.7 to 2.2.91: + + * (The large version number bump is because there was an + internal 2.2.90 release for SUSE 10.1 alphas, which was + supposed to be intermediate between 2.2.7 and 2.4.0. But + 2.4.0 didn't end up happening, and I don't want to regress + the version number at this point.) + + * SoupSession, SoupServer, SoupConnection, SoupSocket, and + SoupAddress now have an "async-context" property that allows + you to use the async API in a non-default GMainContext. + [Based on patches from Armin Bauer and Jürg Billeter.] + + * SoupSession, SoupConnection, and SoupSocket now have a + "timeout" property to stop synchronous sockets from hanging + forever if the remote end is unresponsive (from Varadhan). + + * Fixed some bugs in soup_date_iso8601_parse(). [324671, from + Emmanuele Bassi] + + * More Windows build fixes from Tor. + +Changes in libsoup from 2.2.6.1 to 2.2.7: + + * Fixed a crash when using NTLM connections [316313, probably + also 318252]. (Also 321208, which was a bug introduced in + the original fix for 316313.) + + * Fixed a bug that could cause soup to suck up all available + CPU when a connection to a SoupServer was dropped by the + other side [319305, patch from Jonathan Matthew] + + * Fixed the creation of struct elements in XMLRPC messages + [321362, patch from Sebastian Bauer] + + * Plugged a small memory leak in SoupSocket (from Wang Xin). + + * Fixed two compile problems, a gccism [320349, patch from + Roland Illig], and a strict-aliasing warning from gcc 4.1. + +Changes in libsoup from 2.2.6 to 2.2.6.1: + + * Fixed a crash when using SoupSoapMessage + +Changes from 2.2.5 to 2.2.6: + + * Fixed a crash when canceling a message (from Tambet Ingo) + + * Fixed a bug where a connection could be leaked forever in + some circumstances if a request got a 30x, 401, or 407 + response, eventually causing a hang when the session hit its + maximum connection limit. (Dan/Tambet) + + * Fixed a memory leak. (Tambet) + + * Fixed a bug that would sometimes show up when connecting to + a server on localhost [#312540] + + * Added some API to SoupServer and SoupSocket to help fix a + long-standing rcd bug. + +Changes from 2.2.4 to 2.2.5: + + * Win32 support (from Tor Lillqvist) + + * Up-to-date API documentation pretty much everywhere + + * Basic XMLRPC support (from Mariano Suarez-Alvarez, Fernando + Herrera, and Jeff Bailey) + + * New HTTP timestamp-manipulation methods soup_date_parse, + soup_date_generate, and soup_date_iso8601_parse. + + * SoupSession now handles relative URLs in the Location header + (in violation of RFC 2616, but in line with how some servers + behave.) [270688] + +Changes from 2.2.3 to 2.2.4: + + * Fixed a problem with NTLM authentication against + multi-domain servers. [306877] + + * Fixed DNS lookups on Solaris. [254551, 268389] + +Changes from 2.2.2 to 2.2.3: + + * Now compiles against gnutls 1.2.0 [257811] + + * Fixed a bug that could result in 100% CPU usage if an SSL + server closed the connection uncleanly. [273352] + +Changes from 2.2.1 to 2.2.2: + + * The SSL validation fix from 2.2.1 [264414] is now completely + fixed. (Part of the fix didn't actually make it into 2.2.1) + + * HTTPS certificate validation now works when using an HTTP + proxy. [268583] + + * HTTP proxy code deals better with proxies that try to make + the user do HTML-form-based authentication. [268531] + + * 64-bit fixes for NTLM auth code. [270323, from Michael + Zucchi] + +Changes from 2.2.0 to 2.2.1: + + * Updated for a libgcrypt API change between 1.1.9x and 1.2.x + that caused a crash at runtime if you compiled against + 1.2.x. [266342] + + * SSL certificate validation failure should now always result + in a status of SOUP_STATUS_SSL_FAILED, rather than getting + turned into SOUP_STATUS_IO_ERROR. [264414] + + +Changes in libsoup from the 2.0 series (1.99.x versions) to 2.2: + + * Most of the libsoup datatypes are now GObjects. (SoupUri + is currently an exception to this.) + + * SoupMessage now emits signals at various stages of + processing. (Eg, "wrote_body", "got_headers".) (You + can also still use soup_message_add_*handler().) + + * SoupContexts are gone; soup_message_new() now takes a URI + string. + + * All formerly global state is now maintained by the + SoupSession object. (This includes the connection pool, + proxy server, cached authentication information, SSL + certificates, etc.) + + * You can create a SoupSessionAsync (for 2.0-like + behavior) or SoupSessionSync (for blocking, + synchronous usage). + + * You can add SoupMessageFilter objects to a session + to have certain processing automatically performed + on every message sent via that session. (Eg, setting + up handlers.) + + * NTLM authentication is no longer supported by + default. You must enable it by setting the + SOUP_SESSION_USE_NTLM flag on the session. + + * The preferred method of handling authentication is + now via the "authenticate" and "reauthenticate" + signals on SoupSession. (The old style, of encoding + the user and password information into the url is + also still supported.) + + * The SOUP_ERROR_* values are now SOUP_STATUS_* (so that we + don't have "SOUP_ERROR_OK" and the like). + + * SOUP_MESSAGE_IS_ERROR() is gone, since some cases + want to include 3xx responses and some don't. + + * SOUP_ERROR_CANT_AUTHENTICATE and + SOUP_ERROR_CANT_AUTHENTICATE_PROXY are now gone, + since they didn't carry any information that + SOUP_STATUS_UNAUTHORIZED and + SOUP_STATUS_PROXY_UNAUTHORIZED don't. + + * DNS errors now show up as the new status code + SOUP_STATUS_CANT_RESOLVE rather than being mixed in + with SOUP_ERROR_CANT_CONNECT. + + * Minimal SOAP support has been added back, via + SoupSoapMessage/SoupSoapResponse + + * The HTTP I/O state machine was completely rewritten, fixing + numerous crashes, leaks, and protocol errors. + + * SoupUri now conforms to RFC 2396. Mostly. + + * Various test programs have been added under tests/ + + * Removed: + + * Support for OpenSSL (which was horribly buggy) and + Mozilla NSS (which was never finished). We only + support GNUTLS for SSL now. + + * SOCKS support + + * CGI support in SoupServer diff --git a/README b/README new file mode 100644 index 0000000..3e2251c --- /dev/null +++ b/README @@ -0,0 +1,29 @@ +libsoup is an HTTP client/server library for GNOME. It uses GObjects +and the glib main loop, to integrate well with GNOME applications. + +Features: + * Both asynchronous (GMainLoop and callback-based) and synchronous APIs + * Automatically caches connections + * SSL support + * Proxy support, including authentication and SSL tunneling + * Client support for Digest, NTLM, and Basic authentication + * Server support for Digest and Basic authentication + * XML-RPC support + +See the documentation in docs/reference/ and the test programs in +tests/ for simple examples of how to use the code. The +evolution-data-server and evolution-exchange modules in GNOME git have +some more complicated examples. + +There is a mailing list for libsoup-related questions/discussions at +gnome.org. Visit http://mail.gnome.org/mailman/listinfo/libsoup-list +to subscribe or read the archives. + +Bugs against libsoup can be filed at the GNOME bugzilla: +https://bugzilla.gnome.org/enter_bug.cgi?product=libsoup + +More information (including the libsoup To Do list) is available at +https://wiki.gnome.org/Projects/libsoup + +Licensing: +libsoup is licensed under the LGPL, see COPYING for more details. diff --git a/aclocal.m4 b/aclocal.m4 new file mode 100644 index 0000000..1b134f0 --- /dev/null +++ b/aclocal.m4 @@ -0,0 +1,1725 @@ +# generated automatically by aclocal 1.15.1 -*- Autoconf -*- + +# Copyright (C) 1996-2017 Free Software Foundation, Inc. + +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],, +[m4_warning([this file was generated for autoconf 2.69. +You have another version of autoconf. It may work, but is not guaranteed to. +If you have problems, you may need to regenerate the build system entirely. +To do so, use the procedure documented by the package, typically 'autoreconf'.])]) + +dnl pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- +dnl serial 11 (pkg-config-0.29) +dnl +dnl Copyright © 2004 Scott James Remnant . +dnl Copyright © 2012-2015 Dan Nicholson +dnl +dnl This program is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2 of the License, or +dnl (at your option) any later version. +dnl +dnl This program is distributed in the hope that it will be useful, but +dnl WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +dnl General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with this program; if not, write to the Free Software +dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +dnl 02111-1307, USA. +dnl +dnl As a special exception to the GNU General Public License, if you +dnl distribute this file as part of a program that contains a +dnl configuration script generated by Autoconf, you may include it under +dnl the same distribution terms that you use for the rest of that +dnl program. + +dnl PKG_PREREQ(MIN-VERSION) +dnl ----------------------- +dnl Since: 0.29 +dnl +dnl Verify that the version of the pkg-config macros are at least +dnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's +dnl installed version of pkg-config, this checks the developer's version +dnl of pkg.m4 when generating configure. +dnl +dnl To ensure that this macro is defined, also add: +dnl m4_ifndef([PKG_PREREQ], +dnl [m4_fatal([must install pkg-config 0.29 or later before running autoconf/autogen])]) +dnl +dnl See the "Since" comment for each macro you use to see what version +dnl of the macros you require. +m4_defun([PKG_PREREQ], +[m4_define([PKG_MACROS_VERSION], [0.29]) +m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1, + [m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])]) +])dnl PKG_PREREQ + +dnl PKG_PROG_PKG_CONFIG([MIN-VERSION]) +dnl ---------------------------------- +dnl Since: 0.16 +dnl +dnl Search for the pkg-config tool and set the PKG_CONFIG variable to +dnl first found in the path. Checks that the version of pkg-config found +dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is +dnl used since that's the first version where most current features of +dnl pkg-config existed. +AC_DEFUN([PKG_PROG_PKG_CONFIG], +[m4_pattern_forbid([^_?PKG_[A-Z_]+$]) +m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$]) +m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$]) +AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility]) +AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path]) +AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path]) + +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=m4_default([$1], [0.9.0]) + AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + PKG_CONFIG="" + fi +fi[]dnl +])dnl PKG_PROG_PKG_CONFIG + +dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +dnl ------------------------------------------------------------------- +dnl Since: 0.18 +dnl +dnl Check to see whether a particular set of modules exists. Similar to +dnl PKG_CHECK_MODULES(), but does not set variables or print errors. +dnl +dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +dnl only at the first occurence in configure.ac, so if the first place +dnl it's called might be skipped (such as if it is within an "if", you +dnl have to call PKG_CHECK_EXISTS manually +AC_DEFUN([PKG_CHECK_EXISTS], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +if test -n "$PKG_CONFIG" && \ + AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then + m4_default([$2], [:]) +m4_ifvaln([$3], [else + $3])dnl +fi]) + +dnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) +dnl --------------------------------------------- +dnl Internal wrapper calling pkg-config via PKG_CONFIG and setting +dnl pkg_failed based on the result. +m4_define([_PKG_CONFIG], +[if test -n "$$1"; then + pkg_cv_[]$1="$$1" + elif test -n "$PKG_CONFIG"; then + PKG_CHECK_EXISTS([$3], + [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes ], + [pkg_failed=yes]) + else + pkg_failed=untried +fi[]dnl +])dnl _PKG_CONFIG + +dnl _PKG_SHORT_ERRORS_SUPPORTED +dnl --------------------------- +dnl Internal check to see if pkg-config supports short errors. +AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi[]dnl +])dnl _PKG_SHORT_ERRORS_SUPPORTED + + +dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +dnl [ACTION-IF-NOT-FOUND]) +dnl -------------------------------------------------------------- +dnl Since: 0.4.0 +dnl +dnl Note that if there is a possibility the first call to +dnl PKG_CHECK_MODULES might not happen, you should be sure to include an +dnl explicit call to PKG_PROG_PKG_CONFIG in your configure.ac +AC_DEFUN([PKG_CHECK_MODULES], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl +AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl + +pkg_failed=no +AC_MSG_CHECKING([for $1]) + +_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) +_PKG_CONFIG([$1][_LIBS], [libs], [$2]) + +m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS +and $1[]_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details.]) + +if test $pkg_failed = yes; then + AC_MSG_RESULT([no]) + _PKG_SHORT_ERRORS_SUPPORTED + if test $_pkg_short_errors_supported = yes; then + $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1` + else + $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD + + m4_default([$4], [AC_MSG_ERROR( +[Package requirements ($2) were not met: + +$$1_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +_PKG_TEXT])[]dnl + ]) +elif test $pkg_failed = untried; then + AC_MSG_RESULT([no]) + m4_default([$4], [AC_MSG_FAILURE( +[The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +_PKG_TEXT + +To get pkg-config, see .])[]dnl + ]) +else + $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS + $1[]_LIBS=$pkg_cv_[]$1[]_LIBS + AC_MSG_RESULT([yes]) + $3 +fi[]dnl +])dnl PKG_CHECK_MODULES + + +dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +dnl [ACTION-IF-NOT-FOUND]) +dnl --------------------------------------------------------------------- +dnl Since: 0.29 +dnl +dnl Checks for existence of MODULES and gathers its build flags with +dnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags +dnl and VARIABLE-PREFIX_LIBS from --libs. +dnl +dnl Note that if there is a possibility the first call to +dnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to +dnl include an explicit call to PKG_PROG_PKG_CONFIG in your +dnl configure.ac. +AC_DEFUN([PKG_CHECK_MODULES_STATIC], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +_save_PKG_CONFIG=$PKG_CONFIG +PKG_CONFIG="$PKG_CONFIG --static" +PKG_CHECK_MODULES($@) +PKG_CONFIG=$_save_PKG_CONFIG[]dnl +])dnl PKG_CHECK_MODULES_STATIC + + +dnl PKG_INSTALLDIR([DIRECTORY]) +dnl ------------------------- +dnl Since: 0.27 +dnl +dnl Substitutes the variable pkgconfigdir as the location where a module +dnl should install pkg-config .pc files. By default the directory is +dnl $libdir/pkgconfig, but the default can be changed by passing +dnl DIRECTORY. The user can override through the --with-pkgconfigdir +dnl parameter. +AC_DEFUN([PKG_INSTALLDIR], +[m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])]) +m4_pushdef([pkg_description], + [pkg-config installation directory @<:@]pkg_default[@:>@]) +AC_ARG_WITH([pkgconfigdir], + [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],, + [with_pkgconfigdir=]pkg_default) +AC_SUBST([pkgconfigdir], [$with_pkgconfigdir]) +m4_popdef([pkg_default]) +m4_popdef([pkg_description]) +])dnl PKG_INSTALLDIR + + +dnl PKG_NOARCH_INSTALLDIR([DIRECTORY]) +dnl -------------------------------- +dnl Since: 0.27 +dnl +dnl Substitutes the variable noarch_pkgconfigdir as the location where a +dnl module should install arch-independent pkg-config .pc files. By +dnl default the directory is $datadir/pkgconfig, but the default can be +dnl changed by passing DIRECTORY. The user can override through the +dnl --with-noarch-pkgconfigdir parameter. +AC_DEFUN([PKG_NOARCH_INSTALLDIR], +[m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])]) +m4_pushdef([pkg_description], + [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@]) +AC_ARG_WITH([noarch-pkgconfigdir], + [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],, + [with_noarch_pkgconfigdir=]pkg_default) +AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir]) +m4_popdef([pkg_default]) +m4_popdef([pkg_description]) +])dnl PKG_NOARCH_INSTALLDIR + + +dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE, +dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +dnl ------------------------------------------- +dnl Since: 0.28 +dnl +dnl Retrieves the value of the pkg-config variable for the given module. +AC_DEFUN([PKG_CHECK_VAR], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl + +_PKG_CONFIG([$1], [variable="][$3]["], [$2]) +AS_VAR_COPY([$1], [pkg_cv_][$1]) + +AS_VAR_IF([$1], [""], [$5], [$4])dnl +])dnl PKG_CHECK_VAR + +# Configure paths for GLIB +# Owen Taylor 1997-2001 + +# Increment this whenever this file is changed. +#serial 1 + +dnl AM_PATH_GLIB_2_0([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND [, MODULES]]]]) +dnl Test for GLIB, and define GLIB_CFLAGS and GLIB_LIBS, if gmodule, gobject, +dnl gthread, or gio is specified in MODULES, pass to pkg-config +dnl +AC_DEFUN([AM_PATH_GLIB_2_0], +[dnl +dnl Get the cflags and libraries from pkg-config +dnl +AC_ARG_ENABLE(glibtest, [ --disable-glibtest do not try to compile and run a test GLIB program], + , enable_glibtest=yes) + + pkg_config_args=glib-2.0 + for module in . $4 + do + case "$module" in + gmodule) + pkg_config_args="$pkg_config_args gmodule-2.0" + ;; + gmodule-no-export) + pkg_config_args="$pkg_config_args gmodule-no-export-2.0" + ;; + gobject) + pkg_config_args="$pkg_config_args gobject-2.0" + ;; + gthread) + pkg_config_args="$pkg_config_args gthread-2.0" + ;; + gio*) + pkg_config_args="$pkg_config_args $module-2.0" + ;; + esac + done + + PKG_PROG_PKG_CONFIG([0.16]) + + no_glib="" + + if test "x$PKG_CONFIG" = x ; then + no_glib=yes + PKG_CONFIG=no + fi + + min_glib_version=ifelse([$1], ,2.0.0,$1) + AC_MSG_CHECKING(for GLIB - version >= $min_glib_version) + + if test x$PKG_CONFIG != xno ; then + ## don't try to run the test against uninstalled libtool libs + if $PKG_CONFIG --uninstalled $pkg_config_args; then + echo "Will use uninstalled version of GLib found in PKG_CONFIG_PATH" + enable_glibtest=no + fi + + if $PKG_CONFIG --atleast-version $min_glib_version $pkg_config_args; then + : + else + no_glib=yes + fi + fi + + if test x"$no_glib" = x ; then + GLIB_GENMARSHAL=`$PKG_CONFIG --variable=glib_genmarshal glib-2.0` + GOBJECT_QUERY=`$PKG_CONFIG --variable=gobject_query glib-2.0` + GLIB_MKENUMS=`$PKG_CONFIG --variable=glib_mkenums glib-2.0` + GLIB_COMPILE_RESOURCES=`$PKG_CONFIG --variable=glib_compile_resources gio-2.0` + + GLIB_CFLAGS=`$PKG_CONFIG --cflags $pkg_config_args` + GLIB_LIBS=`$PKG_CONFIG --libs $pkg_config_args` + glib_config_major_version=`$PKG_CONFIG --modversion glib-2.0 | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` + glib_config_minor_version=`$PKG_CONFIG --modversion glib-2.0 | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` + glib_config_micro_version=`$PKG_CONFIG --modversion glib-2.0 | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` + if test "x$enable_glibtest" = "xyes" ; then + ac_save_CFLAGS="$CFLAGS" + ac_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $GLIB_CFLAGS" + LIBS="$GLIB_LIBS $LIBS" +dnl +dnl Now check if the installed GLIB is sufficiently new. (Also sanity +dnl checks the results of pkg-config to some extent) +dnl + rm -f conf.glibtest + AC_TRY_RUN([ +#include +#include +#include + +int +main (void) +{ + unsigned int major, minor, micro; + + fclose (fopen ("conf.glibtest", "w")); + + if (sscanf("$min_glib_version", "%u.%u.%u", &major, &minor, µ) != 3) { + printf("%s, bad version string\n", "$min_glib_version"); + exit(1); + } + + if ((glib_major_version != $glib_config_major_version) || + (glib_minor_version != $glib_config_minor_version) || + (glib_micro_version != $glib_config_micro_version)) + { + printf("\n*** 'pkg-config --modversion glib-2.0' returned %d.%d.%d, but GLIB (%d.%d.%d)\n", + $glib_config_major_version, $glib_config_minor_version, $glib_config_micro_version, + glib_major_version, glib_minor_version, glib_micro_version); + printf ("*** was found! If pkg-config was correct, then it is best\n"); + printf ("*** to remove the old version of GLib. You may also be able to fix the error\n"); + printf("*** by modifying your LD_LIBRARY_PATH enviroment variable, or by editing\n"); + printf("*** /etc/ld.so.conf. Make sure you have run ldconfig if that is\n"); + printf("*** required on your system.\n"); + printf("*** If pkg-config was wrong, set the environment variable PKG_CONFIG_PATH\n"); + printf("*** to point to the correct configuration files\n"); + } + else if ((glib_major_version != GLIB_MAJOR_VERSION) || + (glib_minor_version != GLIB_MINOR_VERSION) || + (glib_micro_version != GLIB_MICRO_VERSION)) + { + printf("*** GLIB header files (version %d.%d.%d) do not match\n", + GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION, GLIB_MICRO_VERSION); + printf("*** library (version %d.%d.%d)\n", + glib_major_version, glib_minor_version, glib_micro_version); + } + else + { + if ((glib_major_version > major) || + ((glib_major_version == major) && (glib_minor_version > minor)) || + ((glib_major_version == major) && (glib_minor_version == minor) && (glib_micro_version >= micro))) + { + return 0; + } + else + { + printf("\n*** An old version of GLIB (%u.%u.%u) was found.\n", + glib_major_version, glib_minor_version, glib_micro_version); + printf("*** You need a version of GLIB newer than %u.%u.%u. The latest version of\n", + major, minor, micro); + printf("*** GLIB is always available from ftp://ftp.gtk.org.\n"); + printf("***\n"); + printf("*** If you have already installed a sufficiently new version, this error\n"); + printf("*** probably means that the wrong copy of the pkg-config shell script is\n"); + printf("*** being found. The easiest way to fix this is to remove the old version\n"); + printf("*** of GLIB, but you can also set the PKG_CONFIG environment to point to the\n"); + printf("*** correct copy of pkg-config. (In this case, you will have to\n"); + printf("*** modify your LD_LIBRARY_PATH enviroment variable, or edit /etc/ld.so.conf\n"); + printf("*** so that the correct libraries are found at run-time))\n"); + } + } + return 1; +} +],, no_glib=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"]) + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + fi + fi + if test "x$no_glib" = x ; then + AC_MSG_RESULT(yes (version $glib_config_major_version.$glib_config_minor_version.$glib_config_micro_version)) + ifelse([$2], , :, [$2]) + else + AC_MSG_RESULT(no) + if test "$PKG_CONFIG" = "no" ; then + echo "*** A new enough version of pkg-config was not found." + echo "*** See http://www.freedesktop.org/software/pkgconfig/" + else + if test -f conf.glibtest ; then + : + else + echo "*** Could not run GLIB test program, checking why..." + ac_save_CFLAGS="$CFLAGS" + ac_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $GLIB_CFLAGS" + LIBS="$LIBS $GLIB_LIBS" + AC_TRY_LINK([ +#include +#include +], [ return ((glib_major_version) || (glib_minor_version) || (glib_micro_version)); ], + [ echo "*** The test program compiled, but did not run. This usually means" + echo "*** that the run-time linker is not finding GLIB or finding the wrong" + echo "*** version of GLIB. If it is not finding GLIB, you'll need to set your" + echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" + echo "*** to the installed location Also, make sure you have run ldconfig if that" + echo "*** is required on your system" + echo "***" + echo "*** If you have an old version installed, it is best to remove it, although" + echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH" ], + [ echo "*** The test program failed to compile or link. See the file config.log for the" + echo "*** exact error that occured. This usually means GLIB is incorrectly installed."]) + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + fi + fi + GLIB_CFLAGS="" + GLIB_LIBS="" + GLIB_GENMARSHAL="" + GOBJECT_QUERY="" + GLIB_MKENUMS="" + GLIB_COMPILE_RESOURCES="" + ifelse([$3], , :, [$3]) + fi + AC_SUBST(GLIB_CFLAGS) + AC_SUBST(GLIB_LIBS) + AC_SUBST(GLIB_GENMARSHAL) + AC_SUBST(GOBJECT_QUERY) + AC_SUBST(GLIB_MKENUMS) + AC_SUBST(GLIB_COMPILE_RESOURCES) + rm -f conf.glibtest +]) + +# nls.m4 serial 5 (gettext-0.18) +dnl Copyright (C) 1995-2003, 2005-2006, 2008-2014, 2016 Free Software +dnl Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +dnl +dnl This file can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +dnl Authors: +dnl Ulrich Drepper , 1995-2000. +dnl Bruno Haible , 2000-2003. + +AC_PREREQ([2.50]) + +AC_DEFUN([AM_NLS], +[ + AC_MSG_CHECKING([whether NLS is requested]) + dnl Default is enabled NLS + AC_ARG_ENABLE([nls], + [ --disable-nls do not use Native Language Support], + USE_NLS=$enableval, USE_NLS=yes) + AC_MSG_RESULT([$USE_NLS]) + AC_SUBST([USE_NLS]) +]) + +# Copyright (C) 2002-2017 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_AUTOMAKE_VERSION(VERSION) +# ---------------------------- +# Automake X.Y traces this macro to ensure aclocal.m4 has been +# generated from the m4 files accompanying Automake X.Y. +# (This private macro should not be called outside this file.) +AC_DEFUN([AM_AUTOMAKE_VERSION], +[am__api_version='1.15' +dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to +dnl require some minimum version. Point them to the right macro. +m4_if([$1], [1.15.1], [], + [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl +]) + +# _AM_AUTOCONF_VERSION(VERSION) +# ----------------------------- +# aclocal traces this macro to find the Autoconf version. +# This is a private macro too. Using m4_define simplifies +# the logic in aclocal, which can simply ignore this definition. +m4_define([_AM_AUTOCONF_VERSION], []) + +# AM_SET_CURRENT_AUTOMAKE_VERSION +# ------------------------------- +# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. +# This function is AC_REQUIREd by AM_INIT_AUTOMAKE. +AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], +[AM_AUTOMAKE_VERSION([1.15.1])dnl +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) + +# AM_AUX_DIR_EXPAND -*- Autoconf -*- + +# Copyright (C) 2001-2017 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets +# $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to +# '$srcdir', '$srcdir/..', or '$srcdir/../..'. +# +# Of course, Automake must honor this variable whenever it calls a +# tool from the auxiliary directory. The problem is that $srcdir (and +# therefore $ac_aux_dir as well) can be either absolute or relative, +# depending on how configure is run. This is pretty annoying, since +# it makes $ac_aux_dir quite unusable in subdirectories: in the top +# source directory, any form will work fine, but in subdirectories a +# relative path needs to be adjusted first. +# +# $ac_aux_dir/missing +# fails when called from a subdirectory if $ac_aux_dir is relative +# $top_srcdir/$ac_aux_dir/missing +# fails if $ac_aux_dir is absolute, +# fails when called from a subdirectory in a VPATH build with +# a relative $ac_aux_dir +# +# The reason of the latter failure is that $top_srcdir and $ac_aux_dir +# are both prefixed by $srcdir. In an in-source build this is usually +# harmless because $srcdir is '.', but things will broke when you +# start a VPATH build or use an absolute $srcdir. +# +# So we could use something similar to $top_srcdir/$ac_aux_dir/missing, +# iff we strip the leading $srcdir from $ac_aux_dir. That would be: +# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` +# and then we would define $MISSING as +# MISSING="\${SHELL} $am_aux_dir/missing" +# This will work as long as MISSING is not called from configure, because +# unfortunately $(top_srcdir) has no meaning in configure. +# However there are other variables, like CC, which are often used in +# configure, and could therefore not use this "fixed" $ac_aux_dir. +# +# Another solution, used here, is to always expand $ac_aux_dir to an +# absolute PATH. The drawback is that using absolute paths prevent a +# configured tree to be moved without reconfiguration. + +AC_DEFUN([AM_AUX_DIR_EXPAND], +[AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl +# Expand $ac_aux_dir to an absolute path. +am_aux_dir=`cd "$ac_aux_dir" && pwd` +]) + +# AM_CONDITIONAL -*- Autoconf -*- + +# Copyright (C) 1997-2017 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_CONDITIONAL(NAME, SHELL-CONDITION) +# ------------------------------------- +# Define a conditional. +AC_DEFUN([AM_CONDITIONAL], +[AC_PREREQ([2.52])dnl + m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], + [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl +AC_SUBST([$1_TRUE])dnl +AC_SUBST([$1_FALSE])dnl +_AM_SUBST_NOTMAKE([$1_TRUE])dnl +_AM_SUBST_NOTMAKE([$1_FALSE])dnl +m4_define([_AM_COND_VALUE_$1], [$2])dnl +if $2; then + $1_TRUE= + $1_FALSE='#' +else + $1_TRUE='#' + $1_FALSE= +fi +AC_CONFIG_COMMANDS_PRE( +[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then + AC_MSG_ERROR([[conditional "$1" was never defined. +Usually this means the macro was only invoked conditionally.]]) +fi])]) + +# Copyright (C) 1999-2017 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + + +# There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be +# written in clear, in which case automake, when reading aclocal.m4, +# will think it sees a *use*, and therefore will trigger all it's +# C support machinery. Also note that it means that autoscan, seeing +# CC etc. in the Makefile, will ask for an AC_PROG_CC use... + + +# _AM_DEPENDENCIES(NAME) +# ---------------------- +# See how the compiler implements dependency checking. +# NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC". +# We try a few techniques and use that to set a single cache variable. +# +# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was +# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular +# dependency, and given that the user is not expected to run this macro, +# just rely on AC_PROG_CC. +AC_DEFUN([_AM_DEPENDENCIES], +[AC_REQUIRE([AM_SET_DEPDIR])dnl +AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl +AC_REQUIRE([AM_MAKE_INCLUDE])dnl +AC_REQUIRE([AM_DEP_TRACK])dnl + +m4_if([$1], [CC], [depcc="$CC" am_compiler_list=], + [$1], [CXX], [depcc="$CXX" am_compiler_list=], + [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'], + [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'], + [$1], [UPC], [depcc="$UPC" am_compiler_list=], + [$1], [GCJ], [depcc="$GCJ" am_compiler_list='gcc3 gcc'], + [depcc="$$1" am_compiler_list=]) + +AC_CACHE_CHECK([dependency style of $depcc], + [am_cv_$1_dependencies_compiler_type], +[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named 'D' -- because '-MD' means "put the output + # in D". + rm -rf conftest.dir + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_$1_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` + fi + am__universal=false + m4_case([$1], [CC], + [case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac], + [CXX], + [case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac]) + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with + # Solaris 10 /bin/sh. + echo '/* dummy */' > sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with '-c' and '-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle '-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs. + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # After this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested. + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvc7 | msvc7msys | msvisualcpp | msvcmsys) + # This compiler won't grok '-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_$1_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_$1_dependencies_compiler_type=none +fi +]) +AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) +AM_CONDITIONAL([am__fastdep$1], [ + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) +]) + + +# AM_SET_DEPDIR +# ------------- +# Choose a directory name for dependency files. +# This macro is AC_REQUIREd in _AM_DEPENDENCIES. +AC_DEFUN([AM_SET_DEPDIR], +[AC_REQUIRE([AM_SET_LEADING_DOT])dnl +AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl +]) + + +# AM_DEP_TRACK +# ------------ +AC_DEFUN([AM_DEP_TRACK], +[AC_ARG_ENABLE([dependency-tracking], [dnl +AS_HELP_STRING( + [--enable-dependency-tracking], + [do not reject slow dependency extractors]) +AS_HELP_STRING( + [--disable-dependency-tracking], + [speeds up one-time build])]) +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' + am__nodep='_no' +fi +AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) +AC_SUBST([AMDEPBACKSLASH])dnl +_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl +AC_SUBST([am__nodep])dnl +_AM_SUBST_NOTMAKE([am__nodep])dnl +]) + +# Generate code to set up dependency tracking. -*- Autoconf -*- + +# Copyright (C) 1999-2017 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + + +# _AM_OUTPUT_DEPENDENCY_COMMANDS +# ------------------------------ +AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], +[{ + # Older Autoconf quotes --file arguments for eval, but not when files + # are listed without --file. Let's play safe and only enable the eval + # if we detect the quoting. + case $CONFIG_FILES in + *\'*) eval set x "$CONFIG_FILES" ;; + *) set x $CONFIG_FILES ;; + esac + shift + for mf + do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named 'Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # Grep'ing the whole file is not good either: AIX grep has a line + # limit of 2048, but all sed's we know have understand at least 4000. + if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then + dirpart=`AS_DIRNAME("$mf")` + else + continue + fi + # Extract the definition of DEPDIR, am__include, and am__quote + # from the Makefile without running 'make'. + DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` + test -z "$DEPDIR" && continue + am__include=`sed -n 's/^am__include = //p' < "$mf"` + test -z "$am__include" && continue + am__quote=`sed -n 's/^am__quote = //p' < "$mf"` + # Find all dependency output files, they are included files with + # $(DEPDIR) in their names. We invoke sed twice because it is the + # simplest approach to changing $(DEPDIR) to its actual value in the + # expansion. + for file in `sed -n " + s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`AS_DIRNAME(["$file"])` + AS_MKDIR_P([$dirpart/$fdir]) + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done + done +} +])# _AM_OUTPUT_DEPENDENCY_COMMANDS + + +# AM_OUTPUT_DEPENDENCY_COMMANDS +# ----------------------------- +# This macro should only be invoked once -- use via AC_REQUIRE. +# +# This code is only required when automatic dependency tracking +# is enabled. FIXME. This creates each '.P' file that we will +# need in order to bootstrap the dependency handling code. +AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], +[AC_CONFIG_COMMANDS([depfiles], + [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], + [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) +]) + +# Do all the work for Automake. -*- Autoconf -*- + +# Copyright (C) 1996-2017 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This macro actually does too much. Some checks are only needed if +# your package does certain things. But this isn't really a big deal. + +dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O. +m4_define([AC_PROG_CC], +m4_defn([AC_PROG_CC]) +[_AM_PROG_CC_C_O +]) + +# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) +# AM_INIT_AUTOMAKE([OPTIONS]) +# ----------------------------------------------- +# The call with PACKAGE and VERSION arguments is the old style +# call (pre autoconf-2.50), which is being phased out. PACKAGE +# and VERSION should now be passed to AC_INIT and removed from +# the call to AM_INIT_AUTOMAKE. +# We support both call styles for the transition. After +# the next Automake release, Autoconf can make the AC_INIT +# arguments mandatory, and then we can depend on a new Autoconf +# release and drop the old call support. +AC_DEFUN([AM_INIT_AUTOMAKE], +[AC_PREREQ([2.65])dnl +dnl Autoconf wants to disallow AM_ names. We explicitly allow +dnl the ones we care about. +m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl +AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl +AC_REQUIRE([AC_PROG_INSTALL])dnl +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) + fi +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi +AC_SUBST([CYGPATH_W]) + +# Define the identity of the package. +dnl Distinguish between old-style and new-style calls. +m4_ifval([$2], +[AC_DIAGNOSE([obsolete], + [$0: two- and three-arguments forms are deprecated.]) +m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl + AC_SUBST([PACKAGE], [$1])dnl + AC_SUBST([VERSION], [$2])], +[_AM_SET_OPTIONS([$1])dnl +dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. +m4_if( + m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]), + [ok:ok],, + [m4_fatal([AC_INIT should be called with package and version arguments])])dnl + AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl + AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl + +_AM_IF_OPTION([no-define],, +[AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package]) + AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl + +# Some tools Automake needs. +AC_REQUIRE([AM_SANITY_CHECK])dnl +AC_REQUIRE([AC_ARG_PROGRAM])dnl +AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}]) +AM_MISSING_PROG([AUTOCONF], [autoconf]) +AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}]) +AM_MISSING_PROG([AUTOHEADER], [autoheader]) +AM_MISSING_PROG([MAKEINFO], [makeinfo]) +AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl +AC_REQUIRE([AC_PROG_MKDIR_P])dnl +# For better backward compatibility. To be removed once Automake 1.9.x +# dies out for good. For more background, see: +# +# +AC_SUBST([mkdir_p], ['$(MKDIR_P)']) +# We need awk for the "check" target (and possibly the TAP driver). The +# system "awk" is bad on some platforms. +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([AC_PROG_MAKE_SET])dnl +AC_REQUIRE([AM_SET_LEADING_DOT])dnl +_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], + [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], + [_AM_PROG_TAR([v7])])]) +_AM_IF_OPTION([no-dependencies],, +[AC_PROVIDE_IFELSE([AC_PROG_CC], + [_AM_DEPENDENCIES([CC])], + [m4_define([AC_PROG_CC], + m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl +AC_PROVIDE_IFELSE([AC_PROG_CXX], + [_AM_DEPENDENCIES([CXX])], + [m4_define([AC_PROG_CXX], + m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl +AC_PROVIDE_IFELSE([AC_PROG_OBJC], + [_AM_DEPENDENCIES([OBJC])], + [m4_define([AC_PROG_OBJC], + m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl +AC_PROVIDE_IFELSE([AC_PROG_OBJCXX], + [_AM_DEPENDENCIES([OBJCXX])], + [m4_define([AC_PROG_OBJCXX], + m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl +]) +AC_REQUIRE([AM_SILENT_RULES])dnl +dnl The testsuite driver may need to know about EXEEXT, so add the +dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This +dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below. +AC_CONFIG_COMMANDS_PRE(dnl +[m4_provide_if([_AM_COMPILER_EXEEXT], + [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl + +# POSIX will say in a future version that running "rm -f" with no argument +# is OK; and we want to be able to make that assumption in our Makefile +# recipes. So use an aggressive probe to check that the usage we want is +# actually supported "in the wild" to an acceptable degree. +# See automake bug#10828. +# To make any issue more visible, cause the running configure to be aborted +# by default if the 'rm' program in use doesn't match our expectations; the +# user can still override this though. +if rm -f && rm -fr && rm -rf; then : OK; else + cat >&2 <<'END' +Oops! + +Your 'rm' program seems unable to run without file operands specified +on the command line, even when the '-f' option is present. This is contrary +to the behaviour of most rm programs out there, and not conforming with +the upcoming POSIX standard: + +Please tell bug-automake@gnu.org about your system, including the value +of your $PATH and any error possibly output before this message. This +can help us improve future automake versions. + +END + if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then + echo 'Configuration will proceed anyway, since you have set the' >&2 + echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 + echo >&2 + else + cat >&2 <<'END' +Aborting the configuration process, to ensure you take notice of the issue. + +You can download and install GNU coreutils to get an 'rm' implementation +that behaves properly: . + +If you want to complete the configuration process using your problematic +'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM +to "yes", and re-run configure. + +END + AC_MSG_ERROR([Your 'rm' program is bad, sorry.]) + fi +fi +dnl The trailing newline in this macro's definition is deliberate, for +dnl backward compatibility and to allow trailing 'dnl'-style comments +dnl after the AM_INIT_AUTOMAKE invocation. See automake bug#16841. +]) + +dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not +dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further +dnl mangled by Autoconf and run in a shell conditional statement. +m4_define([_AC_COMPILER_EXEEXT], +m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) + +# When config.status generates a header, we must update the stamp-h file. +# This file resides in the same directory as the config header +# that is generated. The stamp files are numbered to have different names. + +# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the +# loop where config.status creates the headers, so we can generate +# our stamp files there. +AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], +[# Compute $1's index in $config_headers. +_am_arg=$1 +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $_am_arg | $_am_arg:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) + +# Copyright (C) 2001-2017 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_PROG_INSTALL_SH +# ------------------ +# Define $install_sh. +AC_DEFUN([AM_PROG_INSTALL_SH], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +if test x"${install_sh+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi +AC_SUBST([install_sh])]) + +# Copyright (C) 2003-2017 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# Check whether the underlying file-system supports filenames +# with a leading dot. For instance MS-DOS doesn't. +AC_DEFUN([AM_SET_LEADING_DOT], +[rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null +AC_SUBST([am__leading_dot])]) + +# Check to see how 'make' treats includes. -*- Autoconf -*- + +# Copyright (C) 2001-2017 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_MAKE_INCLUDE() +# ----------------- +# Check to see how make treats includes. +AC_DEFUN([AM_MAKE_INCLUDE], +[am_make=${MAKE-make} +cat > confinc << 'END' +am__doit: + @echo this is the am__doit target +.PHONY: am__doit +END +# If we don't find an include directive, just comment out the code. +AC_MSG_CHECKING([for style of include used by $am_make]) +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# Ignore all kinds of additional output from 'make'. +case `$am_make -s -f confmf 2> /dev/null` in #( +*the\ am__doit\ target*) + am__include=include + am__quote= + _am_result=GNU + ;; +esac +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + case `$am_make -s -f confmf 2> /dev/null` in #( + *the\ am__doit\ target*) + am__include=.include + am__quote="\"" + _am_result=BSD + ;; + esac +fi +AC_SUBST([am__include]) +AC_SUBST([am__quote]) +AC_MSG_RESULT([$_am_result]) +rm -f confinc confmf +]) + +# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- + +# Copyright (C) 1997-2017 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_MISSING_PROG(NAME, PROGRAM) +# ------------------------------ +AC_DEFUN([AM_MISSING_PROG], +[AC_REQUIRE([AM_MISSING_HAS_RUN]) +$1=${$1-"${am_missing_run}$2"} +AC_SUBST($1)]) + +# AM_MISSING_HAS_RUN +# ------------------ +# Define MISSING if not defined so far and test if it is modern enough. +# If it is, set am_missing_run to use it, otherwise, to nothing. +AC_DEFUN([AM_MISSING_HAS_RUN], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +AC_REQUIRE_AUX_FILE([missing])dnl +if test x"${MISSING+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; + *) + MISSING="\${SHELL} $am_aux_dir/missing" ;; + esac +fi +# Use eval to expand $SHELL +if eval "$MISSING --is-lightweight"; then + am_missing_run="$MISSING " +else + am_missing_run= + AC_MSG_WARN(['missing' script is too old or missing]) +fi +]) + +# Helper functions for option handling. -*- Autoconf -*- + +# Copyright (C) 2001-2017 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_MANGLE_OPTION(NAME) +# ----------------------- +AC_DEFUN([_AM_MANGLE_OPTION], +[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) + +# _AM_SET_OPTION(NAME) +# -------------------- +# Set option NAME. Presently that only means defining a flag for this option. +AC_DEFUN([_AM_SET_OPTION], +[m4_define(_AM_MANGLE_OPTION([$1]), [1])]) + +# _AM_SET_OPTIONS(OPTIONS) +# ------------------------ +# OPTIONS is a space-separated list of Automake options. +AC_DEFUN([_AM_SET_OPTIONS], +[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) + +# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) +# ------------------------------------------- +# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. +AC_DEFUN([_AM_IF_OPTION], +[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) + +# Copyright (C) 1999-2017 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_PROG_CC_C_O +# --------------- +# Like AC_PROG_CC_C_O, but changed for automake. We rewrite AC_PROG_CC +# to automatically call this. +AC_DEFUN([_AM_PROG_CC_C_O], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +AC_REQUIRE_AUX_FILE([compile])dnl +AC_LANG_PUSH([C])dnl +AC_CACHE_CHECK( + [whether $CC understands -c and -o together], + [am_cv_prog_cc_c_o], + [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])]) + # Make sure it works both with $CC and with simple cc. + # Following AC_PROG_CC_C_O, we do the test twice because some + # compilers refuse to overwrite an existing .o file with -o, + # though they will create one. + am_cv_prog_cc_c_o=yes + for am_i in 1 2; do + if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \ + && test -f conftest2.$ac_objext; then + : OK + else + am_cv_prog_cc_c_o=no + break + fi + done + rm -f core conftest* + unset am_i]) +if test "$am_cv_prog_cc_c_o" != yes; then + # Losing compiler, so override with the script. + # FIXME: It is wrong to rewrite CC. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__CC in this case, + # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" + CC="$am_aux_dir/compile $CC" +fi +AC_LANG_POP([C])]) + +# For backward compatibility. +AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])]) + +# Copyright (C) 2001-2017 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_RUN_LOG(COMMAND) +# ------------------- +# Run COMMAND, save the exit status in ac_status, and log it. +# (This has been adapted from Autoconf's _AC_RUN_LOG macro.) +AC_DEFUN([AM_RUN_LOG], +[{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD + ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + (exit $ac_status); }]) + +# Check to make sure that the build environment is sane. -*- Autoconf -*- + +# Copyright (C) 1996-2017 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_SANITY_CHECK +# --------------- +AC_DEFUN([AM_SANITY_CHECK], +[AC_MSG_CHECKING([whether build environment is sane]) +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[[\\\"\#\$\&\'\`$am_lf]]*) + AC_MSG_ERROR([unsafe absolute working directory name]);; +esac +case $srcdir in + *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) + AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);; +esac + +# Do 'set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + am_has_slept=no + for am_try in 1 2; do + echo "timestamp, slept: $am_has_slept" > conftest.file + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` + if test "$[*]" = "X"; then + # -L didn't work. + set X `ls -t "$srcdir/configure" conftest.file` + fi + if test "$[*]" != "X $srcdir/configure conftest.file" \ + && test "$[*]" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken + alias in your environment]) + fi + if test "$[2]" = conftest.file || test $am_try -eq 2; then + break + fi + # Just in case. + sleep 1 + am_has_slept=yes + done + test "$[2]" = conftest.file + ) +then + # Ok. + : +else + AC_MSG_ERROR([newly created file is older than distributed files! +Check your system clock]) +fi +AC_MSG_RESULT([yes]) +# If we didn't sleep, we still need to ensure time stamps of config.status and +# generated files are strictly newer. +am_sleep_pid= +if grep 'slept: no' conftest.file >/dev/null 2>&1; then + ( sleep 1 ) & + am_sleep_pid=$! +fi +AC_CONFIG_COMMANDS_PRE( + [AC_MSG_CHECKING([that generated files are newer than configure]) + if test -n "$am_sleep_pid"; then + # Hide warnings about reused PIDs. + wait $am_sleep_pid 2>/dev/null + fi + AC_MSG_RESULT([done])]) +rm -f conftest.file +]) + +# Copyright (C) 2009-2017 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_SILENT_RULES([DEFAULT]) +# -------------------------- +# Enable less verbose build rules; with the default set to DEFAULT +# ("yes" being less verbose, "no" or empty being verbose). +AC_DEFUN([AM_SILENT_RULES], +[AC_ARG_ENABLE([silent-rules], [dnl +AS_HELP_STRING( + [--enable-silent-rules], + [less verbose build output (undo: "make V=1")]) +AS_HELP_STRING( + [--disable-silent-rules], + [verbose build output (undo: "make V=0")])dnl +]) +case $enable_silent_rules in @%:@ ((( + yes) AM_DEFAULT_VERBOSITY=0;; + no) AM_DEFAULT_VERBOSITY=1;; + *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);; +esac +dnl +dnl A few 'make' implementations (e.g., NonStop OS and NextStep) +dnl do not support nested variable expansions. +dnl See automake bug#9928 and bug#10237. +am_make=${MAKE-make} +AC_CACHE_CHECK([whether $am_make supports nested variables], + [am_cv_make_support_nested_variables], + [if AS_ECHO([['TRUE=$(BAR$(V)) +BAR0=false +BAR1=true +V=1 +am__doit: + @$(TRUE) +.PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then + am_cv_make_support_nested_variables=yes +else + am_cv_make_support_nested_variables=no +fi]) +if test $am_cv_make_support_nested_variables = yes; then + dnl Using '$V' instead of '$(V)' breaks IRIX make. + AM_V='$(V)' + AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' +else + AM_V=$AM_DEFAULT_VERBOSITY + AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY +fi +AC_SUBST([AM_V])dnl +AM_SUBST_NOTMAKE([AM_V])dnl +AC_SUBST([AM_DEFAULT_V])dnl +AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl +AC_SUBST([AM_DEFAULT_VERBOSITY])dnl +AM_BACKSLASH='\' +AC_SUBST([AM_BACKSLASH])dnl +_AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl +]) + +# Copyright (C) 2001-2017 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_PROG_INSTALL_STRIP +# --------------------- +# One issue with vendor 'install' (even GNU) is that you can't +# specify the program used to strip binaries. This is especially +# annoying in cross-compiling environments, where the build's strip +# is unlikely to handle the host's binaries. +# Fortunately install-sh will honor a STRIPPROG variable, so we +# always use install-sh in "make install-strip", and initialize +# STRIPPROG with the value of the STRIP variable (set by the user). +AC_DEFUN([AM_PROG_INSTALL_STRIP], +[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +# Installed binaries are usually stripped using 'strip' when the user +# run "make install-strip". However 'strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the 'STRIP' environment variable to overrule this program. +dnl Don't test for $cross_compiling = yes, because it might be 'maybe'. +if test "$cross_compiling" != no; then + AC_CHECK_TOOL([STRIP], [strip], :) +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" +AC_SUBST([INSTALL_STRIP_PROGRAM])]) + +# Copyright (C) 2006-2017 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_SUBST_NOTMAKE(VARIABLE) +# --------------------------- +# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. +# This macro is traced by Automake. +AC_DEFUN([_AM_SUBST_NOTMAKE]) + +# AM_SUBST_NOTMAKE(VARIABLE) +# -------------------------- +# Public sister of _AM_SUBST_NOTMAKE. +AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) + +# Check how to create a tarball. -*- Autoconf -*- + +# Copyright (C) 2004-2017 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_PROG_TAR(FORMAT) +# -------------------- +# Check how to create a tarball in format FORMAT. +# FORMAT should be one of 'v7', 'ustar', or 'pax'. +# +# Substitute a variable $(am__tar) that is a command +# writing to stdout a FORMAT-tarball containing the directory +# $tardir. +# tardir=directory && $(am__tar) > result.tar +# +# Substitute a variable $(am__untar) that extract such +# a tarball read from stdin. +# $(am__untar) < result.tar +# +AC_DEFUN([_AM_PROG_TAR], +[# Always define AMTAR for backward compatibility. Yes, it's still used +# in the wild :-( We should find a proper way to deprecate it ... +AC_SUBST([AMTAR], ['$${TAR-tar}']) + +# We'll loop over all known methods to create a tar archive until one works. +_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' + +m4_if([$1], [v7], + [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], + + [m4_case([$1], + [ustar], + [# The POSIX 1988 'ustar' format is defined with fixed-size fields. + # There is notably a 21 bits limit for the UID and the GID. In fact, + # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343 + # and bug#13588). + am_max_uid=2097151 # 2^21 - 1 + am_max_gid=$am_max_uid + # The $UID and $GID variables are not portable, so we need to resort + # to the POSIX-mandated id(1) utility. Errors in the 'id' calls + # below are definitely unexpected, so allow the users to see them + # (that is, avoid stderr redirection). + am_uid=`id -u || echo unknown` + am_gid=`id -g || echo unknown` + AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format]) + if test $am_uid -le $am_max_uid; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + _am_tools=none + fi + AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format]) + if test $am_gid -le $am_max_gid; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + _am_tools=none + fi], + + [pax], + [], + + [m4_fatal([Unknown tar format])]) + + AC_MSG_CHECKING([how to create a $1 tar archive]) + + # Go ahead even if we have the value already cached. We do so because we + # need to set the values for the 'am__tar' and 'am__untar' variables. + _am_tools=${am_cv_prog_tar_$1-$_am_tools} + + for _am_tool in $_am_tools; do + case $_am_tool in + gnutar) + for _am_tar in tar gnutar gtar; do + AM_RUN_LOG([$_am_tar --version]) && break + done + am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' + am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' + am__untar="$_am_tar -xf -" + ;; + plaintar) + # Must skip GNU tar: if it does not support --format= it doesn't create + # ustar tarball either. + (tar --version) >/dev/null 2>&1 && continue + am__tar='tar chf - "$$tardir"' + am__tar_='tar chf - "$tardir"' + am__untar='tar xf -' + ;; + pax) + am__tar='pax -L -x $1 -w "$$tardir"' + am__tar_='pax -L -x $1 -w "$tardir"' + am__untar='pax -r' + ;; + cpio) + am__tar='find "$$tardir" -print | cpio -o -H $1 -L' + am__tar_='find "$tardir" -print | cpio -o -H $1 -L' + am__untar='cpio -i -H $1 -d' + ;; + none) + am__tar=false + am__tar_=false + am__untar=false + ;; + esac + + # If the value was cached, stop now. We just wanted to have am__tar + # and am__untar set. + test -n "${am_cv_prog_tar_$1}" && break + + # tar/untar a dummy directory, and stop if the command works. + rm -rf conftest.dir + mkdir conftest.dir + echo GrepMe > conftest.dir/file + AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) + rm -rf conftest.dir + if test -s conftest.tar; then + AM_RUN_LOG([$am__untar /dev/null 2>&1 && break + fi + done + rm -rf conftest.dir + + AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) + AC_MSG_RESULT([$am_cv_prog_tar_$1])]) + +AC_SUBST([am__tar]) +AC_SUBST([am__untar]) +]) # _AM_PROG_TAR + +# Autoconf support for the Vala compiler + +# Copyright (C) 2008-2017 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# Check whether the Vala compiler exists in $PATH. If it is found, the +# variable VALAC is set pointing to its absolute path. Otherwise, it is +# simply set to 'valac'. +# Optionally a minimum release number of the compiler can be requested. +# If the ACTION-IF-FOUND parameter is given, it will be run if a proper +# Vala compiler is found. +# Similarly, if the ACTION-IF-FOUND is given, it will be run if no proper +# Vala compiler is found. It defaults to simply print a warning about the +# situation, but otherwise proceeding with the configuration. +# +# AM_PROG_VALAC([MINIMUM-VERSION], [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +# -------------------------------------------------------------------------- +AC_DEFUN([AM_PROG_VALAC], + [AC_PATH_PROG([VALAC], [valac], [valac]) + AS_IF([test "$VALAC" != valac && test -n "$1"], + [AC_MSG_CHECKING([whether $VALAC is at least version $1]) + am__vala_version=`$VALAC --version | sed 's/Vala *//'` + AS_VERSION_COMPARE([$1], ["$am__vala_version"], + [AC_MSG_RESULT([yes])], + [AC_MSG_RESULT([yes])], + [AC_MSG_RESULT([no]) + VALAC=valac])]) + if test "$VALAC" = valac; then + m4_default([$3], + [AC_MSG_WARN([no proper vala compiler found]) + AC_MSG_WARN([you will not be able to compile vala source files])]) + else + m4_default([$2], [:]) + fi]) + +m4_include([m4/ax_code_coverage.m4]) +m4_include([m4/glibtests.m4]) +m4_include([m4/gtk-doc.m4]) +m4_include([m4/intltool.m4]) +m4_include([m4/introspection.m4]) +m4_include([m4/libtool.m4]) +m4_include([m4/ltoptions.m4]) +m4_include([m4/ltsugar.m4]) +m4_include([m4/ltversion.m4]) +m4_include([m4/lt~obsolete.m4]) +m4_include([m4/vapigen.m4]) diff --git a/build-aux/compile b/build-aux/compile new file mode 100755 index 0000000..a85b723 --- /dev/null +++ b/build-aux/compile @@ -0,0 +1,347 @@ +#! /bin/sh +# Wrapper for compilers which do not understand '-c -o'. + +scriptversion=2012-10-14.11; # UTC + +# Copyright (C) 1999-2014 Free Software Foundation, Inc. +# Written by Tom Tromey . +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, 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 file is maintained in Automake, please report +# bugs to or send patches to +# . + +nl=' +' + +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent tools from complaining about whitespace usage. +IFS=" "" $nl" + +file_conv= + +# func_file_conv build_file lazy +# Convert a $build file to $host form and store it in $file +# Currently only supports Windows hosts. If the determined conversion +# type is listed in (the comma separated) LAZY, no conversion will +# take place. +func_file_conv () +{ + file=$1 + case $file in + / | /[!/]*) # absolute file, and not a UNC file + if test -z "$file_conv"; then + # lazily determine how to convert abs files + case `uname -s` in + MINGW*) + file_conv=mingw + ;; + CYGWIN*) + file_conv=cygwin + ;; + *) + file_conv=wine + ;; + esac + fi + case $file_conv/,$2, in + *,$file_conv,*) + ;; + mingw/*) + file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` + ;; + cygwin/*) + file=`cygpath -m "$file" || echo "$file"` + ;; + wine/*) + file=`winepath -w "$file" || echo "$file"` + ;; + esac + ;; + esac +} + +# func_cl_dashL linkdir +# Make cl look for libraries in LINKDIR +func_cl_dashL () +{ + func_file_conv "$1" + if test -z "$lib_path"; then + lib_path=$file + else + lib_path="$lib_path;$file" + fi + linker_opts="$linker_opts -LIBPATH:$file" +} + +# func_cl_dashl library +# Do a library search-path lookup for cl +func_cl_dashl () +{ + lib=$1 + found=no + save_IFS=$IFS + IFS=';' + for dir in $lib_path $LIB + do + IFS=$save_IFS + if $shared && test -f "$dir/$lib.dll.lib"; then + found=yes + lib=$dir/$lib.dll.lib + break + fi + if test -f "$dir/$lib.lib"; then + found=yes + lib=$dir/$lib.lib + break + fi + if test -f "$dir/lib$lib.a"; then + found=yes + lib=$dir/lib$lib.a + break + fi + done + IFS=$save_IFS + + if test "$found" != yes; then + lib=$lib.lib + fi +} + +# func_cl_wrapper cl arg... +# Adjust compile command to suit cl +func_cl_wrapper () +{ + # Assume a capable shell + lib_path= + shared=: + linker_opts= + for arg + do + if test -n "$eat"; then + eat= + else + case $1 in + -o) + # configure might choose to run compile as 'compile cc -o foo foo.c'. + eat=1 + case $2 in + *.o | *.[oO][bB][jJ]) + func_file_conv "$2" + set x "$@" -Fo"$file" + shift + ;; + *) + func_file_conv "$2" + set x "$@" -Fe"$file" + shift + ;; + esac + ;; + -I) + eat=1 + func_file_conv "$2" mingw + set x "$@" -I"$file" + shift + ;; + -I*) + func_file_conv "${1#-I}" mingw + set x "$@" -I"$file" + shift + ;; + -l) + eat=1 + func_cl_dashl "$2" + set x "$@" "$lib" + shift + ;; + -l*) + func_cl_dashl "${1#-l}" + set x "$@" "$lib" + shift + ;; + -L) + eat=1 + func_cl_dashL "$2" + ;; + -L*) + func_cl_dashL "${1#-L}" + ;; + -static) + shared=false + ;; + -Wl,*) + arg=${1#-Wl,} + save_ifs="$IFS"; IFS=',' + for flag in $arg; do + IFS="$save_ifs" + linker_opts="$linker_opts $flag" + done + IFS="$save_ifs" + ;; + -Xlinker) + eat=1 + linker_opts="$linker_opts $2" + ;; + -*) + set x "$@" "$1" + shift + ;; + *.cc | *.CC | *.cxx | *.CXX | *.[cC]++) + func_file_conv "$1" + set x "$@" -Tp"$file" + shift + ;; + *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO]) + func_file_conv "$1" mingw + set x "$@" "$file" + shift + ;; + *) + set x "$@" "$1" + shift + ;; + esac + fi + shift + done + if test -n "$linker_opts"; then + linker_opts="-link$linker_opts" + fi + exec "$@" $linker_opts + exit 1 +} + +eat= + +case $1 in + '') + echo "$0: No command. Try '$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: compile [--help] [--version] PROGRAM [ARGS] + +Wrapper for compilers which do not understand '-c -o'. +Remove '-o dest.o' from ARGS, run PROGRAM with the remaining +arguments, and rename the output as expected. + +If you are trying to build a whole package this is not the +right script to run: please start by reading the file 'INSTALL'. + +Report bugs to . +EOF + exit $? + ;; + -v | --v*) + echo "compile $scriptversion" + exit $? + ;; + cl | *[/\\]cl | cl.exe | *[/\\]cl.exe ) + func_cl_wrapper "$@" # Doesn't return... + ;; +esac + +ofile= +cfile= + +for arg +do + if test -n "$eat"; then + eat= + else + case $1 in + -o) + # configure might choose to run compile as 'compile cc -o foo foo.c'. + # So we strip '-o arg' only if arg is an object. + eat=1 + case $2 in + *.o | *.obj) + ofile=$2 + ;; + *) + set x "$@" -o "$2" + shift + ;; + esac + ;; + *.c) + cfile=$1 + set x "$@" "$1" + shift + ;; + *) + set x "$@" "$1" + shift + ;; + esac + fi + shift +done + +if test -z "$ofile" || test -z "$cfile"; then + # If no '-o' option was seen then we might have been invoked from a + # pattern rule where we don't need one. That is ok -- this is a + # normal compilation that the losing compiler can handle. If no + # '.c' file was seen then we are probably linking. That is also + # ok. + exec "$@" +fi + +# Name of file we expect compiler to create. +cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'` + +# Create the lock directory. +# Note: use '[/\\:.-]' here to ensure that we don't use the same name +# that we are using for the .o file. Also, base the name on the expected +# object file name, since that is what matters with a parallel build. +lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d +while true; do + if mkdir "$lockdir" >/dev/null 2>&1; then + break + fi + sleep 1 +done +# FIXME: race condition here if user kills between mkdir and trap. +trap "rmdir '$lockdir'; exit 1" 1 2 15 + +# Run the compile. +"$@" +ret=$? + +if test -f "$cofile"; then + test "$cofile" = "$ofile" || mv "$cofile" "$ofile" +elif test -f "${cofile}bj"; then + test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile" +fi + +rmdir "$lockdir" +exit $ret + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/build-aux/config.guess b/build-aux/config.guess new file mode 100755 index 0000000..f50dcdb --- /dev/null +++ b/build-aux/config.guess @@ -0,0 +1,1480 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright 1992-2018 Free Software Foundation, Inc. + +timestamp='2018-02-24' + +# 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-2018 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 + +trap 'exit 1' 1 2 15 + +# 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. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { 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) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > "$dummy.c" ; + for c in cc gcc c89 c99 ; do + if ($c -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; 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 ; set_cc_for_build= ;' + +# 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) >/dev/null 2>&1 ; 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 + + eval "$set_cc_for_build" + cat <<-EOF > "$dummy.c" + #include + #if defined(__UCLIBC__) + LIBC=uclibc + #elif defined(__dietlibc__) + LIBC=dietlibc + #else + LIBC=gnu + #endif + EOF + eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`" + + # If ldd exists, use it to detect musl libc. + if command -v ldd >/dev/null && \ + ldd --version 2>&1 | grep -q ^musl + then + LIBC=musl + fi + ;; +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 + 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) + eval "$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 ;; + 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 ;; + *: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.*:*) + eval "$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 [ "$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) + eval "$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 [ "$UNAME_PROCESSOR" = mc88100 ] || [ "$UNAME_PROCESSOR" = mc88110 ] + then + if [ "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx ] || \ + [ "$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 [ -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 + eval "$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 [ -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 [ -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 [ "$HP_ARCH" = "" ]; then + eval "$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 [ "$HP_ARCH" = hppa2.0w ] + then + eval "$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:*:*) + eval "$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 [ -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 ;; + *: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-unknown-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 ;; + i*86:Minix:*:*) + echo "$UNAME_MACHINE"-pc-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` 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:*:*) + eval "$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:*:*) + eval "$set_cc_for_build" + sed 's/^ //' << EOF > "$dummy.c" + #undef CPU + #undef ${UNAME_MACHINE} + #undef ${UNAME_MACHINE}el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=${UNAME_MACHINE}el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=${UNAME_MACHINE} + #else + CPU= + #endif + #endif +EOF + eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU'`" + test "x$CPU" != x && { echo "$CPU-unknown-linux-$LIBC"; 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:*:*) + if objdump -f /bin/sh | grep -q elf32-x86-64; then + echo "$UNAME_MACHINE"-pc-linux-"$LIBC"x32 + else + echo "$UNAME_MACHINE"-pc-linux-"$LIBC" + fi + 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 [ -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 ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + eval "$set_cc_for_build" + if test "$UNAME_PROCESSOR" = unknown ; then + UNAME_PROCESSOR=powerpc + fi + if test "`echo "$UNAME_RELEASE" | sed -e 's/\..*//'`" -le 10 ; then + if [ "$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 + fi + elif test "$UNAME_PROCESSOR" = i386 ; then + # Avoid executing cc on OS X 10.9, as it ships with a stub + # that puts up a graphical alert prompting to install + # developer tools. Any system running Mac OS X 10.7 or + # later (Darwin 11 and later) is required to have a 64-bit + # processor. This is not true of the ARM version of Darwin + # that Apple uses in portable devices. + UNAME_PROCESSOR=x86_64 + 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. + 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 ;; +esac + +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 </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 + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-functions 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/build-aux/config.sub b/build-aux/config.sub new file mode 100755 index 0000000..1d8e98b --- /dev/null +++ b/build-aux/config.sub @@ -0,0 +1,1801 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright 1992-2018 Free Software Foundation, Inc. + +timestamp='2018-02-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"). + + +# Please send patches to . +# +# 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: +# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub + +# 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 or ALIAS + +Canonicalize a configuration name. + +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.sub ($timestamp) + +Copyright 1992-2018 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-android* | linux-dietlibc | linux-newlib* | \ + linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ + knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \ + kopensolaris*-gnu* | cloudabi*-eabi* | \ + storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + android-linux) + os=-linux-android + basic_machine=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown + ;; + *) + 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*178) + os=-lynxos178 + ;; + -lynx*5) + os=-lynxos5 + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo "$1" | sed -e 's/86-.*/86-sequent/'` + ;; + -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 \ + | aarch64 | aarch64_be \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arceb \ + | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ + | avr | avr32 \ + | ba \ + | be32 | be64 \ + | bfin \ + | c4x | c8051 | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | e2k | epiphany \ + | fido | fr30 | frv | ft32 \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | hexagon \ + | i370 | i860 | i960 | ia16 | ia64 \ + | ip2k | iq2000 \ + | k1om \ + | le32 | le64 \ + | lm32 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | microblazeel | 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 \ + | mipsisa32r6 | mipsisa32r6el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64r6 | mipsisa64r6el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipsr5900 | mipsr5900el \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | moxie \ + | mt \ + | msp430 \ + | nds32 | nds32le | nds32be \ + | nios | nios2 | nios2eb | nios2el \ + | ns16k | ns32k \ + | open8 | or1k | or1knd | or32 \ + | pdp10 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle \ + | pru \ + | pyramid \ + | riscv32 | riscv64 \ + | rl78 | rx \ + | score \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu \ + | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ + | ubicom32 \ + | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ + | visium \ + | wasm32 \ + | x86 | xc16x | xstormy16 | xtensa \ + | z8k | z80) + basic_machine=$basic_machine-unknown + ;; + c54x) + basic_machine=tic54x-unknown + ;; + c55x) + basic_machine=tic55x-unknown + ;; + c6x) + basic_machine=tic6x-unknown + ;; + leon|leon[3-9]) + basic_machine=sparc-$basic_machine + ;; + m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip) + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65) + ;; + ms1) + basic_machine=mt-unknown + ;; + + strongarm | thumb | xscale) + basic_machine=arm-unknown + ;; + xgate) + basic_machine=$basic_machine-unknown + os=-none + ;; + xscaleeb) + basic_machine=armeb-unknown + ;; + + xscaleel) + basic_machine=armel-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-* \ + | aarch64-* | aarch64_be-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* | avr32-* \ + | ba-* \ + | be32-* | be64-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* \ + | c8051-* | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | e2k-* | elxsi-* \ + | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | hexagon-* \ + | i*86-* | i860-* | i960-* | ia16-* | ia64-* \ + | ip2k-* | iq2000-* \ + | k1om-* \ + | le32-* | le64-* \ + | lm32-* \ + | m32c-* | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ + | microblaze-* | microblazeel-* \ + | 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-* \ + | mipsisa32r6-* | mipsisa32r6el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64r6-* | mipsisa64r6el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipsr5900-* | mipsr5900el-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | mt-* \ + | msp430-* \ + | nds32-* | nds32le-* | nds32be-* \ + | nios-* | nios2-* | nios2eb-* | nios2el-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | open8-* \ + | or1k*-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ + | pru-* \ + | pyramid-* \ + | riscv32-* | riscv64-* \ + | rl78-* | 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-* | sv1-* | sx*-* \ + | tahoe-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tile*-* \ + | tron-* \ + | ubicom32-* \ + | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ + | vax-* \ + | visium-* \ + | wasm32-* \ + | we32k-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* \ + | 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-pc + 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 + ;; + asmjs) + basic_machine=asmjs-unknown + ;; + 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 + ;; + c54x-*) + basic_machine=tic54x-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + c55x-*) + basic_machine=tic55x-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + c6x-*) + basic_machine=tic6x-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + 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 | 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*) + basic_machine=m68k-bull + os=-sysv3 + ;; + e500v[12]) + basic_machine=powerpc-unknown + os=$os"spe" + ;; + e500v[12]-*) + basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'` + os=$os"spe" + ;; + 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 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; + 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 + ;; + 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 + ;; + leon-*|leon[3-9]-*) + basic_machine=sparc-`echo "$basic_machine" | sed 's/-.*//'` + ;; + m68knommu) + basic_machine=m68k-unknown + os=-linux + ;; + m68knommu-*) + basic_machine=m68k-`echo "$basic_machine" | sed 's/^[^-]*-//'` + os=-linux + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + microblaze*) + basic_machine=microblaze-xilinx + ;; + mingw64) + basic_machine=x86_64-pc + os=-mingw64 + ;; + mingw32) + basic_machine=i686-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 + ;; + moxiebox) + basic_machine=moxie-unknown + os=-moxiebox + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + ms1-*) + basic_machine=`echo "$basic_machine" | sed -e 's/ms1-/mt-/'` + ;; + msys) + basic_machine=i686-pc + os=-msys + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + nacl) + basic_machine=le32-unknown + os=-nacl + ;; + 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 + ;; + neo-tandem) + basic_machine=neo-tandem + ;; + nse-tandem) + basic_machine=nse-tandem + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + nsv-tandem) + basic_machine=nsv-tandem + ;; + nsx-tandem) + basic_machine=nsx-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 | ppcbe) basic_machine=powerpc-unknown + ;; + ppc-* | ppcbe-*) + basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle) + 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) + 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 | rdos64) + basic_machine=x86_64-pc + os=-rdos + ;; + rdos32) + 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 + ;; + sh5el) + basic_machine=sh5le-unknown + ;; + 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 + ;; + strongarm-* | thumb-*) + basic_machine=arm-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + 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 + ;; + tile*) + basic_machine=$basic_machine-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 + ;; + x64) + basic_machine=x86_64-pc + ;; + xbox) + basic_machine=i686-pc + os=-mingw32 + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + xscale-* | xscalee[bl]-*) + basic_machine=`echo "$basic_machine" | sed 's/^xscale/arm/'` + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + 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 + ;; + 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 + ;; + 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 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # es1800 is here to avoid being matched by es* (a different OS) + -es1800*) + os=-ose + ;; + # Now 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* | -plan9* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* | -aros* | -cloudabi* | -sortix* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -knetbsd* | -mirbsd* | -netbsd* \ + | -bitrig* | -openbsd* | -solidbsd* | -libertybsd* \ + | -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* | -glidix* \ + | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -midipix* | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ + | -linux-newlib* | -linux-musl* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \ + | -onefs* | -tirtos* | -phoenix* | -fuchsia* | -redox* | -bme* \ + | -midnightbsd*) + # 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 | -xray | -os68k* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* \ + | -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 + ;; + -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 + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -zvmoe) + os=-zvmoe + ;; + -dicos*) + os=-dicos + ;; + -pikeos*) + # Until real need of OS specific support for + # particular features comes up, bare metal + # configurations are quite functional. + case $basic_machine in + arm*) + os=-eabi + ;; + *) + os=-elf + ;; + esac + ;; + -nacl*) + ;; + -ios) + ;; + -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 + ;; + c8051-*) + os=-elf + ;; + hexagon-*) + os=-elf + ;; + tic54x-*) + os=-coff + ;; + tic55x-*) + os=-coff + ;; + tic6x-*) + 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 + ;; + 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 + ;; + pru-*) + os=-elf + ;; + *-be) + os=-beos + ;; + *-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 + ;; + *-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-functions 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/build-aux/depcomp b/build-aux/depcomp new file mode 100755 index 0000000..b39f98f --- /dev/null +++ b/build-aux/depcomp @@ -0,0 +1,791 @@ +#! /bin/sh +# depcomp - compile a program generating dependencies as side-effects + +scriptversion=2016-01-11.22; # UTC + +# Copyright (C) 1999-2017 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, 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. + +# Originally written by Alexandre Oliva . + +case $1 in + '') + echo "$0: No command. Try '$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: depcomp [--help] [--version] PROGRAM [ARGS] + +Run PROGRAMS ARGS to compile a file, generating dependencies +as side-effects. + +Environment variables: + depmode Dependency tracking mode. + source Source file read by 'PROGRAMS ARGS'. + object Object file output by 'PROGRAMS ARGS'. + DEPDIR directory where to store dependencies. + depfile Dependency file to output. + tmpdepfile Temporary file to use when outputting dependencies. + libtool Whether libtool is used (yes/no). + +Report bugs to . +EOF + exit $? + ;; + -v | --v*) + echo "depcomp $scriptversion" + exit $? + ;; +esac + +# Get the directory component of the given path, and save it in the +# global variables '$dir'. Note that this directory component will +# be either empty or ending with a '/' character. This is deliberate. +set_dir_from () +{ + case $1 in + */*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;; + *) dir=;; + esac +} + +# Get the suffix-stripped basename of the given path, and save it the +# global variable '$base'. +set_base_from () +{ + base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'` +} + +# If no dependency file was actually created by the compiler invocation, +# we still have to create a dummy depfile, to avoid errors with the +# Makefile "include basename.Plo" scheme. +make_dummy_depfile () +{ + echo "#dummy" > "$depfile" +} + +# Factor out some common post-processing of the generated depfile. +# Requires the auxiliary global variable '$tmpdepfile' to be set. +aix_post_process_depfile () +{ + # If the compiler actually managed to produce a dependency file, + # post-process it. + if test -f "$tmpdepfile"; then + # Each line is of the form 'foo.o: dependency.h'. + # Do two passes, one to just change these to + # $object: dependency.h + # and one to simply output + # dependency.h: + # which is needed to avoid the deleted-header problem. + { sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile" + sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile" + } > "$depfile" + rm -f "$tmpdepfile" + else + make_dummy_depfile + fi +} + +# A tabulation character. +tab=' ' +# A newline character. +nl=' +' +# Character ranges might be problematic outside the C locale. +# These definitions help. +upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ +lower=abcdefghijklmnopqrstuvwxyz +digits=0123456789 +alpha=${upper}${lower} + +if test -z "$depmode" || test -z "$source" || test -z "$object"; then + echo "depcomp: Variables source, object and depmode must be set" 1>&2 + exit 1 +fi + +# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. +depfile=${depfile-`echo "$object" | + sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} +tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} + +rm -f "$tmpdepfile" + +# Avoid interferences from the environment. +gccflag= dashmflag= + +# Some modes work just like other modes, but use different flags. We +# parameterize here, but still list the modes in the big case below, +# to make depend.m4 easier to write. Note that we *cannot* use a case +# here, because this file can only contain one case statement. +if test "$depmode" = hp; then + # HP compiler uses -M and no extra arg. + gccflag=-M + depmode=gcc +fi + +if test "$depmode" = dashXmstdout; then + # This is just like dashmstdout with a different argument. + dashmflag=-xM + depmode=dashmstdout +fi + +cygpath_u="cygpath -u -f -" +if test "$depmode" = msvcmsys; then + # This is just like msvisualcpp but w/o cygpath translation. + # Just convert the backslash-escaped backslashes to single forward + # slashes to satisfy depend.m4 + cygpath_u='sed s,\\\\,/,g' + depmode=msvisualcpp +fi + +if test "$depmode" = msvc7msys; then + # This is just like msvc7 but w/o cygpath translation. + # Just convert the backslash-escaped backslashes to single forward + # slashes to satisfy depend.m4 + cygpath_u='sed s,\\\\,/,g' + depmode=msvc7 +fi + +if test "$depmode" = xlc; then + # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information. + gccflag=-qmakedep=gcc,-MF + depmode=gcc +fi + +case "$depmode" in +gcc3) +## gcc 3 implements dependency tracking that does exactly what +## we want. Yay! Note: for some reason libtool 1.4 doesn't like +## it if -MD -MP comes after the -MF stuff. Hmm. +## Unfortunately, FreeBSD c89 acceptance of flags depends upon +## the command line argument order; so add the flags where they +## appear in depend2.am. Note that the slowdown incurred here +## affects only configure: in makefiles, %FASTDEP% shortcuts this. + for arg + do + case $arg in + -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; + *) set fnord "$@" "$arg" ;; + esac + shift # fnord + shift # $arg + done + "$@" + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + mv "$tmpdepfile" "$depfile" + ;; + +gcc) +## Note that this doesn't just cater to obsosete pre-3.x GCC compilers. +## but also to in-use compilers like IMB xlc/xlC and the HP C compiler. +## (see the conditional assignment to $gccflag above). +## There are various ways to get dependency output from gcc. Here's +## why we pick this rather obscure method: +## - Don't want to use -MD because we'd like the dependencies to end +## up in a subdir. Having to rename by hand is ugly. +## (We might end up doing this anyway to support other compilers.) +## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like +## -MM, not -M (despite what the docs say). Also, it might not be +## supported by the other compilers which use the 'gcc' depmode. +## - Using -M directly means running the compiler twice (even worse +## than renaming). + if test -z "$gccflag"; then + gccflag=-MD, + fi + "$@" -Wp,"$gccflag$tmpdepfile" + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + # The second -e expression handles DOS-style file names with drive + # letters. + sed -e 's/^[^:]*: / /' \ + -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" +## This next piece of magic avoids the "deleted header file" problem. +## The problem is that when a header file which appears in a .P file +## is deleted, the dependency causes make to die (because there is +## typically no way to rebuild the header). We avoid this by adding +## dummy dependencies for each header file. Too bad gcc doesn't do +## this for us directly. +## Some versions of gcc put a space before the ':'. On the theory +## that the space means something, we add a space to the output as +## well. hp depmode also adds that space, but also prefixes the VPATH +## to the object. Take care to not repeat it in the output. +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \ + | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +sgi) + if test "$libtool" = yes; then + "$@" "-Wp,-MDupdate,$tmpdepfile" + else + "$@" -MDupdate "$tmpdepfile" + fi + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + + if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files + echo "$object : \\" > "$depfile" + # Clip off the initial element (the dependent). Don't try to be + # clever and replace this with sed code, as IRIX sed won't handle + # lines with more than a fixed number of characters (4096 in + # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; + # the IRIX cc adds comments like '#:fec' to the end of the + # dependency line. + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \ + | tr "$nl" ' ' >> "$depfile" + echo >> "$depfile" + # The second pass generates a dummy entry for each header file. + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ + >> "$depfile" + else + make_dummy_depfile + fi + rm -f "$tmpdepfile" + ;; + +xlc) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +aix) + # The C for AIX Compiler uses -M and outputs the dependencies + # in a .u file. In older versions, this file always lives in the + # current directory. Also, the AIX compiler puts '$object:' at the + # start of each line; $object doesn't have directory information. + # Version 6 uses the directory in both cases. + set_dir_from "$object" + set_base_from "$object" + if test "$libtool" = yes; then + tmpdepfile1=$dir$base.u + tmpdepfile2=$base.u + tmpdepfile3=$dir.libs/$base.u + "$@" -Wc,-M + else + tmpdepfile1=$dir$base.u + tmpdepfile2=$dir$base.u + tmpdepfile3=$dir$base.u + "$@" -M + fi + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + do + test -f "$tmpdepfile" && break + done + aix_post_process_depfile + ;; + +tcc) + # tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26 + # FIXME: That version still under development at the moment of writing. + # Make that this statement remains true also for stable, released + # versions. + # It will wrap lines (doesn't matter whether long or short) with a + # trailing '\', as in: + # + # foo.o : \ + # foo.c \ + # foo.h \ + # + # It will put a trailing '\' even on the last line, and will use leading + # spaces rather than leading tabs (at least since its commit 0394caf7 + # "Emit spaces for -MD"). + "$@" -MD -MF "$tmpdepfile" + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + # Each non-empty line is of the form 'foo.o : \' or ' dep.h \'. + # We have to change lines of the first kind to '$object: \'. + sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile" + # And for each line of the second kind, we have to emit a 'dep.h:' + # dummy dependency, to avoid the deleted-header problem. + sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile" + rm -f "$tmpdepfile" + ;; + +## The order of this option in the case statement is important, since the +## shell code in configure will try each of these formats in the order +## listed in this file. A plain '-MD' option would be understood by many +## compilers, so we must ensure this comes after the gcc and icc options. +pgcc) + # Portland's C compiler understands '-MD'. + # Will always output deps to 'file.d' where file is the root name of the + # source file under compilation, even if file resides in a subdirectory. + # The object file name does not affect the name of the '.d' file. + # pgcc 10.2 will output + # foo.o: sub/foo.c sub/foo.h + # and will wrap long lines using '\' : + # foo.o: sub/foo.c ... \ + # sub/foo.h ... \ + # ... + set_dir_from "$object" + # Use the source, not the object, to determine the base name, since + # that's sadly what pgcc will do too. + set_base_from "$source" + tmpdepfile=$base.d + + # For projects that build the same source file twice into different object + # files, the pgcc approach of using the *source* file root name can cause + # problems in parallel builds. Use a locking strategy to avoid stomping on + # the same $tmpdepfile. + lockdir=$base.d-lock + trap " + echo '$0: caught signal, cleaning up...' >&2 + rmdir '$lockdir' + exit 1 + " 1 2 13 15 + numtries=100 + i=$numtries + while test $i -gt 0; do + # mkdir is a portable test-and-set. + if mkdir "$lockdir" 2>/dev/null; then + # This process acquired the lock. + "$@" -MD + stat=$? + # Release the lock. + rmdir "$lockdir" + break + else + # If the lock is being held by a different process, wait + # until the winning process is done or we timeout. + while test -d "$lockdir" && test $i -gt 0; do + sleep 1 + i=`expr $i - 1` + done + fi + i=`expr $i - 1` + done + trap - 1 2 13 15 + if test $i -le 0; then + echo "$0: failed to acquire lock after $numtries attempts" >&2 + echo "$0: check lockdir '$lockdir'" >&2 + exit 1 + fi + + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + # Each line is of the form `foo.o: dependent.h', + # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process this invocation + # correctly. Breaking it into two sed invocations is a workaround. + sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \ + | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp2) + # The "hp" stanza above does not work with aCC (C++) and HP's ia64 + # compilers, which have integrated preprocessors. The correct option + # to use with these is +Maked; it writes dependencies to a file named + # 'foo.d', which lands next to the object file, wherever that + # happens to be. + # Much of this is similar to the tru64 case; see comments there. + set_dir_from "$object" + set_base_from "$object" + if test "$libtool" = yes; then + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir.libs/$base.d + "$@" -Wc,+Maked + else + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir$base.d + "$@" +Maked + fi + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile1" "$tmpdepfile2" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" + do + test -f "$tmpdepfile" && break + done + if test -f "$tmpdepfile"; then + sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile" + # Add 'dependent.h:' lines. + sed -ne '2,${ + s/^ *// + s/ \\*$// + s/$/:/ + p + }' "$tmpdepfile" >> "$depfile" + else + make_dummy_depfile + fi + rm -f "$tmpdepfile" "$tmpdepfile2" + ;; + +tru64) + # The Tru64 compiler uses -MD to generate dependencies as a side + # effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'. + # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put + # dependencies in 'foo.d' instead, so we check for that too. + # Subdirectories are respected. + set_dir_from "$object" + set_base_from "$object" + + if test "$libtool" = yes; then + # Libtool generates 2 separate objects for the 2 libraries. These + # two compilations output dependencies in $dir.libs/$base.o.d and + # in $dir$base.o.d. We have to check for both files, because + # one of the two compilations can be disabled. We should prefer + # $dir$base.o.d over $dir.libs/$base.o.d because the latter is + # automatically cleaned when .libs/ is deleted, while ignoring + # the former would cause a distcleancheck panic. + tmpdepfile1=$dir$base.o.d # libtool 1.5 + tmpdepfile2=$dir.libs/$base.o.d # Likewise. + tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504 + "$@" -Wc,-MD + else + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir$base.d + tmpdepfile3=$dir$base.d + "$@" -MD + fi + + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + do + test -f "$tmpdepfile" && break + done + # Same post-processing that is required for AIX mode. + aix_post_process_depfile + ;; + +msvc7) + if test "$libtool" = yes; then + showIncludes=-Wc,-showIncludes + else + showIncludes=-showIncludes + fi + "$@" $showIncludes > "$tmpdepfile" + stat=$? + grep -v '^Note: including file: ' "$tmpdepfile" + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + # The first sed program below extracts the file names and escapes + # backslashes for cygpath. The second sed program outputs the file + # name when reading, but also accumulates all include files in the + # hold buffer in order to output them again at the end. This only + # works with sed implementations that can handle large buffers. + sed < "$tmpdepfile" -n ' +/^Note: including file: *\(.*\)/ { + s//\1/ + s/\\/\\\\/g + p +}' | $cygpath_u | sort -u | sed -n ' +s/ /\\ /g +s/\(.*\)/'"$tab"'\1 \\/p +s/.\(.*\) \\/\1:/ +H +$ { + s/.*/'"$tab"'/ + G + p +}' >> "$depfile" + echo >> "$depfile" # make sure the fragment doesn't end with a backslash + rm -f "$tmpdepfile" + ;; + +msvc7msys) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +#nosideeffect) + # This comment above is used by automake to tell side-effect + # dependency tracking mechanisms from slower ones. + +dashmstdout) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout, regardless of -o. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + # Remove '-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + test -z "$dashmflag" && dashmflag=-M + # Require at least two characters before searching for ':' + # in the target name. This is to cope with DOS-style filenames: + # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise. + "$@" $dashmflag | + sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile" + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process this sed invocation + # correctly. Breaking it into two sed invocations is a workaround. + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ + | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +dashXmstdout) + # This case only exists to satisfy depend.m4. It is never actually + # run, as this mode is specially recognized in the preamble. + exit 1 + ;; + +makedepend) + "$@" || exit $? + # Remove any Libtool call + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + # X makedepend + shift + cleared=no eat=no + for arg + do + case $cleared in + no) + set ""; shift + cleared=yes ;; + esac + if test $eat = yes; then + eat=no + continue + fi + case "$arg" in + -D*|-I*) + set fnord "$@" "$arg"; shift ;; + # Strip any option that makedepend may not understand. Remove + # the object too, otherwise makedepend will parse it as a source file. + -arch) + eat=yes ;; + -*|$object) + ;; + *) + set fnord "$@" "$arg"; shift ;; + esac + done + obj_suffix=`echo "$object" | sed 's/^.*\././'` + touch "$tmpdepfile" + ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" + rm -f "$depfile" + # makedepend may prepend the VPATH from the source file name to the object. + # No need to regex-escape $object, excess matching of '.' is harmless. + sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process the last invocation + # correctly. Breaking it into two sed invocations is a workaround. + sed '1,2d' "$tmpdepfile" \ + | tr ' ' "$nl" \ + | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ + | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" "$tmpdepfile".bak + ;; + +cpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + # Remove '-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + "$@" -E \ + | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ + -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ + | sed '$ s: \\$::' > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + cat < "$tmpdepfile" >> "$depfile" + sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvisualcpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + IFS=" " + for arg + do + case "$arg" in + -o) + shift + ;; + $object) + shift + ;; + "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") + set fnord "$@" + shift + shift + ;; + *) + set fnord "$@" "$arg" + shift + shift + ;; + esac + done + "$@" -E 2>/dev/null | + sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile" + echo "$tab" >> "$depfile" + sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvcmsys) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +none) + exec "$@" + ;; + +*) + echo "Unknown depmode $depmode" 1>&2 + exit 1 + ;; +esac + +exit 0 + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC0" +# time-stamp-end: "; # UTC" +# End: diff --git a/build-aux/install-sh b/build-aux/install-sh new file mode 100755 index 0000000..59990a1 --- /dev/null +++ b/build-aux/install-sh @@ -0,0 +1,508 @@ +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2014-09-12.12; # UTC + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# 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 AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# 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. + +tab=' ' +nl=' +' +IFS=" $tab$nl" + +# Set DOITPROG to "echo" to test this script. + +doit=${DOITPROG-} +doit_exec=${doit:-exec} + +# Put in absolute file names if you don't have them in your path; +# or use environment vars. + +chgrpprog=${CHGRPPROG-chgrp} +chmodprog=${CHMODPROG-chmod} +chownprog=${CHOWNPROG-chown} +cmpprog=${CMPPROG-cmp} +cpprog=${CPPROG-cp} +mkdirprog=${MKDIRPROG-mkdir} +mvprog=${MVPROG-mv} +rmprog=${RMPROG-rm} +stripprog=${STRIPPROG-strip} + +posix_mkdir= + +# Desired mode of installed file. +mode=0755 + +chgrpcmd= +chmodcmd=$chmodprog +chowncmd= +mvcmd=$mvprog +rmcmd="$rmprog -f" +stripcmd= + +src= +dst= +dir_arg= +dst_arg= + +copy_on_change=false +is_target_a_directory=possibly + +usage="\ +Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... + +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. + +Options: + --help display this help and exit. + --version display version info and exit. + + -c (ignored) + -C install only if different (preserve the last data modification time) + -d create directories instead of installing files. + -g GROUP $chgrpprog installed files to GROUP. + -m MODE $chmodprog installed files to MODE. + -o USER $chownprog installed files to USER. + -s $stripprog installed files. + -t DIRECTORY install into DIRECTORY. + -T report an error if DSTFILE is a directory. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG + RMPROG STRIPPROG +" + +while test $# -ne 0; do + case $1 in + -c) ;; + + -C) copy_on_change=true;; + + -d) dir_arg=true;; + + -g) chgrpcmd="$chgrpprog $2" + shift;; + + --help) echo "$usage"; exit $?;; + + -m) mode=$2 + case $mode in + *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*) + echo "$0: invalid mode: $mode" >&2 + exit 1;; + esac + shift;; + + -o) chowncmd="$chownprog $2" + shift;; + + -s) stripcmd=$stripprog;; + + -t) + is_target_a_directory=always + dst_arg=$2 + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + shift;; + + -T) is_target_a_directory=never;; + + --version) echo "$0 $scriptversion"; exit $?;; + + --) shift + break;; + + -*) echo "$0: invalid option: $1" >&2 + exit 1;; + + *) break;; + esac + shift +done + +# We allow the use of options -d and -T together, by making -d +# take the precedence; this is for compatibility with GNU install. + +if test -n "$dir_arg"; then + if test -n "$dst_arg"; then + echo "$0: target directory not allowed when installing a directory." >&2 + exit 1 + fi +fi + +if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then + # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dst_arg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dst_arg" + shift # fnord + fi + shift # arg + dst_arg=$arg + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + done +fi + +if test $# -eq 0; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call 'install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +if test -z "$dir_arg"; then + if test $# -gt 1 || test "$is_target_a_directory" = always; then + if test ! -d "$dst_arg"; then + echo "$0: $dst_arg: Is not a directory." >&2 + exit 1 + fi + fi +fi + +if test -z "$dir_arg"; then + do_exit='(exit $ret); exit $ret' + trap "ret=129; $do_exit" 1 + trap "ret=130; $do_exit" 2 + trap "ret=141; $do_exit" 13 + trap "ret=143; $do_exit" 15 + + # Set umask so as not to create temps with too-generous modes. + # However, 'strip' requires both read and write access to temps. + case $mode in + # Optimize common cases. + *644) cp_umask=133;; + *755) cp_umask=22;; + + *[0-7]) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw='% 200' + fi + cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; + *) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw=,u+rw + fi + cp_umask=$mode$u_plus_rw;; + esac +fi + +for src +do + # Protect names problematic for 'test' and other utilities. + case $src in + -* | [=\(\)!]) src=./$src;; + esac + + if test -n "$dir_arg"; then + dst=$src + dstdir=$dst + test -d "$dstdir" + dstdir_status=$? + else + + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dst_arg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + dst=$dst_arg + + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + if test "$is_target_a_directory" = never; then + echo "$0: $dst_arg: Is a directory" >&2 + exit 1 + fi + dstdir=$dst + dst=$dstdir/`basename "$src"` + dstdir_status=0 + else + dstdir=`dirname "$dst"` + test -d "$dstdir" + dstdir_status=$? + fi + fi + + obsolete_mkdir_used=false + + if test $dstdir_status != 0; then + case $posix_mkdir in + '') + # Create intermediate dirs using mode 755 as modified by the umask. + # This is like FreeBSD 'install' as of 1997-10-28. + umask=`umask` + case $stripcmd.$umask in + # Optimize common cases. + *[2367][2367]) mkdir_umask=$umask;; + .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; + + *[0-7]) + mkdir_umask=`expr $umask + 22 \ + - $umask % 100 % 40 + $umask % 20 \ + - $umask % 10 % 4 + $umask % 2 + `;; + *) mkdir_umask=$umask,go-w;; + esac + + # With -d, create the new directory with the user-specified mode. + # Otherwise, rely on $mkdir_umask. + if test -n "$dir_arg"; then + mkdir_mode=-m$mode + else + mkdir_mode= + fi + + posix_mkdir=false + case $umask in + *[123567][0-7][0-7]) + # POSIX mkdir -p sets u+wx bits regardless of umask, which + # is incompatible with FreeBSD 'install' when (umask & 300) != 0. + ;; + *) + # $RANDOM is not portable (e.g. dash); use it when possible to + # lower collision chance + tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ + trap 'ret=$?; rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null; exit $ret' 0 + + # As "mkdir -p" follows symlinks and we work in /tmp possibly; so + # create the $tmpdir first (and fail if unsuccessful) to make sure + # that nobody tries to guess the $tmpdir name. + if (umask $mkdir_umask && + $mkdirprog $mkdir_mode "$tmpdir" && + exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1 + then + if test -z "$dir_arg" || { + # Check for POSIX incompatibilities with -m. + # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or + # other-writable bit of parent directory when it shouldn't. + # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. + test_tmpdir="$tmpdir/a" + ls_ld_tmpdir=`ls -ld "$test_tmpdir"` + case $ls_ld_tmpdir in + d????-?r-*) different_mode=700;; + d????-?--*) different_mode=755;; + *) false;; + esac && + $mkdirprog -m$different_mode -p -- "$test_tmpdir" && { + ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"` + test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" + } + } + then posix_mkdir=: + fi + rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" + else + # Remove any dirs left behind by ancient mkdir implementations. + rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null + fi + trap '' 0;; + esac;; + esac + + if + $posix_mkdir && ( + umask $mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" + ) + then : + else + + # The umask is ridiculous, or mkdir does not conform to POSIX, + # or it failed possibly due to a race condition. Create the + # directory the slow way, step by step, checking for races as we go. + + case $dstdir in + /*) prefix='/';; + [-=\(\)!]*) prefix='./';; + *) prefix='';; + esac + + oIFS=$IFS + IFS=/ + set -f + set fnord $dstdir + shift + set +f + IFS=$oIFS + + prefixes= + + for d + do + test X"$d" = X && continue + + prefix=$prefix$d + if test -d "$prefix"; then + prefixes= + else + if $posix_mkdir; then + (umask=$mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break + # Don't fail if two instances are running concurrently. + test -d "$prefix" || exit 1 + else + case $prefix in + *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; + *) qprefix=$prefix;; + esac + prefixes="$prefixes '$qprefix'" + fi + fi + prefix=$prefix/ + done + + if test -n "$prefixes"; then + # Don't fail if two instances are running concurrently. + (umask $mkdir_umask && + eval "\$doit_exec \$mkdirprog $prefixes") || + test -d "$dstdir" || exit 1 + obsolete_mkdir_used=true + fi + fi + fi + + if test -n "$dir_arg"; then + { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && + { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || + test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 + else + + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + + # Copy the file name to the temp name. + (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && + + # 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 $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && + { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && + { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && + + # If -C, don't bother to copy if it wouldn't change the file. + if $copy_on_change && + old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && + new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && + set -f && + set X $old && old=:$2:$4:$5:$6 && + set X $new && new=:$2:$4:$5:$6 && + set +f && + test "$old" = "$new" && + $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 + then + rm -f "$dsttmp" + else + # Rename the file to the real destination. + $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || + + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + { + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + test ! -f "$dst" || + $doit $rmcmd -f "$dst" 2>/dev/null || + { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && + { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } + } || + { echo "$0: cannot unlink or rename $dst" >&2 + (exit 1); exit 1 + } + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dst" + } + fi || exit 1 + + trap '' 0 + fi +done + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/build-aux/ltmain.sh b/build-aux/ltmain.sh new file mode 100644 index 0000000..e4eda6d --- /dev/null +++ b/build-aux/ltmain.sh @@ -0,0 +1,11346 @@ +#! /bin/sh +## DO NOT EDIT - This file generated from ./build-aux/ltmain.in +## by inline-source v2014-01-03.01 + +# libtool (GNU libtool) 2.4.6 +# Provide generalized library-building support services. +# Written by Gordon Matzigkeit , 1996 + +# Copyright (C) 1996-2015 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. + +# GNU Libtool 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. +# +# As a special exception to the GNU General Public License, +# if you distribute this file as part of a program or library that +# is built using GNU Libtool, you may include this file under the +# same distribution terms that you use for the rest of that program. +# +# GNU Libtool is distributed in the hope that 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 . + + +PROGRAM=libtool +PACKAGE=libtool +VERSION="2.4.6 Debian-2.4.6-2.1" +package_revision=2.4.6 + + +## ------ ## +## Usage. ## +## ------ ## + +# Run './libtool --help' for help with using this script from the +# command line. + + +## ------------------------------- ## +## User overridable command paths. ## +## ------------------------------- ## + +# After configure completes, it has a better idea of some of the +# shell tools we need than the defaults used by the functions shared +# with bootstrap, so set those here where they can still be over- +# ridden by the user, but otherwise take precedence. + +: ${AUTOCONF="autoconf"} +: ${AUTOMAKE="automake"} + + +## -------------------------- ## +## Source external libraries. ## +## -------------------------- ## + +# Much of our low-level functionality needs to be sourced from external +# libraries, which are installed to $pkgauxdir. + +# Set a version string for this script. +scriptversion=2015-10-12.13; # UTC + +# General shell script boiler plate, and helper functions. +# Written by Gary V. Vaughan, 2004 + +# Copyright (C) 2004-2015 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. + +# 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 3 of the License, or +# (at your option) any later version. + +# As a special exception to the GNU General Public License, if you distribute +# this file as part of a program or library that is built using GNU Libtool, +# you may include this file under the same distribution terms that you use +# for the rest of that program. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNES 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 . + +# Please report bugs or propose patches to gary@gnu.org. + + +## ------ ## +## Usage. ## +## ------ ## + +# Evaluate this file near the top of your script to gain access to +# the functions and variables defined here: +# +# . `echo "$0" | ${SED-sed} 's|[^/]*$||'`/build-aux/funclib.sh +# +# If you need to override any of the default environment variable +# settings, do that before evaluating this file. + + +## -------------------- ## +## Shell normalisation. ## +## -------------------- ## + +# Some shells need a little help to be as Bourne compatible as possible. +# Before doing anything else, make sure all that help has been provided! + +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 + +# NLS nuisances: We save the old values in case they are required later. +_G_user_locale= +_G_safe_locale= +for _G_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES +do + eval "if test set = \"\${$_G_var+set}\"; then + save_$_G_var=\$$_G_var + $_G_var=C + export $_G_var + _G_user_locale=\"$_G_var=\\\$save_\$_G_var; \$_G_user_locale\" + _G_safe_locale=\"$_G_var=C; \$_G_safe_locale\" + fi" +done + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# Make sure IFS has a sensible default +sp=' ' +nl=' +' +IFS="$sp $nl" + +# There are apparently some retarded systems that use ';' as a PATH separator! +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 + + + +## ------------------------- ## +## Locate command utilities. ## +## ------------------------- ## + + +# func_executable_p FILE +# ---------------------- +# Check that FILE is an executable regular file. +func_executable_p () +{ + test -f "$1" && test -x "$1" +} + + +# func_path_progs PROGS_LIST CHECK_FUNC [PATH] +# -------------------------------------------- +# Search for either a program that responds to --version with output +# containing "GNU", or else returned by CHECK_FUNC otherwise, by +# trying all the directories in PATH with each of the elements of +# PROGS_LIST. +# +# CHECK_FUNC should accept the path to a candidate program, and +# set $func_check_prog_result if it truncates its output less than +# $_G_path_prog_max characters. +func_path_progs () +{ + _G_progs_list=$1 + _G_check_func=$2 + _G_PATH=${3-"$PATH"} + + _G_path_prog_max=0 + _G_path_prog_found=false + _G_save_IFS=$IFS; IFS=${PATH_SEPARATOR-:} + for _G_dir in $_G_PATH; do + IFS=$_G_save_IFS + test -z "$_G_dir" && _G_dir=. + for _G_prog_name in $_G_progs_list; do + for _exeext in '' .EXE; do + _G_path_prog=$_G_dir/$_G_prog_name$_exeext + func_executable_p "$_G_path_prog" || continue + case `"$_G_path_prog" --version 2>&1` in + *GNU*) func_path_progs_result=$_G_path_prog _G_path_prog_found=: ;; + *) $_G_check_func $_G_path_prog + func_path_progs_result=$func_check_prog_result + ;; + esac + $_G_path_prog_found && break 3 + done + done + done + IFS=$_G_save_IFS + test -z "$func_path_progs_result" && { + echo "no acceptable sed could be found in \$PATH" >&2 + exit 1 + } +} + + +# We want to be able to use the functions in this file before configure +# has figured out where the best binaries are kept, which means we have +# to search for them ourselves - except when the results are already set +# where we skip the searches. + +# Unless the user overrides by setting SED, search the path for either GNU +# sed, or the sed that truncates its output the least. +test -z "$SED" && { + _G_sed_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ + for _G_i in 1 2 3 4 5 6 7; do + _G_sed_script=$_G_sed_script$nl$_G_sed_script + done + echo "$_G_sed_script" 2>/dev/null | sed 99q >conftest.sed + _G_sed_script= + + func_check_prog_sed () + { + _G_path_prog=$1 + + _G_count=0 + printf 0123456789 >conftest.in + while : + do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo '' >> conftest.nl + "$_G_path_prog" -f conftest.sed conftest.out 2>/dev/null || break + diff conftest.out conftest.nl >/dev/null 2>&1 || break + _G_count=`expr $_G_count + 1` + if test "$_G_count" -gt "$_G_path_prog_max"; then + # Best one so far, save it but keep looking for a better one + func_check_prog_result=$_G_path_prog + _G_path_prog_max=$_G_count + fi + # 10*(2^10) chars as input seems more than enough + test 10 -lt "$_G_count" && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out + } + + func_path_progs "sed gsed" func_check_prog_sed $PATH:/usr/xpg4/bin + rm -f conftest.sed + SED=$func_path_progs_result +} + + +# Unless the user overrides by setting GREP, search the path for either GNU +# grep, or the grep that truncates its output the least. +test -z "$GREP" && { + func_check_prog_grep () + { + _G_path_prog=$1 + + _G_count=0 + _G_path_prog_max=0 + printf 0123456789 >conftest.in + while : + do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo 'GREP' >> conftest.nl + "$_G_path_prog" -e 'GREP$' -e '-(cannot match)-' conftest.out 2>/dev/null || break + diff conftest.out conftest.nl >/dev/null 2>&1 || break + _G_count=`expr $_G_count + 1` + if test "$_G_count" -gt "$_G_path_prog_max"; then + # Best one so far, save it but keep looking for a better one + func_check_prog_result=$_G_path_prog + _G_path_prog_max=$_G_count + fi + # 10*(2^10) chars as input seems more than enough + test 10 -lt "$_G_count" && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out + } + + func_path_progs "grep ggrep" func_check_prog_grep $PATH:/usr/xpg4/bin + GREP=$func_path_progs_result +} + + +## ------------------------------- ## +## User overridable command paths. ## +## ------------------------------- ## + +# All uppercase variable names are used for environment variables. These +# variables can be overridden by the user before calling a script that +# uses them if a suitable command of that name is not already available +# in the command search PATH. + +: ${CP="cp -f"} +: ${ECHO="printf %s\n"} +: ${EGREP="$GREP -E"} +: ${FGREP="$GREP -F"} +: ${LN_S="ln -s"} +: ${MAKE="make"} +: ${MKDIR="mkdir"} +: ${MV="mv -f"} +: ${RM="rm -f"} +: ${SHELL="${CONFIG_SHELL-/bin/sh}"} + + +## -------------------- ## +## Useful sed snippets. ## +## -------------------- ## + +sed_dirname='s|/[^/]*$||' +sed_basename='s|^.*/||' + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +sed_quote_subst='s|\([`"$\\]\)|\\\1|g' + +# Same as above, but do not quote variable references. +sed_double_quote_subst='s/\(["`\\]\)/\\\1/g' + +# Sed substitution that turns a string into a regex matching for the +# string literally. +sed_make_literal_regex='s|[].[^$\\*\/]|\\&|g' + +# Sed substitution that converts a w32 file name or path +# that contains forward slashes, into one that contains +# (escaped) backslashes. A very naive implementation. +sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' + +# Re-'\' parameter expansions in output of sed_double_quote_subst that +# were '\'-ed in input to the same. If an odd number of '\' preceded a +# '$' in input to sed_double_quote_subst, that '$' was protected from +# expansion. Since each input '\' is now two '\'s, look for any number +# of runs of four '\'s followed by two '\'s and then a '$'. '\' that '$'. +_G_bs='\\' +_G_bs2='\\\\' +_G_bs4='\\\\\\\\' +_G_dollar='\$' +sed_double_backslash="\ + s/$_G_bs4/&\\ +/g + s/^$_G_bs2$_G_dollar/$_G_bs&/ + s/\\([^$_G_bs]\\)$_G_bs2$_G_dollar/\\1$_G_bs2$_G_bs$_G_dollar/g + s/\n//g" + + +## ----------------- ## +## Global variables. ## +## ----------------- ## + +# Except for the global variables explicitly listed below, the following +# functions in the '^func_' namespace, and the '^require_' namespace +# variables initialised in the 'Resource management' section, sourcing +# this file will not pollute your global namespace with anything +# else. There's no portable way to scope variables in Bourne shell +# though, so actually running these functions will sometimes place +# results into a variable named after the function, and often use +# temporary variables in the '^_G_' namespace. If you are careful to +# avoid using those namespaces casually in your sourcing script, things +# should continue to work as you expect. And, of course, you can freely +# overwrite any of the functions or variables defined here before +# calling anything to customize them. + +EXIT_SUCCESS=0 +EXIT_FAILURE=1 +EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. +EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. + +# Allow overriding, eg assuming that you follow the convention of +# putting '$debug_cmd' at the start of all your functions, you can get +# bash to show function call trace with: +# +# debug_cmd='eval echo "${FUNCNAME[0]} $*" >&2' bash your-script-name +debug_cmd=${debug_cmd-":"} +exit_cmd=: + +# By convention, finish your script with: +# +# exit $exit_status +# +# so that you can set exit_status to non-zero if you want to indicate +# something went wrong during execution without actually bailing out at +# the point of failure. +exit_status=$EXIT_SUCCESS + +# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh +# is ksh but when the shell is invoked as "sh" and the current value of +# the _XPG environment variable is not equal to 1 (one), the special +# positional parameter $0, within a function call, is the name of the +# function. +progpath=$0 + +# The name of this program. +progname=`$ECHO "$progpath" |$SED "$sed_basename"` + +# Make sure we have an absolute progpath for reexecution: +case $progpath in + [\\/]*|[A-Za-z]:\\*) ;; + *[\\/]*) + progdir=`$ECHO "$progpath" |$SED "$sed_dirname"` + progdir=`cd "$progdir" && pwd` + progpath=$progdir/$progname + ;; + *) + _G_IFS=$IFS + IFS=${PATH_SEPARATOR-:} + for progdir in $PATH; do + IFS=$_G_IFS + test -x "$progdir/$progname" && break + done + IFS=$_G_IFS + test -n "$progdir" || progdir=`pwd` + progpath=$progdir/$progname + ;; +esac + + +## ----------------- ## +## Standard options. ## +## ----------------- ## + +# The following options affect the operation of the functions defined +# below, and should be set appropriately depending on run-time para- +# meters passed on the command line. + +opt_dry_run=false +opt_quiet=false +opt_verbose=false + +# Categories 'all' and 'none' are always available. Append any others +# you will pass as the first argument to func_warning from your own +# code. +warning_categories= + +# By default, display warnings according to 'opt_warning_types'. Set +# 'warning_func' to ':' to elide all warnings, or func_fatal_error to +# treat the next displayed warning as a fatal error. +warning_func=func_warn_and_continue + +# Set to 'all' to display all warnings, 'none' to suppress all +# warnings, or a space delimited list of some subset of +# 'warning_categories' to display only the listed warnings. +opt_warning_types=all + + +## -------------------- ## +## Resource management. ## +## -------------------- ## + +# This section contains definitions for functions that each ensure a +# particular resource (a file, or a non-empty configuration variable for +# example) is available, and if appropriate to extract default values +# from pertinent package files. Call them using their associated +# 'require_*' variable to ensure that they are executed, at most, once. +# +# It's entirely deliberate that calling these functions can set +# variables that don't obey the namespace limitations obeyed by the rest +# of this file, in order that that they be as useful as possible to +# callers. + + +# require_term_colors +# ------------------- +# Allow display of bold text on terminals that support it. +require_term_colors=func_require_term_colors +func_require_term_colors () +{ + $debug_cmd + + test -t 1 && { + # COLORTERM and USE_ANSI_COLORS environment variables take + # precedence, because most terminfo databases neglect to describe + # whether color sequences are supported. + test -n "${COLORTERM+set}" && : ${USE_ANSI_COLORS="1"} + + if test 1 = "$USE_ANSI_COLORS"; then + # Standard ANSI escape sequences + tc_reset='' + tc_bold=''; tc_standout='' + tc_red=''; tc_green='' + tc_blue=''; tc_cyan='' + else + # Otherwise trust the terminfo database after all. + test -n "`tput sgr0 2>/dev/null`" && { + tc_reset=`tput sgr0` + test -n "`tput bold 2>/dev/null`" && tc_bold=`tput bold` + tc_standout=$tc_bold + test -n "`tput smso 2>/dev/null`" && tc_standout=`tput smso` + test -n "`tput setaf 1 2>/dev/null`" && tc_red=`tput setaf 1` + test -n "`tput setaf 2 2>/dev/null`" && tc_green=`tput setaf 2` + test -n "`tput setaf 4 2>/dev/null`" && tc_blue=`tput setaf 4` + test -n "`tput setaf 5 2>/dev/null`" && tc_cyan=`tput setaf 5` + } + fi + } + + require_term_colors=: +} + + +## ----------------- ## +## Function library. ## +## ----------------- ## + +# This section contains a variety of useful functions to call in your +# scripts. Take note of the portable wrappers for features provided by +# some modern shells, which will fall back to slower equivalents on +# less featureful shells. + + +# func_append VAR VALUE +# --------------------- +# Append VALUE onto the existing contents of VAR. + + # We should try to minimise forks, especially on Windows where they are + # unreasonably slow, so skip the feature probes when bash or zsh are + # being used: + if test set = "${BASH_VERSION+set}${ZSH_VERSION+set}"; then + : ${_G_HAVE_ARITH_OP="yes"} + : ${_G_HAVE_XSI_OPS="yes"} + # The += operator was introduced in bash 3.1 + case $BASH_VERSION in + [12].* | 3.0 | 3.0*) ;; + *) + : ${_G_HAVE_PLUSEQ_OP="yes"} + ;; + esac + fi + + # _G_HAVE_PLUSEQ_OP + # Can be empty, in which case the shell is probed, "yes" if += is + # useable or anything else if it does not work. + test -z "$_G_HAVE_PLUSEQ_OP" \ + && (eval 'x=a; x+=" b"; test "a b" = "$x"') 2>/dev/null \ + && _G_HAVE_PLUSEQ_OP=yes + +if test yes = "$_G_HAVE_PLUSEQ_OP" +then + # This is an XSI compatible shell, allowing a faster implementation... + eval 'func_append () + { + $debug_cmd + + eval "$1+=\$2" + }' +else + # ...otherwise fall back to using expr, which is often a shell builtin. + func_append () + { + $debug_cmd + + eval "$1=\$$1\$2" + } +fi + + +# func_append_quoted VAR VALUE +# ---------------------------- +# Quote VALUE and append to the end of shell variable VAR, separated +# by a space. +if test yes = "$_G_HAVE_PLUSEQ_OP"; then + eval 'func_append_quoted () + { + $debug_cmd + + func_quote_arg pretty "$2" + eval "$1+=\\ \$func_quote_arg_result" + }' +else + func_append_quoted () + { + $debug_cmd + + func_quote_arg pretty "$2" + eval "$1=\$$1\\ \$func_quote_arg_result" + } +fi + + +# func_append_uniq VAR VALUE +# -------------------------- +# Append unique VALUE onto the existing contents of VAR, assuming +# entries are delimited by the first character of VALUE. For example: +# +# func_append_uniq options " --another-option option-argument" +# +# will only append to $options if " --another-option option-argument " +# is not already present somewhere in $options already (note spaces at +# each end implied by leading space in second argument). +func_append_uniq () +{ + $debug_cmd + + eval _G_current_value='`$ECHO $'$1'`' + _G_delim=`expr "$2" : '\(.\)'` + + case $_G_delim$_G_current_value$_G_delim in + *"$2$_G_delim"*) ;; + *) func_append "$@" ;; + esac +} + + +# func_arith TERM... +# ------------------ +# Set func_arith_result to the result of evaluating TERMs. + test -z "$_G_HAVE_ARITH_OP" \ + && (eval 'test 2 = $(( 1 + 1 ))') 2>/dev/null \ + && _G_HAVE_ARITH_OP=yes + +if test yes = "$_G_HAVE_ARITH_OP"; then + eval 'func_arith () + { + $debug_cmd + + func_arith_result=$(( $* )) + }' +else + func_arith () + { + $debug_cmd + + func_arith_result=`expr "$@"` + } +fi + + +# func_basename FILE +# ------------------ +# Set func_basename_result to FILE with everything up to and including +# the last / stripped. +if test yes = "$_G_HAVE_XSI_OPS"; then + # If this shell supports suffix pattern removal, then use it to avoid + # forking. Hide the definitions single quotes in case the shell chokes + # on unsupported syntax... + _b='func_basename_result=${1##*/}' + _d='case $1 in + */*) func_dirname_result=${1%/*}$2 ;; + * ) func_dirname_result=$3 ;; + esac' + +else + # ...otherwise fall back to using sed. + _b='func_basename_result=`$ECHO "$1" |$SED "$sed_basename"`' + _d='func_dirname_result=`$ECHO "$1" |$SED "$sed_dirname"` + if test "X$func_dirname_result" = "X$1"; then + func_dirname_result=$3 + else + func_append func_dirname_result "$2" + fi' +fi + +eval 'func_basename () +{ + $debug_cmd + + '"$_b"' +}' + + +# func_dirname FILE APPEND NONDIR_REPLACEMENT +# ------------------------------------------- +# Compute the dirname of FILE. If nonempty, add APPEND to the result, +# otherwise set result to NONDIR_REPLACEMENT. +eval 'func_dirname () +{ + $debug_cmd + + '"$_d"' +}' + + +# func_dirname_and_basename FILE APPEND NONDIR_REPLACEMENT +# -------------------------------------------------------- +# Perform func_basename and func_dirname in a single function +# call: +# dirname: Compute the dirname of FILE. If nonempty, +# add APPEND to the result, otherwise set result +# to NONDIR_REPLACEMENT. +# value returned in "$func_dirname_result" +# basename: Compute filename of FILE. +# value retuned in "$func_basename_result" +# For efficiency, we do not delegate to the functions above but instead +# duplicate the functionality here. +eval 'func_dirname_and_basename () +{ + $debug_cmd + + '"$_b"' + '"$_d"' +}' + + +# func_echo ARG... +# ---------------- +# Echo program name prefixed message. +func_echo () +{ + $debug_cmd + + _G_message=$* + + func_echo_IFS=$IFS + IFS=$nl + for _G_line in $_G_message; do + IFS=$func_echo_IFS + $ECHO "$progname: $_G_line" + done + IFS=$func_echo_IFS +} + + +# func_echo_all ARG... +# -------------------- +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "$*" +} + + +# func_echo_infix_1 INFIX ARG... +# ------------------------------ +# Echo program name, followed by INFIX on the first line, with any +# additional lines not showing INFIX. +func_echo_infix_1 () +{ + $debug_cmd + + $require_term_colors + + _G_infix=$1; shift + _G_indent=$_G_infix + _G_prefix="$progname: $_G_infix: " + _G_message=$* + + # Strip color escape sequences before counting printable length + for _G_tc in "$tc_reset" "$tc_bold" "$tc_standout" "$tc_red" "$tc_green" "$tc_blue" "$tc_cyan" + do + test -n "$_G_tc" && { + _G_esc_tc=`$ECHO "$_G_tc" | $SED "$sed_make_literal_regex"` + _G_indent=`$ECHO "$_G_indent" | $SED "s|$_G_esc_tc||g"` + } + done + _G_indent="$progname: "`echo "$_G_indent" | $SED 's|.| |g'`" " ## exclude from sc_prohibit_nested_quotes + + func_echo_infix_1_IFS=$IFS + IFS=$nl + for _G_line in $_G_message; do + IFS=$func_echo_infix_1_IFS + $ECHO "$_G_prefix$tc_bold$_G_line$tc_reset" >&2 + _G_prefix=$_G_indent + done + IFS=$func_echo_infix_1_IFS +} + + +# func_error ARG... +# ----------------- +# Echo program name prefixed message to standard error. +func_error () +{ + $debug_cmd + + $require_term_colors + + func_echo_infix_1 " $tc_standout${tc_red}error$tc_reset" "$*" >&2 +} + + +# func_fatal_error ARG... +# ----------------------- +# Echo program name prefixed message to standard error, and exit. +func_fatal_error () +{ + $debug_cmd + + func_error "$*" + exit $EXIT_FAILURE +} + + +# func_grep EXPRESSION FILENAME +# ----------------------------- +# Check whether EXPRESSION matches any line of FILENAME, without output. +func_grep () +{ + $debug_cmd + + $GREP "$1" "$2" >/dev/null 2>&1 +} + + +# func_len STRING +# --------------- +# Set func_len_result to the length of STRING. STRING may not +# start with a hyphen. + test -z "$_G_HAVE_XSI_OPS" \ + && (eval 'x=a/b/c; + test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ + && _G_HAVE_XSI_OPS=yes + +if test yes = "$_G_HAVE_XSI_OPS"; then + eval 'func_len () + { + $debug_cmd + + func_len_result=${#1} + }' +else + func_len () + { + $debug_cmd + + func_len_result=`expr "$1" : ".*" 2>/dev/null || echo $max_cmd_len` + } +fi + + +# func_mkdir_p DIRECTORY-PATH +# --------------------------- +# Make sure the entire path to DIRECTORY-PATH is available. +func_mkdir_p () +{ + $debug_cmd + + _G_directory_path=$1 + _G_dir_list= + + if test -n "$_G_directory_path" && test : != "$opt_dry_run"; then + + # Protect directory names starting with '-' + case $_G_directory_path in + -*) _G_directory_path=./$_G_directory_path ;; + esac + + # While some portion of DIR does not yet exist... + while test ! -d "$_G_directory_path"; do + # ...make a list in topmost first order. Use a colon delimited + # list incase some portion of path contains whitespace. + _G_dir_list=$_G_directory_path:$_G_dir_list + + # If the last portion added has no slash in it, the list is done + case $_G_directory_path in */*) ;; *) break ;; esac + + # ...otherwise throw away the child directory and loop + _G_directory_path=`$ECHO "$_G_directory_path" | $SED -e "$sed_dirname"` + done + _G_dir_list=`$ECHO "$_G_dir_list" | $SED 's|:*$||'` + + func_mkdir_p_IFS=$IFS; IFS=: + for _G_dir in $_G_dir_list; do + IFS=$func_mkdir_p_IFS + # mkdir can fail with a 'File exist' error if two processes + # try to create one of the directories concurrently. Don't + # stop in that case! + $MKDIR "$_G_dir" 2>/dev/null || : + done + IFS=$func_mkdir_p_IFS + + # Bail out if we (or some other process) failed to create a directory. + test -d "$_G_directory_path" || \ + func_fatal_error "Failed to create '$1'" + fi +} + + +# func_mktempdir [BASENAME] +# ------------------------- +# Make a temporary directory that won't clash with other running +# libtool processes, and avoids race conditions if possible. If +# given, BASENAME is the basename for that directory. +func_mktempdir () +{ + $debug_cmd + + _G_template=${TMPDIR-/tmp}/${1-$progname} + + if test : = "$opt_dry_run"; then + # Return a directory name, but don't create it in dry-run mode + _G_tmpdir=$_G_template-$$ + else + + # If mktemp works, use that first and foremost + _G_tmpdir=`mktemp -d "$_G_template-XXXXXXXX" 2>/dev/null` + + if test ! -d "$_G_tmpdir"; then + # Failing that, at least try and use $RANDOM to avoid a race + _G_tmpdir=$_G_template-${RANDOM-0}$$ + + func_mktempdir_umask=`umask` + umask 0077 + $MKDIR "$_G_tmpdir" + umask $func_mktempdir_umask + fi + + # If we're not in dry-run mode, bomb out on failure + test -d "$_G_tmpdir" || \ + func_fatal_error "cannot create temporary directory '$_G_tmpdir'" + fi + + $ECHO "$_G_tmpdir" +} + + +# func_normal_abspath PATH +# ------------------------ +# Remove doubled-up and trailing slashes, "." path components, +# and cancel out any ".." path components in PATH after making +# it an absolute path. +func_normal_abspath () +{ + $debug_cmd + + # These SED scripts presuppose an absolute path with a trailing slash. + _G_pathcar='s|^/\([^/]*\).*$|\1|' + _G_pathcdr='s|^/[^/]*||' + _G_removedotparts=':dotsl + s|/\./|/|g + t dotsl + s|/\.$|/|' + _G_collapseslashes='s|/\{1,\}|/|g' + _G_finalslash='s|/*$|/|' + + # Start from root dir and reassemble the path. + func_normal_abspath_result= + func_normal_abspath_tpath=$1 + func_normal_abspath_altnamespace= + case $func_normal_abspath_tpath in + "") + # Empty path, that just means $cwd. + func_stripname '' '/' "`pwd`" + func_normal_abspath_result=$func_stripname_result + return + ;; + # The next three entries are used to spot a run of precisely + # two leading slashes without using negated character classes; + # we take advantage of case's first-match behaviour. + ///*) + # Unusual form of absolute path, do nothing. + ;; + //*) + # Not necessarily an ordinary path; POSIX reserves leading '//' + # and for example Cygwin uses it to access remote file shares + # over CIFS/SMB, so we conserve a leading double slash if found. + func_normal_abspath_altnamespace=/ + ;; + /*) + # Absolute path, do nothing. + ;; + *) + # Relative path, prepend $cwd. + func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath + ;; + esac + + # Cancel out all the simple stuff to save iterations. We also want + # the path to end with a slash for ease of parsing, so make sure + # there is one (and only one) here. + func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$_G_removedotparts" -e "$_G_collapseslashes" -e "$_G_finalslash"` + while :; do + # Processed it all yet? + if test / = "$func_normal_abspath_tpath"; then + # If we ascended to the root using ".." the result may be empty now. + if test -z "$func_normal_abspath_result"; then + func_normal_abspath_result=/ + fi + break + fi + func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$_G_pathcar"` + func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$_G_pathcdr"` + # Figure out what to do with it + case $func_normal_abspath_tcomponent in + "") + # Trailing empty path component, ignore it. + ;; + ..) + # Parent dir; strip last assembled component from result. + func_dirname "$func_normal_abspath_result" + func_normal_abspath_result=$func_dirname_result + ;; + *) + # Actual path component, append it. + func_append func_normal_abspath_result "/$func_normal_abspath_tcomponent" + ;; + esac + done + # Restore leading double-slash if one was found on entry. + func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result +} + + +# func_notquiet ARG... +# -------------------- +# Echo program name prefixed message only when not in quiet mode. +func_notquiet () +{ + $debug_cmd + + $opt_quiet || func_echo ${1+"$@"} + + # A bug in bash halts the script if the last line of a function + # fails when set -e is in force, so we need another command to + # work around that: + : +} + + +# func_relative_path SRCDIR DSTDIR +# -------------------------------- +# Set func_relative_path_result to the relative path from SRCDIR to DSTDIR. +func_relative_path () +{ + $debug_cmd + + func_relative_path_result= + func_normal_abspath "$1" + func_relative_path_tlibdir=$func_normal_abspath_result + func_normal_abspath "$2" + func_relative_path_tbindir=$func_normal_abspath_result + + # Ascend the tree starting from libdir + while :; do + # check if we have found a prefix of bindir + case $func_relative_path_tbindir in + $func_relative_path_tlibdir) + # found an exact match + func_relative_path_tcancelled= + break + ;; + $func_relative_path_tlibdir*) + # found a matching prefix + func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir" + func_relative_path_tcancelled=$func_stripname_result + if test -z "$func_relative_path_result"; then + func_relative_path_result=. + fi + break + ;; + *) + func_dirname $func_relative_path_tlibdir + func_relative_path_tlibdir=$func_dirname_result + if test -z "$func_relative_path_tlibdir"; then + # Have to descend all the way to the root! + func_relative_path_result=../$func_relative_path_result + func_relative_path_tcancelled=$func_relative_path_tbindir + break + fi + func_relative_path_result=../$func_relative_path_result + ;; + esac + done + + # Now calculate path; take care to avoid doubling-up slashes. + func_stripname '' '/' "$func_relative_path_result" + func_relative_path_result=$func_stripname_result + func_stripname '/' '/' "$func_relative_path_tcancelled" + if test -n "$func_stripname_result"; then + func_append func_relative_path_result "/$func_stripname_result" + fi + + # Normalisation. If bindir is libdir, return '.' else relative path. + if test -n "$func_relative_path_result"; then + func_stripname './' '' "$func_relative_path_result" + func_relative_path_result=$func_stripname_result + fi + + test -n "$func_relative_path_result" || func_relative_path_result=. + + : +} + + +# func_quote_portable EVAL ARG +# ---------------------------- +# Internal function to portably implement func_quote_arg. Note that we still +# keep attention to performance here so we as much as possible try to avoid +# calling sed binary (so far O(N) complexity as long as func_append is O(1)). +func_quote_portable () +{ + $debug_cmd + + func_quote_portable_result=$2 + + # one-time-loop (easy break) + while true + do + if $1; then + func_quote_portable_result=`$ECHO "$2" | $SED \ + -e "$sed_double_quote_subst" -e "$sed_double_backslash"` + break + fi + + # Quote for eval. + case $func_quote_portable_result in + *[\\\`\"\$]*) + case $func_quote_portable_result in + *[\[\*\?]*) + func_quote_portable_result=`$ECHO "$func_quote_portable_result" | $SED "$sed_quote_subst"` + break + ;; + esac + + func_quote_portable_old_IFS=$IFS + for _G_char in '\' '`' '"' '$' + do + # STATE($1) PREV($2) SEPARATOR($3) + set start "" "" + func_quote_portable_result=dummy"$_G_char$func_quote_portable_result$_G_char"dummy + IFS=$_G_char + for _G_part in $func_quote_portable_result + do + case $1 in + quote) + func_append func_quote_portable_result "$3$2" + set quote "$_G_part" "\\$_G_char" + ;; + start) + set first "" "" + func_quote_portable_result= + ;; + first) + set quote "$_G_part" "" + ;; + esac + done + done + IFS=$func_quote_portable_old_IFS + ;; + *) ;; + esac + break + done + + func_quote_portable_unquoted_result=$func_quote_portable_result + case $func_quote_portable_result in + # double-quote args containing shell metacharacters to delay + # word splitting, command substitution and variable expansion + # for a subsequent eval. + # many bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + func_quote_portable_result=\"$func_quote_portable_result\" + ;; + esac +} + + +# func_quotefast_eval ARG +# ----------------------- +# Quote one ARG (internal). This is equivalent to 'func_quote_arg eval ARG', +# but optimized for speed. Result is stored in $func_quotefast_eval. +if test xyes = `(x=; printf -v x %q yes; echo x"$x") 2>/dev/null`; then + func_quotefast_eval () + { + printf -v func_quotefast_eval_result %q "$1" + } +else + func_quotefast_eval () + { + func_quote_portable false "$1" + func_quotefast_eval_result=$func_quote_portable_result + } +fi + + +# func_quote_arg MODEs ARG +# ------------------------ +# Quote one ARG to be evaled later. MODEs argument may contain zero ore more +# specifiers listed below separated by ',' character. This function returns two +# values: +# i) func_quote_arg_result +# double-quoted (when needed), suitable for a subsequent eval +# ii) func_quote_arg_unquoted_result +# has all characters that are still active within double +# quotes backslashified. Available only if 'unquoted' is specified. +# +# Available modes: +# ---------------- +# 'eval' (default) +# - escape shell special characters +# 'expand' +# - the same as 'eval'; but do not quote variable references +# 'pretty' +# - request aesthetic output, i.e. '"a b"' instead of 'a\ b'. This might +# later used in func_quote to get output like: 'echo "a b"' instead of +# 'echo a\ b'. This is slower than default on some shells. +# 'unquoted' +# - produce also $func_quote_arg_unquoted_result which does not contain +# wrapping double-quotes. +# +# Examples for 'func_quote_arg pretty,unquoted string': +# +# string | *_result | *_unquoted_result +# ------------+-----------------------+------------------- +# " | \" | \" +# a b | "a b" | a b +# "a b" | "\"a b\"" | \"a b\" +# * | "*" | * +# z="${x-$y}" | "z=\"\${x-\$y}\"" | z=\"\${x-\$y}\" +# +# Examples for 'func_quote_arg pretty,unquoted,expand string': +# +# string | *_result | *_unquoted_result +# --------------+---------------------+-------------------- +# z="${x-$y}" | "z=\"${x-$y}\"" | z=\"${x-$y}\" +func_quote_arg () +{ + _G_quote_expand=false + case ,$1, in + *,expand,*) + _G_quote_expand=: + ;; + esac + + case ,$1, in + *,pretty,*|*,expand,*|*,unquoted,*) + func_quote_portable $_G_quote_expand "$2" + func_quote_arg_result=$func_quote_portable_result + func_quote_arg_unquoted_result=$func_quote_portable_unquoted_result + ;; + *) + # Faster quote-for-eval for some shells. + func_quotefast_eval "$2" + func_quote_arg_result=$func_quotefast_eval_result + ;; + esac +} + + +# func_quote MODEs ARGs... +# ------------------------ +# Quote all ARGs to be evaled later and join them into single command. See +# func_quote_arg's description for more info. +func_quote () +{ + $debug_cmd + _G_func_quote_mode=$1 ; shift + func_quote_result= + while test 0 -lt $#; do + func_quote_arg "$_G_func_quote_mode" "$1" + if test -n "$func_quote_result"; then + func_append func_quote_result " $func_quote_arg_result" + else + func_append func_quote_result "$func_quote_arg_result" + fi + shift + done +} + + +# func_stripname PREFIX SUFFIX NAME +# --------------------------------- +# strip PREFIX and SUFFIX from NAME, and store in func_stripname_result. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +if test yes = "$_G_HAVE_XSI_OPS"; then + eval 'func_stripname () + { + $debug_cmd + + # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are + # positional parameters, so assign one to ordinary variable first. + func_stripname_result=$3 + func_stripname_result=${func_stripname_result#"$1"} + func_stripname_result=${func_stripname_result%"$2"} + }' +else + func_stripname () + { + $debug_cmd + + case $2 in + .*) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%\\\\$2\$%%"`;; + *) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%$2\$%%"`;; + esac + } +fi + + +# func_show_eval CMD [FAIL_EXP] +# ----------------------------- +# Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. +func_show_eval () +{ + $debug_cmd + + _G_cmd=$1 + _G_fail_exp=${2-':'} + + func_quote_arg pretty,expand "$_G_cmd" + eval "func_notquiet $func_quote_arg_result" + + $opt_dry_run || { + eval "$_G_cmd" + _G_status=$? + if test 0 -ne "$_G_status"; then + eval "(exit $_G_status); $_G_fail_exp" + fi + } +} + + +# func_show_eval_locale CMD [FAIL_EXP] +# ------------------------------------ +# Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. Use the saved locale for evaluation. +func_show_eval_locale () +{ + $debug_cmd + + _G_cmd=$1 + _G_fail_exp=${2-':'} + + $opt_quiet || { + func_quote_arg expand,pretty "$_G_cmd" + eval "func_echo $func_quote_arg_result" + } + + $opt_dry_run || { + eval "$_G_user_locale + $_G_cmd" + _G_status=$? + eval "$_G_safe_locale" + if test 0 -ne "$_G_status"; then + eval "(exit $_G_status); $_G_fail_exp" + fi + } +} + + +# func_tr_sh +# ---------- +# Turn $1 into a string suitable for a shell variable name. +# Result is stored in $func_tr_sh_result. All characters +# not in the set a-zA-Z0-9_ are replaced with '_'. Further, +# if $1 begins with a digit, a '_' is prepended as well. +func_tr_sh () +{ + $debug_cmd + + case $1 in + [0-9]* | *[!a-zA-Z0-9_]*) + func_tr_sh_result=`$ECHO "$1" | $SED -e 's/^\([0-9]\)/_\1/' -e 's/[^a-zA-Z0-9_]/_/g'` + ;; + * ) + func_tr_sh_result=$1 + ;; + esac +} + + +# func_verbose ARG... +# ------------------- +# Echo program name prefixed message in verbose mode only. +func_verbose () +{ + $debug_cmd + + $opt_verbose && func_echo "$*" + + : +} + + +# func_warn_and_continue ARG... +# ----------------------------- +# Echo program name prefixed warning message to standard error. +func_warn_and_continue () +{ + $debug_cmd + + $require_term_colors + + func_echo_infix_1 "${tc_red}warning$tc_reset" "$*" >&2 +} + + +# func_warning CATEGORY ARG... +# ---------------------------- +# Echo program name prefixed warning message to standard error. Warning +# messages can be filtered according to CATEGORY, where this function +# elides messages where CATEGORY is not listed in the global variable +# 'opt_warning_types'. +func_warning () +{ + $debug_cmd + + # CATEGORY must be in the warning_categories list! + case " $warning_categories " in + *" $1 "*) ;; + *) func_internal_error "invalid warning category '$1'" ;; + esac + + _G_category=$1 + shift + + case " $opt_warning_types " in + *" $_G_category "*) $warning_func ${1+"$@"} ;; + esac +} + + +# func_sort_ver VER1 VER2 +# ----------------------- +# 'sort -V' is not generally available. +# Note this deviates from the version comparison in automake +# in that it treats 1.5 < 1.5.0, and treats 1.4.4a < 1.4-p3a +# but this should suffice as we won't be specifying old +# version formats or redundant trailing .0 in bootstrap.conf. +# If we did want full compatibility then we should probably +# use m4_version_compare from autoconf. +func_sort_ver () +{ + $debug_cmd + + printf '%s\n%s\n' "$1" "$2" \ + | sort -t. -k 1,1n -k 2,2n -k 3,3n -k 4,4n -k 5,5n -k 6,6n -k 7,7n -k 8,8n -k 9,9n +} + +# func_lt_ver PREV CURR +# --------------------- +# Return true if PREV and CURR are in the correct order according to +# func_sort_ver, otherwise false. Use it like this: +# +# func_lt_ver "$prev_ver" "$proposed_ver" || func_fatal_error "..." +func_lt_ver () +{ + $debug_cmd + + test "x$1" = x`func_sort_ver "$1" "$2" | $SED 1q` +} + + +# Local variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC" +# time-stamp-time-zone: "UTC" +# End: +#! /bin/sh + +# Set a version string for this script. +scriptversion=2015-10-12.13; # UTC + +# A portable, pluggable option parser for Bourne shell. +# Written by Gary V. Vaughan, 2010 + +# Copyright (C) 2010-2015 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. + +# 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 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 . + +# Please report bugs or propose patches to gary@gnu.org. + + +## ------ ## +## Usage. ## +## ------ ## + +# This file is a library for parsing options in your shell scripts along +# with assorted other useful supporting features that you can make use +# of too. +# +# For the simplest scripts you might need only: +# +# #!/bin/sh +# . relative/path/to/funclib.sh +# . relative/path/to/options-parser +# scriptversion=1.0 +# func_options ${1+"$@"} +# eval set dummy "$func_options_result"; shift +# ...rest of your script... +# +# In order for the '--version' option to work, you will need to have a +# suitably formatted comment like the one at the top of this file +# starting with '# Written by ' and ending with '# warranty; '. +# +# For '-h' and '--help' to work, you will also need a one line +# description of your script's purpose in a comment directly above the +# '# Written by ' line, like the one at the top of this file. +# +# The default options also support '--debug', which will turn on shell +# execution tracing (see the comment above debug_cmd below for another +# use), and '--verbose' and the func_verbose function to allow your script +# to display verbose messages only when your user has specified +# '--verbose'. +# +# After sourcing this file, you can plug processing for additional +# options by amending the variables from the 'Configuration' section +# below, and following the instructions in the 'Option parsing' +# section further down. + +## -------------- ## +## Configuration. ## +## -------------- ## + +# You should override these variables in your script after sourcing this +# file so that they reflect the customisations you have added to the +# option parser. + +# The usage line for option parsing errors and the start of '-h' and +# '--help' output messages. You can embed shell variables for delayed +# expansion at the time the message is displayed, but you will need to +# quote other shell meta-characters carefully to prevent them being +# expanded when the contents are evaled. +usage='$progpath [OPTION]...' + +# Short help message in response to '-h' and '--help'. Add to this or +# override it after sourcing this library to reflect the full set of +# options your script accepts. +usage_message="\ + --debug enable verbose shell tracing + -W, --warnings=CATEGORY + report the warnings falling in CATEGORY [all] + -v, --verbose verbosely report processing + --version print version information and exit + -h, --help print short or long help message and exit +" + +# Additional text appended to 'usage_message' in response to '--help'. +long_help_message=" +Warning categories include: + 'all' show all warnings + 'none' turn off all the warnings + 'error' warnings are treated as fatal errors" + +# Help message printed before fatal option parsing errors. +fatal_help="Try '\$progname --help' for more information." + + + +## ------------------------- ## +## Hook function management. ## +## ------------------------- ## + +# This section contains functions for adding, removing, and running hooks +# to the main code. A hook is just a named list of of function, that can +# be run in order later on. + +# func_hookable FUNC_NAME +# ----------------------- +# Declare that FUNC_NAME will run hooks added with +# 'func_add_hook FUNC_NAME ...'. +func_hookable () +{ + $debug_cmd + + func_append hookable_fns " $1" +} + + +# func_add_hook FUNC_NAME HOOK_FUNC +# --------------------------------- +# Request that FUNC_NAME call HOOK_FUNC before it returns. FUNC_NAME must +# first have been declared "hookable" by a call to 'func_hookable'. +func_add_hook () +{ + $debug_cmd + + case " $hookable_fns " in + *" $1 "*) ;; + *) func_fatal_error "'$1' does not accept hook functions." ;; + esac + + eval func_append ${1}_hooks '" $2"' +} + + +# func_remove_hook FUNC_NAME HOOK_FUNC +# ------------------------------------ +# Remove HOOK_FUNC from the list of functions called by FUNC_NAME. +func_remove_hook () +{ + $debug_cmd + + eval ${1}_hooks='`$ECHO "\$'$1'_hooks" |$SED "s| '$2'||"`' +} + + +# func_run_hooks FUNC_NAME [ARG]... +# --------------------------------- +# Run all hook functions registered to FUNC_NAME. +# It is assumed that the list of hook functions contains nothing more +# than a whitespace-delimited list of legal shell function names, and +# no effort is wasted trying to catch shell meta-characters or preserve +# whitespace. +func_run_hooks () +{ + $debug_cmd + + _G_rc_run_hooks=false + + case " $hookable_fns " in + *" $1 "*) ;; + *) func_fatal_error "'$1' does not support hook funcions.n" ;; + esac + + eval _G_hook_fns=\$$1_hooks; shift + + for _G_hook in $_G_hook_fns; do + if eval $_G_hook '"$@"'; then + # store returned options list back into positional + # parameters for next 'cmd' execution. + eval _G_hook_result=\$${_G_hook}_result + eval set dummy "$_G_hook_result"; shift + _G_rc_run_hooks=: + fi + done + + $_G_rc_run_hooks && func_run_hooks_result=$_G_hook_result +} + + + +## --------------- ## +## Option parsing. ## +## --------------- ## + +# In order to add your own option parsing hooks, you must accept the +# full positional parameter list in your hook function, you may remove/edit +# any options that you action, and then pass back the remaining unprocessed +# options in '_result', escaped suitably for +# 'eval'. In this case you also must return $EXIT_SUCCESS to let the +# hook's caller know that it should pay attention to +# '_result'. Returning $EXIT_FAILURE signalizes that +# arguments are left untouched by the hook and therefore caller will ignore the +# result variable. +# +# Like this: +# +# my_options_prep () +# { +# $debug_cmd +# +# # Extend the existing usage message. +# usage_message=$usage_message' +# -s, --silent don'\''t print informational messages +# ' +# # No change in '$@' (ignored completely by this hook). There is +# # no need to do the equivalent (but slower) action: +# # func_quote eval ${1+"$@"} +# # my_options_prep_result=$func_quote_result +# false +# } +# func_add_hook func_options_prep my_options_prep +# +# +# my_silent_option () +# { +# $debug_cmd +# +# args_changed=false +# +# # Note that for efficiency, we parse as many options as we can +# # recognise in a loop before passing the remainder back to the +# # caller on the first unrecognised argument we encounter. +# while test $# -gt 0; do +# opt=$1; shift +# case $opt in +# --silent|-s) opt_silent=: +# args_changed=: +# ;; +# # Separate non-argument short options: +# -s*) func_split_short_opt "$_G_opt" +# set dummy "$func_split_short_opt_name" \ +# "-$func_split_short_opt_arg" ${1+"$@"} +# shift +# args_changed=: +# ;; +# *) # Make sure the first unrecognised option "$_G_opt" +# # is added back to "$@", we could need that later +# # if $args_changed is true. +# set dummy "$_G_opt" ${1+"$@"}; shift; break ;; +# esac +# done +# +# if $args_changed; then +# func_quote eval ${1+"$@"} +# my_silent_option_result=$func_quote_result +# fi +# +# $args_changed +# } +# func_add_hook func_parse_options my_silent_option +# +# +# my_option_validation () +# { +# $debug_cmd +# +# $opt_silent && $opt_verbose && func_fatal_help "\ +# '--silent' and '--verbose' options are mutually exclusive." +# +# false +# } +# func_add_hook func_validate_options my_option_validation +# +# You'll also need to manually amend $usage_message to reflect the extra +# options you parse. It's preferable to append if you can, so that +# multiple option parsing hooks can be added safely. + + +# func_options_finish [ARG]... +# ---------------------------- +# Finishing the option parse loop (call 'func_options' hooks ATM). +func_options_finish () +{ + $debug_cmd + + _G_func_options_finish_exit=false + if func_run_hooks func_options ${1+"$@"}; then + func_options_finish_result=$func_run_hooks_result + _G_func_options_finish_exit=: + fi + + $_G_func_options_finish_exit +} + + +# func_options [ARG]... +# --------------------- +# All the functions called inside func_options are hookable. See the +# individual implementations for details. +func_hookable func_options +func_options () +{ + $debug_cmd + + _G_rc_options=false + + for my_func in options_prep parse_options validate_options options_finish + do + if eval func_$my_func '${1+"$@"}'; then + eval _G_res_var='$'"func_${my_func}_result" + eval set dummy "$_G_res_var" ; shift + _G_rc_options=: + fi + done + + # Save modified positional parameters for caller. As a top-level + # options-parser function we always need to set the 'func_options_result' + # variable (regardless the $_G_rc_options value). + if $_G_rc_options; then + func_options_result=$_G_res_var + else + func_quote eval ${1+"$@"} + func_options_result=$func_quote_result + fi + + $_G_rc_options +} + + +# func_options_prep [ARG]... +# -------------------------- +# All initialisations required before starting the option parse loop. +# Note that when calling hook functions, we pass through the list of +# positional parameters. If a hook function modifies that list, and +# needs to propagate that back to rest of this script, then the complete +# modified list must be put in 'func_run_hooks_result' before +# returning $EXIT_SUCCESS (otherwise $EXIT_FAILURE is returned). +func_hookable func_options_prep +func_options_prep () +{ + $debug_cmd + + # Option defaults: + opt_verbose=false + opt_warning_types= + + _G_rc_options_prep=false + if func_run_hooks func_options_prep ${1+"$@"}; then + _G_rc_options_prep=: + # save modified positional parameters for caller + func_options_prep_result=$func_run_hooks_result + fi + + $_G_rc_options_prep +} + + +# func_parse_options [ARG]... +# --------------------------- +# The main option parsing loop. +func_hookable func_parse_options +func_parse_options () +{ + $debug_cmd + + func_parse_options_result= + + _G_rc_parse_options=false + # this just eases exit handling + while test $# -gt 0; do + # Defer to hook functions for initial option parsing, so they + # get priority in the event of reusing an option name. + if func_run_hooks func_parse_options ${1+"$@"}; then + eval set dummy "$func_run_hooks_result"; shift + _G_rc_parse_options=: + fi + + # Break out of the loop if we already parsed every option. + test $# -gt 0 || break + + _G_match_parse_options=: + _G_opt=$1 + shift + case $_G_opt in + --debug|-x) debug_cmd='set -x' + func_echo "enabling shell trace mode" + $debug_cmd + ;; + + --no-warnings|--no-warning|--no-warn) + set dummy --warnings none ${1+"$@"} + shift + ;; + + --warnings|--warning|-W) + if test $# = 0 && func_missing_arg $_G_opt; then + _G_rc_parse_options=: + break + fi + case " $warning_categories $1" in + *" $1 "*) + # trailing space prevents matching last $1 above + func_append_uniq opt_warning_types " $1" + ;; + *all) + opt_warning_types=$warning_categories + ;; + *none) + opt_warning_types=none + warning_func=: + ;; + *error) + opt_warning_types=$warning_categories + warning_func=func_fatal_error + ;; + *) + func_fatal_error \ + "unsupported warning category: '$1'" + ;; + esac + shift + ;; + + --verbose|-v) opt_verbose=: ;; + --version) func_version ;; + -\?|-h) func_usage ;; + --help) func_help ;; + + # Separate optargs to long options (plugins may need this): + --*=*) func_split_equals "$_G_opt" + set dummy "$func_split_equals_lhs" \ + "$func_split_equals_rhs" ${1+"$@"} + shift + ;; + + # Separate optargs to short options: + -W*) + func_split_short_opt "$_G_opt" + set dummy "$func_split_short_opt_name" \ + "$func_split_short_opt_arg" ${1+"$@"} + shift + ;; + + # Separate non-argument short options: + -\?*|-h*|-v*|-x*) + func_split_short_opt "$_G_opt" + set dummy "$func_split_short_opt_name" \ + "-$func_split_short_opt_arg" ${1+"$@"} + shift + ;; + + --) _G_rc_parse_options=: ; break ;; + -*) func_fatal_help "unrecognised option: '$_G_opt'" ;; + *) set dummy "$_G_opt" ${1+"$@"}; shift + _G_match_parse_options=false + break + ;; + esac + + $_G_match_parse_options && _G_rc_parse_options=: + done + + + if $_G_rc_parse_options; then + # save modified positional parameters for caller + func_quote eval ${1+"$@"} + func_parse_options_result=$func_quote_result + fi + + $_G_rc_parse_options +} + + +# func_validate_options [ARG]... +# ------------------------------ +# Perform any sanity checks on option settings and/or unconsumed +# arguments. +func_hookable func_validate_options +func_validate_options () +{ + $debug_cmd + + _G_rc_validate_options=false + + # Display all warnings if -W was not given. + test -n "$opt_warning_types" || opt_warning_types=" $warning_categories" + + if func_run_hooks func_validate_options ${1+"$@"}; then + # save modified positional parameters for caller + func_validate_options_result=$func_run_hooks_result + _G_rc_validate_options=: + fi + + # Bail if the options were screwed! + $exit_cmd $EXIT_FAILURE + + $_G_rc_validate_options +} + + + +## ----------------- ## +## Helper functions. ## +## ----------------- ## + +# This section contains the helper functions used by the rest of the +# hookable option parser framework in ascii-betical order. + + +# func_fatal_help ARG... +# ---------------------- +# Echo program name prefixed message to standard error, followed by +# a help hint, and exit. +func_fatal_help () +{ + $debug_cmd + + eval \$ECHO \""Usage: $usage"\" + eval \$ECHO \""$fatal_help"\" + func_error ${1+"$@"} + exit $EXIT_FAILURE +} + + +# func_help +# --------- +# Echo long help message to standard output and exit. +func_help () +{ + $debug_cmd + + func_usage_message + $ECHO "$long_help_message" + exit 0 +} + + +# func_missing_arg ARGNAME +# ------------------------ +# Echo program name prefixed message to standard error and set global +# exit_cmd. +func_missing_arg () +{ + $debug_cmd + + func_error "Missing argument for '$1'." + exit_cmd=exit +} + + +# func_split_equals STRING +# ------------------------ +# Set func_split_equals_lhs and func_split_equals_rhs shell variables after +# splitting STRING at the '=' sign. +test -z "$_G_HAVE_XSI_OPS" \ + && (eval 'x=a/b/c; + test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ + && _G_HAVE_XSI_OPS=yes + +if test yes = "$_G_HAVE_XSI_OPS" +then + # This is an XSI compatible shell, allowing a faster implementation... + eval 'func_split_equals () + { + $debug_cmd + + func_split_equals_lhs=${1%%=*} + func_split_equals_rhs=${1#*=} + test "x$func_split_equals_lhs" = "x$1" \ + && func_split_equals_rhs= + }' +else + # ...otherwise fall back to using expr, which is often a shell builtin. + func_split_equals () + { + $debug_cmd + + func_split_equals_lhs=`expr "x$1" : 'x\([^=]*\)'` + func_split_equals_rhs= + test "x$func_split_equals_lhs" = "x$1" \ + || func_split_equals_rhs=`expr "x$1" : 'x[^=]*=\(.*\)$'` + } +fi #func_split_equals + + +# func_split_short_opt SHORTOPT +# ----------------------------- +# Set func_split_short_opt_name and func_split_short_opt_arg shell +# variables after splitting SHORTOPT after the 2nd character. +if test yes = "$_G_HAVE_XSI_OPS" +then + # This is an XSI compatible shell, allowing a faster implementation... + eval 'func_split_short_opt () + { + $debug_cmd + + func_split_short_opt_arg=${1#??} + func_split_short_opt_name=${1%"$func_split_short_opt_arg"} + }' +else + # ...otherwise fall back to using expr, which is often a shell builtin. + func_split_short_opt () + { + $debug_cmd + + func_split_short_opt_name=`expr "x$1" : 'x-\(.\)'` + func_split_short_opt_arg=`expr "x$1" : 'x-.\(.*\)$'` + } +fi #func_split_short_opt + + +# func_usage +# ---------- +# Echo short help message to standard output and exit. +func_usage () +{ + $debug_cmd + + func_usage_message + $ECHO "Run '$progname --help |${PAGER-more}' for full usage" + exit 0 +} + + +# func_usage_message +# ------------------ +# Echo short help message to standard output. +func_usage_message () +{ + $debug_cmd + + eval \$ECHO \""Usage: $usage"\" + echo + $SED -n 's|^# || + /^Written by/{ + x;p;x + } + h + /^Written by/q' < "$progpath" + echo + eval \$ECHO \""$usage_message"\" +} + + +# func_version +# ------------ +# Echo version message to standard output and exit. +func_version () +{ + $debug_cmd + + printf '%s\n' "$progname $scriptversion" + $SED -n ' + /(C)/!b go + :more + /\./!{ + N + s|\n# | | + b more + } + :go + /^# Written by /,/# warranty; / { + s|^# || + s|^# *$|| + s|\((C)\)[ 0-9,-]*[ ,-]\([1-9][0-9]* \)|\1 \2| + p + } + /^# Written by / { + s|^# || + p + } + /^warranty; /q' < "$progpath" + + exit $? +} + + +# Local variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC" +# time-stamp-time-zone: "UTC" +# End: + +# Set a version string. +scriptversion='(GNU libtool) 2.4.6' + + +# func_echo ARG... +# ---------------- +# Libtool also displays the current mode in messages, so override +# funclib.sh func_echo with this custom definition. +func_echo () +{ + $debug_cmd + + _G_message=$* + + func_echo_IFS=$IFS + IFS=$nl + for _G_line in $_G_message; do + IFS=$func_echo_IFS + $ECHO "$progname${opt_mode+: $opt_mode}: $_G_line" + done + IFS=$func_echo_IFS +} + + +# func_warning ARG... +# ------------------- +# Libtool warnings are not categorized, so override funclib.sh +# func_warning with this simpler definition. +func_warning () +{ + $debug_cmd + + $warning_func ${1+"$@"} +} + + +## ---------------- ## +## Options parsing. ## +## ---------------- ## + +# Hook in the functions to make sure our own options are parsed during +# the option parsing loop. + +usage='$progpath [OPTION]... [MODE-ARG]...' + +# Short help message in response to '-h'. +usage_message="Options: + --config show all configuration variables + --debug enable verbose shell tracing + -n, --dry-run display commands without modifying any files + --features display basic configuration information and exit + --mode=MODE use operation mode MODE + --no-warnings equivalent to '-Wnone' + --preserve-dup-deps don't remove duplicate dependency libraries + --quiet, --silent don't print informational messages + --tag=TAG use configuration variables from tag TAG + -v, --verbose print more informational messages than default + --version print version information + -W, --warnings=CATEGORY report the warnings falling in CATEGORY [all] + -h, --help, --help-all print short, long, or detailed help message +" + +# Additional text appended to 'usage_message' in response to '--help'. +func_help () +{ + $debug_cmd + + func_usage_message + $ECHO "$long_help_message + +MODE must be one of the following: + + clean remove files from the build directory + compile compile a source file into a libtool object + execute automatically set library path, then run a program + finish complete the installation of libtool libraries + install install libraries or executables + link create a library or an executable + uninstall remove libraries from an installed directory + +MODE-ARGS vary depending on the MODE. When passed as first option, +'--mode=MODE' may be abbreviated as 'MODE' or a unique abbreviation of that. +Try '$progname --help --mode=MODE' for a more detailed description of MODE. + +When reporting a bug, please describe a test case to reproduce it and +include the following information: + + host-triplet: $host + shell: $SHELL + compiler: $LTCC + compiler flags: $LTCFLAGS + linker: $LD (gnu? $with_gnu_ld) + version: $progname $scriptversion Debian-2.4.6-2.1 + automake: `($AUTOMAKE --version) 2>/dev/null |$SED 1q` + autoconf: `($AUTOCONF --version) 2>/dev/null |$SED 1q` + +Report bugs to . +GNU libtool home page: . +General help using GNU software: ." + exit 0 +} + + +# func_lo2o OBJECT-NAME +# --------------------- +# Transform OBJECT-NAME from a '.lo' suffix to the platform specific +# object suffix. + +lo2o=s/\\.lo\$/.$objext/ +o2lo=s/\\.$objext\$/.lo/ + +if test yes = "$_G_HAVE_XSI_OPS"; then + eval 'func_lo2o () + { + case $1 in + *.lo) func_lo2o_result=${1%.lo}.$objext ;; + * ) func_lo2o_result=$1 ;; + esac + }' + + # func_xform LIBOBJ-OR-SOURCE + # --------------------------- + # Transform LIBOBJ-OR-SOURCE from a '.o' or '.c' (or otherwise) + # suffix to a '.lo' libtool-object suffix. + eval 'func_xform () + { + func_xform_result=${1%.*}.lo + }' +else + # ...otherwise fall back to using sed. + func_lo2o () + { + func_lo2o_result=`$ECHO "$1" | $SED "$lo2o"` + } + + func_xform () + { + func_xform_result=`$ECHO "$1" | $SED 's|\.[^.]*$|.lo|'` + } +fi + + +# func_fatal_configuration ARG... +# ------------------------------- +# Echo program name prefixed message to standard error, followed by +# a configuration failure hint, and exit. +func_fatal_configuration () +{ + func__fatal_error ${1+"$@"} \ + "See the $PACKAGE documentation for more information." \ + "Fatal configuration error." +} + + +# func_config +# ----------- +# Display the configuration for all the tags in this script. +func_config () +{ + re_begincf='^# ### BEGIN LIBTOOL' + re_endcf='^# ### END LIBTOOL' + + # Default configuration. + $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath" + + # Now print the configurations for the tags. + for tagname in $taglist; do + $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath" + done + + exit $? +} + + +# func_features +# ------------- +# Display the features supported by this script. +func_features () +{ + echo "host: $host" + if test yes = "$build_libtool_libs"; then + echo "enable shared libraries" + else + echo "disable shared libraries" + fi + if test yes = "$build_old_libs"; then + echo "enable static libraries" + else + echo "disable static libraries" + fi + + exit $? +} + + +# func_enable_tag TAGNAME +# ----------------------- +# Verify that TAGNAME is valid, and either flag an error and exit, or +# enable the TAGNAME tag. We also add TAGNAME to the global $taglist +# variable here. +func_enable_tag () +{ + # Global variable: + tagname=$1 + + re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$" + re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$" + sed_extractcf=/$re_begincf/,/$re_endcf/p + + # Validate tagname. + case $tagname in + *[!-_A-Za-z0-9,/]*) + func_fatal_error "invalid tag name: $tagname" + ;; + esac + + # Don't test for the "default" C tag, as we know it's + # there but not specially marked. + case $tagname in + CC) ;; + *) + if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then + taglist="$taglist $tagname" + + # Evaluate the configuration. Be careful to quote the path + # and the sed script, to avoid splitting on whitespace, but + # also don't use non-portable quotes within backquotes within + # quotes we have to do it in 2 steps: + extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` + eval "$extractedcf" + else + func_error "ignoring unknown tag $tagname" + fi + ;; + esac +} + + +# func_check_version_match +# ------------------------ +# Ensure that we are using m4 macros, and libtool script from the same +# release of libtool. +func_check_version_match () +{ + if test "$package_revision" != "$macro_revision"; then + if test "$VERSION" != "$macro_version"; then + if test -z "$macro_version"; then + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, but the +$progname: definition of this LT_INIT comes from an older release. +$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION +$progname: and run autoconf again. +_LT_EOF + else + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, but the +$progname: definition of this LT_INIT comes from $PACKAGE $macro_version. +$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION +$progname: and run autoconf again. +_LT_EOF + fi + else + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision, +$progname: but the definition of this LT_INIT comes from revision $macro_revision. +$progname: You should recreate aclocal.m4 with macros from revision $package_revision +$progname: of $PACKAGE $VERSION and run autoconf again. +_LT_EOF + fi + + exit $EXIT_MISMATCH + fi +} + + +# libtool_options_prep [ARG]... +# ----------------------------- +# Preparation for options parsed by libtool. +libtool_options_prep () +{ + $debug_mode + + # Option defaults: + opt_config=false + opt_dlopen= + opt_dry_run=false + opt_help=false + opt_mode= + opt_preserve_dup_deps=false + opt_quiet=false + + nonopt= + preserve_args= + + _G_rc_lt_options_prep=: + + # Shorthand for --mode=foo, only valid as the first argument + case $1 in + clean|clea|cle|cl) + shift; set dummy --mode clean ${1+"$@"}; shift + ;; + compile|compil|compi|comp|com|co|c) + shift; set dummy --mode compile ${1+"$@"}; shift + ;; + execute|execut|execu|exec|exe|ex|e) + shift; set dummy --mode execute ${1+"$@"}; shift + ;; + finish|finis|fini|fin|fi|f) + shift; set dummy --mode finish ${1+"$@"}; shift + ;; + install|instal|insta|inst|ins|in|i) + shift; set dummy --mode install ${1+"$@"}; shift + ;; + link|lin|li|l) + shift; set dummy --mode link ${1+"$@"}; shift + ;; + uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) + shift; set dummy --mode uninstall ${1+"$@"}; shift + ;; + *) + _G_rc_lt_options_prep=false + ;; + esac + + if $_G_rc_lt_options_prep; then + # Pass back the list of options. + func_quote eval ${1+"$@"} + libtool_options_prep_result=$func_quote_result + fi + + $_G_rc_lt_options_prep +} +func_add_hook func_options_prep libtool_options_prep + + +# libtool_parse_options [ARG]... +# --------------------------------- +# Provide handling for libtool specific options. +libtool_parse_options () +{ + $debug_cmd + + _G_rc_lt_parse_options=false + + # Perform our own loop to consume as many options as possible in + # each iteration. + while test $# -gt 0; do + _G_match_lt_parse_options=: + _G_opt=$1 + shift + case $_G_opt in + --dry-run|--dryrun|-n) + opt_dry_run=: + ;; + + --config) func_config ;; + + --dlopen|-dlopen) + opt_dlopen="${opt_dlopen+$opt_dlopen +}$1" + shift + ;; + + --preserve-dup-deps) + opt_preserve_dup_deps=: ;; + + --features) func_features ;; + + --finish) set dummy --mode finish ${1+"$@"}; shift ;; + + --help) opt_help=: ;; + + --help-all) opt_help=': help-all' ;; + + --mode) test $# = 0 && func_missing_arg $_G_opt && break + opt_mode=$1 + case $1 in + # Valid mode arguments: + clean|compile|execute|finish|install|link|relink|uninstall) ;; + + # Catch anything else as an error + *) func_error "invalid argument for $_G_opt" + exit_cmd=exit + break + ;; + esac + shift + ;; + + --no-silent|--no-quiet) + opt_quiet=false + func_append preserve_args " $_G_opt" + ;; + + --no-warnings|--no-warning|--no-warn) + opt_warning=false + func_append preserve_args " $_G_opt" + ;; + + --no-verbose) + opt_verbose=false + func_append preserve_args " $_G_opt" + ;; + + --silent|--quiet) + opt_quiet=: + opt_verbose=false + func_append preserve_args " $_G_opt" + ;; + + --tag) test $# = 0 && func_missing_arg $_G_opt && break + opt_tag=$1 + func_append preserve_args " $_G_opt $1" + func_enable_tag "$1" + shift + ;; + + --verbose|-v) opt_quiet=false + opt_verbose=: + func_append preserve_args " $_G_opt" + ;; + + # An option not handled by this hook function: + *) set dummy "$_G_opt" ${1+"$@"} ; shift + _G_match_lt_parse_options=false + break + ;; + esac + $_G_match_lt_parse_options && _G_rc_lt_parse_options=: + done + + if $_G_rc_lt_parse_options; then + # save modified positional parameters for caller + func_quote eval ${1+"$@"} + libtool_parse_options_result=$func_quote_result + fi + + $_G_rc_lt_parse_options +} +func_add_hook func_parse_options libtool_parse_options + + + +# libtool_validate_options [ARG]... +# --------------------------------- +# Perform any sanity checks on option settings and/or unconsumed +# arguments. +libtool_validate_options () +{ + # save first non-option argument + if test 0 -lt $#; then + nonopt=$1 + shift + fi + + # preserve --debug + test : = "$debug_cmd" || func_append preserve_args " --debug" + + case $host in + # Solaris2 added to fix http://debbugs.gnu.org/cgi/bugreport.cgi?bug=16452 + # see also: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59788 + *cygwin* | *mingw* | *pw32* | *cegcc* | *solaris2* | *os2*) + # don't eliminate duplications in $postdeps and $predeps + opt_duplicate_compiler_generated_deps=: + ;; + *) + opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps + ;; + esac + + $opt_help || { + # Sanity checks first: + func_check_version_match + + test yes != "$build_libtool_libs" \ + && test yes != "$build_old_libs" \ + && func_fatal_configuration "not configured to build any kind of library" + + # Darwin sucks + eval std_shrext=\"$shrext_cmds\" + + # Only execute mode is allowed to have -dlopen flags. + if test -n "$opt_dlopen" && test execute != "$opt_mode"; then + func_error "unrecognized option '-dlopen'" + $ECHO "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Change the help message to a mode-specific one. + generic_help=$help + help="Try '$progname --help --mode=$opt_mode' for more information." + } + + # Pass back the unparsed argument list + func_quote eval ${1+"$@"} + libtool_validate_options_result=$func_quote_result +} +func_add_hook func_validate_options libtool_validate_options + + +# Process options as early as possible so that --help and --version +# can return quickly. +func_options ${1+"$@"} +eval set dummy "$func_options_result"; shift + + + +## ----------- ## +## Main. ## +## ----------- ## + +magic='%%%MAGIC variable%%%' +magic_exe='%%%MAGIC EXE variable%%%' + +# Global variables. +extracted_archives= +extracted_serial=0 + +# If this variable is set in any of the actions, the command in it +# will be execed at the end. This prevents here-documents from being +# left over by shells. +exec_cmd= + + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' +} + +# func_generated_by_libtool +# True iff stdin has been generated by Libtool. This function is only +# a basic sanity check; it will hardly flush out determined imposters. +func_generated_by_libtool_p () +{ + $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 +} + +# func_lalib_p file +# True iff FILE is a libtool '.la' library or '.lo' object file. +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_lalib_p () +{ + test -f "$1" && + $SED -e 4q "$1" 2>/dev/null | func_generated_by_libtool_p +} + +# func_lalib_unsafe_p file +# True iff FILE is a libtool '.la' library or '.lo' object file. +# This function implements the same check as func_lalib_p without +# resorting to external programs. To this end, it redirects stdin and +# closes it afterwards, without saving the original file descriptor. +# As a safety measure, use it only where a negative result would be +# fatal anyway. Works if 'file' does not exist. +func_lalib_unsafe_p () +{ + lalib_p=no + if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then + for lalib_p_l in 1 2 3 4 + do + read lalib_p_line + case $lalib_p_line in + \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;; + esac + done + exec 0<&5 5<&- + fi + test yes = "$lalib_p" +} + +# func_ltwrapper_script_p file +# True iff FILE is a libtool wrapper script +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_script_p () +{ + test -f "$1" && + $lt_truncate_bin < "$1" 2>/dev/null | func_generated_by_libtool_p +} + +# func_ltwrapper_executable_p file +# True iff FILE is a libtool wrapper executable +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_executable_p () +{ + func_ltwrapper_exec_suffix= + case $1 in + *.exe) ;; + *) func_ltwrapper_exec_suffix=.exe ;; + esac + $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1 +} + +# func_ltwrapper_scriptname file +# Assumes file is an ltwrapper_executable +# uses $file to determine the appropriate filename for a +# temporary ltwrapper_script. +func_ltwrapper_scriptname () +{ + func_dirname_and_basename "$1" "" "." + func_stripname '' '.exe' "$func_basename_result" + func_ltwrapper_scriptname_result=$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper +} + +# func_ltwrapper_p file +# True iff FILE is a libtool wrapper script or wrapper executable +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_p () +{ + func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1" +} + + +# func_execute_cmds commands fail_cmd +# Execute tilde-delimited COMMANDS. +# If FAIL_CMD is given, eval that upon failure. +# FAIL_CMD may read-access the current command in variable CMD! +func_execute_cmds () +{ + $debug_cmd + + save_ifs=$IFS; IFS='~' + for cmd in $1; do + IFS=$sp$nl + eval cmd=\"$cmd\" + IFS=$save_ifs + func_show_eval "$cmd" "${2-:}" + done + IFS=$save_ifs +} + + +# func_source file +# Source FILE, adding directory component if necessary. +# Note that it is not necessary on cygwin/mingw to append a dot to +# FILE even if both FILE and FILE.exe exist: automatic-append-.exe +# behavior happens only for exec(3), not for open(2)! Also, sourcing +# 'FILE.' does not work on cygwin managed mounts. +func_source () +{ + $debug_cmd + + case $1 in + */* | *\\*) . "$1" ;; + *) . "./$1" ;; + esac +} + + +# func_resolve_sysroot PATH +# Replace a leading = in PATH with a sysroot. Store the result into +# func_resolve_sysroot_result +func_resolve_sysroot () +{ + func_resolve_sysroot_result=$1 + case $func_resolve_sysroot_result in + =*) + func_stripname '=' '' "$func_resolve_sysroot_result" + func_resolve_sysroot_result=$lt_sysroot$func_stripname_result + ;; + esac +} + +# func_replace_sysroot PATH +# If PATH begins with the sysroot, replace it with = and +# store the result into func_replace_sysroot_result. +func_replace_sysroot () +{ + case $lt_sysroot:$1 in + ?*:"$lt_sysroot"*) + func_stripname "$lt_sysroot" '' "$1" + func_replace_sysroot_result='='$func_stripname_result + ;; + *) + # Including no sysroot. + func_replace_sysroot_result=$1 + ;; + esac +} + +# func_infer_tag arg +# Infer tagged configuration to use if any are available and +# if one wasn't chosen via the "--tag" command line option. +# Only attempt this if the compiler in the base compile +# command doesn't match the default compiler. +# arg is usually of the form 'gcc ...' +func_infer_tag () +{ + $debug_cmd + + if test -n "$available_tags" && test -z "$tagname"; then + CC_quoted= + for arg in $CC; do + func_append_quoted CC_quoted "$arg" + done + CC_expanded=`func_echo_all $CC` + CC_quoted_expanded=`func_echo_all $CC_quoted` + case $@ in + # Blanks in the command may have been stripped by the calling shell, + # but not from the CC environment variable when configure was run. + " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ + " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;; + # Blanks at the start of $base_compile will cause this to fail + # if we don't check for them as well. + *) + for z in $available_tags; do + if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then + # Evaluate the configuration. + eval "`$SED -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" + CC_quoted= + for arg in $CC; do + # Double-quote args containing other shell metacharacters. + func_append_quoted CC_quoted "$arg" + done + CC_expanded=`func_echo_all $CC` + CC_quoted_expanded=`func_echo_all $CC_quoted` + case "$@ " in + " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ + " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) + # The compiler in the base compile command matches + # the one in the tagged configuration. + # Assume this is the tagged configuration we want. + tagname=$z + break + ;; + esac + fi + done + # If $tagname still isn't set, then no tagged configuration + # was found and let the user know that the "--tag" command + # line option must be used. + if test -z "$tagname"; then + func_echo "unable to infer tagged configuration" + func_fatal_error "specify a tag with '--tag'" +# else +# func_verbose "using $tagname tagged configuration" + fi + ;; + esac + fi +} + + + +# func_write_libtool_object output_name pic_name nonpic_name +# Create a libtool object file (analogous to a ".la" file), +# but don't create it if we're doing a dry run. +func_write_libtool_object () +{ + write_libobj=$1 + if test yes = "$build_libtool_libs"; then + write_lobj=\'$2\' + else + write_lobj=none + fi + + if test yes = "$build_old_libs"; then + write_oldobj=\'$3\' + else + write_oldobj=none + fi + + $opt_dry_run || { + cat >${write_libobj}T </dev/null` + if test "$?" -eq 0 && test -n "$func_convert_core_file_wine_to_w32_tmp"; then + func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" | + $SED -e "$sed_naive_backslashify"` + else + func_convert_core_file_wine_to_w32_result= + fi + fi +} +# end: func_convert_core_file_wine_to_w32 + + +# func_convert_core_path_wine_to_w32 ARG +# Helper function used by path conversion functions when $build is *nix, and +# $host is mingw, cygwin, or some other w32 environment. Relies on a correctly +# configured wine environment available, with the winepath program in $build's +# $PATH. Assumes ARG has no leading or trailing path separator characters. +# +# ARG is path to be converted from $build format to win32. +# Result is available in $func_convert_core_path_wine_to_w32_result. +# Unconvertible file (directory) names in ARG are skipped; if no directory names +# are convertible, then the result may be empty. +func_convert_core_path_wine_to_w32 () +{ + $debug_cmd + + # unfortunately, winepath doesn't convert paths, only file names + func_convert_core_path_wine_to_w32_result= + if test -n "$1"; then + oldIFS=$IFS + IFS=: + for func_convert_core_path_wine_to_w32_f in $1; do + IFS=$oldIFS + func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f" + if test -n "$func_convert_core_file_wine_to_w32_result"; then + if test -z "$func_convert_core_path_wine_to_w32_result"; then + func_convert_core_path_wine_to_w32_result=$func_convert_core_file_wine_to_w32_result + else + func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result" + fi + fi + done + IFS=$oldIFS + fi +} +# end: func_convert_core_path_wine_to_w32 + + +# func_cygpath ARGS... +# Wrapper around calling the cygpath program via LT_CYGPATH. This is used when +# when (1) $build is *nix and Cygwin is hosted via a wine environment; or (2) +# $build is MSYS and $host is Cygwin, or (3) $build is Cygwin. In case (1) or +# (2), returns the Cygwin file name or path in func_cygpath_result (input +# file name or path is assumed to be in w32 format, as previously converted +# from $build's *nix or MSYS format). In case (3), returns the w32 file name +# or path in func_cygpath_result (input file name or path is assumed to be in +# Cygwin format). Returns an empty string on error. +# +# ARGS are passed to cygpath, with the last one being the file name or path to +# be converted. +# +# Specify the absolute *nix (or w32) name to cygpath in the LT_CYGPATH +# environment variable; do not put it in $PATH. +func_cygpath () +{ + $debug_cmd + + if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then + func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null` + if test "$?" -ne 0; then + # on failure, ensure result is empty + func_cygpath_result= + fi + else + func_cygpath_result= + func_error "LT_CYGPATH is empty or specifies non-existent file: '$LT_CYGPATH'" + fi +} +#end: func_cygpath + + +# func_convert_core_msys_to_w32 ARG +# Convert file name or path ARG from MSYS format to w32 format. Return +# result in func_convert_core_msys_to_w32_result. +func_convert_core_msys_to_w32 () +{ + $debug_cmd + + # awkward: cmd appends spaces to result + func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null | + $SED -e 's/[ ]*$//' -e "$sed_naive_backslashify"` +} +#end: func_convert_core_msys_to_w32 + + +# func_convert_file_check ARG1 ARG2 +# Verify that ARG1 (a file name in $build format) was converted to $host +# format in ARG2. Otherwise, emit an error message, but continue (resetting +# func_to_host_file_result to ARG1). +func_convert_file_check () +{ + $debug_cmd + + if test -z "$2" && test -n "$1"; then + func_error "Could not determine host file name corresponding to" + func_error " '$1'" + func_error "Continuing, but uninstalled executables may not work." + # Fallback: + func_to_host_file_result=$1 + fi +} +# end func_convert_file_check + + +# func_convert_path_check FROM_PATHSEP TO_PATHSEP FROM_PATH TO_PATH +# Verify that FROM_PATH (a path in $build format) was converted to $host +# format in TO_PATH. Otherwise, emit an error message, but continue, resetting +# func_to_host_file_result to a simplistic fallback value (see below). +func_convert_path_check () +{ + $debug_cmd + + if test -z "$4" && test -n "$3"; then + func_error "Could not determine the host path corresponding to" + func_error " '$3'" + func_error "Continuing, but uninstalled executables may not work." + # Fallback. This is a deliberately simplistic "conversion" and + # should not be "improved". See libtool.info. + if test "x$1" != "x$2"; then + lt_replace_pathsep_chars="s|$1|$2|g" + func_to_host_path_result=`echo "$3" | + $SED -e "$lt_replace_pathsep_chars"` + else + func_to_host_path_result=$3 + fi + fi +} +# end func_convert_path_check + + +# func_convert_path_front_back_pathsep FRONTPAT BACKPAT REPL ORIG +# Modifies func_to_host_path_result by prepending REPL if ORIG matches FRONTPAT +# and appending REPL if ORIG matches BACKPAT. +func_convert_path_front_back_pathsep () +{ + $debug_cmd + + case $4 in + $1 ) func_to_host_path_result=$3$func_to_host_path_result + ;; + esac + case $4 in + $2 ) func_append func_to_host_path_result "$3" + ;; + esac +} +# end func_convert_path_front_back_pathsep + + +################################################## +# $build to $host FILE NAME CONVERSION FUNCTIONS # +################################################## +# invoked via '$to_host_file_cmd ARG' +# +# In each case, ARG is the path to be converted from $build to $host format. +# Result will be available in $func_to_host_file_result. + + +# func_to_host_file ARG +# Converts the file name ARG from $build format to $host format. Return result +# in func_to_host_file_result. +func_to_host_file () +{ + $debug_cmd + + $to_host_file_cmd "$1" +} +# end func_to_host_file + + +# func_to_tool_file ARG LAZY +# converts the file name ARG from $build format to toolchain format. Return +# result in func_to_tool_file_result. If the conversion in use is listed +# in (the comma separated) LAZY, no conversion takes place. +func_to_tool_file () +{ + $debug_cmd + + case ,$2, in + *,"$to_tool_file_cmd",*) + func_to_tool_file_result=$1 + ;; + *) + $to_tool_file_cmd "$1" + func_to_tool_file_result=$func_to_host_file_result + ;; + esac +} +# end func_to_tool_file + + +# func_convert_file_noop ARG +# Copy ARG to func_to_host_file_result. +func_convert_file_noop () +{ + func_to_host_file_result=$1 +} +# end func_convert_file_noop + + +# func_convert_file_msys_to_w32 ARG +# Convert file name ARG from (mingw) MSYS to (mingw) w32 format; automatic +# conversion to w32 is not available inside the cwrapper. Returns result in +# func_to_host_file_result. +func_convert_file_msys_to_w32 () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + func_convert_core_msys_to_w32 "$1" + func_to_host_file_result=$func_convert_core_msys_to_w32_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_msys_to_w32 + + +# func_convert_file_cygwin_to_w32 ARG +# Convert file name ARG from Cygwin to w32 format. Returns result in +# func_to_host_file_result. +func_convert_file_cygwin_to_w32 () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + # because $build is cygwin, we call "the" cygpath in $PATH; no need to use + # LT_CYGPATH in this case. + func_to_host_file_result=`cygpath -m "$1"` + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_cygwin_to_w32 + + +# func_convert_file_nix_to_w32 ARG +# Convert file name ARG from *nix to w32 format. Requires a wine environment +# and a working winepath. Returns result in func_to_host_file_result. +func_convert_file_nix_to_w32 () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + func_convert_core_file_wine_to_w32 "$1" + func_to_host_file_result=$func_convert_core_file_wine_to_w32_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_nix_to_w32 + + +# func_convert_file_msys_to_cygwin ARG +# Convert file name ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. +# Returns result in func_to_host_file_result. +func_convert_file_msys_to_cygwin () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + func_convert_core_msys_to_w32 "$1" + func_cygpath -u "$func_convert_core_msys_to_w32_result" + func_to_host_file_result=$func_cygpath_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_msys_to_cygwin + + +# func_convert_file_nix_to_cygwin ARG +# Convert file name ARG from *nix to Cygwin format. Requires Cygwin installed +# in a wine environment, working winepath, and LT_CYGPATH set. Returns result +# in func_to_host_file_result. +func_convert_file_nix_to_cygwin () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + # convert from *nix to w32, then use cygpath to convert from w32 to cygwin. + func_convert_core_file_wine_to_w32 "$1" + func_cygpath -u "$func_convert_core_file_wine_to_w32_result" + func_to_host_file_result=$func_cygpath_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_nix_to_cygwin + + +############################################# +# $build to $host PATH CONVERSION FUNCTIONS # +############################################# +# invoked via '$to_host_path_cmd ARG' +# +# In each case, ARG is the path to be converted from $build to $host format. +# The result will be available in $func_to_host_path_result. +# +# Path separators are also converted from $build format to $host format. If +# ARG begins or ends with a path separator character, it is preserved (but +# converted to $host format) on output. +# +# All path conversion functions are named using the following convention: +# file name conversion function : func_convert_file_X_to_Y () +# path conversion function : func_convert_path_X_to_Y () +# where, for any given $build/$host combination the 'X_to_Y' value is the +# same. If conversion functions are added for new $build/$host combinations, +# the two new functions must follow this pattern, or func_init_to_host_path_cmd +# will break. + + +# func_init_to_host_path_cmd +# Ensures that function "pointer" variable $to_host_path_cmd is set to the +# appropriate value, based on the value of $to_host_file_cmd. +to_host_path_cmd= +func_init_to_host_path_cmd () +{ + $debug_cmd + + if test -z "$to_host_path_cmd"; then + func_stripname 'func_convert_file_' '' "$to_host_file_cmd" + to_host_path_cmd=func_convert_path_$func_stripname_result + fi +} + + +# func_to_host_path ARG +# Converts the path ARG from $build format to $host format. Return result +# in func_to_host_path_result. +func_to_host_path () +{ + $debug_cmd + + func_init_to_host_path_cmd + $to_host_path_cmd "$1" +} +# end func_to_host_path + + +# func_convert_path_noop ARG +# Copy ARG to func_to_host_path_result. +func_convert_path_noop () +{ + func_to_host_path_result=$1 +} +# end func_convert_path_noop + + +# func_convert_path_msys_to_w32 ARG +# Convert path ARG from (mingw) MSYS to (mingw) w32 format; automatic +# conversion to w32 is not available inside the cwrapper. Returns result in +# func_to_host_path_result. +func_convert_path_msys_to_w32 () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # Remove leading and trailing path separator characters from ARG. MSYS + # behavior is inconsistent here; cygpath turns them into '.;' and ';.'; + # and winepath ignores them completely. + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" + func_to_host_path_result=$func_convert_core_msys_to_w32_result + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_msys_to_w32 + + +# func_convert_path_cygwin_to_w32 ARG +# Convert path ARG from Cygwin to w32 format. Returns result in +# func_to_host_file_result. +func_convert_path_cygwin_to_w32 () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_to_host_path_result=`cygpath -m -p "$func_to_host_path_tmp1"` + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_cygwin_to_w32 + + +# func_convert_path_nix_to_w32 ARG +# Convert path ARG from *nix to w32 format. Requires a wine environment and +# a working winepath. Returns result in func_to_host_file_result. +func_convert_path_nix_to_w32 () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" + func_to_host_path_result=$func_convert_core_path_wine_to_w32_result + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_nix_to_w32 + + +# func_convert_path_msys_to_cygwin ARG +# Convert path ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. +# Returns result in func_to_host_file_result. +func_convert_path_msys_to_cygwin () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" + func_cygpath -u -p "$func_convert_core_msys_to_w32_result" + func_to_host_path_result=$func_cygpath_result + func_convert_path_check : : \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" : "$1" + fi +} +# end func_convert_path_msys_to_cygwin + + +# func_convert_path_nix_to_cygwin ARG +# Convert path ARG from *nix to Cygwin format. Requires Cygwin installed in a +# a wine environment, working winepath, and LT_CYGPATH set. Returns result in +# func_to_host_file_result. +func_convert_path_nix_to_cygwin () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # Remove leading and trailing path separator characters from + # ARG. msys behavior is inconsistent here, cygpath turns them + # into '.;' and ';.', and winepath ignores them completely. + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" + func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result" + func_to_host_path_result=$func_cygpath_result + func_convert_path_check : : \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" : "$1" + fi +} +# end func_convert_path_nix_to_cygwin + + +# func_dll_def_p FILE +# True iff FILE is a Windows DLL '.def' file. +# Keep in sync with _LT_DLL_DEF_P in libtool.m4 +func_dll_def_p () +{ + $debug_cmd + + func_dll_def_p_tmp=`$SED -n \ + -e 's/^[ ]*//' \ + -e '/^\(;.*\)*$/d' \ + -e 's/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p' \ + -e q \ + "$1"` + test DEF = "$func_dll_def_p_tmp" +} + + +# func_mode_compile arg... +func_mode_compile () +{ + $debug_cmd + + # Get the compilation command and the source file. + base_compile= + srcfile=$nonopt # always keep a non-empty value in "srcfile" + suppress_opt=yes + suppress_output= + arg_mode=normal + libobj= + later= + pie_flag= + + for arg + do + case $arg_mode in + arg ) + # do not "continue". Instead, add this to base_compile + lastarg=$arg + arg_mode=normal + ;; + + target ) + libobj=$arg + arg_mode=normal + continue + ;; + + normal ) + # Accept any command-line options. + case $arg in + -o) + test -n "$libobj" && \ + func_fatal_error "you cannot specify '-o' more than once" + arg_mode=target + continue + ;; + + -pie | -fpie | -fPIE) + func_append pie_flag " $arg" + continue + ;; + + -shared | -static | -prefer-pic | -prefer-non-pic) + func_append later " $arg" + continue + ;; + + -no-suppress) + suppress_opt=no + continue + ;; + + -Xcompiler) + arg_mode=arg # the next one goes into the "base_compile" arg list + continue # The current "srcfile" will either be retained or + ;; # replaced later. I would guess that would be a bug. + + -Wc,*) + func_stripname '-Wc,' '' "$arg" + args=$func_stripname_result + lastarg= + save_ifs=$IFS; IFS=, + for arg in $args; do + IFS=$save_ifs + func_append_quoted lastarg "$arg" + done + IFS=$save_ifs + func_stripname ' ' '' "$lastarg" + lastarg=$func_stripname_result + + # Add the arguments to base_compile. + func_append base_compile " $lastarg" + continue + ;; + + *) + # Accept the current argument as the source file. + # The previous "srcfile" becomes the current argument. + # + lastarg=$srcfile + srcfile=$arg + ;; + esac # case $arg + ;; + esac # case $arg_mode + + # Aesthetically quote the previous argument. + func_append_quoted base_compile "$lastarg" + done # for arg + + case $arg_mode in + arg) + func_fatal_error "you must specify an argument for -Xcompile" + ;; + target) + func_fatal_error "you must specify a target with '-o'" + ;; + *) + # Get the name of the library object. + test -z "$libobj" && { + func_basename "$srcfile" + libobj=$func_basename_result + } + ;; + esac + + # Recognize several different file suffixes. + # If the user specifies -o file.o, it is replaced with file.lo + case $libobj in + *.[cCFSifmso] | \ + *.ada | *.adb | *.ads | *.asm | \ + *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \ + *.[fF][09]? | *.for | *.java | *.go | *.obj | *.sx | *.cu | *.cup) + func_xform "$libobj" + libobj=$func_xform_result + ;; + esac + + case $libobj in + *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;; + *) + func_fatal_error "cannot determine name of library object from '$libobj'" + ;; + esac + + func_infer_tag $base_compile + + for arg in $later; do + case $arg in + -shared) + test yes = "$build_libtool_libs" \ + || func_fatal_configuration "cannot build a shared library" + build_old_libs=no + continue + ;; + + -static) + build_libtool_libs=no + build_old_libs=yes + continue + ;; + + -prefer-pic) + pic_mode=yes + continue + ;; + + -prefer-non-pic) + pic_mode=no + continue + ;; + esac + done + + func_quote_arg pretty "$libobj" + test "X$libobj" != "X$func_quote_arg_result" \ + && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"' &()|`$[]' \ + && func_warning "libobj name '$libobj' may not contain shell special characters." + func_dirname_and_basename "$obj" "/" "" + objname=$func_basename_result + xdir=$func_dirname_result + lobj=$xdir$objdir/$objname + + test -z "$base_compile" && \ + func_fatal_help "you must specify a compilation command" + + # Delete any leftover library objects. + if test yes = "$build_old_libs"; then + removelist="$obj $lobj $libobj ${libobj}T" + else + removelist="$lobj $libobj ${libobj}T" + fi + + # On Cygwin there's no "real" PIC flag so we must build both object types + case $host_os in + cygwin* | mingw* | pw32* | os2* | cegcc*) + pic_mode=default + ;; + esac + if test no = "$pic_mode" && test pass_all != "$deplibs_check_method"; then + # non-PIC code in shared libraries is not supported + pic_mode=default + fi + + # Calculate the filename of the output object if compiler does + # not support -o with -c + if test no = "$compiler_c_o"; then + output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.$objext + lockfile=$output_obj.lock + else + output_obj= + need_locks=no + lockfile= + fi + + # Lock this critical section if it is needed + # We use this script file to make the link, it avoids creating a new file + if test yes = "$need_locks"; then + until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do + func_echo "Waiting for $lockfile to be removed" + sleep 2 + done + elif test warn = "$need_locks"; then + if test -f "$lockfile"; then + $ECHO "\ +*** ERROR, $lockfile exists and contains: +`cat $lockfile 2>/dev/null` + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support '-c' and '-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + func_append removelist " $output_obj" + $ECHO "$srcfile" > "$lockfile" + fi + + $opt_dry_run || $RM $removelist + func_append removelist " $lockfile" + trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15 + + func_to_tool_file "$srcfile" func_convert_file_msys_to_w32 + srcfile=$func_to_tool_file_result + func_quote_arg pretty "$srcfile" + qsrcfile=$func_quote_arg_result + + # Only build a PIC object if we are building libtool libraries. + if test yes = "$build_libtool_libs"; then + # Without this assignment, base_compile gets emptied. + fbsd_hideous_sh_bug=$base_compile + + if test no != "$pic_mode"; then + command="$base_compile $qsrcfile $pic_flag" + else + # Don't build PIC code + command="$base_compile $qsrcfile" + fi + + func_mkdir_p "$xdir$objdir" + + if test -z "$output_obj"; then + # Place PIC objects in $objdir + func_append command " -o $lobj" + fi + + func_show_eval_locale "$command" \ + 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE' + + if test warn = "$need_locks" && + test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then + $ECHO "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support '-c' and '-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed, then go on to compile the next one + if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then + func_show_eval '$MV "$output_obj" "$lobj"' \ + 'error=$?; $opt_dry_run || $RM $removelist; exit $error' + fi + + # Allow error messages only from the first compilation. + if test yes = "$suppress_opt"; then + suppress_output=' >/dev/null 2>&1' + fi + fi + + # Only build a position-dependent object if we build old libraries. + if test yes = "$build_old_libs"; then + if test yes != "$pic_mode"; then + # Don't build PIC code + command="$base_compile $qsrcfile$pie_flag" + else + command="$base_compile $qsrcfile $pic_flag" + fi + if test yes = "$compiler_c_o"; then + func_append command " -o $obj" + fi + + # Suppress compiler output if we already did a PIC compilation. + func_append command "$suppress_output" + func_show_eval_locale "$command" \ + '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' + + if test warn = "$need_locks" && + test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then + $ECHO "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support '-c' and '-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed + if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then + func_show_eval '$MV "$output_obj" "$obj"' \ + 'error=$?; $opt_dry_run || $RM $removelist; exit $error' + fi + fi + + $opt_dry_run || { + func_write_libtool_object "$libobj" "$objdir/$objname" "$objname" + + # Unlock the critical section if it was locked + if test no != "$need_locks"; then + removelist=$lockfile + $RM "$lockfile" + fi + } + + exit $EXIT_SUCCESS +} + +$opt_help || { + test compile = "$opt_mode" && func_mode_compile ${1+"$@"} +} + +func_mode_help () +{ + # We need to display help for each of the modes. + case $opt_mode in + "") + # Generic help is extracted from the usage comments + # at the start of this file. + func_help + ;; + + clean) + $ECHO \ +"Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE... + +Remove files from the build directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed +to RM. + +If FILE is a libtool library, object or program, all the files associated +with it are deleted. Otherwise, only FILE itself is deleted using RM." + ;; + + compile) + $ECHO \ +"Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE + +Compile a source file into a libtool library object. + +This mode accepts the following additional options: + + -o OUTPUT-FILE set the output file name to OUTPUT-FILE + -no-suppress do not suppress compiler output for multiple passes + -prefer-pic try to build PIC objects only + -prefer-non-pic try to build non-PIC objects only + -shared do not build a '.o' file suitable for static linking + -static only build a '.o' file suitable for static linking + -Wc,FLAG pass FLAG directly to the compiler + +COMPILE-COMMAND is a command to be used in creating a 'standard' object file +from the given SOURCEFILE. + +The output file name is determined by removing the directory component from +SOURCEFILE, then substituting the C source code suffix '.c' with the +library object suffix, '.lo'." + ;; + + execute) + $ECHO \ +"Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]... + +Automatically set library path, then run a program. + +This mode accepts the following additional options: + + -dlopen FILE add the directory containing FILE to the library path + +This mode sets the library path environment variable according to '-dlopen' +flags. + +If any of the ARGS are libtool executable wrappers, then they are translated +into their corresponding uninstalled binary, and any of their required library +directories are added to the library path. + +Then, COMMAND is executed, with ARGS as arguments." + ;; + + finish) + $ECHO \ +"Usage: $progname [OPTION]... --mode=finish [LIBDIR]... + +Complete the installation of libtool libraries. + +Each LIBDIR is a directory that contains libtool libraries. + +The commands that this mode executes may require superuser privileges. Use +the '--dry-run' option if you just want to see what would be executed." + ;; + + install) + $ECHO \ +"Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND... + +Install executables or libraries. + +INSTALL-COMMAND is the installation command. The first component should be +either the 'install' or 'cp' program. + +The following components of INSTALL-COMMAND are treated specially: + + -inst-prefix-dir PREFIX-DIR Use PREFIX-DIR as a staging area for installation + +The rest of the components are interpreted as arguments to that command (only +BSD-compatible install options are recognized)." + ;; + + link) + $ECHO \ +"Usage: $progname [OPTION]... --mode=link LINK-COMMAND... + +Link object files or libraries together to form another library, or to +create an executable program. + +LINK-COMMAND is a command using the C compiler that you would use to create +a program from several object files. + +The following components of LINK-COMMAND are treated specially: + + -all-static do not do any dynamic linking at all + -avoid-version do not add a version suffix if possible + -bindir BINDIR specify path to binaries directory (for systems where + libraries must be found in the PATH setting at runtime) + -dlopen FILE '-dlpreopen' FILE if it cannot be dlopened at runtime + -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols + -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) + -export-symbols SYMFILE + try to export only the symbols listed in SYMFILE + -export-symbols-regex REGEX + try to export only the symbols matching REGEX + -LLIBDIR search LIBDIR for required installed libraries + -lNAME OUTPUT-FILE requires the installed library libNAME + -module build a library that can dlopened + -no-fast-install disable the fast-install mode + -no-install link a not-installable executable + -no-undefined declare that a library does not refer to external symbols + -o OUTPUT-FILE create OUTPUT-FILE from the specified objects + -objectlist FILE use a list of object files found in FILE to specify objects + -os2dllname NAME force a short DLL name on OS/2 (no effect on other OSes) + -precious-files-regex REGEX + don't remove output files matching REGEX + -release RELEASE specify package release information + -rpath LIBDIR the created library will eventually be installed in LIBDIR + -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries + -shared only do dynamic linking of libtool libraries + -shrext SUFFIX override the standard shared library file extension + -static do not do any dynamic linking of uninstalled libtool libraries + -static-libtool-libs + do not do any dynamic linking of libtool libraries + -version-info CURRENT[:REVISION[:AGE]] + specify library version info [each variable defaults to 0] + -weak LIBNAME declare that the target provides the LIBNAME interface + -Wc,FLAG + -Xcompiler FLAG pass linker-specific FLAG directly to the compiler + -Wl,FLAG + -Xlinker FLAG pass linker-specific FLAG directly to the linker + -XCClinker FLAG pass link-specific FLAG to the compiler driver (CC) + +All other options (arguments beginning with '-') are ignored. + +Every other argument is treated as a filename. Files ending in '.la' are +treated as uninstalled libtool libraries, other files are standard or library +object files. + +If the OUTPUT-FILE ends in '.la', then a libtool library is created, +only library objects ('.lo' files) may be specified, and '-rpath' is +required, except when creating a convenience library. + +If OUTPUT-FILE ends in '.a' or '.lib', then a standard library is created +using 'ar' and 'ranlib', or on Windows using 'lib'. + +If OUTPUT-FILE ends in '.lo' or '.$objext', then a reloadable object file +is created, otherwise an executable program is created." + ;; + + uninstall) + $ECHO \ +"Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... + +Remove libraries from an installation directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed +to RM. + +If FILE is a libtool library, all the files associated with it are deleted. +Otherwise, only FILE itself is deleted using RM." + ;; + + *) + func_fatal_help "invalid operation mode '$opt_mode'" + ;; + esac + + echo + $ECHO "Try '$progname --help' for more information about other modes." +} + +# Now that we've collected a possible --mode arg, show help if necessary +if $opt_help; then + if test : = "$opt_help"; then + func_mode_help + else + { + func_help noexit + for opt_mode in compile link execute install finish uninstall clean; do + func_mode_help + done + } | $SED -n '1p; 2,$s/^Usage:/ or: /p' + { + func_help noexit + for opt_mode in compile link execute install finish uninstall clean; do + echo + func_mode_help + done + } | + $SED '1d + /^When reporting/,/^Report/{ + H + d + } + $x + /information about other modes/d + /more detailed .*MODE/d + s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/' + fi + exit $? +fi + + +# func_mode_execute arg... +func_mode_execute () +{ + $debug_cmd + + # The first argument is the command name. + cmd=$nonopt + test -z "$cmd" && \ + func_fatal_help "you must specify a COMMAND" + + # Handle -dlopen flags immediately. + for file in $opt_dlopen; do + test -f "$file" \ + || func_fatal_help "'$file' is not a file" + + dir= + case $file in + *.la) + func_resolve_sysroot "$file" + file=$func_resolve_sysroot_result + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$file" \ + || func_fatal_help "'$lib' is not a valid libtool archive" + + # Read the libtool library. + dlname= + library_names= + func_source "$file" + + # Skip this library if it cannot be dlopened. + if test -z "$dlname"; then + # Warn if it was a shared library. + test -n "$library_names" && \ + func_warning "'$file' was not linked with '-export-dynamic'" + continue + fi + + func_dirname "$file" "" "." + dir=$func_dirname_result + + if test -f "$dir/$objdir/$dlname"; then + func_append dir "/$objdir" + else + if test ! -f "$dir/$dlname"; then + func_fatal_error "cannot find '$dlname' in '$dir' or '$dir/$objdir'" + fi + fi + ;; + + *.lo) + # Just add the directory containing the .lo file. + func_dirname "$file" "" "." + dir=$func_dirname_result + ;; + + *) + func_warning "'-dlopen' is ignored for non-libtool libraries and objects" + continue + ;; + esac + + # Get the absolute pathname. + absdir=`cd "$dir" && pwd` + test -n "$absdir" && dir=$absdir + + # Now add the directory to shlibpath_var. + if eval "test -z \"\$$shlibpath_var\""; then + eval "$shlibpath_var=\"\$dir\"" + else + eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" + fi + done + + # This variable tells wrapper scripts just to set shlibpath_var + # rather than running their programs. + libtool_execute_magic=$magic + + # Check if any of the arguments is a wrapper script. + args= + for file + do + case $file in + -* | *.la | *.lo ) ;; + *) + # Do a test to see if this is really a libtool program. + if func_ltwrapper_script_p "$file"; then + func_source "$file" + # Transform arg to wrapped name. + file=$progdir/$program + elif func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + func_source "$func_ltwrapper_scriptname_result" + # Transform arg to wrapped name. + file=$progdir/$program + fi + ;; + esac + # Quote arguments (to preserve shell metacharacters). + func_append_quoted args "$file" + done + + if $opt_dry_run; then + # Display what would be done. + if test -n "$shlibpath_var"; then + eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" + echo "export $shlibpath_var" + fi + $ECHO "$cmd$args" + exit $EXIT_SUCCESS + else + if test -n "$shlibpath_var"; then + # Export the shlibpath_var. + eval "export $shlibpath_var" + fi + + # Restore saved environment variables + for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES + do + eval "if test \"\${save_$lt_var+set}\" = set; then + $lt_var=\$save_$lt_var; export $lt_var + else + $lt_unset $lt_var + fi" + done + + # Now prepare to actually exec the command. + exec_cmd=\$cmd$args + fi +} + +test execute = "$opt_mode" && func_mode_execute ${1+"$@"} + + +# func_mode_finish arg... +func_mode_finish () +{ + $debug_cmd + + libs= + libdirs= + admincmds= + + for opt in "$nonopt" ${1+"$@"} + do + if test -d "$opt"; then + func_append libdirs " $opt" + + elif test -f "$opt"; then + if func_lalib_unsafe_p "$opt"; then + func_append libs " $opt" + else + func_warning "'$opt' is not a valid libtool archive" + fi + + else + func_fatal_error "invalid argument '$opt'" + fi + done + + if test -n "$libs"; then + if test -n "$lt_sysroot"; then + sysroot_regex=`$ECHO "$lt_sysroot" | $SED "$sed_make_literal_regex"` + sysroot_cmd="s/\([ ']\)$sysroot_regex/\1/g;" + else + sysroot_cmd= + fi + + # Remove sysroot references + if $opt_dry_run; then + for lib in $libs; do + echo "removing references to $lt_sysroot and '=' prefixes from $lib" + done + else + tmpdir=`func_mktempdir` + for lib in $libs; do + $SED -e "$sysroot_cmd s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \ + > $tmpdir/tmp-la + mv -f $tmpdir/tmp-la $lib + done + ${RM}r "$tmpdir" + fi + fi + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + for libdir in $libdirs; do + if test -n "$finish_cmds"; then + # Do each command in the finish commands. + func_execute_cmds "$finish_cmds" 'admincmds="$admincmds +'"$cmd"'"' + fi + if test -n "$finish_eval"; then + # Do the single finish_eval. + eval cmds=\"$finish_eval\" + $opt_dry_run || eval "$cmds" || func_append admincmds " + $cmds" + fi + done + fi + + # Exit here if they wanted silent mode. + $opt_quiet && exit $EXIT_SUCCESS + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + echo "----------------------------------------------------------------------" + echo "Libraries have been installed in:" + for libdir in $libdirs; do + $ECHO " $libdir" + done + echo + echo "If you ever happen to want to link against installed libraries" + echo "in a given directory, LIBDIR, you must either use libtool, and" + echo "specify the full pathname of the library, or use the '-LLIBDIR'" + echo "flag during linking and do at least one of the following:" + if test -n "$shlibpath_var"; then + echo " - add LIBDIR to the '$shlibpath_var' environment variable" + echo " during execution" + fi + if test -n "$runpath_var"; then + echo " - add LIBDIR to the '$runpath_var' environment variable" + echo " during linking" + fi + if test -n "$hardcode_libdir_flag_spec"; then + libdir=LIBDIR + eval flag=\"$hardcode_libdir_flag_spec\" + + $ECHO " - use the '$flag' linker flag" + fi + if test -n "$admincmds"; then + $ECHO " - have your system administrator run these commands:$admincmds" + fi + if test -f /etc/ld.so.conf; then + echo " - have your system administrator add LIBDIR to '/etc/ld.so.conf'" + fi + echo + + echo "See any operating system documentation about shared libraries for" + case $host in + solaris2.[6789]|solaris2.1[0-9]) + echo "more information, such as the ld(1), crle(1) and ld.so(8) manual" + echo "pages." + ;; + *) + echo "more information, such as the ld(1) and ld.so(8) manual pages." + ;; + esac + echo "----------------------------------------------------------------------" + fi + exit $EXIT_SUCCESS +} + +test finish = "$opt_mode" && func_mode_finish ${1+"$@"} + + +# func_mode_install arg... +func_mode_install () +{ + $debug_cmd + + # There may be an optional sh(1) argument at the beginning of + # install_prog (especially on Windows NT). + if test "$SHELL" = "$nonopt" || test /bin/sh = "$nonopt" || + # Allow the use of GNU shtool's install command. + case $nonopt in *shtool*) :;; *) false;; esac + then + # Aesthetically quote it. + func_quote_arg pretty "$nonopt" + install_prog="$func_quote_arg_result " + arg=$1 + shift + else + install_prog= + arg=$nonopt + fi + + # The real first argument should be the name of the installation program. + # Aesthetically quote it. + func_quote_arg pretty "$arg" + func_append install_prog "$func_quote_arg_result" + install_shared_prog=$install_prog + case " $install_prog " in + *[\\\ /]cp\ *) install_cp=: ;; + *) install_cp=false ;; + esac + + # We need to accept at least all the BSD install flags. + dest= + files= + opts= + prev= + install_type= + isdir=false + stripme= + no_mode=: + for arg + do + arg2= + if test -n "$dest"; then + func_append files " $dest" + dest=$arg + continue + fi + + case $arg in + -d) isdir=: ;; + -f) + if $install_cp; then :; else + prev=$arg + fi + ;; + -g | -m | -o) + prev=$arg + ;; + -s) + stripme=" -s" + continue + ;; + -*) + ;; + *) + # If the previous option needed an argument, then skip it. + if test -n "$prev"; then + if test X-m = "X$prev" && test -n "$install_override_mode"; then + arg2=$install_override_mode + no_mode=false + fi + prev= + else + dest=$arg + continue + fi + ;; + esac + + # Aesthetically quote the argument. + func_quote_arg pretty "$arg" + func_append install_prog " $func_quote_arg_result" + if test -n "$arg2"; then + func_quote_arg pretty "$arg2" + fi + func_append install_shared_prog " $func_quote_arg_result" + done + + test -z "$install_prog" && \ + func_fatal_help "you must specify an install program" + + test -n "$prev" && \ + func_fatal_help "the '$prev' option requires an argument" + + if test -n "$install_override_mode" && $no_mode; then + if $install_cp; then :; else + func_quote_arg pretty "$install_override_mode" + func_append install_shared_prog " -m $func_quote_arg_result" + fi + fi + + if test -z "$files"; then + if test -z "$dest"; then + func_fatal_help "no file or destination specified" + else + func_fatal_help "you must specify a destination" + fi + fi + + # Strip any trailing slash from the destination. + func_stripname '' '/' "$dest" + dest=$func_stripname_result + + # Check to see that the destination is a directory. + test -d "$dest" && isdir=: + if $isdir; then + destdir=$dest + destname= + else + func_dirname_and_basename "$dest" "" "." + destdir=$func_dirname_result + destname=$func_basename_result + + # Not a directory, so check to see that there is only one file specified. + set dummy $files; shift + test "$#" -gt 1 && \ + func_fatal_help "'$dest' is not a directory" + fi + case $destdir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + for file in $files; do + case $file in + *.lo) ;; + *) + func_fatal_help "'$destdir' must be an absolute directory name" + ;; + esac + done + ;; + esac + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic=$magic + + staticlibs= + future_libdirs= + current_libdirs= + for file in $files; do + + # Do each installation. + case $file in + *.$libext) + # Do the static libraries later. + func_append staticlibs " $file" + ;; + + *.la) + func_resolve_sysroot "$file" + file=$func_resolve_sysroot_result + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$file" \ + || func_fatal_help "'$file' is not a valid libtool archive" + + library_names= + old_library= + relink_command= + func_source "$file" + + # Add the libdir to current_libdirs if it is the destination. + if test "X$destdir" = "X$libdir"; then + case "$current_libdirs " in + *" $libdir "*) ;; + *) func_append current_libdirs " $libdir" ;; + esac + else + # Note the libdir as a future libdir. + case "$future_libdirs " in + *" $libdir "*) ;; + *) func_append future_libdirs " $libdir" ;; + esac + fi + + func_dirname "$file" "/" "" + dir=$func_dirname_result + func_append dir "$objdir" + + if test -n "$relink_command"; then + # Determine the prefix the user has applied to our future dir. + inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"` + + # Don't allow the user to place us outside of our expected + # location b/c this prevents finding dependent libraries that + # are installed to the same prefix. + # At present, this check doesn't affect windows .dll's that + # are installed into $libdir/../bin (currently, that works fine) + # but it's something to keep an eye on. + test "$inst_prefix_dir" = "$destdir" && \ + func_fatal_error "error: cannot install '$file' to a directory not ending in $libdir" + + if test -n "$inst_prefix_dir"; then + # Stick the inst_prefix_dir data into the link command. + relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` + else + relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"` + fi + + func_warning "relinking '$file'" + func_show_eval "$relink_command" \ + 'func_fatal_error "error: relink '\''$file'\'' with the above command before installing it"' + fi + + # See the names of the shared library. + set dummy $library_names; shift + if test -n "$1"; then + realname=$1 + shift + + srcname=$realname + test -n "$relink_command" && srcname=${realname}T + + # Install the shared library and build the symlinks. + func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \ + 'exit $?' + tstripme=$stripme + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + case $realname in + *.dll.a) + tstripme= + ;; + esac + ;; + os2*) + case $realname in + *_dll.a) + tstripme= + ;; + esac + ;; + esac + if test -n "$tstripme" && test -n "$striplib"; then + func_show_eval "$striplib $destdir/$realname" 'exit $?' + fi + + if test "$#" -gt 0; then + # Delete the old symlinks, and create new ones. + # Try 'ln -sf' first, because the 'ln' binary might depend on + # the symlink we replace! Solaris /bin/ln does not understand -f, + # so we also need to try rm && ln -s. + for linkname + do + test "$linkname" != "$realname" \ + && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })" + done + fi + + # Do each command in the postinstall commands. + lib=$destdir/$realname + func_execute_cmds "$postinstall_cmds" 'exit $?' + fi + + # Install the pseudo-library for information purposes. + func_basename "$file" + name=$func_basename_result + instname=$dir/${name}i + func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' + + # Maybe install the static library, too. + test -n "$old_library" && func_append staticlibs " $dir/$old_library" + ;; + + *.lo) + # Install (i.e. copy) a libtool object. + + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile=$destdir/$destname + else + func_basename "$file" + destfile=$func_basename_result + destfile=$destdir/$destfile + fi + + # Deduce the name of the destination old-style object file. + case $destfile in + *.lo) + func_lo2o "$destfile" + staticdest=$func_lo2o_result + ;; + *.$objext) + staticdest=$destfile + destfile= + ;; + *) + func_fatal_help "cannot copy a libtool object to '$destfile'" + ;; + esac + + # Install the libtool object if requested. + test -n "$destfile" && \ + func_show_eval "$install_prog $file $destfile" 'exit $?' + + # Install the old object if enabled. + if test yes = "$build_old_libs"; then + # Deduce the name of the old-style object file. + func_lo2o "$file" + staticobj=$func_lo2o_result + func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?' + fi + exit $EXIT_SUCCESS + ;; + + *) + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile=$destdir/$destname + else + func_basename "$file" + destfile=$func_basename_result + destfile=$destdir/$destfile + fi + + # If the file is missing, and there is a .exe on the end, strip it + # because it is most likely a libtool script we actually want to + # install + stripped_ext= + case $file in + *.exe) + if test ! -f "$file"; then + func_stripname '' '.exe' "$file" + file=$func_stripname_result + stripped_ext=.exe + fi + ;; + esac + + # Do a test to see if this is really a libtool program. + case $host in + *cygwin* | *mingw*) + if func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + wrapper=$func_ltwrapper_scriptname_result + else + func_stripname '' '.exe' "$file" + wrapper=$func_stripname_result + fi + ;; + *) + wrapper=$file + ;; + esac + if func_ltwrapper_script_p "$wrapper"; then + notinst_deplibs= + relink_command= + + func_source "$wrapper" + + # Check the variables that should have been set. + test -z "$generated_by_libtool_version" && \ + func_fatal_error "invalid libtool wrapper script '$wrapper'" + + finalize=: + for lib in $notinst_deplibs; do + # Check to see that each library is installed. + libdir= + if test -f "$lib"; then + func_source "$lib" + fi + libfile=$libdir/`$ECHO "$lib" | $SED 's%^.*/%%g'` + if test -n "$libdir" && test ! -f "$libfile"; then + func_warning "'$lib' has not been installed in '$libdir'" + finalize=false + fi + done + + relink_command= + func_source "$wrapper" + + outputname= + if test no = "$fast_install" && test -n "$relink_command"; then + $opt_dry_run || { + if $finalize; then + tmpdir=`func_mktempdir` + func_basename "$file$stripped_ext" + file=$func_basename_result + outputname=$tmpdir/$file + # Replace the output file specification. + relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'` + + $opt_quiet || { + func_quote_arg expand,pretty "$relink_command" + eval "func_echo $func_quote_arg_result" + } + if eval "$relink_command"; then : + else + func_error "error: relink '$file' with the above command before installing it" + $opt_dry_run || ${RM}r "$tmpdir" + continue + fi + file=$outputname + else + func_warning "cannot relink '$file'" + fi + } + else + # Install the binary that we compiled earlier. + file=`$ECHO "$file$stripped_ext" | $SED "s%\([^/]*\)$%$objdir/\1%"` + fi + fi + + # remove .exe since cygwin /usr/bin/install will append another + # one anyway + case $install_prog,$host in + */usr/bin/install*,*cygwin*) + case $file:$destfile in + *.exe:*.exe) + # this is ok + ;; + *.exe:*) + destfile=$destfile.exe + ;; + *:*.exe) + func_stripname '' '.exe' "$destfile" + destfile=$func_stripname_result + ;; + esac + ;; + esac + func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?' + $opt_dry_run || if test -n "$outputname"; then + ${RM}r "$tmpdir" + fi + ;; + esac + done + + for file in $staticlibs; do + func_basename "$file" + name=$func_basename_result + + # Set up the ranlib parameters. + oldlib=$destdir/$name + func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 + tool_oldlib=$func_to_tool_file_result + + func_show_eval "$install_prog \$file \$oldlib" 'exit $?' + + if test -n "$stripme" && test -n "$old_striplib"; then + func_show_eval "$old_striplib $tool_oldlib" 'exit $?' + fi + + # Do each command in the postinstall commands. + func_execute_cmds "$old_postinstall_cmds" 'exit $?' + done + + test -n "$future_libdirs" && \ + func_warning "remember to run '$progname --finish$future_libdirs'" + + if test -n "$current_libdirs"; then + # Maybe just do a dry run. + $opt_dry_run && current_libdirs=" -n$current_libdirs" + exec_cmd='$SHELL "$progpath" $preserve_args --finish$current_libdirs' + else + exit $EXIT_SUCCESS + fi +} + +test install = "$opt_mode" && func_mode_install ${1+"$@"} + + +# func_generate_dlsyms outputname originator pic_p +# Extract symbols from dlprefiles and create ${outputname}S.o with +# a dlpreopen symbol table. +func_generate_dlsyms () +{ + $debug_cmd + + my_outputname=$1 + my_originator=$2 + my_pic_p=${3-false} + my_prefix=`$ECHO "$my_originator" | $SED 's%[^a-zA-Z0-9]%_%g'` + my_dlsyms= + + if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then + if test -n "$NM" && test -n "$global_symbol_pipe"; then + my_dlsyms=${my_outputname}S.c + else + func_error "not configured to extract global symbols from dlpreopened files" + fi + fi + + if test -n "$my_dlsyms"; then + case $my_dlsyms in + "") ;; + *.c) + # Discover the nlist of each of the dlfiles. + nlist=$output_objdir/$my_outputname.nm + + func_show_eval "$RM $nlist ${nlist}S ${nlist}T" + + # Parse the name list into a source file. + func_verbose "creating $output_objdir/$my_dlsyms" + + $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\ +/* $my_dlsyms - symbol resolution table for '$my_outputname' dlsym emulation. */ +/* Generated by $PROGRAM (GNU $PACKAGE) $VERSION */ + +#ifdef __cplusplus +extern \"C\" { +#endif + +#if defined __GNUC__ && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4)) +#pragma GCC diagnostic ignored \"-Wstrict-prototypes\" +#endif + +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE +/* DATA imports from DLLs on WIN32 can't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT_DLSYM_CONST +#elif defined __osf__ +/* This system does not cope well with relocations in const data. */ +# define LT_DLSYM_CONST +#else +# define LT_DLSYM_CONST const +#endif + +#define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0) + +/* External symbol declarations for the compiler. */\ +" + + if test yes = "$dlself"; then + func_verbose "generating symbol list for '$output'" + + $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" + + # Add our own program objects to the symbol list. + progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP` + for progfile in $progfiles; do + func_to_tool_file "$progfile" func_convert_file_msys_to_w32 + func_verbose "extracting global C symbols from '$func_to_tool_file_result'" + $opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'" + done + + if test -n "$exclude_expsyms"; then + $opt_dry_run || { + eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + } + fi + + if test -n "$export_symbols_regex"; then + $opt_dry_run || { + eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + } + fi + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + export_symbols=$output_objdir/$outputname.exp + $opt_dry_run || { + $RM $export_symbols + eval "$SED -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' + case $host in + *cygwin* | *mingw* | *cegcc* ) + eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' + ;; + esac + } + else + $opt_dry_run || { + eval "$SED -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' + eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + case $host in + *cygwin* | *mingw* | *cegcc* ) + eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' + ;; + esac + } + fi + fi + + for dlprefile in $dlprefiles; do + func_verbose "extracting global C symbols from '$dlprefile'" + func_basename "$dlprefile" + name=$func_basename_result + case $host in + *cygwin* | *mingw* | *cegcc* ) + # if an import library, we need to obtain dlname + if func_win32_import_lib_p "$dlprefile"; then + func_tr_sh "$dlprefile" + eval "curr_lafile=\$libfile_$func_tr_sh_result" + dlprefile_dlbasename= + if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then + # Use subshell, to avoid clobbering current variable values + dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"` + if test -n "$dlprefile_dlname"; then + func_basename "$dlprefile_dlname" + dlprefile_dlbasename=$func_basename_result + else + # no lafile. user explicitly requested -dlpreopen . + $sharedlib_from_linklib_cmd "$dlprefile" + dlprefile_dlbasename=$sharedlib_from_linklib_result + fi + fi + $opt_dry_run || { + if test -n "$dlprefile_dlbasename"; then + eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"' + else + func_warning "Could not compute DLL name from $name" + eval '$ECHO ": $name " >> "$nlist"' + fi + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe | + $SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' >> '$nlist'" + } + else # not an import lib + $opt_dry_run || { + eval '$ECHO ": $name " >> "$nlist"' + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" + } + fi + ;; + *) + $opt_dry_run || { + eval '$ECHO ": $name " >> "$nlist"' + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" + } + ;; + esac + done + + $opt_dry_run || { + # Make sure we have at least an empty file. + test -f "$nlist" || : > "$nlist" + + if test -n "$exclude_expsyms"; then + $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T + $MV "$nlist"T "$nlist" + fi + + # Try sorting and uniquifying the output. + if $GREP -v "^: " < "$nlist" | + if sort -k 3 /dev/null 2>&1; then + sort -k 3 + else + sort +2 + fi | + uniq > "$nlist"S; then + : + else + $GREP -v "^: " < "$nlist" > "$nlist"S + fi + + if test -f "$nlist"S; then + eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"' + else + echo '/* NONE */' >> "$output_objdir/$my_dlsyms" + fi + + func_show_eval '$RM "${nlist}I"' + if test -n "$global_symbol_to_import"; then + eval "$global_symbol_to_import"' < "$nlist"S > "$nlist"I' + fi + + echo >> "$output_objdir/$my_dlsyms" "\ + +/* The mapping between symbol names and symbols. */ +typedef struct { + const char *name; + void *address; +} lt_dlsymlist; +extern LT_DLSYM_CONST lt_dlsymlist +lt_${my_prefix}_LTX_preloaded_symbols[];\ +" + + if test -s "$nlist"I; then + echo >> "$output_objdir/$my_dlsyms" "\ +static void lt_syminit(void) +{ + LT_DLSYM_CONST lt_dlsymlist *symbol = lt_${my_prefix}_LTX_preloaded_symbols; + for (; symbol->name; ++symbol) + {" + $SED 's/.*/ if (STREQ (symbol->name, \"&\")) symbol->address = (void *) \&&;/' < "$nlist"I >> "$output_objdir/$my_dlsyms" + echo >> "$output_objdir/$my_dlsyms" "\ + } +}" + fi + echo >> "$output_objdir/$my_dlsyms" "\ +LT_DLSYM_CONST lt_dlsymlist +lt_${my_prefix}_LTX_preloaded_symbols[] = +{ {\"$my_originator\", (void *) 0}," + + if test -s "$nlist"I; then + echo >> "$output_objdir/$my_dlsyms" "\ + {\"@INIT@\", (void *) <_syminit}," + fi + + case $need_lib_prefix in + no) + eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms" + ;; + *) + eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms" + ;; + esac + echo >> "$output_objdir/$my_dlsyms" "\ + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt_${my_prefix}_LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif\ +" + } # !$opt_dry_run + + pic_flag_for_symtable= + case "$compile_command " in + *" -static "*) ;; + *) + case $host in + # compiling the symbol table file with pic_flag works around + # a FreeBSD bug that causes programs to crash when -lm is + # linked before any other PIC object. But we must not use + # pic_flag when linking with -static. The problem exists in + # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. + *-*-freebsd2.*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) + pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;; + *-*-hpux*) + pic_flag_for_symtable=" $pic_flag" ;; + *) + $my_pic_p && pic_flag_for_symtable=" $pic_flag" + ;; + esac + ;; + esac + symtab_cflags= + for arg in $LTCFLAGS; do + case $arg in + -pie | -fpie | -fPIE) ;; + *) func_append symtab_cflags " $arg" ;; + esac + done + + # Now compile the dynamic symbol file. + func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' + + # Clean up the generated files. + func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T" "${nlist}I"' + + # Transform the symbol file into the correct name. + symfileobj=$output_objdir/${my_outputname}S.$objext + case $host in + *cygwin* | *mingw* | *cegcc* ) + if test -f "$output_objdir/$my_outputname.def"; then + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` + else + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` + fi + ;; + *) + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` + ;; + esac + ;; + *) + func_fatal_error "unknown suffix for '$my_dlsyms'" + ;; + esac + else + # We keep going just in case the user didn't refer to + # lt_preloaded_symbols. The linker will fail if global_symbol_pipe + # really was required. + + # Nullify the symbol file. + compile_command=`$ECHO "$compile_command" | $SED "s% @SYMFILE@%%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"` + fi +} + +# func_cygming_gnu_implib_p ARG +# This predicate returns with zero status (TRUE) if +# ARG is a GNU/binutils-style import library. Returns +# with nonzero status (FALSE) otherwise. +func_cygming_gnu_implib_p () +{ + $debug_cmd + + func_to_tool_file "$1" func_convert_file_msys_to_w32 + func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'` + test -n "$func_cygming_gnu_implib_tmp" +} + +# func_cygming_ms_implib_p ARG +# This predicate returns with zero status (TRUE) if +# ARG is an MS-style import library. Returns +# with nonzero status (FALSE) otherwise. +func_cygming_ms_implib_p () +{ + $debug_cmd + + func_to_tool_file "$1" func_convert_file_msys_to_w32 + func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'` + test -n "$func_cygming_ms_implib_tmp" +} + +# func_win32_libid arg +# return the library type of file 'arg' +# +# Need a lot of goo to handle *both* DLLs and import libs +# Has to be a shell function in order to 'eat' the argument +# that is supplied when $file_magic_command is called. +# Despite the name, also deal with 64 bit binaries. +func_win32_libid () +{ + $debug_cmd + + win32_libid_type=unknown + win32_fileres=`file -L $1 2>/dev/null` + case $win32_fileres in + *ar\ archive\ import\ library*) # definitely import + win32_libid_type="x86 archive import" + ;; + *ar\ archive*) # could be an import, or static + # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD. + if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | + $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then + case $nm_interface in + "MS dumpbin") + if func_cygming_ms_implib_p "$1" || + func_cygming_gnu_implib_p "$1" + then + win32_nmres=import + else + win32_nmres= + fi + ;; + *) + func_to_tool_file "$1" func_convert_file_msys_to_w32 + win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" | + $SED -n -e ' + 1,100{ + / I /{ + s|.*|import| + p + q + } + }'` + ;; + esac + case $win32_nmres in + import*) win32_libid_type="x86 archive import";; + *) win32_libid_type="x86 archive static";; + esac + fi + ;; + *DLL*) + win32_libid_type="x86 DLL" + ;; + *executable*) # but shell scripts are "executable" too... + case $win32_fileres in + *MS\ Windows\ PE\ Intel*) + win32_libid_type="x86 DLL" + ;; + esac + ;; + esac + $ECHO "$win32_libid_type" +} + +# func_cygming_dll_for_implib ARG +# +# Platform-specific function to extract the +# name of the DLL associated with the specified +# import library ARG. +# Invoked by eval'ing the libtool variable +# $sharedlib_from_linklib_cmd +# Result is available in the variable +# $sharedlib_from_linklib_result +func_cygming_dll_for_implib () +{ + $debug_cmd + + sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"` +} + +# func_cygming_dll_for_implib_fallback_core SECTION_NAME LIBNAMEs +# +# The is the core of a fallback implementation of a +# platform-specific function to extract the name of the +# DLL associated with the specified import library LIBNAME. +# +# SECTION_NAME is either .idata$6 or .idata$7, depending +# on the platform and compiler that created the implib. +# +# Echos the name of the DLL associated with the +# specified import library. +func_cygming_dll_for_implib_fallback_core () +{ + $debug_cmd + + match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"` + $OBJDUMP -s --section "$1" "$2" 2>/dev/null | + $SED '/^Contents of section '"$match_literal"':/{ + # Place marker at beginning of archive member dllname section + s/.*/====MARK====/ + p + d + } + # These lines can sometimes be longer than 43 characters, but + # are always uninteresting + /:[ ]*file format pe[i]\{,1\}-/d + /^In archive [^:]*:/d + # Ensure marker is printed + /^====MARK====/p + # Remove all lines with less than 43 characters + /^.\{43\}/!d + # From remaining lines, remove first 43 characters + s/^.\{43\}//' | + $SED -n ' + # Join marker and all lines until next marker into a single line + /^====MARK====/ b para + H + $ b para + b + :para + x + s/\n//g + # Remove the marker + s/^====MARK====// + # Remove trailing dots and whitespace + s/[\. \t]*$// + # Print + /./p' | + # we now have a list, one entry per line, of the stringified + # contents of the appropriate section of all members of the + # archive that possess that section. Heuristic: eliminate + # all those that have a first or second character that is + # a '.' (that is, objdump's representation of an unprintable + # character.) This should work for all archives with less than + # 0x302f exports -- but will fail for DLLs whose name actually + # begins with a literal '.' or a single character followed by + # a '.'. + # + # Of those that remain, print the first one. + $SED -e '/^\./d;/^.\./d;q' +} + +# func_cygming_dll_for_implib_fallback ARG +# Platform-specific function to extract the +# name of the DLL associated with the specified +# import library ARG. +# +# This fallback implementation is for use when $DLLTOOL +# does not support the --identify-strict option. +# Invoked by eval'ing the libtool variable +# $sharedlib_from_linklib_cmd +# Result is available in the variable +# $sharedlib_from_linklib_result +func_cygming_dll_for_implib_fallback () +{ + $debug_cmd + + if func_cygming_gnu_implib_p "$1"; then + # binutils import library + sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"` + elif func_cygming_ms_implib_p "$1"; then + # ms-generated import library + sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"` + else + # unknown + sharedlib_from_linklib_result= + fi +} + + +# func_extract_an_archive dir oldlib +func_extract_an_archive () +{ + $debug_cmd + + f_ex_an_ar_dir=$1; shift + f_ex_an_ar_oldlib=$1 + if test yes = "$lock_old_archive_extraction"; then + lockfile=$f_ex_an_ar_oldlib.lock + until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do + func_echo "Waiting for $lockfile to be removed" + sleep 2 + done + fi + func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \ + 'stat=$?; rm -f "$lockfile"; exit $stat' + if test yes = "$lock_old_archive_extraction"; then + $opt_dry_run || rm -f "$lockfile" + fi + if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then + : + else + func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" + fi +} + + +# func_extract_archives gentop oldlib ... +func_extract_archives () +{ + $debug_cmd + + my_gentop=$1; shift + my_oldlibs=${1+"$@"} + my_oldobjs= + my_xlib= + my_xabs= + my_xdir= + + for my_xlib in $my_oldlibs; do + # Extract the objects. + case $my_xlib in + [\\/]* | [A-Za-z]:[\\/]*) my_xabs=$my_xlib ;; + *) my_xabs=`pwd`"/$my_xlib" ;; + esac + func_basename "$my_xlib" + my_xlib=$func_basename_result + my_xlib_u=$my_xlib + while :; do + case " $extracted_archives " in + *" $my_xlib_u "*) + func_arith $extracted_serial + 1 + extracted_serial=$func_arith_result + my_xlib_u=lt$extracted_serial-$my_xlib ;; + *) break ;; + esac + done + extracted_archives="$extracted_archives $my_xlib_u" + my_xdir=$my_gentop/$my_xlib_u + + func_mkdir_p "$my_xdir" + + case $host in + *-darwin*) + func_verbose "Extracting $my_xabs" + # Do not bother doing anything if just a dry run + $opt_dry_run || { + darwin_orig_dir=`pwd` + cd $my_xdir || exit $? + darwin_archive=$my_xabs + darwin_curdir=`pwd` + func_basename "$darwin_archive" + darwin_base_archive=$func_basename_result + darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` + if test -n "$darwin_arches"; then + darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` + darwin_arch= + func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" + for darwin_arch in $darwin_arches; do + func_mkdir_p "unfat-$$/$darwin_base_archive-$darwin_arch" + $LIPO -thin $darwin_arch -output "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" "$darwin_archive" + cd "unfat-$$/$darwin_base_archive-$darwin_arch" + func_extract_an_archive "`pwd`" "$darwin_base_archive" + cd "$darwin_curdir" + $RM "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" + done # $darwin_arches + ## Okay now we've a bunch of thin objects, gotta fatten them up :) + darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$sed_basename" | sort -u` + darwin_file= + darwin_files= + for darwin_file in $darwin_filelist; do + darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP` + $LIPO -create -output "$darwin_file" $darwin_files + done # $darwin_filelist + $RM -rf unfat-$$ + cd "$darwin_orig_dir" + else + cd $darwin_orig_dir + func_extract_an_archive "$my_xdir" "$my_xabs" + fi # $darwin_arches + } # !$opt_dry_run + ;; + *) + func_extract_an_archive "$my_xdir" "$my_xabs" + ;; + esac + my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP` + done + + func_extract_archives_result=$my_oldobjs +} + + +# func_emit_wrapper [arg=no] +# +# Emit a libtool wrapper script on stdout. +# Don't directly open a file because we may want to +# incorporate the script contents within a cygwin/mingw +# wrapper executable. Must ONLY be called from within +# func_mode_link because it depends on a number of variables +# set therein. +# +# ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR +# variable will take. If 'yes', then the emitted script +# will assume that the directory where it is stored is +# the $objdir directory. This is a cygwin/mingw-specific +# behavior. +func_emit_wrapper () +{ + func_emit_wrapper_arg1=${1-no} + + $ECHO "\ +#! $SHELL + +# $output - temporary wrapper script for $objdir/$outputname +# Generated by $PROGRAM (GNU $PACKAGE) $VERSION +# +# The $output program cannot be directly executed until all the libtool +# libraries that it depends on are installed. +# +# This wrapper script should never be moved out of the build directory. +# If it is, it will not operate correctly. + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +sed_quote_subst='$sed_quote_subst' + +# Be Bourne compatible +if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs 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 +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +relink_command=\"$relink_command\" + +# This environment variable determines our operation mode. +if test \"\$libtool_install_magic\" = \"$magic\"; then + # install mode needs the following variables: + generated_by_libtool_version='$macro_version' + notinst_deplibs='$notinst_deplibs' +else + # When we are sourced in execute mode, \$file and \$ECHO are already set. + if test \"\$libtool_execute_magic\" != \"$magic\"; then + file=\"\$0\"" + + func_quote_arg pretty "$ECHO" + qECHO=$func_quote_arg_result + $ECHO "\ + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$1 +_LTECHO_EOF' +} + ECHO=$qECHO + fi + +# Very basic option parsing. These options are (a) specific to +# the libtool wrapper, (b) are identical between the wrapper +# /script/ and the wrapper /executable/ that is used only on +# windows platforms, and (c) all begin with the string "--lt-" +# (application programs are unlikely to have options that match +# this pattern). +# +# There are only two supported options: --lt-debug and +# --lt-dump-script. There is, deliberately, no --lt-help. +# +# The first argument to this parsing function should be the +# script's $0 value, followed by "$@". +lt_option_debug= +func_parse_lt_options () +{ + lt_script_arg0=\$0 + shift + for lt_opt + do + case \"\$lt_opt\" in + --lt-debug) lt_option_debug=1 ;; + --lt-dump-script) + lt_dump_D=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%/[^/]*$%%'\` + test \"X\$lt_dump_D\" = \"X\$lt_script_arg0\" && lt_dump_D=. + lt_dump_F=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%^.*/%%'\` + cat \"\$lt_dump_D/\$lt_dump_F\" + exit 0 + ;; + --lt-*) + \$ECHO \"Unrecognized --lt- option: '\$lt_opt'\" 1>&2 + exit 1 + ;; + esac + done + + # Print the debug banner immediately: + if test -n \"\$lt_option_debug\"; then + echo \"$outputname:$output:\$LINENO: libtool wrapper (GNU $PACKAGE) $VERSION\" 1>&2 + fi +} + +# Used when --lt-debug. Prints its arguments to stdout +# (redirection is the responsibility of the caller) +func_lt_dump_args () +{ + lt_dump_args_N=1; + for lt_arg + do + \$ECHO \"$outputname:$output:\$LINENO: newargv[\$lt_dump_args_N]: \$lt_arg\" + lt_dump_args_N=\`expr \$lt_dump_args_N + 1\` + done +} + +# Core function for launching the target application +func_exec_program_core () +{ +" + case $host in + # Backslashes separate directories on plain windows + *-*-mingw | *-*-os2* | *-cegcc*) + $ECHO "\ + if test -n \"\$lt_option_debug\"; then + \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir\\\\\$program\" 1>&2 + func_lt_dump_args \${1+\"\$@\"} 1>&2 + fi + exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} +" + ;; + + *) + $ECHO "\ + if test -n \"\$lt_option_debug\"; then + \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir/\$program\" 1>&2 + func_lt_dump_args \${1+\"\$@\"} 1>&2 + fi + exec \"\$progdir/\$program\" \${1+\"\$@\"} +" + ;; + esac + $ECHO "\ + \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 + exit 1 +} + +# A function to encapsulate launching the target application +# Strips options in the --lt-* namespace from \$@ and +# launches target application with the remaining arguments. +func_exec_program () +{ + case \" \$* \" in + *\\ --lt-*) + for lt_wr_arg + do + case \$lt_wr_arg in + --lt-*) ;; + *) set x \"\$@\" \"\$lt_wr_arg\"; shift;; + esac + shift + done ;; + esac + func_exec_program_core \${1+\"\$@\"} +} + + # Parse options + func_parse_lt_options \"\$0\" \${1+\"\$@\"} + + # Find the directory that this script lives in. + thisdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*$%%'\` + test \"x\$thisdir\" = \"x\$file\" && thisdir=. + + # Follow symbolic links until we get to the real thisdir. + file=\`ls -ld \"\$file\" | $SED -n 's/.*-> //p'\` + while test -n \"\$file\"; do + destdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*\$%%'\` + + # If there was a directory component, then change thisdir. + if test \"x\$destdir\" != \"x\$file\"; then + case \"\$destdir\" in + [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; + *) thisdir=\"\$thisdir/\$destdir\" ;; + esac + fi + + file=\`\$ECHO \"\$file\" | $SED 's%^.*/%%'\` + file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\` + done + + # Usually 'no', except on cygwin/mingw when embedded into + # the cwrapper. + WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1 + if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then + # special case for '.' + if test \"\$thisdir\" = \".\"; then + thisdir=\`pwd\` + fi + # remove .libs from thisdir + case \"\$thisdir\" in + *[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;; + $objdir ) thisdir=. ;; + esac + fi + + # Try to get the absolute directory name. + absdir=\`cd \"\$thisdir\" && pwd\` + test -n \"\$absdir\" && thisdir=\"\$absdir\" +" + + if test yes = "$fast_install"; then + $ECHO "\ + program=lt-'$outputname'$exeext + progdir=\"\$thisdir/$objdir\" + + if test ! -f \"\$progdir/\$program\" || + { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | $SED 1q\`; \\ + test \"X\$file\" != \"X\$progdir/\$program\"; }; then + + file=\"\$\$-\$program\" + + if test ! -d \"\$progdir\"; then + $MKDIR \"\$progdir\" + else + $RM \"\$progdir/\$file\" + fi" + + $ECHO "\ + + # relink executable if necessary + if test -n \"\$relink_command\"; then + if relink_command_output=\`eval \$relink_command 2>&1\`; then : + else + \$ECHO \"\$relink_command_output\" >&2 + $RM \"\$progdir/\$file\" + exit 1 + fi + fi + + $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || + { $RM \"\$progdir/\$program\"; + $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; } + $RM \"\$progdir/\$file\" + fi" + else + $ECHO "\ + program='$outputname' + progdir=\"\$thisdir/$objdir\" +" + fi + + $ECHO "\ + + if test -f \"\$progdir/\$program\"; then" + + # fixup the dll searchpath if we need to. + # + # Fix the DLL searchpath if we need to. Do this before prepending + # to shlibpath, because on Windows, both are PATH and uninstalled + # libraries must come first. + if test -n "$dllsearchpath"; then + $ECHO "\ + # Add the dll search path components to the executable PATH + PATH=$dllsearchpath:\$PATH +" + fi + + # Export our shlibpath_var if we have one. + if test yes = "$shlibpath_overrides_runpath" && test -n "$shlibpath_var" && test -n "$temp_rpath"; then + $ECHO "\ + # Add our own library path to $shlibpath_var + $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" + + # Some systems cannot cope with colon-terminated $shlibpath_var + # The second colon is a workaround for a bug in BeOS R4 sed + $shlibpath_var=\`\$ECHO \"\$$shlibpath_var\" | $SED 's/::*\$//'\` + + export $shlibpath_var +" + fi + + $ECHO "\ + if test \"\$libtool_execute_magic\" != \"$magic\"; then + # Run the actual program with our arguments. + func_exec_program \${1+\"\$@\"} + fi + else + # The program doesn't exist. + \$ECHO \"\$0: error: '\$progdir/\$program' does not exist\" 1>&2 + \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 + \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 + exit 1 + fi +fi\ +" +} + + +# func_emit_cwrapperexe_src +# emit the source code for a wrapper executable on stdout +# Must ONLY be called from within func_mode_link because +# it depends on a number of variable set therein. +func_emit_cwrapperexe_src () +{ + cat < +#include +#ifdef _MSC_VER +# include +# include +# include +#else +# include +# include +# ifdef __CYGWIN__ +# include +# endif +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +#define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0) + +/* declarations of non-ANSI functions */ +#if defined __MINGW32__ +# ifdef __STRICT_ANSI__ +int _putenv (const char *); +# endif +#elif defined __CYGWIN__ +# ifdef __STRICT_ANSI__ +char *realpath (const char *, char *); +int putenv (char *); +int setenv (const char *, const char *, int); +# endif +/* #elif defined other_platform || defined ... */ +#endif + +/* portability defines, excluding path handling macros */ +#if defined _MSC_VER +# define setmode _setmode +# define stat _stat +# define chmod _chmod +# define getcwd _getcwd +# define putenv _putenv +# define S_IXUSR _S_IEXEC +#elif defined __MINGW32__ +# define setmode _setmode +# define stat _stat +# define chmod _chmod +# define getcwd _getcwd +# define putenv _putenv +#elif defined __CYGWIN__ +# define HAVE_SETENV +# define FOPEN_WB "wb" +/* #elif defined other platforms ... */ +#endif + +#if defined PATH_MAX +# define LT_PATHMAX PATH_MAX +#elif defined MAXPATHLEN +# define LT_PATHMAX MAXPATHLEN +#else +# define LT_PATHMAX 1024 +#endif + +#ifndef S_IXOTH +# define S_IXOTH 0 +#endif +#ifndef S_IXGRP +# define S_IXGRP 0 +#endif + +/* path handling portability macros */ +#ifndef DIR_SEPARATOR +# define DIR_SEPARATOR '/' +# define PATH_SEPARATOR ':' +#endif + +#if defined _WIN32 || defined __MSDOS__ || defined __DJGPP__ || \ + defined __OS2__ +# define HAVE_DOS_BASED_FILE_SYSTEM +# define FOPEN_WB "wb" +# ifndef DIR_SEPARATOR_2 +# define DIR_SEPARATOR_2 '\\' +# endif +# ifndef PATH_SEPARATOR_2 +# define PATH_SEPARATOR_2 ';' +# endif +#endif + +#ifndef DIR_SEPARATOR_2 +# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) +#else /* DIR_SEPARATOR_2 */ +# define IS_DIR_SEPARATOR(ch) \ + (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) +#endif /* DIR_SEPARATOR_2 */ + +#ifndef PATH_SEPARATOR_2 +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) +#else /* PATH_SEPARATOR_2 */ +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) +#endif /* PATH_SEPARATOR_2 */ + +#ifndef FOPEN_WB +# define FOPEN_WB "w" +#endif +#ifndef _O_BINARY +# define _O_BINARY 0 +#endif + +#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) +#define XFREE(stale) do { \ + if (stale) { free (stale); stale = 0; } \ +} while (0) + +#if defined LT_DEBUGWRAPPER +static int lt_debug = 1; +#else +static int lt_debug = 0; +#endif + +const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */ + +void *xmalloc (size_t num); +char *xstrdup (const char *string); +const char *base_name (const char *name); +char *find_executable (const char *wrapper); +char *chase_symlinks (const char *pathspec); +int make_executable (const char *path); +int check_executable (const char *path); +char *strendzap (char *str, const char *pat); +void lt_debugprintf (const char *file, int line, const char *fmt, ...); +void lt_fatal (const char *file, int line, const char *message, ...); +static const char *nonnull (const char *s); +static const char *nonempty (const char *s); +void lt_setenv (const char *name, const char *value); +char *lt_extend_str (const char *orig_value, const char *add, int to_end); +void lt_update_exe_path (const char *name, const char *value); +void lt_update_lib_path (const char *name, const char *value); +char **prepare_spawn (char **argv); +void lt_dump_script (FILE *f); +EOF + + cat <= 0) + && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) + return 1; + else + return 0; +} + +int +make_executable (const char *path) +{ + int rval = 0; + struct stat st; + + lt_debugprintf (__FILE__, __LINE__, "(make_executable): %s\n", + nonempty (path)); + if ((!path) || (!*path)) + return 0; + + if (stat (path, &st) >= 0) + { + rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR); + } + return rval; +} + +/* Searches for the full path of the wrapper. Returns + newly allocated full path name if found, NULL otherwise + Does not chase symlinks, even on platforms that support them. +*/ +char * +find_executable (const char *wrapper) +{ + int has_slash = 0; + const char *p; + const char *p_next; + /* static buffer for getcwd */ + char tmp[LT_PATHMAX + 1]; + size_t tmp_len; + char *concat_name; + + lt_debugprintf (__FILE__, __LINE__, "(find_executable): %s\n", + nonempty (wrapper)); + + if ((wrapper == NULL) || (*wrapper == '\0')) + return NULL; + + /* Absolute path? */ +#if defined HAVE_DOS_BASED_FILE_SYSTEM + if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':') + { + concat_name = xstrdup (wrapper); + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } + else + { +#endif + if (IS_DIR_SEPARATOR (wrapper[0])) + { + concat_name = xstrdup (wrapper); + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } +#if defined HAVE_DOS_BASED_FILE_SYSTEM + } +#endif + + for (p = wrapper; *p; p++) + if (*p == '/') + { + has_slash = 1; + break; + } + if (!has_slash) + { + /* no slashes; search PATH */ + const char *path = getenv ("PATH"); + if (path != NULL) + { + for (p = path; *p; p = p_next) + { + const char *q; + size_t p_len; + for (q = p; *q; q++) + if (IS_PATH_SEPARATOR (*q)) + break; + p_len = (size_t) (q - p); + p_next = (*q == '\0' ? q : q + 1); + if (p_len == 0) + { + /* empty path: current directory */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", + nonnull (strerror (errno))); + tmp_len = strlen (tmp); + concat_name = + XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + } + else + { + concat_name = + XMALLOC (char, p_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, p, p_len); + concat_name[p_len] = '/'; + strcpy (concat_name + p_len + 1, wrapper); + } + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } + } + /* not found in PATH; assume curdir */ + } + /* Relative path | not found in path: prepend cwd */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", + nonnull (strerror (errno))); + tmp_len = strlen (tmp); + concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + return NULL; +} + +char * +chase_symlinks (const char *pathspec) +{ +#ifndef S_ISLNK + return xstrdup (pathspec); +#else + char buf[LT_PATHMAX]; + struct stat s; + char *tmp_pathspec = xstrdup (pathspec); + char *p; + int has_symlinks = 0; + while (strlen (tmp_pathspec) && !has_symlinks) + { + lt_debugprintf (__FILE__, __LINE__, + "checking path component for symlinks: %s\n", + tmp_pathspec); + if (lstat (tmp_pathspec, &s) == 0) + { + if (S_ISLNK (s.st_mode) != 0) + { + has_symlinks = 1; + break; + } + + /* search backwards for last DIR_SEPARATOR */ + p = tmp_pathspec + strlen (tmp_pathspec) - 1; + while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) + p--; + if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) + { + /* no more DIR_SEPARATORS left */ + break; + } + *p = '\0'; + } + else + { + lt_fatal (__FILE__, __LINE__, + "error accessing file \"%s\": %s", + tmp_pathspec, nonnull (strerror (errno))); + } + } + XFREE (tmp_pathspec); + + if (!has_symlinks) + { + return xstrdup (pathspec); + } + + tmp_pathspec = realpath (pathspec, buf); + if (tmp_pathspec == 0) + { + lt_fatal (__FILE__, __LINE__, + "could not follow symlinks for %s", pathspec); + } + return xstrdup (tmp_pathspec); +#endif +} + +char * +strendzap (char *str, const char *pat) +{ + size_t len, patlen; + + assert (str != NULL); + assert (pat != NULL); + + len = strlen (str); + patlen = strlen (pat); + + if (patlen <= len) + { + str += len - patlen; + if (STREQ (str, pat)) + *str = '\0'; + } + return str; +} + +void +lt_debugprintf (const char *file, int line, const char *fmt, ...) +{ + va_list args; + if (lt_debug) + { + (void) fprintf (stderr, "%s:%s:%d: ", program_name, file, line); + va_start (args, fmt); + (void) vfprintf (stderr, fmt, args); + va_end (args); + } +} + +static void +lt_error_core (int exit_status, const char *file, + int line, const char *mode, + const char *message, va_list ap) +{ + fprintf (stderr, "%s:%s:%d: %s: ", program_name, file, line, mode); + vfprintf (stderr, message, ap); + fprintf (stderr, ".\n"); + + if (exit_status >= 0) + exit (exit_status); +} + +void +lt_fatal (const char *file, int line, const char *message, ...) +{ + va_list ap; + va_start (ap, message); + lt_error_core (EXIT_FAILURE, file, line, "FATAL", message, ap); + va_end (ap); +} + +static const char * +nonnull (const char *s) +{ + return s ? s : "(null)"; +} + +static const char * +nonempty (const char *s) +{ + return (s && !*s) ? "(empty)" : nonnull (s); +} + +void +lt_setenv (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_setenv) setting '%s' to '%s'\n", + nonnull (name), nonnull (value)); + { +#ifdef HAVE_SETENV + /* always make a copy, for consistency with !HAVE_SETENV */ + char *str = xstrdup (value); + setenv (name, str, 1); +#else + size_t len = strlen (name) + 1 + strlen (value) + 1; + char *str = XMALLOC (char, len); + sprintf (str, "%s=%s", name, value); + if (putenv (str) != EXIT_SUCCESS) + { + XFREE (str); + } +#endif + } +} + +char * +lt_extend_str (const char *orig_value, const char *add, int to_end) +{ + char *new_value; + if (orig_value && *orig_value) + { + size_t orig_value_len = strlen (orig_value); + size_t add_len = strlen (add); + new_value = XMALLOC (char, add_len + orig_value_len + 1); + if (to_end) + { + strcpy (new_value, orig_value); + strcpy (new_value + orig_value_len, add); + } + else + { + strcpy (new_value, add); + strcpy (new_value + add_len, orig_value); + } + } + else + { + new_value = xstrdup (add); + } + return new_value; +} + +void +lt_update_exe_path (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_update_exe_path) modifying '%s' by prepending '%s'\n", + nonnull (name), nonnull (value)); + + if (name && *name && value && *value) + { + char *new_value = lt_extend_str (getenv (name), value, 0); + /* some systems can't cope with a ':'-terminated path #' */ + size_t len = strlen (new_value); + while ((len > 0) && IS_PATH_SEPARATOR (new_value[len-1])) + { + new_value[--len] = '\0'; + } + lt_setenv (name, new_value); + XFREE (new_value); + } +} + +void +lt_update_lib_path (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_update_lib_path) modifying '%s' by prepending '%s'\n", + nonnull (name), nonnull (value)); + + if (name && *name && value && *value) + { + char *new_value = lt_extend_str (getenv (name), value, 0); + lt_setenv (name, new_value); + XFREE (new_value); + } +} + +EOF + case $host_os in + mingw*) + cat <<"EOF" + +/* Prepares an argument vector before calling spawn(). + Note that spawn() does not by itself call the command interpreter + (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") : + ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&v); + v.dwPlatformId == VER_PLATFORM_WIN32_NT; + }) ? "cmd.exe" : "command.com"). + Instead it simply concatenates the arguments, separated by ' ', and calls + CreateProcess(). We must quote the arguments since Win32 CreateProcess() + interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a + special way: + - Space and tab are interpreted as delimiters. They are not treated as + delimiters if they are surrounded by double quotes: "...". + - Unescaped double quotes are removed from the input. Their only effect is + that within double quotes, space and tab are treated like normal + characters. + - Backslashes not followed by double quotes are not special. + - But 2*n+1 backslashes followed by a double quote become + n backslashes followed by a double quote (n >= 0): + \" -> " + \\\" -> \" + \\\\\" -> \\" + */ +#define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" +#define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" +char ** +prepare_spawn (char **argv) +{ + size_t argc; + char **new_argv; + size_t i; + + /* Count number of arguments. */ + for (argc = 0; argv[argc] != NULL; argc++) + ; + + /* Allocate new argument vector. */ + new_argv = XMALLOC (char *, argc + 1); + + /* Put quoted arguments into the new argument vector. */ + for (i = 0; i < argc; i++) + { + const char *string = argv[i]; + + if (string[0] == '\0') + new_argv[i] = xstrdup ("\"\""); + else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL) + { + int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL); + size_t length; + unsigned int backslashes; + const char *s; + char *quoted_string; + char *p; + + length = 0; + backslashes = 0; + if (quote_around) + length++; + for (s = string; *s != '\0'; s++) + { + char c = *s; + if (c == '"') + length += backslashes + 1; + length++; + if (c == '\\') + backslashes++; + else + backslashes = 0; + } + if (quote_around) + length += backslashes + 1; + + quoted_string = XMALLOC (char, length + 1); + + p = quoted_string; + backslashes = 0; + if (quote_around) + *p++ = '"'; + for (s = string; *s != '\0'; s++) + { + char c = *s; + if (c == '"') + { + unsigned int j; + for (j = backslashes + 1; j > 0; j--) + *p++ = '\\'; + } + *p++ = c; + if (c == '\\') + backslashes++; + else + backslashes = 0; + } + if (quote_around) + { + unsigned int j; + for (j = backslashes; j > 0; j--) + *p++ = '\\'; + *p++ = '"'; + } + *p = '\0'; + + new_argv[i] = quoted_string; + } + else + new_argv[i] = (char *) string; + } + new_argv[argc] = NULL; + + return new_argv; +} +EOF + ;; + esac + + cat <<"EOF" +void lt_dump_script (FILE* f) +{ +EOF + func_emit_wrapper yes | + $SED -n -e ' +s/^\(.\{79\}\)\(..*\)/\1\ +\2/ +h +s/\([\\"]\)/\\\1/g +s/$/\\n/ +s/\([^\n]*\).*/ fputs ("\1", f);/p +g +D' + cat <<"EOF" +} +EOF +} +# end: func_emit_cwrapperexe_src + +# func_win32_import_lib_p ARG +# True if ARG is an import lib, as indicated by $file_magic_cmd +func_win32_import_lib_p () +{ + $debug_cmd + + case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in + *import*) : ;; + *) false ;; + esac +} + +# func_suncc_cstd_abi +# !!ONLY CALL THIS FOR SUN CC AFTER $compile_command IS FULLY EXPANDED!! +# Several compiler flags select an ABI that is incompatible with the +# Cstd library. Avoid specifying it if any are in CXXFLAGS. +func_suncc_cstd_abi () +{ + $debug_cmd + + case " $compile_command " in + *" -compat=g "*|*\ -std=c++[0-9][0-9]\ *|*" -library=stdcxx4 "*|*" -library=stlport4 "*) + suncc_use_cstd_abi=no + ;; + *) + suncc_use_cstd_abi=yes + ;; + esac +} + +# func_mode_link arg... +func_mode_link () +{ + $debug_cmd + + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + # It is impossible to link a dll without this setting, and + # we shouldn't force the makefile maintainer to figure out + # what system we are compiling for in order to pass an extra + # flag for every libtool invocation. + # allow_undefined=no + + # FIXME: Unfortunately, there are problems with the above when trying + # to make a dll that has undefined symbols, in which case not + # even a static library is built. For now, we need to specify + # -no-undefined on the libtool link line when we can be certain + # that all symbols are satisfied, otherwise we get a static library. + allow_undefined=yes + ;; + *) + allow_undefined=yes + ;; + esac + libtool_args=$nonopt + base_compile="$nonopt $@" + compile_command=$nonopt + finalize_command=$nonopt + + compile_rpath= + finalize_rpath= + compile_shlibpath= + finalize_shlibpath= + convenience= + old_convenience= + deplibs= + old_deplibs= + compiler_flags= + linker_flags= + dllsearchpath= + lib_search_path=`pwd` + inst_prefix_dir= + new_inherited_linker_flags= + + avoid_version=no + bindir= + dlfiles= + dlprefiles= + dlself=no + export_dynamic=no + export_symbols= + export_symbols_regex= + generated= + libobjs= + ltlibs= + module=no + no_install=no + objs= + os2dllname= + non_pic_objects= + precious_files_regex= + prefer_static_libs=no + preload=false + prev= + prevarg= + release= + rpath= + xrpath= + perm_rpath= + temp_rpath= + thread_safe=no + vinfo= + vinfo_number=no + weak_libs= + single_module=$wl-single_module + func_infer_tag $base_compile + + # We need to know -static, to get the right output filenames. + for arg + do + case $arg in + -shared) + test yes != "$build_libtool_libs" \ + && func_fatal_configuration "cannot build a shared library" + build_old_libs=no + break + ;; + -all-static | -static | -static-libtool-libs) + case $arg in + -all-static) + if test yes = "$build_libtool_libs" && test -z "$link_static_flag"; then + func_warning "complete static linking is impossible in this configuration" + fi + if test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + ;; + -static) + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=built + ;; + -static-libtool-libs) + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + ;; + esac + build_libtool_libs=no + build_old_libs=yes + break + ;; + esac + done + + # See if our shared archives depend on static archives. + test -n "$old_archive_from_new_cmds" && build_old_libs=yes + + # Go through the arguments, transforming them on the way. + while test "$#" -gt 0; do + arg=$1 + shift + func_quote_arg pretty,unquoted "$arg" + qarg=$func_quote_arg_unquoted_result + func_append libtool_args " $func_quote_arg_result" + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case $prev in + output) + func_append compile_command " @OUTPUT@" + func_append finalize_command " @OUTPUT@" + ;; + esac + + case $prev in + bindir) + bindir=$arg + prev= + continue + ;; + dlfiles|dlprefiles) + $preload || { + # Add the symbol object into the linking commands. + func_append compile_command " @SYMFILE@" + func_append finalize_command " @SYMFILE@" + preload=: + } + case $arg in + *.la | *.lo) ;; # We handle these cases below. + force) + if test no = "$dlself"; then + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + self) + if test dlprefiles = "$prev"; then + dlself=yes + elif test dlfiles = "$prev" && test yes != "$dlopen_self"; then + dlself=yes + else + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + *) + if test dlfiles = "$prev"; then + func_append dlfiles " $arg" + else + func_append dlprefiles " $arg" + fi + prev= + continue + ;; + esac + ;; + expsyms) + export_symbols=$arg + test -f "$arg" \ + || func_fatal_error "symbol file '$arg' does not exist" + prev= + continue + ;; + expsyms_regex) + export_symbols_regex=$arg + prev= + continue + ;; + framework) + case $host in + *-*-darwin*) + case "$deplibs " in + *" $qarg.ltframework "*) ;; + *) func_append deplibs " $qarg.ltframework" # this is fixed later + ;; + esac + ;; + esac + prev= + continue + ;; + inst_prefix) + inst_prefix_dir=$arg + prev= + continue + ;; + mllvm) + # Clang does not use LLVM to link, so we can simply discard any + # '-mllvm $arg' options when doing the link step. + prev= + continue + ;; + objectlist) + if test -f "$arg"; then + save_arg=$arg + moreargs= + for fil in `cat "$save_arg"` + do +# func_append moreargs " $fil" + arg=$fil + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if func_lalib_unsafe_p "$arg"; then + pic_object= + non_pic_object= + + # Read the .lo file + func_source "$arg" + + if test -z "$pic_object" || + test -z "$non_pic_object" || + test none = "$pic_object" && + test none = "$non_pic_object"; then + func_fatal_error "cannot find name of object for '$arg'" + fi + + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + if test none != "$pic_object"; then + # Prepend the subdirectory the object is found in. + pic_object=$xdir$pic_object + + if test dlfiles = "$prev"; then + if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then + func_append dlfiles " $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test dlprefiles = "$prev"; then + # Preload the old-style object. + func_append dlprefiles " $pic_object" + prev= + fi + + # A PIC object. + func_append libobjs " $pic_object" + arg=$pic_object + fi + + # Non-PIC object. + if test none != "$non_pic_object"; then + # Prepend the subdirectory the object is found in. + non_pic_object=$xdir$non_pic_object + + # A standard non-PIC object + func_append non_pic_objects " $non_pic_object" + if test -z "$pic_object" || test none = "$pic_object"; then + arg=$non_pic_object + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object=$pic_object + func_append non_pic_objects " $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if $opt_dry_run; then + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + func_lo2o "$arg" + pic_object=$xdir$objdir/$func_lo2o_result + non_pic_object=$xdir$func_lo2o_result + func_append libobjs " $pic_object" + func_append non_pic_objects " $non_pic_object" + else + func_fatal_error "'$arg' is not a valid libtool object" + fi + fi + done + else + func_fatal_error "link input file '$arg' does not exist" + fi + arg=$save_arg + prev= + continue + ;; + os2dllname) + os2dllname=$arg + prev= + continue + ;; + precious_regex) + precious_files_regex=$arg + prev= + continue + ;; + release) + release=-$arg + prev= + continue + ;; + rpath | xrpath) + # We need an absolute path. + case $arg in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + func_fatal_error "only absolute run-paths are allowed" + ;; + esac + if test rpath = "$prev"; then + case "$rpath " in + *" $arg "*) ;; + *) func_append rpath " $arg" ;; + esac + else + case "$xrpath " in + *" $arg "*) ;; + *) func_append xrpath " $arg" ;; + esac + fi + prev= + continue + ;; + shrext) + shrext_cmds=$arg + prev= + continue + ;; + weak) + func_append weak_libs " $arg" + prev= + continue + ;; + xcclinker) + func_append linker_flags " $qarg" + func_append compiler_flags " $qarg" + prev= + func_append compile_command " $qarg" + func_append finalize_command " $qarg" + continue + ;; + xcompiler) + func_append compiler_flags " $qarg" + prev= + func_append compile_command " $qarg" + func_append finalize_command " $qarg" + continue + ;; + xlinker) + func_append linker_flags " $qarg" + func_append compiler_flags " $wl$qarg" + prev= + func_append compile_command " $wl$qarg" + func_append finalize_command " $wl$qarg" + continue + ;; + *) + eval "$prev=\"\$arg\"" + prev= + continue + ;; + esac + fi # test -n "$prev" + + prevarg=$arg + + case $arg in + -all-static) + if test -n "$link_static_flag"; then + # See comment for -static flag below, for more details. + func_append compile_command " $link_static_flag" + func_append finalize_command " $link_static_flag" + fi + continue + ;; + + -allow-undefined) + # FIXME: remove this flag sometime in the future. + func_fatal_error "'-allow-undefined' must not be used because it is the default" + ;; + + -avoid-version) + avoid_version=yes + continue + ;; + + -bindir) + prev=bindir + continue + ;; + + -dlopen) + prev=dlfiles + continue + ;; + + -dlpreopen) + prev=dlprefiles + continue + ;; + + -export-dynamic) + export_dynamic=yes + continue + ;; + + -export-symbols | -export-symbols-regex) + if test -n "$export_symbols" || test -n "$export_symbols_regex"; then + func_fatal_error "more than one -exported-symbols argument is not allowed" + fi + if test X-export-symbols = "X$arg"; then + prev=expsyms + else + prev=expsyms_regex + fi + continue + ;; + + -framework) + prev=framework + continue + ;; + + -inst-prefix-dir) + prev=inst_prefix + continue + ;; + + # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* + # so, if we see these flags be careful not to treat them like -L + -L[A-Z][A-Z]*:*) + case $with_gcc/$host in + no/*-*-irix* | /*-*-irix*) + func_append compile_command " $arg" + func_append finalize_command " $arg" + ;; + esac + continue + ;; + + -L*) + func_stripname "-L" '' "$arg" + if test -z "$func_stripname_result"; then + if test "$#" -gt 0; then + func_fatal_error "require no space between '-L' and '$1'" + else + func_fatal_error "need path for '-L' option" + fi + fi + func_resolve_sysroot "$func_stripname_result" + dir=$func_resolve_sysroot_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + absdir=`cd "$dir" && pwd` + test -z "$absdir" && \ + func_fatal_error "cannot determine absolute directory name of '$dir'" + dir=$absdir + ;; + esac + case "$deplibs " in + *" -L$dir "* | *" $arg "*) + # Will only happen for absolute or sysroot arguments + ;; + *) + # Preserve sysroot, but never include relative directories + case $dir in + [\\/]* | [A-Za-z]:[\\/]* | =*) func_append deplibs " $arg" ;; + *) func_append deplibs " -L$dir" ;; + esac + func_append lib_search_path " $dir" + ;; + esac + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$dir:"*) ;; + ::) dllsearchpath=$dir;; + *) func_append dllsearchpath ":$dir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + ::) dllsearchpath=$testbindir;; + *) func_append dllsearchpath ":$testbindir";; + esac + ;; + esac + continue + ;; + + -l*) + if test X-lc = "X$arg" || test X-lm = "X$arg"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*) + # These systems don't actually have a C or math library (as such) + continue + ;; + *-*-os2*) + # These systems don't actually have a C library (as such) + test X-lc = "X$arg" && continue + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*) + # Do not include libc due to us having libc/libc_r. + test X-lc = "X$arg" && continue + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C and math libraries are in the System framework + func_append deplibs " System.ltframework" + continue + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + test X-lc = "X$arg" && continue + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + test X-lc = "X$arg" && continue + ;; + esac + elif test X-lc_r = "X$arg"; then + case $host in + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*) + # Do not include libc_r directly, use -pthread flag. + continue + ;; + esac + fi + func_append deplibs " $arg" + continue + ;; + + -mllvm) + prev=mllvm + continue + ;; + + -module) + module=yes + continue + ;; + + # Tru64 UNIX uses -model [arg] to determine the layout of C++ + # classes, name mangling, and exception handling. + # Darwin uses the -arch flag to determine output architecture. + -model|-arch|-isysroot|--sysroot) + func_append compiler_flags " $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + prev=xcompiler + continue + ;; + + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ + |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) + func_append compiler_flags " $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + case "$new_inherited_linker_flags " in + *" $arg "*) ;; + * ) func_append new_inherited_linker_flags " $arg" ;; + esac + continue + ;; + + -multi_module) + single_module=$wl-multi_module + continue + ;; + + -no-fast-install) + fast_install=no + continue + ;; + + -no-install) + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) + # The PATH hackery in wrapper scripts is required on Windows + # and Darwin in order for the loader to find any dlls it needs. + func_warning "'-no-install' is ignored for $host" + func_warning "assuming '-no-fast-install' instead" + fast_install=no + ;; + *) no_install=yes ;; + esac + continue + ;; + + -no-undefined) + allow_undefined=no + continue + ;; + + -objectlist) + prev=objectlist + continue + ;; + + -os2dllname) + prev=os2dllname + continue + ;; + + -o) prev=output ;; + + -precious-files-regex) + prev=precious_regex + continue + ;; + + -release) + prev=release + continue + ;; + + -rpath) + prev=rpath + continue + ;; + + -R) + prev=xrpath + continue + ;; + + -R*) + func_stripname '-R' '' "$arg" + dir=$func_stripname_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + =*) + func_stripname '=' '' "$dir" + dir=$lt_sysroot$func_stripname_result + ;; + *) + func_fatal_error "only absolute run-paths are allowed" + ;; + esac + case "$xrpath " in + *" $dir "*) ;; + *) func_append xrpath " $dir" ;; + esac + continue + ;; + + -shared) + # The effects of -shared are defined in a previous loop. + continue + ;; + + -shrext) + prev=shrext + continue + ;; + + -static | -static-libtool-libs) + # The effects of -static are defined in a previous loop. + # We used to do the same as -all-static on platforms that + # didn't have a PIC flag, but the assumption that the effects + # would be equivalent was wrong. It would break on at least + # Digital Unix and AIX. + continue + ;; + + -thread-safe) + thread_safe=yes + continue + ;; + + -version-info) + prev=vinfo + continue + ;; + + -version-number) + prev=vinfo + vinfo_number=yes + continue + ;; + + -weak) + prev=weak + continue + ;; + + -Wc,*) + func_stripname '-Wc,' '' "$arg" + args=$func_stripname_result + arg= + save_ifs=$IFS; IFS=, + for flag in $args; do + IFS=$save_ifs + func_quote_arg pretty "$flag" + func_append arg " $func_quote_arg_result" + func_append compiler_flags " $func_quote_arg_result" + done + IFS=$save_ifs + func_stripname ' ' '' "$arg" + arg=$func_stripname_result + ;; + + -Wl,*) + func_stripname '-Wl,' '' "$arg" + args=$func_stripname_result + arg= + save_ifs=$IFS; IFS=, + for flag in $args; do + IFS=$save_ifs + func_quote_arg pretty "$flag" + func_append arg " $wl$func_quote_arg_result" + func_append compiler_flags " $wl$func_quote_arg_result" + func_append linker_flags " $func_quote_arg_result" + done + IFS=$save_ifs + func_stripname ' ' '' "$arg" + arg=$func_stripname_result + ;; + + -Xcompiler) + prev=xcompiler + continue + ;; + + -Xlinker) + prev=xlinker + continue + ;; + + -XCClinker) + prev=xcclinker + continue + ;; + + # -msg_* for osf cc + -msg_*) + func_quote_arg pretty "$arg" + arg=$func_quote_arg_result + ;; + + # Flags to be passed through unchanged, with rationale: + # -64, -mips[0-9] enable 64-bit mode for the SGI compiler + # -r[0-9][0-9]* specify processor for the SGI compiler + # -xarch=*, -xtarget=* enable 64-bit mode for the Sun compiler + # +DA*, +DD* enable 64-bit mode for the HP compiler + # -q* compiler args for the IBM compiler + # -m*, -t[45]*, -txscale* architecture-specific flags for GCC + # -F/path path to uninstalled frameworks, gcc on darwin + # -p, -pg, --coverage, -fprofile-* profiling flags for GCC + # -fstack-protector* stack protector flags for GCC + # @file GCC response files + # -tp=* Portland pgcc target processor selection + # --sysroot=* for sysroot support + # -O*, -g*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization + # -specs=* GCC specs files + # -stdlib=* select c++ std lib with clang + # -fsanitize=* Clang/GCC memory and address sanitizer + -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ + -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \ + -O*|-g*|-flto*|-fwhopr*|-fuse-linker-plugin|-fstack-protector*|-stdlib=*| \ + -specs=*|-fsanitize=*) + func_quote_arg pretty "$arg" + arg=$func_quote_arg_result + func_append compile_command " $arg" + func_append finalize_command " $arg" + func_append compiler_flags " $arg" + continue + ;; + + -Z*) + if test os2 = "`expr $host : '.*\(os2\)'`"; then + # OS/2 uses -Zxxx to specify OS/2-specific options + compiler_flags="$compiler_flags $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + case $arg in + -Zlinker | -Zstack) + prev=xcompiler + ;; + esac + continue + else + # Otherwise treat like 'Some other compiler flag' below + func_quote_arg pretty "$arg" + arg=$func_quote_arg_result + fi + ;; + + # Some other compiler flag. + -* | +*) + func_quote_arg pretty "$arg" + arg=$func_quote_arg_result + ;; + + *.$objext) + # A standard object. + func_append objs " $arg" + ;; + + *.lo) + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if func_lalib_unsafe_p "$arg"; then + pic_object= + non_pic_object= + + # Read the .lo file + func_source "$arg" + + if test -z "$pic_object" || + test -z "$non_pic_object" || + test none = "$pic_object" && + test none = "$non_pic_object"; then + func_fatal_error "cannot find name of object for '$arg'" + fi + + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + test none = "$pic_object" || { + # Prepend the subdirectory the object is found in. + pic_object=$xdir$pic_object + + if test dlfiles = "$prev"; then + if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then + func_append dlfiles " $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test dlprefiles = "$prev"; then + # Preload the old-style object. + func_append dlprefiles " $pic_object" + prev= + fi + + # A PIC object. + func_append libobjs " $pic_object" + arg=$pic_object + } + + # Non-PIC object. + if test none != "$non_pic_object"; then + # Prepend the subdirectory the object is found in. + non_pic_object=$xdir$non_pic_object + + # A standard non-PIC object + func_append non_pic_objects " $non_pic_object" + if test -z "$pic_object" || test none = "$pic_object"; then + arg=$non_pic_object + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object=$pic_object + func_append non_pic_objects " $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if $opt_dry_run; then + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + func_lo2o "$arg" + pic_object=$xdir$objdir/$func_lo2o_result + non_pic_object=$xdir$func_lo2o_result + func_append libobjs " $pic_object" + func_append non_pic_objects " $non_pic_object" + else + func_fatal_error "'$arg' is not a valid libtool object" + fi + fi + ;; + + *.$libext) + # An archive. + func_append deplibs " $arg" + func_append old_deplibs " $arg" + continue + ;; + + *.la) + # A libtool-controlled library. + + func_resolve_sysroot "$arg" + if test dlfiles = "$prev"; then + # This library was specified with -dlopen. + func_append dlfiles " $func_resolve_sysroot_result" + prev= + elif test dlprefiles = "$prev"; then + # The library was specified with -dlpreopen. + func_append dlprefiles " $func_resolve_sysroot_result" + prev= + else + func_append deplibs " $func_resolve_sysroot_result" + fi + continue + ;; + + # Some other compiler argument. + *) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + func_quote_arg pretty "$arg" + arg=$func_quote_arg_result + ;; + esac # arg + + # Now actually substitute the argument into the commands. + if test -n "$arg"; then + func_append compile_command " $arg" + func_append finalize_command " $arg" + fi + done # argument parsing loop + + test -n "$prev" && \ + func_fatal_help "the '$prevarg' option requires an argument" + + if test yes = "$export_dynamic" && test -n "$export_dynamic_flag_spec"; then + eval arg=\"$export_dynamic_flag_spec\" + func_append compile_command " $arg" + func_append finalize_command " $arg" + fi + + oldlibs= + # calculate the name of the file, without its directory + func_basename "$output" + outputname=$func_basename_result + libobjs_save=$libobjs + + if test -n "$shlibpath_var"; then + # get the directories listed in $shlibpath_var + eval shlib_search_path=\`\$ECHO \"\$$shlibpath_var\" \| \$SED \'s/:/ /g\'\` + else + shlib_search_path= + fi + eval sys_lib_search_path=\"$sys_lib_search_path_spec\" + eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" + + # Definition is injected by LT_CONFIG during libtool generation. + func_munge_path_list sys_lib_dlsearch_path "$LT_SYS_LIBRARY_PATH" + + func_dirname "$output" "/" "" + output_objdir=$func_dirname_result$objdir + func_to_tool_file "$output_objdir/" + tool_output_objdir=$func_to_tool_file_result + # Create the object directory. + func_mkdir_p "$output_objdir" + + # Determine the type of output + case $output in + "") + func_fatal_help "you must specify an output file" + ;; + *.$libext) linkmode=oldlib ;; + *.lo | *.$objext) linkmode=obj ;; + *.la) linkmode=lib ;; + *) linkmode=prog ;; # Anything else should be a program. + esac + + specialdeplibs= + + libs= + # Find all interdependent deplibs by searching for libraries + # that are linked more than once (e.g. -la -lb -la) + for deplib in $deplibs; do + if $opt_preserve_dup_deps; then + case "$libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append libs " $deplib" + done + + if test lib = "$linkmode"; then + libs="$predeps $libs $compiler_lib_search_path $postdeps" + + # Compute libraries that are listed more than once in $predeps + # $postdeps and mark them as special (i.e., whose duplicates are + # not to be eliminated). + pre_post_deps= + if $opt_duplicate_compiler_generated_deps; then + for pre_post_dep in $predeps $postdeps; do + case "$pre_post_deps " in + *" $pre_post_dep "*) func_append specialdeplibs " $pre_post_deps" ;; + esac + func_append pre_post_deps " $pre_post_dep" + done + fi + pre_post_deps= + fi + + deplibs= + newdependency_libs= + newlib_search_path= + need_relink=no # whether we're linking any uninstalled libtool libraries + notinst_deplibs= # not-installed libtool libraries + notinst_path= # paths that contain not-installed libtool libraries + + case $linkmode in + lib) + passes="conv dlpreopen link" + for file in $dlfiles $dlprefiles; do + case $file in + *.la) ;; + *) + func_fatal_help "libraries can '-dlopen' only libtool libraries: $file" + ;; + esac + done + ;; + prog) + compile_deplibs= + finalize_deplibs= + alldeplibs=false + newdlfiles= + newdlprefiles= + passes="conv scan dlopen dlpreopen link" + ;; + *) passes="conv" + ;; + esac + + for pass in $passes; do + # The preopen pass in lib mode reverses $deplibs; put it back here + # so that -L comes before libs that need it for instance... + if test lib,link = "$linkmode,$pass"; then + ## FIXME: Find the place where the list is rebuilt in the wrong + ## order, and fix it there properly + tmp_deplibs= + for deplib in $deplibs; do + tmp_deplibs="$deplib $tmp_deplibs" + done + deplibs=$tmp_deplibs + fi + + if test lib,link = "$linkmode,$pass" || + test prog,scan = "$linkmode,$pass"; then + libs=$deplibs + deplibs= + fi + if test prog = "$linkmode"; then + case $pass in + dlopen) libs=$dlfiles ;; + dlpreopen) libs=$dlprefiles ;; + link) + libs="$deplibs %DEPLIBS%" + test "X$link_all_deplibs" != Xno && libs="$libs $dependency_libs" + ;; + esac + fi + if test lib,dlpreopen = "$linkmode,$pass"; then + # Collect and forward deplibs of preopened libtool libs + for lib in $dlprefiles; do + # Ignore non-libtool-libs + dependency_libs= + func_resolve_sysroot "$lib" + case $lib in + *.la) func_source "$func_resolve_sysroot_result" ;; + esac + + # Collect preopened libtool deplibs, except any this library + # has declared as weak libs + for deplib in $dependency_libs; do + func_basename "$deplib" + deplib_base=$func_basename_result + case " $weak_libs " in + *" $deplib_base "*) ;; + *) func_append deplibs " $deplib" ;; + esac + done + done + libs=$dlprefiles + fi + if test dlopen = "$pass"; then + # Collect dlpreopened libraries + save_deplibs=$deplibs + deplibs= + fi + + for deplib in $libs; do + lib= + found=false + case $deplib in + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ + |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + func_append compiler_flags " $deplib" + if test lib = "$linkmode"; then + case "$new_inherited_linker_flags " in + *" $deplib "*) ;; + * ) func_append new_inherited_linker_flags " $deplib" ;; + esac + fi + fi + continue + ;; + -l*) + if test lib != "$linkmode" && test prog != "$linkmode"; then + func_warning "'-l' is ignored for archives/objects" + continue + fi + func_stripname '-l' '' "$deplib" + name=$func_stripname_result + if test lib = "$linkmode"; then + searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" + else + searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" + fi + for searchdir in $searchdirs; do + for search_ext in .la $std_shrext .so .a; do + # Search the libtool library + lib=$searchdir/lib$name$search_ext + if test -f "$lib"; then + if test .la = "$search_ext"; then + found=: + else + found=false + fi + break 2 + fi + done + done + if $found; then + # deplib is a libtool library + # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, + # We need to do some special things here, and not later. + if test yes = "$allow_libtool_libs_with_static_runtimes"; then + case " $predeps $postdeps " in + *" $deplib "*) + if func_lalib_p "$lib"; then + library_names= + old_library= + func_source "$lib" + for l in $old_library $library_names; do + ll=$l + done + if test "X$ll" = "X$old_library"; then # only static version available + found=false + func_dirname "$lib" "" "." + ladir=$func_dirname_result + lib=$ladir/$old_library + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs" + fi + continue + fi + fi + ;; + *) ;; + esac + fi + else + # deplib doesn't seem to be a libtool library + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs" + fi + continue + fi + ;; # -l + *.ltframework) + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + if test lib = "$linkmode"; then + case "$new_inherited_linker_flags " in + *" $deplib "*) ;; + * ) func_append new_inherited_linker_flags " $deplib" ;; + esac + fi + fi + continue + ;; + -L*) + case $linkmode in + lib) + deplibs="$deplib $deplibs" + test conv = "$pass" && continue + newdependency_libs="$deplib $newdependency_libs" + func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + prog) + if test conv = "$pass"; then + deplibs="$deplib $deplibs" + continue + fi + if test scan = "$pass"; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + *) + func_warning "'-L' is ignored for archives/objects" + ;; + esac # linkmode + continue + ;; # -L + -R*) + if test link = "$pass"; then + func_stripname '-R' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + dir=$func_resolve_sysroot_result + # Make sure the xrpath contains only unique directories. + case "$xrpath " in + *" $dir "*) ;; + *) func_append xrpath " $dir" ;; + esac + fi + deplibs="$deplib $deplibs" + continue + ;; + *.la) + func_resolve_sysroot "$deplib" + lib=$func_resolve_sysroot_result + ;; + *.$libext) + if test conv = "$pass"; then + deplibs="$deplib $deplibs" + continue + fi + case $linkmode in + lib) + # Linking convenience modules into shared libraries is allowed, + # but linking other static libraries is non-portable. + case " $dlpreconveniencelibs " in + *" $deplib "*) ;; + *) + valid_a_lib=false + case $deplibs_check_method in + match_pattern*) + set dummy $deplibs_check_method; shift + match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` + if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \ + | $EGREP "$match_pattern_regex" > /dev/null; then + valid_a_lib=: + fi + ;; + pass_all) + valid_a_lib=: + ;; + esac + if $valid_a_lib; then + echo + $ECHO "*** Warning: Linking the shared library $output against the" + $ECHO "*** static library $deplib is not portable!" + deplibs="$deplib $deplibs" + else + echo + $ECHO "*** Warning: Trying to link with static lib archive $deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because the file extensions .$libext of this argument makes me believe" + echo "*** that it is just a static archive that I should not use here." + fi + ;; + esac + continue + ;; + prog) + if test link != "$pass"; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + continue + ;; + esac # linkmode + ;; # *.$libext + *.lo | *.$objext) + if test conv = "$pass"; then + deplibs="$deplib $deplibs" + elif test prog = "$linkmode"; then + if test dlpreopen = "$pass" || test yes != "$dlopen_support" || test no = "$build_libtool_libs"; then + # If there is no dlopen support or we're linking statically, + # we need to preload. + func_append newdlprefiles " $deplib" + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + func_append newdlfiles " $deplib" + fi + fi + continue + ;; + %DEPLIBS%) + alldeplibs=: + continue + ;; + esac # case $deplib + + $found || test -f "$lib" \ + || func_fatal_error "cannot find the library '$lib' or unhandled argument '$deplib'" + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$lib" \ + || func_fatal_error "'$lib' is not a valid libtool archive" + + func_dirname "$lib" "" "." + ladir=$func_dirname_result + + dlname= + dlopen= + dlpreopen= + libdir= + library_names= + old_library= + inherited_linker_flags= + # If the library was installed with an old release of libtool, + # it will not redefine variables installed, or shouldnotlink + installed=yes + shouldnotlink=no + avoidtemprpath= + + + # Read the .la file + func_source "$lib" + + # Convert "-framework foo" to "foo.ltframework" + if test -n "$inherited_linker_flags"; then + tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'` + for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do + case " $new_inherited_linker_flags " in + *" $tmp_inherited_linker_flag "*) ;; + *) func_append new_inherited_linker_flags " $tmp_inherited_linker_flag";; + esac + done + fi + dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + if test lib,link = "$linkmode,$pass" || + test prog,scan = "$linkmode,$pass" || + { test prog != "$linkmode" && test lib != "$linkmode"; }; then + test -n "$dlopen" && func_append dlfiles " $dlopen" + test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen" + fi + + if test conv = "$pass"; then + # Only check for convenience libraries + deplibs="$lib $deplibs" + if test -z "$libdir"; then + if test -z "$old_library"; then + func_fatal_error "cannot find name of link library for '$lib'" + fi + # It is a libtool convenience library, so add in its objects. + func_append convenience " $ladir/$objdir/$old_library" + func_append old_convenience " $ladir/$objdir/$old_library" + tmp_libs= + for deplib in $dependency_libs; do + deplibs="$deplib $deplibs" + if $opt_preserve_dup_deps; then + case "$tmp_libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append tmp_libs " $deplib" + done + elif test prog != "$linkmode" && test lib != "$linkmode"; then + func_fatal_error "'$lib' is not a convenience library" + fi + continue + fi # $pass = conv + + + # Get the name of the library we link against. + linklib= + if test -n "$old_library" && + { test yes = "$prefer_static_libs" || + test built,no = "$prefer_static_libs,$installed"; }; then + linklib=$old_library + else + for l in $old_library $library_names; do + linklib=$l + done + fi + if test -z "$linklib"; then + func_fatal_error "cannot find name of link library for '$lib'" + fi + + # This library was specified with -dlopen. + if test dlopen = "$pass"; then + test -z "$libdir" \ + && func_fatal_error "cannot -dlopen a convenience library: '$lib'" + if test -z "$dlname" || + test yes != "$dlopen_support" || + test no = "$build_libtool_libs" + then + # If there is no dlname, no dlopen support or we're linking + # statically, we need to preload. We also need to preload any + # dependent libraries so libltdl's deplib preloader doesn't + # bomb out in the load deplibs phase. + func_append dlprefiles " $lib $dependency_libs" + else + func_append newdlfiles " $lib" + fi + continue + fi # $pass = dlopen + + # We need an absolute path. + case $ladir in + [\\/]* | [A-Za-z]:[\\/]*) abs_ladir=$ladir ;; + *) + abs_ladir=`cd "$ladir" && pwd` + if test -z "$abs_ladir"; then + func_warning "cannot determine absolute directory name of '$ladir'" + func_warning "passing it literally to the linker, although it might fail" + abs_ladir=$ladir + fi + ;; + esac + func_basename "$lib" + laname=$func_basename_result + + # Find the relevant object directory and library name. + if test yes = "$installed"; then + if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then + func_warning "library '$lib' was moved." + dir=$ladir + absdir=$abs_ladir + libdir=$abs_ladir + else + dir=$lt_sysroot$libdir + absdir=$lt_sysroot$libdir + fi + test yes = "$hardcode_automatic" && avoidtemprpath=yes + else + if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then + dir=$ladir + absdir=$abs_ladir + # Remove this search path later + func_append notinst_path " $abs_ladir" + else + dir=$ladir/$objdir + absdir=$abs_ladir/$objdir + # Remove this search path later + func_append notinst_path " $abs_ladir" + fi + fi # $installed = yes + func_stripname 'lib' '.la' "$laname" + name=$func_stripname_result + + # This library was specified with -dlpreopen. + if test dlpreopen = "$pass"; then + if test -z "$libdir" && test prog = "$linkmode"; then + func_fatal_error "only libraries may -dlpreopen a convenience library: '$lib'" + fi + case $host in + # special handling for platforms with PE-DLLs. + *cygwin* | *mingw* | *cegcc* ) + # Linker will automatically link against shared library if both + # static and shared are present. Therefore, ensure we extract + # symbols from the import library if a shared library is present + # (otherwise, the dlopen module name will be incorrect). We do + # this by putting the import library name into $newdlprefiles. + # We recover the dlopen module name by 'saving' the la file + # name in a special purpose variable, and (later) extracting the + # dlname from the la file. + if test -n "$dlname"; then + func_tr_sh "$dir/$linklib" + eval "libfile_$func_tr_sh_result=\$abs_ladir/\$laname" + func_append newdlprefiles " $dir/$linklib" + else + func_append newdlprefiles " $dir/$old_library" + # Keep a list of preopened convenience libraries to check + # that they are being used correctly in the link pass. + test -z "$libdir" && \ + func_append dlpreconveniencelibs " $dir/$old_library" + fi + ;; + * ) + # Prefer using a static library (so that no silly _DYNAMIC symbols + # are required to link). + if test -n "$old_library"; then + func_append newdlprefiles " $dir/$old_library" + # Keep a list of preopened convenience libraries to check + # that they are being used correctly in the link pass. + test -z "$libdir" && \ + func_append dlpreconveniencelibs " $dir/$old_library" + # Otherwise, use the dlname, so that lt_dlopen finds it. + elif test -n "$dlname"; then + func_append newdlprefiles " $dir/$dlname" + else + func_append newdlprefiles " $dir/$linklib" + fi + ;; + esac + fi # $pass = dlpreopen + + if test -z "$libdir"; then + # Link the convenience library + if test lib = "$linkmode"; then + deplibs="$dir/$old_library $deplibs" + elif test prog,link = "$linkmode,$pass"; then + compile_deplibs="$dir/$old_library $compile_deplibs" + finalize_deplibs="$dir/$old_library $finalize_deplibs" + else + deplibs="$lib $deplibs" # used for prog,scan pass + fi + continue + fi + + + if test prog = "$linkmode" && test link != "$pass"; then + func_append newlib_search_path " $ladir" + deplibs="$lib $deplibs" + + linkalldeplibs=false + if test no != "$link_all_deplibs" || test -z "$library_names" || + test no = "$build_libtool_libs"; then + linkalldeplibs=: + fi + + tmp_libs= + for deplib in $dependency_libs; do + case $deplib in + -L*) func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + esac + # Need to link against all dependency_libs? + if $linkalldeplibs; then + deplibs="$deplib $deplibs" + else + # Need to hardcode shared library paths + # or/and link against static libraries + newdependency_libs="$deplib $newdependency_libs" + fi + if $opt_preserve_dup_deps; then + case "$tmp_libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append tmp_libs " $deplib" + done # for deplib + continue + fi # $linkmode = prog... + + if test prog,link = "$linkmode,$pass"; then + if test -n "$library_names" && + { { test no = "$prefer_static_libs" || + test built,yes = "$prefer_static_libs,$installed"; } || + test -z "$old_library"; }; then + # We need to hardcode the library path + if test -n "$shlibpath_var" && test -z "$avoidtemprpath"; then + # Make sure the rpath contains only unique directories. + case $temp_rpath: in + *"$absdir:"*) ;; + *) func_append temp_rpath "$absdir:" ;; + esac + fi + + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) func_append compile_rpath " $absdir" ;; + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + ;; + esac + fi # $linkmode,$pass = prog,link... + + if $alldeplibs && + { test pass_all = "$deplibs_check_method" || + { test yes = "$build_libtool_libs" && + test -n "$library_names"; }; }; then + # We only need to search for static libraries + continue + fi + fi + + link_static=no # Whether the deplib will be linked statically + use_static_libs=$prefer_static_libs + if test built = "$use_static_libs" && test yes = "$installed"; then + use_static_libs=no + fi + if test -n "$library_names" && + { test no = "$use_static_libs" || test -z "$old_library"; }; then + case $host in + *cygwin* | *mingw* | *cegcc* | *os2*) + # No point in relinking DLLs because paths are not encoded + func_append notinst_deplibs " $lib" + need_relink=no + ;; + *) + if test no = "$installed"; then + func_append notinst_deplibs " $lib" + need_relink=yes + fi + ;; + esac + # This is a shared library + + # Warn about portability, can't link against -module's on some + # systems (darwin). Don't bleat about dlopened modules though! + dlopenmodule= + for dlpremoduletest in $dlprefiles; do + if test "X$dlpremoduletest" = "X$lib"; then + dlopenmodule=$dlpremoduletest + break + fi + done + if test -z "$dlopenmodule" && test yes = "$shouldnotlink" && test link = "$pass"; then + echo + if test prog = "$linkmode"; then + $ECHO "*** Warning: Linking the executable $output against the loadable module" + else + $ECHO "*** Warning: Linking the shared library $output against the loadable module" + fi + $ECHO "*** $linklib is not portable!" + fi + if test lib = "$linkmode" && + test yes = "$hardcode_into_libs"; then + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) func_append compile_rpath " $absdir" ;; + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + ;; + esac + fi + + if test -n "$old_archive_from_expsyms_cmds"; then + # figure out the soname + set dummy $library_names + shift + realname=$1 + shift + libname=`eval "\\$ECHO \"$libname_spec\""` + # use dlname if we got it. it's perfectly good, no? + if test -n "$dlname"; then + soname=$dlname + elif test -n "$soname_spec"; then + # bleh windows + case $host in + *cygwin* | mingw* | *cegcc* | *os2*) + func_arith $current - $age + major=$func_arith_result + versuffix=-$major + ;; + esac + eval soname=\"$soname_spec\" + else + soname=$realname + fi + + # Make a new name for the extract_expsyms_cmds to use + soroot=$soname + func_basename "$soroot" + soname=$func_basename_result + func_stripname 'lib' '.dll' "$soname" + newlib=libimp-$func_stripname_result.a + + # If the library has no export list, then create one now + if test -f "$output_objdir/$soname-def"; then : + else + func_verbose "extracting exported symbol list from '$soname'" + func_execute_cmds "$extract_expsyms_cmds" 'exit $?' + fi + + # Create $newlib + if test -f "$output_objdir/$newlib"; then :; else + func_verbose "generating import library for '$soname'" + func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' + fi + # make sure the library variables are pointing to the new library + dir=$output_objdir + linklib=$newlib + fi # test -n "$old_archive_from_expsyms_cmds" + + if test prog = "$linkmode" || test relink != "$opt_mode"; then + add_shlibpath= + add_dir= + add= + lib_linked=yes + case $hardcode_action in + immediate | unsupported) + if test no = "$hardcode_direct"; then + add=$dir/$linklib + case $host in + *-*-sco3.2v5.0.[024]*) add_dir=-L$dir ;; + *-*-sysv4*uw2*) add_dir=-L$dir ;; + *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ + *-*-unixware7*) add_dir=-L$dir ;; + *-*-darwin* ) + # if the lib is a (non-dlopened) module then we cannot + # link against it, someone is ignoring the earlier warnings + if /usr/bin/file -L $add 2> /dev/null | + $GREP ": [^:]* bundle" >/dev/null; then + if test "X$dlopenmodule" != "X$lib"; then + $ECHO "*** Warning: lib $linklib is a module, not a shared library" + if test -z "$old_library"; then + echo + echo "*** And there doesn't seem to be a static archive available" + echo "*** The link will probably fail, sorry" + else + add=$dir/$old_library + fi + elif test -n "$old_library"; then + add=$dir/$old_library + fi + fi + esac + elif test no = "$hardcode_minus_L"; then + case $host in + *-*-sunos*) add_shlibpath=$dir ;; + esac + add_dir=-L$dir + add=-l$name + elif test no = "$hardcode_shlibpath_var"; then + add_shlibpath=$dir + add=-l$name + else + lib_linked=no + fi + ;; + relink) + if test yes = "$hardcode_direct" && + test no = "$hardcode_direct_absolute"; then + add=$dir/$linklib + elif test yes = "$hardcode_minus_L"; then + add_dir=-L$absdir + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + func_append add_dir " -L$inst_prefix_dir$libdir" + ;; + esac + fi + add=-l$name + elif test yes = "$hardcode_shlibpath_var"; then + add_shlibpath=$dir + add=-l$name + else + lib_linked=no + fi + ;; + *) lib_linked=no ;; + esac + + if test yes != "$lib_linked"; then + func_fatal_configuration "unsupported hardcode properties" + fi + + if test -n "$add_shlibpath"; then + case :$compile_shlibpath: in + *":$add_shlibpath:"*) ;; + *) func_append compile_shlibpath "$add_shlibpath:" ;; + esac + fi + if test prog = "$linkmode"; then + test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" + test -n "$add" && compile_deplibs="$add $compile_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + if test yes != "$hardcode_direct" && + test yes != "$hardcode_minus_L" && + test yes = "$hardcode_shlibpath_var"; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) func_append finalize_shlibpath "$libdir:" ;; + esac + fi + fi + fi + + if test prog = "$linkmode" || test relink = "$opt_mode"; then + add_shlibpath= + add_dir= + add= + # Finalize command for both is simple: just hardcode it. + if test yes = "$hardcode_direct" && + test no = "$hardcode_direct_absolute"; then + add=$libdir/$linklib + elif test yes = "$hardcode_minus_L"; then + add_dir=-L$libdir + add=-l$name + elif test yes = "$hardcode_shlibpath_var"; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) func_append finalize_shlibpath "$libdir:" ;; + esac + add=-l$name + elif test yes = "$hardcode_automatic"; then + if test -n "$inst_prefix_dir" && + test -f "$inst_prefix_dir$libdir/$linklib"; then + add=$inst_prefix_dir$libdir/$linklib + else + add=$libdir/$linklib + fi + else + # We cannot seem to hardcode it, guess we'll fake it. + add_dir=-L$libdir + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + func_append add_dir " -L$inst_prefix_dir$libdir" + ;; + esac + fi + add=-l$name + fi + + if test prog = "$linkmode"; then + test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" + test -n "$add" && finalize_deplibs="$add $finalize_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + fi + fi + elif test prog = "$linkmode"; then + # Here we assume that one of hardcode_direct or hardcode_minus_L + # is not unsupported. This is valid on all known static and + # shared platforms. + if test unsupported != "$hardcode_direct"; then + test -n "$old_library" && linklib=$old_library + compile_deplibs="$dir/$linklib $compile_deplibs" + finalize_deplibs="$dir/$linklib $finalize_deplibs" + else + compile_deplibs="-l$name -L$dir $compile_deplibs" + finalize_deplibs="-l$name -L$dir $finalize_deplibs" + fi + elif test yes = "$build_libtool_libs"; then + # Not a shared library + if test pass_all != "$deplibs_check_method"; then + # We're trying link a shared library against a static one + # but the system doesn't support it. + + # Just print a warning and add the library to dependency_libs so + # that the program can be linked against the static library. + echo + $ECHO "*** Warning: This system cannot link to static lib archive $lib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have." + if test yes = "$module"; then + echo "*** But as you try to build a module library, libtool will still create " + echo "*** a static module, that should work as long as the dlopening application" + echo "*** is linked with the -dlopen flag to resolve symbols at runtime." + if test -z "$global_symbol_pipe"; then + echo + echo "*** However, this would only work if libtool was able to extract symbol" + echo "*** lists from a program, using 'nm' or equivalent, but libtool could" + echo "*** not find such a program. So, this module is probably useless." + echo "*** 'nm' from GNU binutils and a full rebuild may help." + fi + if test no = "$build_old_libs"; then + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + else + deplibs="$dir/$old_library $deplibs" + link_static=yes + fi + fi # link shared/static library? + + if test lib = "$linkmode"; then + if test -n "$dependency_libs" && + { test yes != "$hardcode_into_libs" || + test yes = "$build_old_libs" || + test yes = "$link_static"; }; then + # Extract -R from dependency_libs + temp_deplibs= + for libdir in $dependency_libs; do + case $libdir in + -R*) func_stripname '-R' '' "$libdir" + temp_xrpath=$func_stripname_result + case " $xrpath " in + *" $temp_xrpath "*) ;; + *) func_append xrpath " $temp_xrpath";; + esac;; + *) func_append temp_deplibs " $libdir";; + esac + done + dependency_libs=$temp_deplibs + fi + + func_append newlib_search_path " $absdir" + # Link against this library + test no = "$link_static" && newdependency_libs="$abs_ladir/$laname $newdependency_libs" + # ... and its dependency_libs + tmp_libs= + for deplib in $dependency_libs; do + newdependency_libs="$deplib $newdependency_libs" + case $deplib in + -L*) func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result";; + *) func_resolve_sysroot "$deplib" ;; + esac + if $opt_preserve_dup_deps; then + case "$tmp_libs " in + *" $func_resolve_sysroot_result "*) + func_append specialdeplibs " $func_resolve_sysroot_result" ;; + esac + fi + func_append tmp_libs " $func_resolve_sysroot_result" + done + + if test no != "$link_all_deplibs"; then + # Add the search paths of all dependency libraries + for deplib in $dependency_libs; do + path= + case $deplib in + -L*) path=$deplib ;; + *.la) + func_resolve_sysroot "$deplib" + deplib=$func_resolve_sysroot_result + func_dirname "$deplib" "" "." + dir=$func_dirname_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) absdir=$dir ;; + *) + absdir=`cd "$dir" && pwd` + if test -z "$absdir"; then + func_warning "cannot determine absolute directory name of '$dir'" + absdir=$dir + fi + ;; + esac + if $GREP "^installed=no" $deplib > /dev/null; then + case $host in + *-*-darwin*) + depdepl= + eval deplibrary_names=`$SED -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` + if test -n "$deplibrary_names"; then + for tmp in $deplibrary_names; do + depdepl=$tmp + done + if test -f "$absdir/$objdir/$depdepl"; then + depdepl=$absdir/$objdir/$depdepl + darwin_install_name=`$OTOOL -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + if test -z "$darwin_install_name"; then + darwin_install_name=`$OTOOL64 -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + fi + func_append compiler_flags " $wl-dylib_file $wl$darwin_install_name:$depdepl" + func_append linker_flags " -dylib_file $darwin_install_name:$depdepl" + path= + fi + fi + ;; + *) + path=-L$absdir/$objdir + ;; + esac + else + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + test -z "$libdir" && \ + func_fatal_error "'$deplib' is not a valid libtool archive" + test "$absdir" != "$libdir" && \ + func_warning "'$deplib' seems to be moved" + + path=-L$absdir + fi + ;; + esac + case " $deplibs " in + *" $path "*) ;; + *) deplibs="$path $deplibs" ;; + esac + done + fi # link_all_deplibs != no + fi # linkmode = lib + done # for deplib in $libs + if test link = "$pass"; then + if test prog = "$linkmode"; then + compile_deplibs="$new_inherited_linker_flags $compile_deplibs" + finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" + else + compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + fi + fi + dependency_libs=$newdependency_libs + if test dlpreopen = "$pass"; then + # Link the dlpreopened libraries before other libraries + for deplib in $save_deplibs; do + deplibs="$deplib $deplibs" + done + fi + if test dlopen != "$pass"; then + test conv = "$pass" || { + # Make sure lib_search_path contains only unique directories. + lib_search_path= + for dir in $newlib_search_path; do + case "$lib_search_path " in + *" $dir "*) ;; + *) func_append lib_search_path " $dir" ;; + esac + done + newlib_search_path= + } + + if test prog,link = "$linkmode,$pass"; then + vars="compile_deplibs finalize_deplibs" + else + vars=deplibs + fi + for var in $vars dependency_libs; do + # Add libraries to $var in reverse order + eval tmp_libs=\"\$$var\" + new_libs= + for deplib in $tmp_libs; do + # FIXME: Pedantically, this is the right thing to do, so + # that some nasty dependency loop isn't accidentally + # broken: + #new_libs="$deplib $new_libs" + # Pragmatically, this seems to cause very few problems in + # practice: + case $deplib in + -L*) new_libs="$deplib $new_libs" ;; + -R*) ;; + *) + # And here is the reason: when a library appears more + # than once as an explicit dependence of a library, or + # is implicitly linked in more than once by the + # compiler, it is considered special, and multiple + # occurrences thereof are not removed. Compare this + # with having the same library being listed as a + # dependency of multiple other libraries: in this case, + # we know (pedantically, we assume) the library does not + # need to be listed more than once, so we keep only the + # last copy. This is not always right, but it is rare + # enough that we require users that really mean to play + # such unportable linking tricks to link the library + # using -Wl,-lname, so that libtool does not consider it + # for duplicate removal. + case " $specialdeplibs " in + *" $deplib "*) new_libs="$deplib $new_libs" ;; + *) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$deplib $new_libs" ;; + esac + ;; + esac + ;; + esac + done + tmp_libs= + for deplib in $new_libs; do + case $deplib in + -L*) + case " $tmp_libs " in + *" $deplib "*) ;; + *) func_append tmp_libs " $deplib" ;; + esac + ;; + *) func_append tmp_libs " $deplib" ;; + esac + done + eval $var=\"$tmp_libs\" + done # for var + fi + + # Add Sun CC postdeps if required: + test CXX = "$tagname" && { + case $host_os in + linux*) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C++ 5.9 + func_suncc_cstd_abi + + if test no != "$suncc_use_cstd_abi"; then + func_append postdeps ' -library=Cstd -library=Crun' + fi + ;; + esac + ;; + + solaris*) + func_cc_basename "$CC" + case $func_cc_basename_result in + CC* | sunCC*) + func_suncc_cstd_abi + + if test no != "$suncc_use_cstd_abi"; then + func_append postdeps ' -library=Cstd -library=Crun' + fi + ;; + esac + ;; + esac + } + + # Last step: remove runtime libs from dependency_libs + # (they stay in deplibs) + tmp_libs= + for i in $dependency_libs; do + case " $predeps $postdeps $compiler_lib_search_path " in + *" $i "*) + i= + ;; + esac + if test -n "$i"; then + func_append tmp_libs " $i" + fi + done + dependency_libs=$tmp_libs + done # for pass + if test prog = "$linkmode"; then + dlfiles=$newdlfiles + fi + if test prog = "$linkmode" || test lib = "$linkmode"; then + dlprefiles=$newdlprefiles + fi + + case $linkmode in + oldlib) + if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then + func_warning "'-dlopen' is ignored for archives" + fi + + case " $deplibs" in + *\ -l* | *\ -L*) + func_warning "'-l' and '-L' are ignored for archives" ;; + esac + + test -n "$rpath" && \ + func_warning "'-rpath' is ignored for archives" + + test -n "$xrpath" && \ + func_warning "'-R' is ignored for archives" + + test -n "$vinfo" && \ + func_warning "'-version-info/-version-number' is ignored for archives" + + test -n "$release" && \ + func_warning "'-release' is ignored for archives" + + test -n "$export_symbols$export_symbols_regex" && \ + func_warning "'-export-symbols' is ignored for archives" + + # Now set the variables for building old libraries. + build_libtool_libs=no + oldlibs=$output + func_append objs "$old_deplibs" + ;; + + lib) + # Make sure we only generate libraries of the form 'libNAME.la'. + case $outputname in + lib*) + func_stripname 'lib' '.la' "$outputname" + name=$func_stripname_result + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + ;; + *) + test no = "$module" \ + && func_fatal_help "libtool library '$output' must begin with 'lib'" + + if test no != "$need_lib_prefix"; then + # Add the "lib" prefix for modules if required + func_stripname '' '.la' "$outputname" + name=$func_stripname_result + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + else + func_stripname '' '.la' "$outputname" + libname=$func_stripname_result + fi + ;; + esac + + if test -n "$objs"; then + if test pass_all != "$deplibs_check_method"; then + func_fatal_error "cannot build libtool library '$output' from non-libtool objects on this host:$objs" + else + echo + $ECHO "*** Warning: Linking the shared library $output against the non-libtool" + $ECHO "*** objects $objs is not portable!" + func_append libobjs " $objs" + fi + fi + + test no = "$dlself" \ + || func_warning "'-dlopen self' is ignored for libtool libraries" + + set dummy $rpath + shift + test 1 -lt "$#" \ + && func_warning "ignoring multiple '-rpath's for a libtool library" + + install_libdir=$1 + + oldlibs= + if test -z "$rpath"; then + if test yes = "$build_libtool_libs"; then + # Building a libtool convenience library. + # Some compilers have problems with a '.al' extension so + # convenience libraries should have the same extension an + # archive normally would. + oldlibs="$output_objdir/$libname.$libext $oldlibs" + build_libtool_libs=convenience + build_old_libs=yes + fi + + test -n "$vinfo" && \ + func_warning "'-version-info/-version-number' is ignored for convenience libraries" + + test -n "$release" && \ + func_warning "'-release' is ignored for convenience libraries" + else + + # Parse the version information argument. + save_ifs=$IFS; IFS=: + set dummy $vinfo 0 0 0 + shift + IFS=$save_ifs + + test -n "$7" && \ + func_fatal_help "too many parameters to '-version-info'" + + # convert absolute version numbers to libtool ages + # this retains compatibility with .la files and attempts + # to make the code below a bit more comprehensible + + case $vinfo_number in + yes) + number_major=$1 + number_minor=$2 + number_revision=$3 + # + # There are really only two kinds -- those that + # use the current revision as the major version + # and those that subtract age and use age as + # a minor version. But, then there is irix + # that has an extra 1 added just for fun + # + case $version_type in + # correct linux to gnu/linux during the next big refactor + darwin|freebsd-elf|linux|osf|windows|none) + func_arith $number_major + $number_minor + current=$func_arith_result + age=$number_minor + revision=$number_revision + ;; + freebsd-aout|qnx|sunos) + current=$number_major + revision=$number_minor + age=0 + ;; + irix|nonstopux) + func_arith $number_major + $number_minor + current=$func_arith_result + age=$number_minor + revision=$number_minor + lt_irix_increment=no + ;; + *) + func_fatal_configuration "$modename: unknown library version type '$version_type'" + ;; + esac + ;; + no) + current=$1 + revision=$2 + age=$3 + ;; + esac + + # Check that each of the things are valid numbers. + case $current in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "CURRENT '$current' must be a nonnegative integer" + func_fatal_error "'$vinfo' is not valid version information" + ;; + esac + + case $revision in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "REVISION '$revision' must be a nonnegative integer" + func_fatal_error "'$vinfo' is not valid version information" + ;; + esac + + case $age in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "AGE '$age' must be a nonnegative integer" + func_fatal_error "'$vinfo' is not valid version information" + ;; + esac + + if test "$age" -gt "$current"; then + func_error "AGE '$age' is greater than the current interface number '$current'" + func_fatal_error "'$vinfo' is not valid version information" + fi + + # Calculate the version variables. + major= + versuffix= + verstring= + case $version_type in + none) ;; + + darwin) + # Like Linux, but with the current version available in + # verstring for coding it into the library header + func_arith $current - $age + major=.$func_arith_result + versuffix=$major.$age.$revision + # Darwin ld doesn't like 0 for these options... + func_arith $current + 1 + minor_current=$func_arith_result + xlcverstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" + verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" + # On Darwin other compilers + case $CC in + nagfor*) + verstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" + ;; + *) + verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" + ;; + esac + ;; + + freebsd-aout) + major=.$current + versuffix=.$current.$revision + ;; + + freebsd-elf) + func_arith $current - $age + major=.$func_arith_result + versuffix=$major.$age.$revision + ;; + + irix | nonstopux) + if test no = "$lt_irix_increment"; then + func_arith $current - $age + else + func_arith $current - $age + 1 + fi + major=$func_arith_result + + case $version_type in + nonstopux) verstring_prefix=nonstopux ;; + *) verstring_prefix=sgi ;; + esac + verstring=$verstring_prefix$major.$revision + + # Add in all the interfaces that we are compatible with. + loop=$revision + while test 0 -ne "$loop"; do + func_arith $revision - $loop + iface=$func_arith_result + func_arith $loop - 1 + loop=$func_arith_result + verstring=$verstring_prefix$major.$iface:$verstring + done + + # Before this point, $major must not contain '.'. + major=.$major + versuffix=$major.$revision + ;; + + linux) # correct to gnu/linux during the next big refactor + func_arith $current - $age + major=.$func_arith_result + versuffix=$major.$age.$revision + ;; + + osf) + func_arith $current - $age + major=.$func_arith_result + versuffix=.$current.$age.$revision + verstring=$current.$age.$revision + + # Add in all the interfaces that we are compatible with. + loop=$age + while test 0 -ne "$loop"; do + func_arith $current - $loop + iface=$func_arith_result + func_arith $loop - 1 + loop=$func_arith_result + verstring=$verstring:$iface.0 + done + + # Make executables depend on our current version. + func_append verstring ":$current.0" + ;; + + qnx) + major=.$current + versuffix=.$current + ;; + + sco) + major=.$current + versuffix=.$current + ;; + + sunos) + major=.$current + versuffix=.$current.$revision + ;; + + windows) + # Use '-' rather than '.', since we only want one + # extension on DOS 8.3 file systems. + func_arith $current - $age + major=$func_arith_result + versuffix=-$major + ;; + + *) + func_fatal_configuration "unknown library version type '$version_type'" + ;; + esac + + # Clear the version info if we defaulted, and they specified a release. + if test -z "$vinfo" && test -n "$release"; then + major= + case $version_type in + darwin) + # we can't check for "0.0" in archive_cmds due to quoting + # problems, so we reset it completely + verstring= + ;; + *) + verstring=0.0 + ;; + esac + if test no = "$need_version"; then + versuffix= + else + versuffix=.0.0 + fi + fi + + # Remove version info from name if versioning should be avoided + if test yes,no = "$avoid_version,$need_version"; then + major= + versuffix= + verstring= + fi + + # Check to see if the archive will have undefined symbols. + if test yes = "$allow_undefined"; then + if test unsupported = "$allow_undefined_flag"; then + if test yes = "$build_old_libs"; then + func_warning "undefined symbols not allowed in $host shared libraries; building static only" + build_libtool_libs=no + else + func_fatal_error "can't build $host shared library unless -no-undefined is specified" + fi + fi + else + # Don't allow undefined symbols. + allow_undefined_flag=$no_undefined_flag + fi + + fi + + func_generate_dlsyms "$libname" "$libname" : + func_append libobjs " $symfileobj" + test " " = "$libobjs" && libobjs= + + if test relink != "$opt_mode"; then + # Remove our outputs, but don't remove object files since they + # may have been created when compiling PIC objects. + removelist= + tempremovelist=`$ECHO "$output_objdir/*"` + for p in $tempremovelist; do + case $p in + *.$objext | *.gcno) + ;; + $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/$libname$release.*) + if test -n "$precious_files_regex"; then + if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 + then + continue + fi + fi + func_append removelist " $p" + ;; + *) ;; + esac + done + test -n "$removelist" && \ + func_show_eval "${RM}r \$removelist" + fi + + # Now set the variables for building old libraries. + if test yes = "$build_old_libs" && test convenience != "$build_libtool_libs"; then + func_append oldlibs " $output_objdir/$libname.$libext" + + # Transform .lo files to .o files. + oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; $lo2o" | $NL2SP` + fi + + # Eliminate all temporary directories. + #for path in $notinst_path; do + # lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"` + # deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"` + # dependency_libs=`$ECHO "$dependency_libs " | $SED "s% -L$path % %g"` + #done + + if test -n "$xrpath"; then + # If the user specified any rpath flags, then add them. + temp_xrpath= + for libdir in $xrpath; do + func_replace_sysroot "$libdir" + func_append temp_xrpath " -R$func_replace_sysroot_result" + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + done + if test yes != "$hardcode_into_libs" || test yes = "$build_old_libs"; then + dependency_libs="$temp_xrpath $dependency_libs" + fi + fi + + # Make sure dlfiles contains only unique files that won't be dlpreopened + old_dlfiles=$dlfiles + dlfiles= + for lib in $old_dlfiles; do + case " $dlprefiles $dlfiles " in + *" $lib "*) ;; + *) func_append dlfiles " $lib" ;; + esac + done + + # Make sure dlprefiles contains only unique files + old_dlprefiles=$dlprefiles + dlprefiles= + for lib in $old_dlprefiles; do + case "$dlprefiles " in + *" $lib "*) ;; + *) func_append dlprefiles " $lib" ;; + esac + done + + if test yes = "$build_libtool_libs"; then + if test -n "$rpath"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*) + # these systems don't actually have a c library (as such)! + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C library is in the System framework + func_append deplibs " System.ltframework" + ;; + *-*-netbsd*) + # Don't link with libc until the a.out ld.so is fixed. + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc due to us having libc/libc_r. + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + ;; + *) + # Add libc to deplibs on all other systems if necessary. + if test yes = "$build_libtool_need_lc"; then + func_append deplibs " -lc" + fi + ;; + esac + fi + + # Transform deplibs into only deplibs that can be linked in shared. + name_save=$name + libname_save=$libname + release_save=$release + versuffix_save=$versuffix + major_save=$major + # I'm not sure if I'm treating the release correctly. I think + # release should show up in the -l (ie -lgmp5) so we don't want to + # add it in twice. Is that correct? + release= + versuffix= + major= + newdeplibs= + droppeddeps=no + case $deplibs_check_method in + pass_all) + # Don't check for shared/static. Everything works. + # This might be a little naive. We might want to check + # whether the library exists or not. But this is on + # osf3 & osf4 and I'm not really sure... Just + # implementing what was already the behavior. + newdeplibs=$deplibs + ;; + test_compile) + # This code stresses the "libraries are programs" paradigm to its + # limits. Maybe even breaks it. We compile a program, linking it + # against the deplibs as a proxy for the library. Then we can check + # whether they linked in statically or dynamically with ldd. + $opt_dry_run || $RM conftest.c + cat > conftest.c </dev/null` + $nocaseglob + else + potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null` + fi + for potent_lib in $potential_libs; do + # Follow soft links. + if ls -lLd "$potent_lib" 2>/dev/null | + $GREP " -> " >/dev/null; then + continue + fi + # The statement above tries to avoid entering an + # endless loop below, in case of cyclic links. + # We might still enter an endless loop, since a link + # loop can be closed while we follow links, + # but so what? + potlib=$potent_lib + while test -h "$potlib" 2>/dev/null; do + potliblink=`ls -ld $potlib | $SED 's/.* -> //'` + case $potliblink in + [\\/]* | [A-Za-z]:[\\/]*) potlib=$potliblink;; + *) potlib=`$ECHO "$potlib" | $SED 's|[^/]*$||'`"$potliblink";; + esac + done + if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | + $SED -e 10q | + $EGREP "$file_magic_regex" > /dev/null; then + func_append newdeplibs " $a_deplib" + a_deplib= + break 2 + fi + done + done + fi + if test -n "$a_deplib"; then + droppeddeps=yes + echo + $ECHO "*** Warning: linker path does not have real file for library $a_deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib"; then + $ECHO "*** with $libname but no candidates were found. (...for file magic test)" + else + $ECHO "*** with $libname and none of the candidates passed a file format test" + $ECHO "*** using a file magic. Last file checked: $potlib" + fi + fi + ;; + *) + # Add a -L argument. + func_append newdeplibs " $a_deplib" + ;; + esac + done # Gone through all deplibs. + ;; + match_pattern*) + set dummy $deplibs_check_method; shift + match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` + for a_deplib in $deplibs; do + case $a_deplib in + -l*) + func_stripname -l '' "$a_deplib" + name=$func_stripname_result + if test yes = "$allow_libtool_libs_with_static_runtimes"; then + case " $predeps $postdeps " in + *" $a_deplib "*) + func_append newdeplibs " $a_deplib" + a_deplib= + ;; + esac + fi + if test -n "$a_deplib"; then + libname=`eval "\\$ECHO \"$libname_spec\""` + for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do + potential_libs=`ls $i/$libname[.-]* 2>/dev/null` + for potent_lib in $potential_libs; do + potlib=$potent_lib # see symlink-check above in file_magic test + if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \ + $EGREP "$match_pattern_regex" > /dev/null; then + func_append newdeplibs " $a_deplib" + a_deplib= + break 2 + fi + done + done + fi + if test -n "$a_deplib"; then + droppeddeps=yes + echo + $ECHO "*** Warning: linker path does not have real file for library $a_deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib"; then + $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" + else + $ECHO "*** with $libname and none of the candidates passed a file format test" + $ECHO "*** using a regex pattern. Last file checked: $potlib" + fi + fi + ;; + *) + # Add a -L argument. + func_append newdeplibs " $a_deplib" + ;; + esac + done # Gone through all deplibs. + ;; + none | unknown | *) + newdeplibs= + tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'` + if test yes = "$allow_libtool_libs_with_static_runtimes"; then + for i in $predeps $postdeps; do + # can't use Xsed below, because $i might contain '/' + tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s|$i||"` + done + fi + case $tmp_deplibs in + *[!\ \ ]*) + echo + if test none = "$deplibs_check_method"; then + echo "*** Warning: inter-library dependencies are not supported in this platform." + else + echo "*** Warning: inter-library dependencies are not known to be supported." + fi + echo "*** All declared inter-library dependencies are being dropped." + droppeddeps=yes + ;; + esac + ;; + esac + versuffix=$versuffix_save + major=$major_save + release=$release_save + libname=$libname_save + name=$name_save + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library with the System framework + newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'` + ;; + esac + + if test yes = "$droppeddeps"; then + if test yes = "$module"; then + echo + echo "*** Warning: libtool could not satisfy all declared inter-library" + $ECHO "*** dependencies of module $libname. Therefore, libtool will create" + echo "*** a static module, that should work as long as the dlopening" + echo "*** application is linked with the -dlopen flag." + if test -z "$global_symbol_pipe"; then + echo + echo "*** However, this would only work if libtool was able to extract symbol" + echo "*** lists from a program, using 'nm' or equivalent, but libtool could" + echo "*** not find such a program. So, this module is probably useless." + echo "*** 'nm' from GNU binutils and a full rebuild may help." + fi + if test no = "$build_old_libs"; then + oldlibs=$output_objdir/$libname.$libext + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + else + echo "*** The inter-library dependencies that have been dropped here will be" + echo "*** automatically added whenever a program is linked with this library" + echo "*** or is declared to -dlopen it." + + if test no = "$allow_undefined"; then + echo + echo "*** Since this library must not contain undefined symbols," + echo "*** because either the platform does not support them or" + echo "*** it was explicitly requested with -no-undefined," + echo "*** libtool will only create a static version of it." + if test no = "$build_old_libs"; then + oldlibs=$output_objdir/$libname.$libext + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + fi + fi + # Done checking deplibs! + deplibs=$newdeplibs + fi + # Time to change all our "foo.ltframework" stuff back to "-framework foo" + case $host in + *-*-darwin*) + newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + ;; + esac + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $deplibs " in + *" -L$path/$objdir "*) + func_append new_libs " -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) func_append new_libs " $deplib" ;; + esac + ;; + *) func_append new_libs " $deplib" ;; + esac + done + deplibs=$new_libs + + # All the library-specific variables (install_libdir is set above). + library_names= + old_library= + dlname= + + # Test again, we may have decided not to build it any more + if test yes = "$build_libtool_libs"; then + # Remove $wl instances when linking with ld. + # FIXME: should test the right _cmds variable. + case $archive_cmds in + *\$LD\ *) wl= ;; + esac + if test yes = "$hardcode_into_libs"; then + # Hardcode the library paths + hardcode_libdirs= + dep_rpath= + rpath=$finalize_rpath + test relink = "$opt_mode" || rpath=$compile_rpath$rpath + for libdir in $rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + func_replace_sysroot "$libdir" + libdir=$func_replace_sysroot_result + if test -z "$hardcode_libdirs"; then + hardcode_libdirs=$libdir + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append dep_rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) func_append perm_rpath " $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir=$hardcode_libdirs + eval "dep_rpath=\"$hardcode_libdir_flag_spec\"" + fi + if test -n "$runpath_var" && test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + func_append rpath "$dir:" + done + eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" + fi + test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" + fi + + shlibpath=$finalize_shlibpath + test relink = "$opt_mode" || shlibpath=$compile_shlibpath$shlibpath + if test -n "$shlibpath"; then + eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" + fi + + # Get the real and link names of the library. + eval shared_ext=\"$shrext_cmds\" + eval library_names=\"$library_names_spec\" + set dummy $library_names + shift + realname=$1 + shift + + if test -n "$soname_spec"; then + eval soname=\"$soname_spec\" + else + soname=$realname + fi + if test -z "$dlname"; then + dlname=$soname + fi + + lib=$output_objdir/$realname + linknames= + for link + do + func_append linknames " $link" + done + + # Use standard objects if they are pic + test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP` + test "X$libobjs" = "X " && libobjs= + + delfiles= + if test -n "$export_symbols" && test -n "$include_expsyms"; then + $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" + export_symbols=$output_objdir/$libname.uexp + func_append delfiles " $export_symbols" + fi + + orig_export_symbols= + case $host_os in + cygwin* | mingw* | cegcc*) + if test -n "$export_symbols" && test -z "$export_symbols_regex"; then + # exporting using user supplied symfile + func_dll_def_p "$export_symbols" || { + # and it's NOT already a .def file. Must figure out + # which of the given symbols are data symbols and tag + # them as such. So, trigger use of export_symbols_cmds. + # export_symbols gets reassigned inside the "prepare + # the list of exported symbols" if statement, so the + # include_expsyms logic still works. + orig_export_symbols=$export_symbols + export_symbols= + always_export_symbols=yes + } + fi + ;; + esac + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + if test yes = "$always_export_symbols" || test -n "$export_symbols_regex"; then + func_verbose "generating symbol list for '$libname.la'" + export_symbols=$output_objdir/$libname.exp + $opt_dry_run || $RM $export_symbols + cmds=$export_symbols_cmds + save_ifs=$IFS; IFS='~' + for cmd1 in $cmds; do + IFS=$save_ifs + # Take the normal branch if the nm_file_list_spec branch + # doesn't work or if tool conversion is not needed. + case $nm_file_list_spec~$to_tool_file_cmd in + *~func_convert_file_noop | *~func_convert_file_msys_to_w32 | ~*) + try_normal_branch=yes + eval cmd=\"$cmd1\" + func_len " $cmd" + len=$func_len_result + ;; + *) + try_normal_branch=no + ;; + esac + if test yes = "$try_normal_branch" \ + && { test "$len" -lt "$max_cmd_len" \ + || test "$max_cmd_len" -le -1; } + then + func_show_eval "$cmd" 'exit $?' + skipped_export=false + elif test -n "$nm_file_list_spec"; then + func_basename "$output" + output_la=$func_basename_result + save_libobjs=$libobjs + save_output=$output + output=$output_objdir/$output_la.nm + func_to_tool_file "$output" + libobjs=$nm_file_list_spec$func_to_tool_file_result + func_append delfiles " $output" + func_verbose "creating $NM input file list: $output" + for obj in $save_libobjs; do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" + done > "$output" + eval cmd=\"$cmd1\" + func_show_eval "$cmd" 'exit $?' + output=$save_output + libobjs=$save_libobjs + skipped_export=false + else + # The command line is too long to execute in one step. + func_verbose "using reloadable object file for export list..." + skipped_export=: + # Break out early, otherwise skipped_export may be + # set to false by a later but shorter cmd. + break + fi + done + IFS=$save_ifs + if test -n "$export_symbols_regex" && test : != "$skipped_export"; then + func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + func_show_eval '$MV "${export_symbols}T" "$export_symbols"' + fi + fi + fi + + if test -n "$export_symbols" && test -n "$include_expsyms"; then + tmp_export_symbols=$export_symbols + test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols + $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' + fi + + if test : != "$skipped_export" && test -n "$orig_export_symbols"; then + # The given exports_symbols file has to be filtered, so filter it. + func_verbose "filter symbol list for '$libname.la' to tag DATA exports" + # FIXME: $output_objdir/$libname.filter potentially contains lots of + # 's' commands, which not all seds can handle. GNU sed should be fine + # though. Also, the filter scales superlinearly with the number of + # global variables. join(1) would be nice here, but unfortunately + # isn't a blessed tool. + $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter + func_append delfiles " $export_symbols $output_objdir/$libname.filter" + export_symbols=$output_objdir/$libname.def + $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols + fi + + tmp_deplibs= + for test_deplib in $deplibs; do + case " $convenience " in + *" $test_deplib "*) ;; + *) + func_append tmp_deplibs " $test_deplib" + ;; + esac + done + deplibs=$tmp_deplibs + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec" && + test yes = "$compiler_needs_object" && + test -z "$libobjs"; then + # extract the archives, so we have objects to list. + # TODO: could optimize this to just extract one archive. + whole_archive_flag_spec= + fi + if test -n "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + test "X$libobjs" = "X " && libobjs= + else + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $convenience + func_append libobjs " $func_extract_archives_result" + test "X$libobjs" = "X " && libobjs= + fi + fi + + if test yes = "$thread_safe" && test -n "$thread_safe_flag_spec"; then + eval flag=\"$thread_safe_flag_spec\" + func_append linker_flags " $flag" + fi + + # Make a backup of the uninstalled library when relinking + if test relink = "$opt_mode"; then + $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? + fi + + # Do each of the archive commands. + if test yes = "$module" && test -n "$module_cmds"; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + eval test_cmds=\"$module_expsym_cmds\" + cmds=$module_expsym_cmds + else + eval test_cmds=\"$module_cmds\" + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + eval test_cmds=\"$archive_expsym_cmds\" + cmds=$archive_expsym_cmds + else + eval test_cmds=\"$archive_cmds\" + cmds=$archive_cmds + fi + fi + + if test : != "$skipped_export" && + func_len " $test_cmds" && + len=$func_len_result && + test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + : + else + # The command line is too long to link in one step, link piecewise + # or, if using GNU ld and skipped_export is not :, use a linker + # script. + + # Save the value of $output and $libobjs because we want to + # use them later. If we have whole_archive_flag_spec, we + # want to use save_libobjs as it was before + # whole_archive_flag_spec was expanded, because we can't + # assume the linker understands whole_archive_flag_spec. + # This may have to be revisited, in case too many + # convenience libraries get linked in and end up exceeding + # the spec. + if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + fi + save_output=$output + func_basename "$output" + output_la=$func_basename_result + + # Clear the reloadable object creation command queue and + # initialize k to one. + test_cmds= + concat_cmds= + objlist= + last_robj= + k=1 + + if test -n "$save_libobjs" && test : != "$skipped_export" && test yes = "$with_gnu_ld"; then + output=$output_objdir/$output_la.lnkscript + func_verbose "creating GNU ld script: $output" + echo 'INPUT (' > $output + for obj in $save_libobjs + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" >> $output + done + echo ')' >> $output + func_append delfiles " $output" + func_to_tool_file "$output" + output=$func_to_tool_file_result + elif test -n "$save_libobjs" && test : != "$skipped_export" && test -n "$file_list_spec"; then + output=$output_objdir/$output_la.lnk + func_verbose "creating linker input file list: $output" + : > $output + set x $save_libobjs + shift + firstobj= + if test yes = "$compiler_needs_object"; then + firstobj="$1 " + shift + fi + for obj + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" >> $output + done + func_append delfiles " $output" + func_to_tool_file "$output" + output=$firstobj\"$file_list_spec$func_to_tool_file_result\" + else + if test -n "$save_libobjs"; then + func_verbose "creating reloadable object files..." + output=$output_objdir/$output_la-$k.$objext + eval test_cmds=\"$reload_cmds\" + func_len " $test_cmds" + len0=$func_len_result + len=$len0 + + # Loop over the list of objects to be linked. + for obj in $save_libobjs + do + func_len " $obj" + func_arith $len + $func_len_result + len=$func_arith_result + if test -z "$objlist" || + test "$len" -lt "$max_cmd_len"; then + func_append objlist " $obj" + else + # The command $test_cmds is almost too long, add a + # command to the queue. + if test 1 -eq "$k"; then + # The first file doesn't have a previous command to add. + reload_objs=$objlist + eval concat_cmds=\"$reload_cmds\" + else + # All subsequent reloadable object files will link in + # the last one created. + reload_objs="$objlist $last_robj" + eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\" + fi + last_robj=$output_objdir/$output_la-$k.$objext + func_arith $k + 1 + k=$func_arith_result + output=$output_objdir/$output_la-$k.$objext + objlist=" $obj" + func_len " $last_robj" + func_arith $len0 + $func_len_result + len=$func_arith_result + fi + done + # Handle the remaining objects by creating one last + # reloadable object file. All subsequent reloadable object + # files will link in the last one created. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + reload_objs="$objlist $last_robj" + eval concat_cmds=\"\$concat_cmds$reload_cmds\" + if test -n "$last_robj"; then + eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" + fi + func_append delfiles " $output" + + else + output= + fi + + ${skipped_export-false} && { + func_verbose "generating symbol list for '$libname.la'" + export_symbols=$output_objdir/$libname.exp + $opt_dry_run || $RM $export_symbols + libobjs=$output + # Append the command to create the export file. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\" + if test -n "$last_robj"; then + eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" + fi + } + + test -n "$save_libobjs" && + func_verbose "creating a temporary reloadable object file: $output" + + # Loop through the commands generated above and execute them. + save_ifs=$IFS; IFS='~' + for cmd in $concat_cmds; do + IFS=$save_ifs + $opt_quiet || { + func_quote_arg expand,pretty "$cmd" + eval "func_echo $func_quote_arg_result" + } + $opt_dry_run || eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test relink = "$opt_mode"; then + ( cd "$output_objdir" && \ + $RM "${realname}T" && \ + $MV "${realname}U" "$realname" ) + fi + + exit $lt_exit + } + done + IFS=$save_ifs + + if test -n "$export_symbols_regex" && ${skipped_export-false}; then + func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + func_show_eval '$MV "${export_symbols}T" "$export_symbols"' + fi + fi + + ${skipped_export-false} && { + if test -n "$export_symbols" && test -n "$include_expsyms"; then + tmp_export_symbols=$export_symbols + test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols + $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' + fi + + if test -n "$orig_export_symbols"; then + # The given exports_symbols file has to be filtered, so filter it. + func_verbose "filter symbol list for '$libname.la' to tag DATA exports" + # FIXME: $output_objdir/$libname.filter potentially contains lots of + # 's' commands, which not all seds can handle. GNU sed should be fine + # though. Also, the filter scales superlinearly with the number of + # global variables. join(1) would be nice here, but unfortunately + # isn't a blessed tool. + $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter + func_append delfiles " $export_symbols $output_objdir/$libname.filter" + export_symbols=$output_objdir/$libname.def + $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols + fi + } + + libobjs=$output + # Restore the value of output. + output=$save_output + + if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + test "X$libobjs" = "X " && libobjs= + fi + # Expand the library linking commands again to reset the + # value of $libobjs for piecewise linking. + + # Do each of the archive commands. + if test yes = "$module" && test -n "$module_cmds"; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + cmds=$module_expsym_cmds + else + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + cmds=$archive_expsym_cmds + else + cmds=$archive_cmds + fi + fi + fi + + if test -n "$delfiles"; then + # Append the command to remove temporary files to $cmds. + eval cmds=\"\$cmds~\$RM $delfiles\" + fi + + # Add any objects from preloaded convenience libraries + if test -n "$dlprefiles"; then + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $dlprefiles + func_append libobjs " $func_extract_archives_result" + test "X$libobjs" = "X " && libobjs= + fi + + save_ifs=$IFS; IFS='~' + for cmd in $cmds; do + IFS=$sp$nl + eval cmd=\"$cmd\" + IFS=$save_ifs + $opt_quiet || { + func_quote_arg expand,pretty "$cmd" + eval "func_echo $func_quote_arg_result" + } + $opt_dry_run || eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test relink = "$opt_mode"; then + ( cd "$output_objdir" && \ + $RM "${realname}T" && \ + $MV "${realname}U" "$realname" ) + fi + + exit $lt_exit + } + done + IFS=$save_ifs + + # Restore the uninstalled library and exit + if test relink = "$opt_mode"; then + $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $? + + if test -n "$convenience"; then + if test -z "$whole_archive_flag_spec"; then + func_show_eval '${RM}r "$gentop"' + fi + fi + + exit $EXIT_SUCCESS + fi + + # Create links to the real library. + for linkname in $linknames; do + if test "$realname" != "$linkname"; then + func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?' + fi + done + + # If -module or -export-dynamic was specified, set the dlname. + if test yes = "$module" || test yes = "$export_dynamic"; then + # On all known operating systems, these are identical. + dlname=$soname + fi + fi + ;; + + obj) + if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then + func_warning "'-dlopen' is ignored for objects" + fi + + case " $deplibs" in + *\ -l* | *\ -L*) + func_warning "'-l' and '-L' are ignored for objects" ;; + esac + + test -n "$rpath" && \ + func_warning "'-rpath' is ignored for objects" + + test -n "$xrpath" && \ + func_warning "'-R' is ignored for objects" + + test -n "$vinfo" && \ + func_warning "'-version-info' is ignored for objects" + + test -n "$release" && \ + func_warning "'-release' is ignored for objects" + + case $output in + *.lo) + test -n "$objs$old_deplibs" && \ + func_fatal_error "cannot build library object '$output' from non-libtool objects" + + libobj=$output + func_lo2o "$libobj" + obj=$func_lo2o_result + ;; + *) + libobj= + obj=$output + ;; + esac + + # Delete the old objects. + $opt_dry_run || $RM $obj $libobj + + # Objects from convenience libraries. This assumes + # single-version convenience libraries. Whenever we create + # different ones for PIC/non-PIC, this we'll have to duplicate + # the extraction. + reload_conv_objs= + gentop= + # if reload_cmds runs $LD directly, get rid of -Wl from + # whole_archive_flag_spec and hope we can get by with turning comma + # into space. + case $reload_cmds in + *\$LD[\ \$]*) wl= ;; + esac + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec"; then + eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" + test -n "$wl" || tmp_whole_archive_flags=`$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'` + reload_conv_objs=$reload_objs\ $tmp_whole_archive_flags + else + gentop=$output_objdir/${obj}x + func_append generated " $gentop" + + func_extract_archives $gentop $convenience + reload_conv_objs="$reload_objs $func_extract_archives_result" + fi + fi + + # If we're not building shared, we need to use non_pic_objs + test yes = "$build_libtool_libs" || libobjs=$non_pic_objects + + # Create the old-style object. + reload_objs=$objs$old_deplibs' '`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; /\.lib$/d; $lo2o" | $NL2SP`' '$reload_conv_objs + + output=$obj + func_execute_cmds "$reload_cmds" 'exit $?' + + # Exit if we aren't doing a library object file. + if test -z "$libobj"; then + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + exit $EXIT_SUCCESS + fi + + test yes = "$build_libtool_libs" || { + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + # Create an invalid libtool object if no PIC, so that we don't + # accidentally link it into a program. + # $show "echo timestamp > $libobj" + # $opt_dry_run || eval "echo timestamp > $libobj" || exit $? + exit $EXIT_SUCCESS + } + + if test -n "$pic_flag" || test default != "$pic_mode"; then + # Only do commands if we really have different PIC objects. + reload_objs="$libobjs $reload_conv_objs" + output=$libobj + func_execute_cmds "$reload_cmds" 'exit $?' + fi + + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + exit $EXIT_SUCCESS + ;; + + prog) + case $host in + *cygwin*) func_stripname '' '.exe' "$output" + output=$func_stripname_result.exe;; + esac + test -n "$vinfo" && \ + func_warning "'-version-info' is ignored for programs" + + test -n "$release" && \ + func_warning "'-release' is ignored for programs" + + $preload \ + && test unknown,unknown,unknown = "$dlopen_support,$dlopen_self,$dlopen_self_static" \ + && func_warning "'LT_INIT([dlopen])' not used. Assuming no dlopen support." + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library is the System framework + compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'` + finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'` + ;; + esac + + case $host in + *-*-darwin*) + # Don't allow lazy linking, it breaks C++ global constructors + # But is supposedly fixed on 10.4 or later (yay!). + if test CXX = "$tagname"; then + case ${MACOSX_DEPLOYMENT_TARGET-10.0} in + 10.[0123]) + func_append compile_command " $wl-bind_at_load" + func_append finalize_command " $wl-bind_at_load" + ;; + esac + fi + # Time to change all our "foo.ltframework" stuff back to "-framework foo" + compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + ;; + esac + + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $compile_deplibs " in + *" -L$path/$objdir "*) + func_append new_libs " -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $compile_deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) func_append new_libs " $deplib" ;; + esac + ;; + *) func_append new_libs " $deplib" ;; + esac + done + compile_deplibs=$new_libs + + + func_append compile_command " $compile_deplibs" + func_append finalize_command " $finalize_deplibs" + + if test -n "$rpath$xrpath"; then + # If the user specified any rpath flags, then add them. + for libdir in $rpath $xrpath; do + # This is the magic to use -rpath. + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + done + fi + + # Now hardcode the library paths + rpath= + hardcode_libdirs= + for libdir in $compile_rpath $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs=$libdir + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) func_append perm_rpath " $libdir" ;; + esac + fi + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + testbindir=`$ECHO "$libdir" | $SED -e 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$libdir:"*) ;; + ::) dllsearchpath=$libdir;; + *) func_append dllsearchpath ":$libdir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + ::) dllsearchpath=$testbindir;; + *) func_append dllsearchpath ":$testbindir";; + esac + ;; + esac + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir=$hardcode_libdirs + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + compile_rpath=$rpath + + rpath= + hardcode_libdirs= + for libdir in $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs=$libdir + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$finalize_perm_rpath " in + *" $libdir "*) ;; + *) func_append finalize_perm_rpath " $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir=$hardcode_libdirs + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + finalize_rpath=$rpath + + if test -n "$libobjs" && test yes = "$build_old_libs"; then + # Transform all the library objects into standard objects. + compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP` + finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP` + fi + + func_generate_dlsyms "$outputname" "@PROGRAM@" false + + # template prelinking step + if test -n "$prelink_cmds"; then + func_execute_cmds "$prelink_cmds" 'exit $?' + fi + + wrappers_required=: + case $host in + *cegcc* | *mingw32ce*) + # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway. + wrappers_required=false + ;; + *cygwin* | *mingw* ) + test yes = "$build_libtool_libs" || wrappers_required=false + ;; + *) + if test no = "$need_relink" || test yes != "$build_libtool_libs"; then + wrappers_required=false + fi + ;; + esac + $wrappers_required || { + # Replace the output file specification. + compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'` + link_command=$compile_command$compile_rpath + + # We have no uninstalled library dependencies, so finalize right now. + exit_status=0 + func_show_eval "$link_command" 'exit_status=$?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + # Delete the generated files. + if test -f "$output_objdir/${outputname}S.$objext"; then + func_show_eval '$RM "$output_objdir/${outputname}S.$objext"' + fi + + exit $exit_status + } + + if test -n "$compile_shlibpath$finalize_shlibpath"; then + compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" + fi + if test -n "$finalize_shlibpath"; then + finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" + fi + + compile_var= + finalize_var= + if test -n "$runpath_var"; then + if test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + func_append rpath "$dir:" + done + compile_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + if test -n "$finalize_perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $finalize_perm_rpath; do + func_append rpath "$dir:" + done + finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + fi + + if test yes = "$no_install"; then + # We don't need to create a wrapper script. + link_command=$compile_var$compile_command$compile_rpath + # Replace the output file specification. + link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'` + # Delete the old output file. + $opt_dry_run || $RM $output + # Link the executable and exit + func_show_eval "$link_command" 'exit $?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + exit $EXIT_SUCCESS + fi + + case $hardcode_action,$fast_install in + relink,*) + # Fast installation is not supported + link_command=$compile_var$compile_command$compile_rpath + relink_command=$finalize_var$finalize_command$finalize_rpath + + func_warning "this platform does not like uninstalled shared libraries" + func_warning "'$output' will be relinked during installation" + ;; + *,yes) + link_command=$finalize_var$compile_command$finalize_rpath + relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'` + ;; + *,no) + link_command=$compile_var$compile_command$compile_rpath + relink_command=$finalize_var$finalize_command$finalize_rpath + ;; + *,needless) + link_command=$finalize_var$compile_command$finalize_rpath + relink_command= + ;; + esac + + # Replace the output file specification. + link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` + + # Delete the old output files. + $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname + + func_show_eval "$link_command" 'exit $?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output_objdir/$outputname" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + # Now create the wrapper script. + func_verbose "creating $output" + + # Quote the relink command for shipping. + if test -n "$relink_command"; then + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + func_quote_arg pretty "$var_value" + relink_command="$var=$func_quote_arg_result; export $var; $relink_command" + fi + done + func_quote_arg pretty,unquoted "(cd `pwd`; $relink_command)" + relink_command=$func_quote_arg_unquoted_result + fi + + # Only actually do things if not in dry run mode. + $opt_dry_run || { + # win32 will think the script is a binary if it has + # a .exe suffix, so we strip it off here. + case $output in + *.exe) func_stripname '' '.exe' "$output" + output=$func_stripname_result ;; + esac + # test for cygwin because mv fails w/o .exe extensions + case $host in + *cygwin*) + exeext=.exe + func_stripname '' '.exe' "$outputname" + outputname=$func_stripname_result ;; + *) exeext= ;; + esac + case $host in + *cygwin* | *mingw* ) + func_dirname_and_basename "$output" "" "." + output_name=$func_basename_result + output_path=$func_dirname_result + cwrappersource=$output_path/$objdir/lt-$output_name.c + cwrapper=$output_path/$output_name.exe + $RM $cwrappersource $cwrapper + trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 + + func_emit_cwrapperexe_src > $cwrappersource + + # The wrapper executable is built using the $host compiler, + # because it contains $host paths and files. If cross- + # compiling, it, like the target executable, must be + # executed on the $host or under an emulation environment. + $opt_dry_run || { + $LTCC $LTCFLAGS -o $cwrapper $cwrappersource + $STRIP $cwrapper + } + + # Now, create the wrapper script for func_source use: + func_ltwrapper_scriptname $cwrapper + $RM $func_ltwrapper_scriptname_result + trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 + $opt_dry_run || { + # note: this script will not be executed, so do not chmod. + if test "x$build" = "x$host"; then + $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result + else + func_emit_wrapper no > $func_ltwrapper_scriptname_result + fi + } + ;; + * ) + $RM $output + trap "$RM $output; exit $EXIT_FAILURE" 1 2 15 + + func_emit_wrapper no > $output + chmod +x $output + ;; + esac + } + exit $EXIT_SUCCESS + ;; + esac + + # See if we need to build an old-fashioned archive. + for oldlib in $oldlibs; do + + case $build_libtool_libs in + convenience) + oldobjs="$libobjs_save $symfileobj" + addlibs=$convenience + build_libtool_libs=no + ;; + module) + oldobjs=$libobjs_save + addlibs=$old_convenience + build_libtool_libs=no + ;; + *) + oldobjs="$old_deplibs $non_pic_objects" + $preload && test -f "$symfileobj" \ + && func_append oldobjs " $symfileobj" + addlibs=$old_convenience + ;; + esac + + if test -n "$addlibs"; then + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $addlibs + func_append oldobjs " $func_extract_archives_result" + fi + + # Do each command in the archive commands. + if test -n "$old_archive_from_new_cmds" && test yes = "$build_libtool_libs"; then + cmds=$old_archive_from_new_cmds + else + + # Add any objects from preloaded convenience libraries + if test -n "$dlprefiles"; then + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $dlprefiles + func_append oldobjs " $func_extract_archives_result" + fi + + # POSIX demands no paths to be encoded in archives. We have + # to avoid creating archives with duplicate basenames if we + # might have to extract them afterwards, e.g., when creating a + # static archive out of a convenience library, or when linking + # the entirety of a libtool archive into another (currently + # not supported by libtool). + if (for obj in $oldobjs + do + func_basename "$obj" + $ECHO "$func_basename_result" + done | sort | sort -uc >/dev/null 2>&1); then + : + else + echo "copying selected object files to avoid basename conflicts..." + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + func_mkdir_p "$gentop" + save_oldobjs=$oldobjs + oldobjs= + counter=1 + for obj in $save_oldobjs + do + func_basename "$obj" + objbase=$func_basename_result + case " $oldobjs " in + " ") oldobjs=$obj ;; + *[\ /]"$objbase "*) + while :; do + # Make sure we don't pick an alternate name that also + # overlaps. + newobj=lt$counter-$objbase + func_arith $counter + 1 + counter=$func_arith_result + case " $oldobjs " in + *[\ /]"$newobj "*) ;; + *) if test ! -f "$gentop/$newobj"; then break; fi ;; + esac + done + func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" + func_append oldobjs " $gentop/$newobj" + ;; + *) func_append oldobjs " $obj" ;; + esac + done + fi + func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 + tool_oldlib=$func_to_tool_file_result + eval cmds=\"$old_archive_cmds\" + + func_len " $cmds" + len=$func_len_result + if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + cmds=$old_archive_cmds + elif test -n "$archiver_list_spec"; then + func_verbose "using command file archive linking..." + for obj in $oldobjs + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" + done > $output_objdir/$libname.libcmd + func_to_tool_file "$output_objdir/$libname.libcmd" + oldobjs=" $archiver_list_spec$func_to_tool_file_result" + cmds=$old_archive_cmds + else + # the command line is too long to link in one step, link in parts + func_verbose "using piecewise archive linking..." + save_RANLIB=$RANLIB + RANLIB=: + objlist= + concat_cmds= + save_oldobjs=$oldobjs + oldobjs= + # Is there a better way of finding the last object in the list? + for obj in $save_oldobjs + do + last_oldobj=$obj + done + eval test_cmds=\"$old_archive_cmds\" + func_len " $test_cmds" + len0=$func_len_result + len=$len0 + for obj in $save_oldobjs + do + func_len " $obj" + func_arith $len + $func_len_result + len=$func_arith_result + func_append objlist " $obj" + if test "$len" -lt "$max_cmd_len"; then + : + else + # the above command should be used before it gets too long + oldobjs=$objlist + if test "$obj" = "$last_oldobj"; then + RANLIB=$save_RANLIB + fi + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\$concat_cmds$old_archive_cmds\" + objlist= + len=$len0 + fi + done + RANLIB=$save_RANLIB + oldobjs=$objlist + if test -z "$oldobjs"; then + eval cmds=\"\$concat_cmds\" + else + eval cmds=\"\$concat_cmds~\$old_archive_cmds\" + fi + fi + fi + func_execute_cmds "$cmds" 'exit $?' + done + + test -n "$generated" && \ + func_show_eval "${RM}r$generated" + + # Now create the libtool archive. + case $output in + *.la) + old_library= + test yes = "$build_old_libs" && old_library=$libname.$libext + func_verbose "creating $output" + + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + func_quote_arg pretty,unquoted "$var_value" + relink_command="$var=$func_quote_arg_unquoted_result; export $var; $relink_command" + fi + done + # Quote the link command for shipping. + relink_command="(cd `pwd`; $SHELL \"$progpath\" $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" + func_quote_arg pretty,unquoted "$relink_command" + relink_command=$func_quote_arg_unquoted_result + if test yes = "$hardcode_automatic"; then + relink_command= + fi + + # Only create the output if not a dry run. + $opt_dry_run || { + for installed in no yes; do + if test yes = "$installed"; then + if test -z "$install_libdir"; then + break + fi + output=$output_objdir/${outputname}i + # Replace all uninstalled libtool libraries with the installed ones + newdependency_libs= + for deplib in $dependency_libs; do + case $deplib in + *.la) + func_basename "$deplib" + name=$func_basename_result + func_resolve_sysroot "$deplib" + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $func_resolve_sysroot_result` + test -z "$libdir" && \ + func_fatal_error "'$deplib' is not a valid libtool archive" + func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name" + ;; + -L*) + func_stripname -L '' "$deplib" + func_replace_sysroot "$func_stripname_result" + func_append newdependency_libs " -L$func_replace_sysroot_result" + ;; + -R*) + func_stripname -R '' "$deplib" + func_replace_sysroot "$func_stripname_result" + func_append newdependency_libs " -R$func_replace_sysroot_result" + ;; + *) func_append newdependency_libs " $deplib" ;; + esac + done + dependency_libs=$newdependency_libs + newdlfiles= + + for lib in $dlfiles; do + case $lib in + *.la) + func_basename "$lib" + name=$func_basename_result + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + test -z "$libdir" && \ + func_fatal_error "'$lib' is not a valid libtool archive" + func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name" + ;; + *) func_append newdlfiles " $lib" ;; + esac + done + dlfiles=$newdlfiles + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + *.la) + # Only pass preopened files to the pseudo-archive (for + # eventual linking with the app. that links it) if we + # didn't already link the preopened objects directly into + # the library: + func_basename "$lib" + name=$func_basename_result + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + test -z "$libdir" && \ + func_fatal_error "'$lib' is not a valid libtool archive" + func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name" + ;; + esac + done + dlprefiles=$newdlprefiles + else + newdlfiles= + for lib in $dlfiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; + *) abs=`pwd`"/$lib" ;; + esac + func_append newdlfiles " $abs" + done + dlfiles=$newdlfiles + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; + *) abs=`pwd`"/$lib" ;; + esac + func_append newdlprefiles " $abs" + done + dlprefiles=$newdlprefiles + fi + $RM $output + # place dlname in correct position for cygwin + # In fact, it would be nice if we could use this code for all target + # systems that can't hard-code library paths into their executables + # and that have no shared library path variable independent of PATH, + # but it turns out we can't easily determine that from inspecting + # libtool variables, so we have to hard-code the OSs to which it + # applies here; at the moment, that means platforms that use the PE + # object format with DLL files. See the long comment at the top of + # tests/bindir.at for full details. + tdlname=$dlname + case $host,$output,$installed,$module,$dlname in + *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) + # If a -bindir argument was supplied, place the dll there. + if test -n "$bindir"; then + func_relative_path "$install_libdir" "$bindir" + tdlname=$func_relative_path_result/$dlname + else + # Otherwise fall back on heuristic. + tdlname=../bin/$dlname + fi + ;; + esac + $ECHO > $output "\ +# $outputname - a libtool library file +# Generated by $PROGRAM (GNU $PACKAGE) $VERSION +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='$tdlname' + +# Names of this library. +library_names='$library_names' + +# The name of the static archive. +old_library='$old_library' + +# Linker flags that cannot go in dependency_libs. +inherited_linker_flags='$new_inherited_linker_flags' + +# Libraries that this one depends upon. +dependency_libs='$dependency_libs' + +# Names of additional weak libraries provided by this library +weak_library_names='$weak_libs' + +# Version information for $libname. +current=$current +age=$age +revision=$revision + +# Is this an already installed library? +installed=$installed + +# Should we warn about portability when linking against -modules? +shouldnotlink=$module + +# Files to dlopen/dlpreopen +dlopen='$dlfiles' +dlpreopen='$dlprefiles' + +# Directory that this library needs to be installed in: +libdir='$install_libdir'" + if test no,yes = "$installed,$need_relink"; then + $ECHO >> $output "\ +relink_command=\"$relink_command\"" + fi + done + } + + # Do a symbolic link so that the libtool archive can be found in + # LD_LIBRARY_PATH before the program is installed. + func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?' + ;; + esac + exit $EXIT_SUCCESS +} + +if test link = "$opt_mode" || test relink = "$opt_mode"; then + func_mode_link ${1+"$@"} +fi + + +# func_mode_uninstall arg... +func_mode_uninstall () +{ + $debug_cmd + + RM=$nonopt + files= + rmforce=false + exit_status=0 + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic=$magic + + for arg + do + case $arg in + -f) func_append RM " $arg"; rmforce=: ;; + -*) func_append RM " $arg" ;; + *) func_append files " $arg" ;; + esac + done + + test -z "$RM" && \ + func_fatal_help "you must specify an RM program" + + rmdirs= + + for file in $files; do + func_dirname "$file" "" "." + dir=$func_dirname_result + if test . = "$dir"; then + odir=$objdir + else + odir=$dir/$objdir + fi + func_basename "$file" + name=$func_basename_result + test uninstall = "$opt_mode" && odir=$dir + + # Remember odir for removal later, being careful to avoid duplicates + if test clean = "$opt_mode"; then + case " $rmdirs " in + *" $odir "*) ;; + *) func_append rmdirs " $odir" ;; + esac + fi + + # Don't error if the file doesn't exist and rm -f was used. + if { test -L "$file"; } >/dev/null 2>&1 || + { test -h "$file"; } >/dev/null 2>&1 || + test -f "$file"; then + : + elif test -d "$file"; then + exit_status=1 + continue + elif $rmforce; then + continue + fi + + rmfiles=$file + + case $name in + *.la) + # Possibly a libtool archive, so verify it. + if func_lalib_p "$file"; then + func_source $dir/$name + + # Delete the libtool libraries and symlinks. + for n in $library_names; do + func_append rmfiles " $odir/$n" + done + test -n "$old_library" && func_append rmfiles " $odir/$old_library" + + case $opt_mode in + clean) + case " $library_names " in + *" $dlname "*) ;; + *) test -n "$dlname" && func_append rmfiles " $odir/$dlname" ;; + esac + test -n "$libdir" && func_append rmfiles " $odir/$name $odir/${name}i" + ;; + uninstall) + if test -n "$library_names"; then + # Do each command in the postuninstall commands. + func_execute_cmds "$postuninstall_cmds" '$rmforce || exit_status=1' + fi + + if test -n "$old_library"; then + # Do each command in the old_postuninstall commands. + func_execute_cmds "$old_postuninstall_cmds" '$rmforce || exit_status=1' + fi + # FIXME: should reinstall the best remaining shared library. + ;; + esac + fi + ;; + + *.lo) + # Possibly a libtool object, so verify it. + if func_lalib_p "$file"; then + + # Read the .lo file + func_source $dir/$name + + # Add PIC object to the list of files to remove. + if test -n "$pic_object" && test none != "$pic_object"; then + func_append rmfiles " $dir/$pic_object" + fi + + # Add non-PIC object to the list of files to remove. + if test -n "$non_pic_object" && test none != "$non_pic_object"; then + func_append rmfiles " $dir/$non_pic_object" + fi + fi + ;; + + *) + if test clean = "$opt_mode"; then + noexename=$name + case $file in + *.exe) + func_stripname '' '.exe' "$file" + file=$func_stripname_result + func_stripname '' '.exe' "$name" + noexename=$func_stripname_result + # $file with .exe has already been added to rmfiles, + # add $file without .exe + func_append rmfiles " $file" + ;; + esac + # Do a test to see if this is a libtool program. + if func_ltwrapper_p "$file"; then + if func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + relink_command= + func_source $func_ltwrapper_scriptname_result + func_append rmfiles " $func_ltwrapper_scriptname_result" + else + relink_command= + func_source $dir/$noexename + fi + + # note $name still contains .exe if it was in $file originally + # as does the version of $file that was added into $rmfiles + func_append rmfiles " $odir/$name $odir/${name}S.$objext" + if test yes = "$fast_install" && test -n "$relink_command"; then + func_append rmfiles " $odir/lt-$name" + fi + if test "X$noexename" != "X$name"; then + func_append rmfiles " $odir/lt-$noexename.c" + fi + fi + fi + ;; + esac + func_show_eval "$RM $rmfiles" 'exit_status=1' + done + + # Try to remove the $objdir's in the directories where we deleted files + for dir in $rmdirs; do + if test -d "$dir"; then + func_show_eval "rmdir $dir >/dev/null 2>&1" + fi + done + + exit $exit_status +} + +if test uninstall = "$opt_mode" || test clean = "$opt_mode"; then + func_mode_uninstall ${1+"$@"} +fi + +test -z "$opt_mode" && { + help=$generic_help + func_fatal_help "you must specify a MODE" +} + +test -z "$exec_cmd" && \ + func_fatal_help "invalid operation mode '$opt_mode'" + +if test -n "$exec_cmd"; then + eval exec "$exec_cmd" + exit $EXIT_FAILURE +fi + +exit $exit_status + + +# The TAGs below are defined such that we never get into a situation +# where we disable both kinds of libraries. Given conflicting +# choices, we go for a static library, that is the most portable, +# since we can't tell whether shared libraries were disabled because +# the user asked for that or because the platform doesn't support +# them. This is particularly important on AIX, because we don't +# support having both static and shared libraries enabled at the same +# time on that platform, so we default to a shared-only configuration. +# If a disable-shared tag is given, we'll fallback to a static-only +# configuration. But we'll never go from static-only to shared-only. + +# ### BEGIN LIBTOOL TAG CONFIG: disable-shared +build_libtool_libs=no +build_old_libs=yes +# ### END LIBTOOL TAG CONFIG: disable-shared + +# ### BEGIN LIBTOOL TAG CONFIG: disable-static +build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` +# ### END LIBTOOL TAG CONFIG: disable-static + +# Local Variables: +# mode:shell-script +# sh-indentation:2 +# End: diff --git a/build-aux/missing b/build-aux/missing new file mode 100755 index 0000000..f62bbae --- /dev/null +++ b/build-aux/missing @@ -0,0 +1,215 @@ +#! /bin/sh +# Common wrapper for a few potentially missing GNU programs. + +scriptversion=2013-10-28.13; # UTC + +# Copyright (C) 1996-2014 Free Software Foundation, Inc. +# Originally written by Fran,cois Pinard , 1996. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, 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. + +if test $# -eq 0; then + echo 1>&2 "Try '$0 --help' for more information" + exit 1 +fi + +case $1 in + + --is-lightweight) + # Used by our autoconf macros to check whether the available missing + # script is modern enough. + exit 0 + ;; + + --run) + # Back-compat with the calling convention used by older automake. + shift + ;; + + -h|--h|--he|--hel|--help) + echo "\ +$0 [OPTION]... PROGRAM [ARGUMENT]... + +Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due +to PROGRAM being missing or too old. + +Options: + -h, --help display this help and exit + -v, --version output version information and exit + +Supported PROGRAM values: + aclocal autoconf autoheader autom4te automake makeinfo + bison yacc flex lex help2man + +Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and +'g' are ignored when checking the name. + +Send bug reports to ." + exit $? + ;; + + -v|--v|--ve|--ver|--vers|--versi|--versio|--version) + echo "missing $scriptversion (GNU Automake)" + exit $? + ;; + + -*) + echo 1>&2 "$0: unknown '$1' option" + echo 1>&2 "Try '$0 --help' for more information" + exit 1 + ;; + +esac + +# Run the given program, remember its exit status. +"$@"; st=$? + +# If it succeeded, we are done. +test $st -eq 0 && exit 0 + +# Also exit now if we it failed (or wasn't found), and '--version' was +# passed; such an option is passed most likely to detect whether the +# program is present and works. +case $2 in --version|--help) exit $st;; esac + +# Exit code 63 means version mismatch. This often happens when the user +# tries to use an ancient version of a tool on a file that requires a +# minimum version. +if test $st -eq 63; then + msg="probably too old" +elif test $st -eq 127; then + # Program was missing. + msg="missing on your system" +else + # Program was found and executed, but failed. Give up. + exit $st +fi + +perl_URL=http://www.perl.org/ +flex_URL=http://flex.sourceforge.net/ +gnu_software_URL=http://www.gnu.org/software + +program_details () +{ + case $1 in + aclocal|automake) + echo "The '$1' program is part of the GNU Automake package:" + echo "<$gnu_software_URL/automake>" + echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" + echo "<$gnu_software_URL/autoconf>" + echo "<$gnu_software_URL/m4/>" + echo "<$perl_URL>" + ;; + autoconf|autom4te|autoheader) + echo "The '$1' program is part of the GNU Autoconf package:" + echo "<$gnu_software_URL/autoconf/>" + echo "It also requires GNU m4 and Perl in order to run:" + echo "<$gnu_software_URL/m4/>" + echo "<$perl_URL>" + ;; + esac +} + +give_advice () +{ + # Normalize program name to check for. + normalized_program=`echo "$1" | sed ' + s/^gnu-//; t + s/^gnu//; t + s/^g//; t'` + + printf '%s\n' "'$1' is $msg." + + configure_deps="'configure.ac' or m4 files included by 'configure.ac'" + case $normalized_program in + autoconf*) + echo "You should only need it if you modified 'configure.ac'," + echo "or m4 files included by it." + program_details 'autoconf' + ;; + autoheader*) + echo "You should only need it if you modified 'acconfig.h' or" + echo "$configure_deps." + program_details 'autoheader' + ;; + automake*) + echo "You should only need it if you modified 'Makefile.am' or" + echo "$configure_deps." + program_details 'automake' + ;; + aclocal*) + echo "You should only need it if you modified 'acinclude.m4' or" + echo "$configure_deps." + program_details 'aclocal' + ;; + autom4te*) + echo "You might have modified some maintainer files that require" + echo "the 'autom4te' program to be rebuilt." + program_details 'autom4te' + ;; + bison*|yacc*) + echo "You should only need it if you modified a '.y' file." + echo "You may want to install the GNU Bison package:" + echo "<$gnu_software_URL/bison/>" + ;; + lex*|flex*) + echo "You should only need it if you modified a '.l' file." + echo "You may want to install the Fast Lexical Analyzer package:" + echo "<$flex_URL>" + ;; + help2man*) + echo "You should only need it if you modified a dependency" \ + "of a man page." + echo "You may want to install the GNU Help2man package:" + echo "<$gnu_software_URL/help2man/>" + ;; + makeinfo*) + echo "You should only need it if you modified a '.texi' file, or" + echo "any other file indirectly affecting the aspect of the manual." + echo "You might want to install the Texinfo package:" + echo "<$gnu_software_URL/texinfo/>" + echo "The spurious makeinfo call might also be the consequence of" + echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" + echo "want to install GNU make:" + echo "<$gnu_software_URL/make/>" + ;; + *) + echo "You might have modified some files without having the proper" + echo "tools for further handling them. Check the 'README' file, it" + echo "often tells you about the needed prerequisites for installing" + echo "this package. You may also peek at any GNU archive site, in" + echo "case some other package contains this missing '$1' program." + ;; + esac +} + +give_advice "$1" | sed -e '1s/^/WARNING: /' \ + -e '2,$s/^/ /' >&2 + +# Propagate the correct exit status (expected to be 127 for a program +# not found, 63 for a program that failed due to version mismatch). +exit $st + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/build-aux/test-driver b/build-aux/test-driver new file mode 100755 index 0000000..8e575b0 --- /dev/null +++ b/build-aux/test-driver @@ -0,0 +1,148 @@ +#! /bin/sh +# test-driver - basic testsuite driver script. + +scriptversion=2013-07-13.22; # UTC + +# Copyright (C) 2011-2014 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, 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 file is maintained in Automake, please report +# bugs to or send patches to +# . + +# Make unconditional expansion of undefined variables an error. This +# helps a lot in preventing typo-related bugs. +set -u + +usage_error () +{ + echo "$0: $*" >&2 + print_usage >&2 + exit 2 +} + +print_usage () +{ + cat <$log_file 2>&1 +estatus=$? + +if test $enable_hard_errors = no && test $estatus -eq 99; then + tweaked_estatus=1 +else + tweaked_estatus=$estatus +fi + +case $tweaked_estatus:$expect_failure in + 0:yes) col=$red res=XPASS recheck=yes gcopy=yes;; + 0:*) col=$grn res=PASS recheck=no gcopy=no;; + 77:*) col=$blu res=SKIP recheck=no gcopy=yes;; + 99:*) col=$mgn res=ERROR recheck=yes gcopy=yes;; + *:yes) col=$lgn res=XFAIL recheck=no gcopy=yes;; + *:*) col=$red res=FAIL recheck=yes gcopy=yes;; +esac + +# Report the test outcome and exit status in the logs, so that one can +# know whether the test passed or failed simply by looking at the '.log' +# file, without the need of also peaking into the corresponding '.trs' +# file (automake bug#11814). +echo "$res $test_name (exit status: $estatus)" >>$log_file + +# Report outcome to console. +echo "${col}${res}${std}: $test_name" + +# Register the test result, and other relevant metadata. +echo ":test-result: $res" > $trs_file +echo ":global-test-result: $res" >> $trs_file +echo ":recheck: $recheck" >> $trs_file +echo ":copy-in-global-log: $gcopy" >> $trs_file + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/compile b/compile new file mode 100755 index 0000000..a85b723 --- /dev/null +++ b/compile @@ -0,0 +1,347 @@ +#! /bin/sh +# Wrapper for compilers which do not understand '-c -o'. + +scriptversion=2012-10-14.11; # UTC + +# Copyright (C) 1999-2014 Free Software Foundation, Inc. +# Written by Tom Tromey . +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, 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 file is maintained in Automake, please report +# bugs to or send patches to +# . + +nl=' +' + +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent tools from complaining about whitespace usage. +IFS=" "" $nl" + +file_conv= + +# func_file_conv build_file lazy +# Convert a $build file to $host form and store it in $file +# Currently only supports Windows hosts. If the determined conversion +# type is listed in (the comma separated) LAZY, no conversion will +# take place. +func_file_conv () +{ + file=$1 + case $file in + / | /[!/]*) # absolute file, and not a UNC file + if test -z "$file_conv"; then + # lazily determine how to convert abs files + case `uname -s` in + MINGW*) + file_conv=mingw + ;; + CYGWIN*) + file_conv=cygwin + ;; + *) + file_conv=wine + ;; + esac + fi + case $file_conv/,$2, in + *,$file_conv,*) + ;; + mingw/*) + file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` + ;; + cygwin/*) + file=`cygpath -m "$file" || echo "$file"` + ;; + wine/*) + file=`winepath -w "$file" || echo "$file"` + ;; + esac + ;; + esac +} + +# func_cl_dashL linkdir +# Make cl look for libraries in LINKDIR +func_cl_dashL () +{ + func_file_conv "$1" + if test -z "$lib_path"; then + lib_path=$file + else + lib_path="$lib_path;$file" + fi + linker_opts="$linker_opts -LIBPATH:$file" +} + +# func_cl_dashl library +# Do a library search-path lookup for cl +func_cl_dashl () +{ + lib=$1 + found=no + save_IFS=$IFS + IFS=';' + for dir in $lib_path $LIB + do + IFS=$save_IFS + if $shared && test -f "$dir/$lib.dll.lib"; then + found=yes + lib=$dir/$lib.dll.lib + break + fi + if test -f "$dir/$lib.lib"; then + found=yes + lib=$dir/$lib.lib + break + fi + if test -f "$dir/lib$lib.a"; then + found=yes + lib=$dir/lib$lib.a + break + fi + done + IFS=$save_IFS + + if test "$found" != yes; then + lib=$lib.lib + fi +} + +# func_cl_wrapper cl arg... +# Adjust compile command to suit cl +func_cl_wrapper () +{ + # Assume a capable shell + lib_path= + shared=: + linker_opts= + for arg + do + if test -n "$eat"; then + eat= + else + case $1 in + -o) + # configure might choose to run compile as 'compile cc -o foo foo.c'. + eat=1 + case $2 in + *.o | *.[oO][bB][jJ]) + func_file_conv "$2" + set x "$@" -Fo"$file" + shift + ;; + *) + func_file_conv "$2" + set x "$@" -Fe"$file" + shift + ;; + esac + ;; + -I) + eat=1 + func_file_conv "$2" mingw + set x "$@" -I"$file" + shift + ;; + -I*) + func_file_conv "${1#-I}" mingw + set x "$@" -I"$file" + shift + ;; + -l) + eat=1 + func_cl_dashl "$2" + set x "$@" "$lib" + shift + ;; + -l*) + func_cl_dashl "${1#-l}" + set x "$@" "$lib" + shift + ;; + -L) + eat=1 + func_cl_dashL "$2" + ;; + -L*) + func_cl_dashL "${1#-L}" + ;; + -static) + shared=false + ;; + -Wl,*) + arg=${1#-Wl,} + save_ifs="$IFS"; IFS=',' + for flag in $arg; do + IFS="$save_ifs" + linker_opts="$linker_opts $flag" + done + IFS="$save_ifs" + ;; + -Xlinker) + eat=1 + linker_opts="$linker_opts $2" + ;; + -*) + set x "$@" "$1" + shift + ;; + *.cc | *.CC | *.cxx | *.CXX | *.[cC]++) + func_file_conv "$1" + set x "$@" -Tp"$file" + shift + ;; + *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO]) + func_file_conv "$1" mingw + set x "$@" "$file" + shift + ;; + *) + set x "$@" "$1" + shift + ;; + esac + fi + shift + done + if test -n "$linker_opts"; then + linker_opts="-link$linker_opts" + fi + exec "$@" $linker_opts + exit 1 +} + +eat= + +case $1 in + '') + echo "$0: No command. Try '$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: compile [--help] [--version] PROGRAM [ARGS] + +Wrapper for compilers which do not understand '-c -o'. +Remove '-o dest.o' from ARGS, run PROGRAM with the remaining +arguments, and rename the output as expected. + +If you are trying to build a whole package this is not the +right script to run: please start by reading the file 'INSTALL'. + +Report bugs to . +EOF + exit $? + ;; + -v | --v*) + echo "compile $scriptversion" + exit $? + ;; + cl | *[/\\]cl | cl.exe | *[/\\]cl.exe ) + func_cl_wrapper "$@" # Doesn't return... + ;; +esac + +ofile= +cfile= + +for arg +do + if test -n "$eat"; then + eat= + else + case $1 in + -o) + # configure might choose to run compile as 'compile cc -o foo foo.c'. + # So we strip '-o arg' only if arg is an object. + eat=1 + case $2 in + *.o | *.obj) + ofile=$2 + ;; + *) + set x "$@" -o "$2" + shift + ;; + esac + ;; + *.c) + cfile=$1 + set x "$@" "$1" + shift + ;; + *) + set x "$@" "$1" + shift + ;; + esac + fi + shift +done + +if test -z "$ofile" || test -z "$cfile"; then + # If no '-o' option was seen then we might have been invoked from a + # pattern rule where we don't need one. That is ok -- this is a + # normal compilation that the losing compiler can handle. If no + # '.c' file was seen then we are probably linking. That is also + # ok. + exec "$@" +fi + +# Name of file we expect compiler to create. +cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'` + +# Create the lock directory. +# Note: use '[/\\:.-]' here to ensure that we don't use the same name +# that we are using for the .o file. Also, base the name on the expected +# object file name, since that is what matters with a parallel build. +lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d +while true; do + if mkdir "$lockdir" >/dev/null 2>&1; then + break + fi + sleep 1 +done +# FIXME: race condition here if user kills between mkdir and trap. +trap "rmdir '$lockdir'; exit 1" 1 2 15 + +# Run the compile. +"$@" +ret=$? + +if test -f "$cofile"; then + test "$cofile" = "$ofile" || mv "$cofile" "$ofile" +elif test -f "${cofile}bj"; then + test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile" +fi + +rmdir "$lockdir" +exit $ret + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/config.guess b/config.guess new file mode 100755 index 0000000..f50dcdb --- /dev/null +++ b/config.guess @@ -0,0 +1,1480 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright 1992-2018 Free Software Foundation, Inc. + +timestamp='2018-02-24' + +# 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-2018 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 + +trap 'exit 1' 1 2 15 + +# 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. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { 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) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > "$dummy.c" ; + for c in cc gcc c89 c99 ; do + if ($c -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; 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 ; set_cc_for_build= ;' + +# 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) >/dev/null 2>&1 ; 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 + + eval "$set_cc_for_build" + cat <<-EOF > "$dummy.c" + #include + #if defined(__UCLIBC__) + LIBC=uclibc + #elif defined(__dietlibc__) + LIBC=dietlibc + #else + LIBC=gnu + #endif + EOF + eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`" + + # If ldd exists, use it to detect musl libc. + if command -v ldd >/dev/null && \ + ldd --version 2>&1 | grep -q ^musl + then + LIBC=musl + fi + ;; +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 + 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) + eval "$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 ;; + 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 ;; + *: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.*:*) + eval "$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 [ "$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) + eval "$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 [ "$UNAME_PROCESSOR" = mc88100 ] || [ "$UNAME_PROCESSOR" = mc88110 ] + then + if [ "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx ] || \ + [ "$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 [ -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 + eval "$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 [ -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 [ -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 [ "$HP_ARCH" = "" ]; then + eval "$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 [ "$HP_ARCH" = hppa2.0w ] + then + eval "$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:*:*) + eval "$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 [ -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 ;; + *: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-unknown-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 ;; + i*86:Minix:*:*) + echo "$UNAME_MACHINE"-pc-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` 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:*:*) + eval "$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:*:*) + eval "$set_cc_for_build" + sed 's/^ //' << EOF > "$dummy.c" + #undef CPU + #undef ${UNAME_MACHINE} + #undef ${UNAME_MACHINE}el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=${UNAME_MACHINE}el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=${UNAME_MACHINE} + #else + CPU= + #endif + #endif +EOF + eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU'`" + test "x$CPU" != x && { echo "$CPU-unknown-linux-$LIBC"; 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:*:*) + if objdump -f /bin/sh | grep -q elf32-x86-64; then + echo "$UNAME_MACHINE"-pc-linux-"$LIBC"x32 + else + echo "$UNAME_MACHINE"-pc-linux-"$LIBC" + fi + 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 [ -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 ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + eval "$set_cc_for_build" + if test "$UNAME_PROCESSOR" = unknown ; then + UNAME_PROCESSOR=powerpc + fi + if test "`echo "$UNAME_RELEASE" | sed -e 's/\..*//'`" -le 10 ; then + if [ "$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 + fi + elif test "$UNAME_PROCESSOR" = i386 ; then + # Avoid executing cc on OS X 10.9, as it ships with a stub + # that puts up a graphical alert prompting to install + # developer tools. Any system running Mac OS X 10.7 or + # later (Darwin 11 and later) is required to have a 64-bit + # processor. This is not true of the ARM version of Darwin + # that Apple uses in portable devices. + UNAME_PROCESSOR=x86_64 + 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. + 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 ;; +esac + +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 </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 + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-functions 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/config.h.in b/config.h.in new file mode 100644 index 0000000..227df01 --- /dev/null +++ b/config.h.in @@ -0,0 +1,96 @@ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Apache httpd */ +#undef APACHE_HTTPD + +/* The gettext domain name */ +#undef GETTEXT_PACKAGE + +/* Whether or not apache can be used for tests */ +#undef HAVE_APACHE + +/* Whether or not curl can be used for tests */ +#undef HAVE_CURL + +/* Define to 1 if you have the header file. */ +#undef HAVE_DLFCN_H + +/* Define to 1 if you have the `gmtime_r' function. */ +#undef HAVE_GMTIME_R + +/* Defined if GNOME support is enabled */ +#undef HAVE_GNOME + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Have php-xmlrpc */ +#undef HAVE_PHP_XMLRPC + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Whether or not GSSAPI libs are available */ +#undef LIBSOUP_HAVE_GSSAPI + +/* Define to the sub-directory where libtool stores uninstalled libraries. */ +#undef LT_OBJDIR + +/* Samba's 'winbind' daemon helper 'ntlm_auth' which can be used for NTLM + single-sign-on */ +#undef NTLM_AUTH + +/* Name of package */ +#undef PACKAGE + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#undef PACKAGE_URL + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Whether or not use Samba's 'winbind' daemon helper 'ntlm_auth' for NTLM + single-sign-on */ +#undef USE_NTLM_AUTH + +/* Version number of package */ +#undef VERSION + +/* defines how to decorate public symbols while building */ +#undef _SOUP_EXTERN diff --git a/config.h.win32 b/config.h.win32 new file mode 100644 index 0000000..5def019 --- /dev/null +++ b/config.h.win32 @@ -0,0 +1,116 @@ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Apache httpd */ +/* #undef APACHE_HTTPD */ + +/* The gettext domain name */ +#define GETTEXT_PACKAGE "libsoup" + +/* Whether or not apache can be used for tests */ +/* #undef HAVE_APACHE */ + +/* Apache is 2.2.x */ +/* #undef HAVE_APACHE_2_2 */ + +/* Apache is 2.4.x */ +/* #undef HAVE_APACHE_2_4 */ + +/* Whether or not curl can be used for tests */ +#define HAVE_CURL 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_DLFCN_H */ + +/* Define to 1 if you have the `gmtime_r' function. */ +/* #undef HAVE_GMTIME_R */ + +/* Defined if GNOME support is enabled */ +#define HAVE_GNOME 1 + +/* Define to 1 if you have the header file. */ +#if !defined (_MSC_VER) || (_MSC_VER >= 1800) +#define HAVE_INTTYPES_H 1 +#endif + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Have php-xmlrpc */ +/* #undef HAVE_PHP_XMLRPC */ + +/* Define to 1 if you have the header file. */ +#if !defined (_MSC_VER) || (_MSC_VER >= 1600) +#define HAVE_STDINT_H 1 +#endif + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the header file. */ +#ifndef _MSC_VER +#define HAVE_STRINGS_H 1 +#endif + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#ifndef _MSC_VER +#defin HAVE_UNISTD_H 1 +#endif + +/* Whether or not GSSAPI libs are available */ +/* Note: This is activated in the projects when the appropriate config is selected */ +/* #undef LIBSOUP_HAVE_GSSAPI */ + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#define LT_OBJDIR ".libs/" + +/* Samba's 'winbind' daemon helper 'ntlm_auth' which can be used for NTLM + single-sign-on */ +/* #undef NTLM_AUTH */ + +/* Name of package */ +#define PACKAGE "libsoup" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "http://bugzilla.gnome.org/enter_bug.cgi?product=libsoup" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "libsoup" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "libsoup 2.62.3" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "libsoup" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "2.62.3" + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Whether or not use Samba's 'winbind' daemon helper 'ntlm_auth' for NTLM + single-sign-on */ +/* #undef USE_NTLM_AUTH */ + +/* Version number of package */ +#define VERSION "@PACKAGE_VERSION" + +/* defines how to decorate public symbols while building */ +#ifdef _MSC_VER +#define _SOUP_EXTERN __declspec (dllexport) extern +#else +#define _SOUP_EXTERN __attribute__((visibility("default"))) __declspec (dllexport) extern +#endif diff --git a/config.h.win32.in b/config.h.win32.in new file mode 100644 index 0000000..6231dad --- /dev/null +++ b/config.h.win32.in @@ -0,0 +1,116 @@ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Apache httpd */ +/* #undef APACHE_HTTPD */ + +/* The gettext domain name */ +#define GETTEXT_PACKAGE "libsoup" + +/* Whether or not apache can be used for tests */ +/* #undef HAVE_APACHE */ + +/* Apache is 2.2.x */ +/* #undef HAVE_APACHE_2_2 */ + +/* Apache is 2.4.x */ +/* #undef HAVE_APACHE_2_4 */ + +/* Whether or not curl can be used for tests */ +#define HAVE_CURL 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_DLFCN_H */ + +/* Define to 1 if you have the `gmtime_r' function. */ +/* #undef HAVE_GMTIME_R */ + +/* Defined if GNOME support is enabled */ +#define HAVE_GNOME 1 + +/* Define to 1 if you have the header file. */ +#if !defined (_MSC_VER) || (_MSC_VER >= 1800) +#define HAVE_INTTYPES_H 1 +#endif + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Have php-xmlrpc */ +/* #undef HAVE_PHP_XMLRPC */ + +/* Define to 1 if you have the header file. */ +#if !defined (_MSC_VER) || (_MSC_VER >= 1600) +#define HAVE_STDINT_H 1 +#endif + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the header file. */ +#ifndef _MSC_VER +#define HAVE_STRINGS_H 1 +#endif + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#ifndef _MSC_VER +#defin HAVE_UNISTD_H 1 +#endif + +/* Whether or not GSSAPI libs are available */ +/* Note: This is activated in the projects when the appropriate config is selected */ +/* #undef LIBSOUP_HAVE_GSSAPI */ + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#define LT_OBJDIR ".libs/" + +/* Samba's 'winbind' daemon helper 'ntlm_auth' which can be used for NTLM + single-sign-on */ +/* #undef NTLM_AUTH */ + +/* Name of package */ +#define PACKAGE "@PACKAGE@" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "@PACKAGE_BUGREPORT@" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "@PACKAGE_NAME@" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "@PACKAGE_NAME@ @PACKAGE_VERSION@" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "@PACKAGE_TARNAME@" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "@PACKAGE_VERSION@" + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Whether or not use Samba's 'winbind' daemon helper 'ntlm_auth' for NTLM + single-sign-on */ +/* #undef USE_NTLM_AUTH */ + +/* Version number of package */ +#define VERSION "@PACKAGE_VERSION" + +/* defines how to decorate public symbols while building */ +#ifdef _MSC_VER +#define _SOUP_EXTERN __declspec (dllexport) extern +#else +#define _SOUP_EXTERN __attribute__((visibility("default"))) __declspec (dllexport) extern +#endif diff --git a/config.sub b/config.sub new file mode 100755 index 0000000..1d8e98b --- /dev/null +++ b/config.sub @@ -0,0 +1,1801 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright 1992-2018 Free Software Foundation, Inc. + +timestamp='2018-02-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"). + + +# Please send patches to . +# +# 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: +# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub + +# 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 or ALIAS + +Canonicalize a configuration name. + +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.sub ($timestamp) + +Copyright 1992-2018 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-android* | linux-dietlibc | linux-newlib* | \ + linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ + knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \ + kopensolaris*-gnu* | cloudabi*-eabi* | \ + storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + android-linux) + os=-linux-android + basic_machine=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown + ;; + *) + 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*178) + os=-lynxos178 + ;; + -lynx*5) + os=-lynxos5 + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo "$1" | sed -e 's/86-.*/86-sequent/'` + ;; + -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 \ + | aarch64 | aarch64_be \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arceb \ + | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ + | avr | avr32 \ + | ba \ + | be32 | be64 \ + | bfin \ + | c4x | c8051 | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | e2k | epiphany \ + | fido | fr30 | frv | ft32 \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | hexagon \ + | i370 | i860 | i960 | ia16 | ia64 \ + | ip2k | iq2000 \ + | k1om \ + | le32 | le64 \ + | lm32 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | microblazeel | 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 \ + | mipsisa32r6 | mipsisa32r6el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64r6 | mipsisa64r6el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipsr5900 | mipsr5900el \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | moxie \ + | mt \ + | msp430 \ + | nds32 | nds32le | nds32be \ + | nios | nios2 | nios2eb | nios2el \ + | ns16k | ns32k \ + | open8 | or1k | or1knd | or32 \ + | pdp10 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle \ + | pru \ + | pyramid \ + | riscv32 | riscv64 \ + | rl78 | rx \ + | score \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu \ + | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ + | ubicom32 \ + | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ + | visium \ + | wasm32 \ + | x86 | xc16x | xstormy16 | xtensa \ + | z8k | z80) + basic_machine=$basic_machine-unknown + ;; + c54x) + basic_machine=tic54x-unknown + ;; + c55x) + basic_machine=tic55x-unknown + ;; + c6x) + basic_machine=tic6x-unknown + ;; + leon|leon[3-9]) + basic_machine=sparc-$basic_machine + ;; + m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip) + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65) + ;; + ms1) + basic_machine=mt-unknown + ;; + + strongarm | thumb | xscale) + basic_machine=arm-unknown + ;; + xgate) + basic_machine=$basic_machine-unknown + os=-none + ;; + xscaleeb) + basic_machine=armeb-unknown + ;; + + xscaleel) + basic_machine=armel-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-* \ + | aarch64-* | aarch64_be-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* | avr32-* \ + | ba-* \ + | be32-* | be64-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* \ + | c8051-* | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | e2k-* | elxsi-* \ + | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | hexagon-* \ + | i*86-* | i860-* | i960-* | ia16-* | ia64-* \ + | ip2k-* | iq2000-* \ + | k1om-* \ + | le32-* | le64-* \ + | lm32-* \ + | m32c-* | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ + | microblaze-* | microblazeel-* \ + | 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-* \ + | mipsisa32r6-* | mipsisa32r6el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64r6-* | mipsisa64r6el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipsr5900-* | mipsr5900el-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | mt-* \ + | msp430-* \ + | nds32-* | nds32le-* | nds32be-* \ + | nios-* | nios2-* | nios2eb-* | nios2el-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | open8-* \ + | or1k*-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ + | pru-* \ + | pyramid-* \ + | riscv32-* | riscv64-* \ + | rl78-* | 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-* | sv1-* | sx*-* \ + | tahoe-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tile*-* \ + | tron-* \ + | ubicom32-* \ + | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ + | vax-* \ + | visium-* \ + | wasm32-* \ + | we32k-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* \ + | 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-pc + 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 + ;; + asmjs) + basic_machine=asmjs-unknown + ;; + 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 + ;; + c54x-*) + basic_machine=tic54x-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + c55x-*) + basic_machine=tic55x-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + c6x-*) + basic_machine=tic6x-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + 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 | 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*) + basic_machine=m68k-bull + os=-sysv3 + ;; + e500v[12]) + basic_machine=powerpc-unknown + os=$os"spe" + ;; + e500v[12]-*) + basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'` + os=$os"spe" + ;; + 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 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; + 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 + ;; + 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 + ;; + leon-*|leon[3-9]-*) + basic_machine=sparc-`echo "$basic_machine" | sed 's/-.*//'` + ;; + m68knommu) + basic_machine=m68k-unknown + os=-linux + ;; + m68knommu-*) + basic_machine=m68k-`echo "$basic_machine" | sed 's/^[^-]*-//'` + os=-linux + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + microblaze*) + basic_machine=microblaze-xilinx + ;; + mingw64) + basic_machine=x86_64-pc + os=-mingw64 + ;; + mingw32) + basic_machine=i686-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 + ;; + moxiebox) + basic_machine=moxie-unknown + os=-moxiebox + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + ms1-*) + basic_machine=`echo "$basic_machine" | sed -e 's/ms1-/mt-/'` + ;; + msys) + basic_machine=i686-pc + os=-msys + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + nacl) + basic_machine=le32-unknown + os=-nacl + ;; + 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 + ;; + neo-tandem) + basic_machine=neo-tandem + ;; + nse-tandem) + basic_machine=nse-tandem + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + nsv-tandem) + basic_machine=nsv-tandem + ;; + nsx-tandem) + basic_machine=nsx-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 | ppcbe) basic_machine=powerpc-unknown + ;; + ppc-* | ppcbe-*) + basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle) + 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) + 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 | rdos64) + basic_machine=x86_64-pc + os=-rdos + ;; + rdos32) + 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 + ;; + sh5el) + basic_machine=sh5le-unknown + ;; + 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 + ;; + strongarm-* | thumb-*) + basic_machine=arm-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + 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 + ;; + tile*) + basic_machine=$basic_machine-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 + ;; + x64) + basic_machine=x86_64-pc + ;; + xbox) + basic_machine=i686-pc + os=-mingw32 + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + xscale-* | xscalee[bl]-*) + basic_machine=`echo "$basic_machine" | sed 's/^xscale/arm/'` + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + 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 + ;; + 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 + ;; + 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 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # es1800 is here to avoid being matched by es* (a different OS) + -es1800*) + os=-ose + ;; + # Now 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* | -plan9* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* | -aros* | -cloudabi* | -sortix* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -knetbsd* | -mirbsd* | -netbsd* \ + | -bitrig* | -openbsd* | -solidbsd* | -libertybsd* \ + | -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* | -glidix* \ + | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -midipix* | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ + | -linux-newlib* | -linux-musl* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \ + | -onefs* | -tirtos* | -phoenix* | -fuchsia* | -redox* | -bme* \ + | -midnightbsd*) + # 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 | -xray | -os68k* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* \ + | -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 + ;; + -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 + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -zvmoe) + os=-zvmoe + ;; + -dicos*) + os=-dicos + ;; + -pikeos*) + # Until real need of OS specific support for + # particular features comes up, bare metal + # configurations are quite functional. + case $basic_machine in + arm*) + os=-eabi + ;; + *) + os=-elf + ;; + esac + ;; + -nacl*) + ;; + -ios) + ;; + -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 + ;; + c8051-*) + os=-elf + ;; + hexagon-*) + os=-elf + ;; + tic54x-*) + os=-coff + ;; + tic55x-*) + os=-coff + ;; + tic6x-*) + 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 + ;; + 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 + ;; + pru-*) + os=-elf + ;; + *-be) + os=-beos + ;; + *-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 + ;; + *-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-functions 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/configure b/configure new file mode 100755 index 0000000..2ab00a6 --- /dev/null +++ b/configure @@ -0,0 +1,17861 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.69 for libsoup 2.62.3. +# +# Report bugs to . +# +# +# Copyright (C) 1992-1996, 1998-2012 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. +as_myself= +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 + +# Use a proper internal environment variable to ensure we don't fall + # into an infinite loop, continuously re-executing ourselves. + if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then + _as_can_reexec=no; export _as_can_reexec; + # 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. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +as_fn_exit 255 + fi + # We don't want this to propagate to other subprocesses. + { _as_can_reexec=; unset _as_can_reexec;} +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 +test -x / || 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 -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || ( + ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' + ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO + ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO + PATH=/empty FPATH=/empty; export PATH FPATH + test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\ + || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || 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 : + export CONFIG_SHELL + # 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. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +exit 255 +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 and +$0: http://bugzilla.gnome.org/enter_bug.cgi?product=libsoup +$0: about your system, including any error possibly output +$0: before this message. Then install a modern shell, or +$0: manually run the script under such a shell if you do +$0: 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_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_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; } + + # If we had to re-execute with $CONFIG_SHELL, we're ensured to have + # already done that, so ensure we don't try to do so again and fall + # in an infinite loop. This has already happened in practice. + _as_can_reexec=no; export _as_can_reexec + # 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 -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +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 + +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# 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'" + +SHELL=${CONFIG_SHELL-/bin/sh} + +as_awk_strverscmp=' + # Use only awk features that work with 7th edition Unix awk (1978). + # My, what an old awk you have, Mr. Solaris! + END { + while (length(v1) && length(v2)) { + # Set d1 to be the next thing to compare from v1, and likewise for d2. + # Normally this is a single character, but if v1 and v2 contain digits, + # compare them as integers and fractions as strverscmp does. + if (v1 ~ /^[0-9]/ && v2 ~ /^[0-9]/) { + # Split v1 and v2 into their leading digit string components d1 and d2, + # and advance v1 and v2 past the leading digit strings. + for (len1 = 1; substr(v1, len1 + 1) ~ /^[0-9]/; len1++) continue + for (len2 = 1; substr(v2, len2 + 1) ~ /^[0-9]/; len2++) continue + d1 = substr(v1, 1, len1); v1 = substr(v1, len1 + 1) + d2 = substr(v2, 1, len2); v2 = substr(v2, len2 + 1) + if (d1 ~ /^0/) { + if (d2 ~ /^0/) { + # Compare two fractions. + while (d1 ~ /^0/ && d2 ~ /^0/) { + d1 = substr(d1, 2); len1-- + d2 = substr(d2, 2); len2-- + } + if (len1 != len2 && ! (len1 && len2 && substr(d1, 1, 1) == substr(d2, 1, 1))) { + # The two components differ in length, and the common prefix + # contains only leading zeros. Consider the longer to be less. + d1 = -len1 + d2 = -len2 + } else { + # Otherwise, compare as strings. + d1 = "x" d1 + d2 = "x" d2 + } + } else { + # A fraction is less than an integer. + exit 1 + } + } else { + if (d2 ~ /^0/) { + # An integer is greater than a fraction. + exit 2 + } else { + # Compare two integers. + d1 += 0 + d2 += 0 + } + } + } else { + # The normal case, without worrying about digits. + d1 = substr(v1, 1, 1); v1 = substr(v1, 2) + d2 = substr(v2, 1, 1); v2 = substr(v2, 2) + } + if (d1 < d2) exit 1 + if (d1 > d2) exit 2 + } + # Beware Solaris /usr/xgp4/bin/awk (at least through Solaris 10), + # which mishandles some comparisons of empty strings to integers. + if (length(v2)) exit 1 + if (length(v1)) exit 2 + } +' + +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='libsoup' +PACKAGE_TARNAME='libsoup' +PACKAGE_VERSION='2.62.3' +PACKAGE_STRING='libsoup 2.62.3' +PACKAGE_BUGREPORT='http://bugzilla.gnome.org/enter_bug.cgi?product=libsoup' +PACKAGE_URL='' + +ac_unique_file="libsoup-2.4.pc.in" +# 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_subst_vars='am__EXEEXT_FALSE +am__EXEEXT_TRUE +LTLIBOBJS +LIBOBJS +MSVC_NO_TOOLSET_SET_FALSE +MSVC_NO_TOOLSET_SET_TRUE +MSVC_BASE_NO_TOOLSET_SET_FALSE +MSVC_BASE_NO_TOOLSET_SET_TRUE +SOUP_HIDDEN_VISIBILITY_CFLAGS +KRB5_LIBS +KRB5_CFLAGS +KRB5_CONFIG +CODE_COVERAGE_RULES +CODE_COVERAGE_LDFLAGS +CODE_COVERAGE_CXXFLAGS +CODE_COVERAGE_CFLAGS +CODE_COVERAGE_CPPFLAGS +GENHTML +LCOV +GCOV +CODE_COVERAGE_ENABLED +CODE_COVERAGE_ENABLED_FALSE +CODE_COVERAGE_ENABLED_TRUE +ntlm_auth +CURL +IF_HAVE_MOD_UNIXD +IF_HAVE_PHP +PHP +HAVE_APACHE_FALSE +HAVE_APACHE_TRUE +APACHE_PHP_MODULE_DIR +APACHE_SSL_MODULE_DIR +APACHE_MODULE_DIR +APACHE_HTTPD +ENABLE_VAPIGEN_FALSE +ENABLE_VAPIGEN_TRUE +VAPIGEN_MAKEFILE +VAPIDIR +VAPIGEN_VAPIDIR +VAPIGEN +VALAC +HAVE_INTROSPECTION_FALSE +HAVE_INTROSPECTION_TRUE +INTROSPECTION_MAKEFILE +INTROSPECTION_LIBS +INTROSPECTION_CFLAGS +INTROSPECTION_TYPELIBDIR +INTROSPECTION_GIRDIR +INTROSPECTION_GENERATE +INTROSPECTION_COMPILER +INTROSPECTION_SCANNER +GTK_DOC_USE_REBASE_FALSE +GTK_DOC_USE_REBASE_TRUE +GTK_DOC_USE_LIBTOOL_FALSE +GTK_DOC_USE_LIBTOOL_TRUE +GTK_DOC_BUILD_PDF_FALSE +GTK_DOC_BUILD_PDF_TRUE +GTK_DOC_BUILD_HTML_FALSE +GTK_DOC_BUILD_HTML_TRUE +ENABLE_GTK_DOC_FALSE +ENABLE_GTK_DOC_TRUE +HAVE_GTK_DOC_FALSE +HAVE_GTK_DOC_TRUE +GTKDOC_DEPS_LIBS +GTKDOC_DEPS_CFLAGS +HTML_DIR +GTKDOC_MKPDF +GTKDOC_REBASE +GTKDOC_CHECK_PATH +GTKDOC_CHECK +HAVE_GNOME +BUILD_LIBSOUP_GNOME_FALSE +BUILD_LIBSOUP_GNOME_TRUE +GETTEXT_PACKAGE +ALL_LINGUAS +INTLTOOL_PERL +GMSGFMT +MSGFMT +MSGMERGE +XGETTEXT +INTLTOOL_POLICY_RULE +INTLTOOL_SERVICE_RULE +INTLTOOL_THEME_RULE +INTLTOOL_SCHEMAS_RULE +INTLTOOL_CAVES_RULE +INTLTOOL_XML_NOMERGE_RULE +INTLTOOL_XML_RULE +INTLTOOL_KBD_RULE +INTLTOOL_XAM_RULE +INTLTOOL_UI_RULE +INTLTOOL_SOUNDLIST_RULE +INTLTOOL_SHEET_RULE +INTLTOOL_SERVER_RULE +INTLTOOL_PONG_RULE +INTLTOOL_OAF_RULE +INTLTOOL_PROP_RULE +INTLTOOL_KEYS_RULE +INTLTOOL_DIRECTORY_RULE +INTLTOOL_DESKTOP_RULE +intltool__v_merge_options_0 +intltool__v_merge_options_ +INTLTOOL_V_MERGE_OPTIONS +INTLTOOL__v_MERGE_0 +INTLTOOL__v_MERGE_ +INTLTOOL_V_MERGE +INTLTOOL_EXTRACT +INTLTOOL_MERGE +INTLTOOL_UPDATE +USE_NLS +OS_LINUX_FALSE +OS_LINUX_TRUE +OS_WIN32_FALSE +OS_WIN32_TRUE +SQLITE_LIBS +SQLITE_CFLAGS +XML_LIBS +XML_CFLAGS +installed_testdir +installed_test_metadir +ENABLE_ALWAYS_BUILD_TESTS_FALSE +ENABLE_ALWAYS_BUILD_TESTS_TRUE +ENABLE_INSTALLED_TESTS_FALSE +ENABLE_INSTALLED_TESTS_TRUE +GLIB_MAKEFILE +GLIB_COMPILE_RESOURCES +GLIB_MKENUMS +GOBJECT_QUERY +GLIB_GENMARSHAL +GLIB_LIBS +GLIB_CFLAGS +PKG_CONFIG_LIBDIR +PKG_CONFIG_PATH +PKG_CONFIG +CPP +LT_SYS_LIBRARY_PATH +OTOOL64 +OTOOL +LIPO +NMEDIT +DSYMUTIL +MANIFEST_TOOL +RANLIB +ac_ct_AR +AR +LN_S +NM +ac_ct_DUMPBIN +DUMPBIN +LD +FGREP +EGREP +GREP +SED +host_os +host_vendor +host_cpu +host +build_os +build_vendor +build_cpu +build +LIBTOOL +OBJDUMP +DLLTOOL +AS +am__fastdepCC_FALSE +am__fastdepCC_TRUE +CCDEPMODE +am__nodep +AMDEPBACKSLASH +AMDEP_FALSE +AMDEP_TRUE +am__quote +am__include +DEPDIR +OBJEXT +EXEEXT +ac_ct_CC +CPPFLAGS +LDFLAGS +CFLAGS +CC +SOUP_DEBUG_FLAGS +SOUP_AGE +SOUP_REVISION +SOUP_CURRENT +SOUP_API_VERSION +SOUP_MICRO_VERSION +SOUP_MINOR_VERSION +SOUP_MAJOR_VERSION +AM_BACKSLASH +AM_DEFAULT_VERBOSITY +AM_DEFAULT_V +AM_V +am__untar +am__tar +AMTAR +am__leading_dot +SET_MAKE +AWK +mkdir_p +MKDIR_P +INSTALL_STRIP_PROGRAM +STRIP +install_sh +MAKEINFO +AUTOHEADER +AUTOMAKE +AUTOCONF +ACLOCAL +VERSION +PACKAGE +CYGPATH_W +am__isrc +INSTALL_DATA +INSTALL_SCRIPT +INSTALL_PROGRAM +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 +runstatedir +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 +enable_silent_rules +enable_debug +enable_dependency_tracking +enable_shared +enable_static +with_pic +enable_fast_install +with_aix_soname +with_gnu_ld +with_sysroot +enable_libtool_lock +enable_glibtest +enable_installed_tests +enable_always_build_tests +enable_nls +with_gnome +with_html_dir +enable_gtk_doc +enable_gtk_doc_html +enable_gtk_doc_pdf +enable_introspection +enable_vala +enable_tls_check +with_apache_httpd +with_apache_module_dir +with_ntlm_auth +with_gcov +enable_code_coverage +with_gssapi +with_krb5_config +enable_more_warnings +' + ac_precious_vars='build_alias +host_alias +target_alias +CC +CFLAGS +LDFLAGS +LIBS +CPPFLAGS +LT_SYS_LIBRARY_PATH +CPP +PKG_CONFIG +PKG_CONFIG_PATH +PKG_CONFIG_LIBDIR +XML_CFLAGS +XML_LIBS +SQLITE_CFLAGS +SQLITE_LIBS +GTKDOC_DEPS_CFLAGS +GTKDOC_DEPS_LIBS' + + +# 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' +runstatedir='${localstatedir}/run' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' +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 ;; + + -runstatedir | --runstatedir | --runstatedi | --runstated \ + | --runstate | --runstat | --runsta | --runst | --runs \ + | --run | --ru | --r) + ac_prev=runstatedir ;; + -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ + | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ + | --run=* | --ru=* | --r=*) + runstatedir=$ac_optarg ;; + + -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 runstatedir +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 + 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 libsoup 2.62.3 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] + --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] + --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/libsoup] + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] +_ACEOF + + cat <<\_ACEOF + +Program names: + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM run sed PROGRAM on installed program names + +System types: + --build=BUILD configure for building on BUILD [guessed] + --host=HOST cross-compile to build programs to run on HOST [BUILD] +_ACEOF +fi + +if test -n "$ac_init_help"; then + case $ac_init_help in + short | recursive ) echo "Configuration of libsoup 2.62.3:";; + esac + cat <<\_ACEOF + +Optional Features: + --disable-option-checking ignore unrecognized --enable/--with options + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --enable-silent-rules less verbose build output (undo: "make V=1") + --disable-silent-rules verbose build output (undo: "make V=0") + --enable-debug=no/minimum/yes + turn on debugging (default=$debug_default) + --enable-dependency-tracking + do not reject slow dependency extractors + --disable-dependency-tracking + speeds up one-time build + --enable-shared[=PKGS] build shared libraries [default=yes] + --enable-static[=PKGS] build static libraries [default=yes] + --enable-fast-install[=PKGS] + optimize for fast installation [default=yes] + --disable-libtool-lock avoid locking (might break parallel builds) + --disable-glibtest do not try to compile and run a test GLIB program + --enable-installed-tests + Enable installation of some test cases + --enable-always-build-tests + Enable always building tests during 'make all' + --disable-nls do not use Native Language Support + --enable-gtk-doc use gtk-doc to build documentation [[default=no]] + --enable-gtk-doc-html build documentation in html format [[default=yes]] + --enable-gtk-doc-pdf build documentation in pdf format [[default=no]] + --enable-introspection=[no/auto/yes] + Enable introspection for this build + --enable-vala=[no/auto/yes] + build Vala bindings [default=auto] + --disable-tls-check Don't error out if glib-networking is unavailable + --enable-code-coverage Whether to enable code coverage support + --disable-more-warnings Inhibit compiler warnings + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-pic[=PKGS] try to use only PIC/non-PIC objects [default=use + both] + --with-aix-soname=aix|svr4|both + shared library versioning (aka "SONAME") variant to + provide on AIX, [default=aix]. + --with-gnu-ld assume the C compiler uses GNU ld [default=no] + --with-sysroot[=DIR] Search for dependent libraries within DIR (or the + compiler's sysroot if not specified). + --without-gnome Do not build libsoup-gnome + --with-html-dir=PATH path to installed docs + --with-apache-httpd Path to apache httpd (for tests) + --with-apache-module-dir + Apache modules dirs (for tests) + --with-ntlm-auth=PATH Where to look for ntlm_auth, path points to + ntlm_auth installation (default: /usr/bin/ntlm_auth) + --with-gcov=GCOV use given GCOV for coverage (GCOV=gcov). + --with-gssapi Build with GSSAPI support [default=auto] + --with-krb5-config=PATH Where to look for krb5-config, path points to + krb5-config installation (default: + /usr/kerberos/bin/) + +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 + LT_SYS_LIBRARY_PATH + User-defined run-time library search path. + CPP C preprocessor + PKG_CONFIG path to pkg-config utility + PKG_CONFIG_PATH + directories to add to pkg-config's search path + PKG_CONFIG_LIBDIR + path overriding pkg-config's built-in search path + XML_CFLAGS C compiler flags for XML, overriding pkg-config + XML_LIBS linker flags for XML, overriding pkg-config + SQLITE_CFLAGS + C compiler flags for SQLITE, overriding pkg-config + SQLITE_LIBS linker flags for SQLITE, overriding pkg-config + GTKDOC_DEPS_CFLAGS + C compiler flags for GTKDOC_DEPS, overriding pkg-config + GTKDOC_DEPS_LIBS + linker flags for GTKDOC_DEPS, overriding pkg-config + +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 . +_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 +libsoup configure 2.62.3 +generated by GNU Autoconf 2.69 + +Copyright (C) 2012 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; ${as_lineno_stack:+:} 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 || + 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; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_link + +# 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 \${$3+:} false; 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; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_compile + +# 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; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_cpp + +# 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; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_run + +# 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 \${$3+:} false; 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; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_func +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 libsoup $as_me 2.62.3, which was +generated by GNU Autoconf 2.69. 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 + +# 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 + + + + +ac_aux_dir= +for ac_dir in build-aux "$srcdir"/build-aux; 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 build-aux \"$srcdir\"/build-aux" "$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. + + + +am__api_version='1.15' + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# OS/2's system install, which has a completely different semantic +# ./install, which can be erroneously created by make from ./install.sh. +# Reject install programs that cannot install multiple files. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 +$as_echo_n "checking for a BSD-compatible install... " >&6; } +if test -z "$INSTALL"; then +if ${ac_cv_path_install+:} false; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in #(( + ./ | .// | /[cC]/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + rm -rf conftest.one conftest.two conftest.dir + echo one > conftest.one + echo two > conftest.two + mkdir conftest.dir + if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && + test -s conftest.one && test -s conftest.two && + test -s conftest.dir/conftest.one && + test -s conftest.dir/conftest.two + then + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + fi + done + done + ;; +esac + + done +IFS=$as_save_IFS + +rm -rf conftest.one conftest.two conftest.dir + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. Don't cache a + # value for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + INSTALL=$ac_install_sh + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 +$as_echo "$INSTALL" >&6; } + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 +$as_echo_n "checking whether build environment is sane... " >&6; } +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[\\\"\#\$\&\'\`$am_lf]*) + as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;; +esac +case $srcdir in + *[\\\"\#\$\&\'\`$am_lf\ \ ]*) + as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;; +esac + +# Do 'set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + am_has_slept=no + for am_try in 1 2; do + echo "timestamp, slept: $am_has_slept" > conftest.file + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` + if test "$*" = "X"; then + # -L didn't work. + set X `ls -t "$srcdir/configure" conftest.file` + fi + if test "$*" != "X $srcdir/configure conftest.file" \ + && test "$*" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + as_fn_error $? "ls -t appears to fail. Make sure there is not a broken + alias in your environment" "$LINENO" 5 + fi + if test "$2" = conftest.file || test $am_try -eq 2; then + break + fi + # Just in case. + sleep 1 + am_has_slept=yes + done + test "$2" = conftest.file + ) +then + # Ok. + : +else + as_fn_error $? "newly created file is older than distributed files! +Check your system clock" "$LINENO" 5 +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +# If we didn't sleep, we still need to ensure time stamps of config.status and +# generated files are strictly newer. +am_sleep_pid= +if grep 'slept: no' conftest.file >/dev/null 2>&1; then + ( sleep 1 ) & + am_sleep_pid=$! +fi + +rm -f conftest.file + +test "$program_prefix" != NONE && + program_transform_name="s&^&$program_prefix&;$program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s&\$&$program_suffix&;$program_transform_name" +# Double any \ or $. +# By default was `s,x,x', remove it if useless. +ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' +program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` + +# Expand $ac_aux_dir to an absolute path. +am_aux_dir=`cd "$ac_aux_dir" && pwd` + +if test x"${MISSING+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; + *) + MISSING="\${SHELL} $am_aux_dir/missing" ;; + esac +fi +# Use eval to expand $SHELL +if eval "$MISSING --is-lightweight"; then + am_missing_run="$MISSING " +else + am_missing_run= + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5 +$as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;} +fi + +if test x"${install_sh+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi + +# Installed binaries are usually stripped using 'strip' when the user +# run "make install-strip". However 'strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the 'STRIP' environment variable to overrule this program. +if test "$cross_compiling" != no; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + $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 +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_STRIP="strip" + $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_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +$as_echo "$ac_ct_STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + 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 + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 +$as_echo_n "checking for a thread-safe mkdir -p... " >&6; } +if test -z "$MKDIR_P"; then + if ${ac_cv_path_mkdir+:} false; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in mkdir gmkdir; do + for ac_exec_ext in '' $ac_executable_extensions; do + as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue + case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( + 'mkdir (GNU coreutils) '* | \ + 'mkdir (coreutils) '* | \ + 'mkdir (fileutils) '4.1*) + ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext + break 3;; + esac + done + done + done +IFS=$as_save_IFS + +fi + + test -d ./--version && rmdir ./--version + if test "${ac_cv_path_mkdir+set}" = set; then + MKDIR_P="$ac_cv_path_mkdir -p" + else + # As a last resort, use the slow shell script. Don't cache a + # value for MKDIR_P within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + MKDIR_P="$ac_install_sh -d" + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 +$as_echo "$MKDIR_P" >&6; } + +for ac_prog in gawk mawk nawk awk +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 ${ac_cv_prog_AWK+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AWK"; then + ac_cv_prog_AWK="$AWK" # 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AWK="$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 +AWK=$ac_cv_prog_AWK +if test -n "$AWK"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 +$as_echo "$AWK" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AWK" && break +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } +set x ${MAKE-make} +ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` +if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat >conftest.make <<\_ACEOF +SHELL = /bin/sh +all: + @echo '@@@%%%=$(MAKE)=@@@%%%' +_ACEOF +# GNU make sometimes prints "make[1]: Entering ...", which would confuse us. +case `${MAKE-make} -f conftest.make 2>/dev/null` in + *@@@%%%=?*=@@@%%%*) + eval ac_cv_prog_make_${ac_make}_set=yes;; + *) + eval ac_cv_prog_make_${ac_make}_set=no;; +esac +rm -f conftest.make +fi +if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + SET_MAKE= +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + SET_MAKE="MAKE=${MAKE-make}" +fi + +rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null + +# Check whether --enable-silent-rules was given. +if test "${enable_silent_rules+set}" = set; then : + enableval=$enable_silent_rules; +fi + +case $enable_silent_rules in # ((( + yes) AM_DEFAULT_VERBOSITY=0;; + no) AM_DEFAULT_VERBOSITY=1;; + *) AM_DEFAULT_VERBOSITY=1;; +esac +am_make=${MAKE-make} +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 +$as_echo_n "checking whether $am_make supports nested variables... " >&6; } +if ${am_cv_make_support_nested_variables+:} false; then : + $as_echo_n "(cached) " >&6 +else + if $as_echo 'TRUE=$(BAR$(V)) +BAR0=false +BAR1=true +V=1 +am__doit: + @$(TRUE) +.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then + am_cv_make_support_nested_variables=yes +else + am_cv_make_support_nested_variables=no +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 +$as_echo "$am_cv_make_support_nested_variables" >&6; } +if test $am_cv_make_support_nested_variables = yes; then + AM_V='$(V)' + AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' +else + AM_V=$AM_DEFAULT_VERBOSITY + AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY +fi +AM_BACKSLASH='\' + +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + am__isrc=' -I$(srcdir)' + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 + fi +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi + + +# Define the identity of the package. + PACKAGE='libsoup' + VERSION='2.62.3' + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE "$PACKAGE" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define VERSION "$VERSION" +_ACEOF + +# Some tools Automake needs. + +ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} + + +AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} + + +AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} + + +AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} + + +MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} + +# For better backward compatibility. To be removed once Automake 1.9.x +# dies out for good. For more background, see: +# +# +mkdir_p='$(MKDIR_P)' + +# We need awk for the "check" target (and possibly the TAP driver). The +# system "awk" is bad on some platforms. +# Always define AMTAR for backward compatibility. Yes, it's still used +# in the wild :-( We should find a proper way to deprecate it ... +AMTAR='$${TAR-tar}' + + +# We'll loop over all known methods to create a tar archive until one works. +_am_tools='gnutar pax cpio none' + +am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -' + + + + + + +# POSIX will say in a future version that running "rm -f" with no argument +# is OK; and we want to be able to make that assumption in our Makefile +# recipes. So use an aggressive probe to check that the usage we want is +# actually supported "in the wild" to an acceptable degree. +# See automake bug#10828. +# To make any issue more visible, cause the running configure to be aborted +# by default if the 'rm' program in use doesn't match our expectations; the +# user can still override this though. +if rm -f && rm -fr && rm -rf; then : OK; else + cat >&2 <<'END' +Oops! + +Your 'rm' program seems unable to run without file operands specified +on the command line, even when the '-f' option is present. This is contrary +to the behaviour of most rm programs out there, and not conforming with +the upcoming POSIX standard: + +Please tell bug-automake@gnu.org about your system, including the value +of your $PATH and any error possibly output before this message. This +can help us improve future automake versions. + +END + if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then + echo 'Configuration will proceed anyway, since you have set the' >&2 + echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 + echo >&2 + else + cat >&2 <<'END' +Aborting the configuration process, to ensure you take notice of the issue. + +You can download and install GNU coreutils to get an 'rm' implementation +that behaves properly: . + +If you want to complete the configuration process using your problematic +'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM +to "yes", and re-run configure. + +END + as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5 + fi +fi + +# Check whether --enable-silent-rules was given. +if test "${enable_silent_rules+set}" = set; then : + enableval=$enable_silent_rules; +fi + +case $enable_silent_rules in # ((( + yes) AM_DEFAULT_VERBOSITY=0;; + no) AM_DEFAULT_VERBOSITY=1;; + *) AM_DEFAULT_VERBOSITY=0;; +esac +am_make=${MAKE-make} +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 +$as_echo_n "checking whether $am_make supports nested variables... " >&6; } +if ${am_cv_make_support_nested_variables+:} false; then : + $as_echo_n "(cached) " >&6 +else + if $as_echo 'TRUE=$(BAR$(V)) +BAR0=false +BAR1=true +V=1 +am__doit: + @$(TRUE) +.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then + am_cv_make_support_nested_variables=yes +else + am_cv_make_support_nested_variables=no +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 +$as_echo "$am_cv_make_support_nested_variables" >&6; } +if test $am_cv_make_support_nested_variables = yes; then + AM_V='$(V)' + AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' +else + AM_V=$AM_DEFAULT_VERBOSITY + AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY +fi +AM_BACKSLASH='\' + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } +set x ${MAKE-make} +ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` +if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat >conftest.make <<\_ACEOF +SHELL = /bin/sh +all: + @echo '@@@%%%=$(MAKE)=@@@%%%' +_ACEOF +# GNU make sometimes prints "make[1]: Entering ...", which would confuse us. +case `${MAKE-make} -f conftest.make 2>/dev/null` in + *@@@%%%=?*=@@@%%%*) + eval ac_cv_prog_make_${ac_make}_set=yes;; + *) + eval ac_cv_prog_make_${ac_make}_set=no;; +esac +rm -f conftest.make +fi +if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + SET_MAKE= +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + SET_MAKE="MAKE=${MAKE-make}" +fi + + +SOUP_MAJOR_VERSION=2 +SOUP_MINOR_VERSION=62 +SOUP_MICRO_VERSION=3 + + + + +SOUP_API_VERSION=2.4 + + +# Increment on interface addition. Reset on removal. +SOUP_AGE=8 + +# Increment on interface add, remove, or change. +SOUP_CURRENT=9 + +# Increment on source change. Reset when CURRENT changes. +SOUP_REVISION=0 + + + + + + +debug_default=minimum + +# Declare --enable-* args and collect ac_help strings +# Check whether --enable-debug was given. +if test "${enable_debug+set}" = set; then : + enableval=$enable_debug; +else + enable_debug=$debug_default +fi + + +# Set the debug flags +if test "x$enable_debug" = "xyes"; then + test "$cflags_set" = set || CFLAGS="$CFLAGS -g" + SOUP_DEBUG_FLAGS="-DG_ENABLE_DEBUG" +else + if test "x$enable_debug" = "xno"; then + SOUP_DEBUG_FLAGS="-DG_DISABLE_ASSERT -DG_DISABLE_CHECKS" + 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 +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 ${ac_cv_prog_CC+:} false; 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 as_fn_executable_p "$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 ${ac_cv_prog_ac_ct_CC+:} false; 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 as_fn_executable_p "$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 ${ac_cv_prog_CC+:} false; 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 as_fn_executable_p "$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 ${ac_cv_prog_CC+:} false; 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 as_fn_executable_p "$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 ${ac_cv_prog_CC+:} false; 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 as_fn_executable_p "$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 ${ac_cv_prog_ac_ct_CC+:} false; 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 as_fn_executable_p "$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 ${ac_cv_objext+:} false; 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 ${ac_cv_c_compiler_gnu+:} false; 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 ${ac_cv_prog_cc_g+:} false; 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 ${ac_cv_prog_cc_c89+:} false; 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 +struct stat; +/* 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 + +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 whether $CC understands -c and -o together" >&5 +$as_echo_n "checking whether $CC understands -c and -o together... " >&6; } +if ${am_cv_prog_cc_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF + # Make sure it works both with $CC and with simple cc. + # Following AC_PROG_CC_C_O, we do the test twice because some + # compilers refuse to overwrite an existing .o file with -o, + # though they will create one. + am_cv_prog_cc_c_o=yes + for am_i in 1 2; do + if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5 + ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } \ + && test -f conftest2.$ac_objext; then + : OK + else + am_cv_prog_cc_c_o=no + break + fi + done + rm -f core conftest* + unset am_i +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5 +$as_echo "$am_cv_prog_cc_c_o" >&6; } +if test "$am_cv_prog_cc_c_o" != yes; then + # Losing compiler, so override with the script. + # FIXME: It is wrong to rewrite CC. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__CC in this case, + # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" + CC="$am_aux_dir/compile $CC" +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 + +DEPDIR="${am__leading_dot}deps" + +ac_config_commands="$ac_config_commands depfiles" + + +am_make=${MAKE-make} +cat > confinc << 'END' +am__doit: + @echo this is the am__doit target +.PHONY: am__doit +END +# If we don't find an include directive, just comment out the code. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5 +$as_echo_n "checking for style of include used by $am_make... " >&6; } +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# Ignore all kinds of additional output from 'make'. +case `$am_make -s -f confmf 2> /dev/null` in #( +*the\ am__doit\ target*) + am__include=include + am__quote= + _am_result=GNU + ;; +esac +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + case `$am_make -s -f confmf 2> /dev/null` in #( + *the\ am__doit\ target*) + am__include=.include + am__quote="\"" + _am_result=BSD + ;; + esac +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5 +$as_echo "$_am_result" >&6; } +rm -f confinc confmf + +# Check whether --enable-dependency-tracking was given. +if test "${enable_dependency_tracking+set}" = set; then : + enableval=$enable_dependency_tracking; +fi + +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' + am__nodep='_no' +fi + if test "x$enable_dependency_tracking" != xno; then + AMDEP_TRUE= + AMDEP_FALSE='#' +else + AMDEP_TRUE='#' + AMDEP_FALSE= +fi + + + +depcc="$CC" am_compiler_list= + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 +$as_echo_n "checking dependency style of $depcc... " >&6; } +if ${am_cv_CC_dependencies_compiler_type+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named 'D' -- because '-MD' means "put the output + # in D". + rm -rf conftest.dir + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_CC_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` + fi + am__universal=false + case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with + # Solaris 10 /bin/sh. + echo '/* dummy */' > sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with '-c' and '-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle '-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs. + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # After this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested. + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvc7 | msvc7msys | msvisualcpp | msvcmsys) + # This compiler won't grok '-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_CC_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_CC_dependencies_compiler_type=none +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 +$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } +CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type + + if + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then + am__fastdepCC_TRUE= + am__fastdepCC_FALSE='#' +else + am__fastdepCC_TRUE='#' + am__fastdepCC_FALSE= +fi + + + + +# Initialize libtool +case `pwd` in + *\ * | *\ *) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5 +$as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;; +esac + + + +macro_version='2.4.6' +macro_revision='2.4.6' + + + + + + + + + + + + + +ltmain=$ac_aux_dir/ltmain.sh + +# 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 ${ac_cv_build+:} false; 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 ${ac_cv_host+:} false; 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 + + +# Backslashify metacharacters that are still active within +# double-quoted strings. +sed_quote_subst='s/\(["`$\\]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\(["`\\]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to delay expansion of an escaped single quote. +delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' + +ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5 +$as_echo_n "checking how to print strings... " >&6; } +# Test print first, because it will be a builtin if present. +if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ + test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='print -r --' +elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='printf %s\n' +else + # Use this function as a fallback that always works. + func_fallback_echo () + { + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' + } + ECHO='func_fallback_echo' +fi + +# func_echo_all arg... +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "" +} + +case $ECHO in + printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5 +$as_echo "printf" >&6; } ;; + print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5 +$as_echo "print -r" >&6; } ;; + *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5 +$as_echo "cat" >&6; } ;; +esac + + + + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 +$as_echo_n "checking for a sed that does not truncate output... " >&6; } +if ${ac_cv_path_SED+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ + for ac_i in 1 2 3 4 5 6 7; do + ac_script="$ac_script$as_nl$ac_script" + done + echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed + { ac_script=; unset ac_script;} + if test -z "$SED"; then + ac_path_SED_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 +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_SED" || continue +# Check for GNU ac_path_SED and select it if it is found. + # Check for GNU $ac_path_SED +case `"$ac_path_SED" --version 2>&1` in +*GNU*) + ac_cv_path_SED="$ac_path_SED" ac_path_SED_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 '' >> "conftest.nl" + "$ac_path_SED" -f conftest.sed < "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_SED_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_SED="$ac_path_SED" + ac_path_SED_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_SED_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_SED"; then + as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 + fi +else + ac_cv_path_SED=$SED +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 +$as_echo "$ac_cv_path_SED" >&6; } + SED="$ac_cv_path_SED" + rm -f conftest.sed + +test -z "$SED" && SED=sed +Xsed="$SED -e 1s/^X//" + + + + + + + + + + + +{ $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 ${ac_cv_path_GREP+:} false; 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" + as_fn_executable_p "$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 ${ac_cv_path_EGREP+:} false; 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" + as_fn_executable_p "$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 fgrep" >&5 +$as_echo_n "checking for fgrep... " >&6; } +if ${ac_cv_path_FGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1 + then ac_cv_path_FGREP="$GREP -F" + else + if test -z "$FGREP"; then + ac_path_FGREP_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 fgrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_FGREP" || continue +# Check for GNU ac_path_FGREP and select it if it is found. + # Check for GNU $ac_path_FGREP +case `"$ac_path_FGREP" --version 2>&1` in +*GNU*) + ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_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 'FGREP' >> "conftest.nl" + "$ac_path_FGREP" FGREP < "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_FGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_FGREP="$ac_path_FGREP" + ac_path_FGREP_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_FGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_FGREP"; then + as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_FGREP=$FGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5 +$as_echo "$ac_cv_path_FGREP" >&6; } + FGREP="$ac_cv_path_FGREP" + + +test -z "$GREP" && GREP=grep + + + + + + + + + + + + + + + + + + + +# Check whether --with-gnu-ld was given. +if test "${with_gnu_ld+set}" = set; then : + withval=$with_gnu_ld; test no = "$withval" || with_gnu_ld=yes +else + with_gnu_ld=no +fi + +ac_prog=ld +if test yes = "$GCC"; then + # Check if gcc -print-prog-name=ld gives a path. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 +$as_echo_n "checking for ld used by $CC... " >&6; } + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return, which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [\\/]* | ?:[\\/]*) + re_direlt='/[^/][^/]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` + while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do + ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD=$ac_prog + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test yes = "$with_gnu_ld"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 +$as_echo_n "checking for GNU ld... " >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 +$as_echo_n "checking for non-GNU ld... " >&6; } +fi +if ${lt_cv_path_LD+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$LD"; then + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD=$ac_dir/$ac_prog + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &5 +$as_echo "$LD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 +$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } +if ${lt_cv_prog_gnu_ld+:} false; then : + $as_echo_n "(cached) " >&6 +else + # I'd rather use --version here, but apparently some GNU lds only accept -v. +case `$LD -v 2>&1 &5 +$as_echo "$lt_cv_prog_gnu_ld" >&6; } +with_gnu_ld=$lt_cv_prog_gnu_ld + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5 +$as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; } +if ${lt_cv_path_NM+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM=$NM +else + lt_nm_to_check=${ac_tool_prefix}nm + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + tmp_nm=$ac_dir/$lt_tmp_nm + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the 'sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty + case $build_os in + mingw*) lt_bad_file=conftest.nm/nofile ;; + *) lt_bad_file=/dev/null ;; + esac + case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in + *$lt_bad_file* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break 2 + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break 2 + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + ;; + esac + fi + done + IFS=$lt_save_ifs + done + : ${lt_cv_path_NM=no} +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5 +$as_echo "$lt_cv_path_NM" >&6; } +if test no != "$lt_cv_path_NM"; then + NM=$lt_cv_path_NM +else + # Didn't find any BSD compatible name lister, look for dumpbin. + if test -n "$DUMPBIN"; then : + # Let the user override the test. + else + if test -n "$ac_tool_prefix"; then + for ac_prog in dumpbin "link -dump" + 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 ${ac_cv_prog_DUMPBIN+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DUMPBIN"; then + ac_cv_prog_DUMPBIN="$DUMPBIN" # 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_DUMPBIN="$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 +DUMPBIN=$ac_cv_prog_DUMPBIN +if test -n "$DUMPBIN"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5 +$as_echo "$DUMPBIN" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$DUMPBIN" && break + done +fi +if test -z "$DUMPBIN"; then + ac_ct_DUMPBIN=$DUMPBIN + for ac_prog in dumpbin "link -dump" +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 ${ac_cv_prog_ac_ct_DUMPBIN+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DUMPBIN"; then + ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_DUMPBIN="$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_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN +if test -n "$ac_ct_DUMPBIN"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5 +$as_echo "$ac_ct_DUMPBIN" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_DUMPBIN" && break +done + + if test "x$ac_ct_DUMPBIN" = x; then + DUMPBIN=":" + 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 + DUMPBIN=$ac_ct_DUMPBIN + fi +fi + + case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in + *COFF*) + DUMPBIN="$DUMPBIN -symbols -headers" + ;; + *) + DUMPBIN=: + ;; + esac + fi + + if test : != "$DUMPBIN"; then + NM=$DUMPBIN + fi +fi +test -z "$NM" && NM=nm + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5 +$as_echo_n "checking the name lister ($NM) interface... " >&6; } +if ${lt_cv_nm_interface+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_nm_interface="BSD nm" + echo "int some_variable = 0;" > conftest.$ac_ext + (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5) + (eval "$ac_compile" 2>conftest.err) + cat conftest.err >&5 + (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5) + (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) + cat conftest.err >&5 + (eval echo "\"\$as_me:$LINENO: output\"" >&5) + cat conftest.out >&5 + if $GREP 'External.*some_variable' conftest.out > /dev/null; then + lt_cv_nm_interface="MS dumpbin" + fi + rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5 +$as_echo "$lt_cv_nm_interface" >&6; } + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 +$as_echo_n "checking whether ln -s works... " >&6; } +LN_S=$as_ln_s +if test "$LN_S" = "ln -s"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 +$as_echo "no, using $LN_S" >&6; } +fi + +# find the maximum length of command line arguments +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5 +$as_echo_n "checking the maximum length of command line arguments... " >&6; } +if ${lt_cv_sys_max_cmd_len+:} false; then : + $as_echo_n "(cached) " >&6 +else + i=0 + teststring=ABCD + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw* | cegcc*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + mint*) + # On MiNT this can take a long time and run out of memory. + lt_cv_sys_max_cmd_len=8192; + ;; + + amigaos*) + # On AmigaOS with pdksh, this test takes hours, literally. + # So we just punt and use a minimum line length of 8192. + lt_cv_sys_max_cmd_len=8192; + ;; + + bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*) + # This has been around since 386BSD, at least. Likely further. + if test -x /sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + ;; + + interix*) + # We know the value 262144 and hardcode it with a safety zone (like BSD) + lt_cv_sys_max_cmd_len=196608 + ;; + + os2*) + # The test takes a long time on OS/2. + lt_cv_sys_max_cmd_len=8192 + ;; + + osf*) + # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure + # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + sco3.2v5*) + lt_cv_sys_max_cmd_len=102400 + ;; + sysv5* | sco5v6* | sysv4.2uw2*) + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) + lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` + if test -n "$lt_cv_sys_max_cmd_len" && \ + test undefined != "$lt_cv_sys_max_cmd_len"; then + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + else + # Make teststring a little bigger before we do anything with it. + # a 1K string should be a reasonable start. + for i in 1 2 3 4 5 6 7 8; do + teststring=$teststring$teststring + done + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + # If test is not a shell built-in, we'll probably end up computing a + # maximum length that is only half of the actual maximum length, but + # we can't tell. + while { test X`env echo "$teststring$teststring" 2>/dev/null` \ + = "X$teststring$teststring"; } >/dev/null 2>&1 && + test 17 != "$i" # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + # Only check the string length outside the loop. + lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` + teststring= + # Add a significant safety factor because C++ compilers can tack on + # massive amounts of additional arguments before passing them to the + # linker. It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + fi + ;; + esac + +fi + +if test -n "$lt_cv_sys_max_cmd_len"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5 +$as_echo "$lt_cv_sys_max_cmd_len" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 +$as_echo "none" >&6; } +fi +max_cmd_len=$lt_cv_sys_max_cmd_len + + + + + + +: ${CP="cp -f"} +: ${MV="mv -f"} +: ${RM="rm -f"} + +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + lt_unset=unset +else + lt_unset=false +fi + + + + + +# test EBCDIC or ASCII +case `echo X|tr X '\101'` in + A) # ASCII based system + # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr + lt_SP2NL='tr \040 \012' + lt_NL2SP='tr \015\012 \040\040' + ;; + *) # EBCDIC based system + lt_SP2NL='tr \100 \n' + lt_NL2SP='tr \r\n \100\100' + ;; +esac + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to $host format" >&5 +$as_echo_n "checking how to convert $build file names to $host format... " >&6; } +if ${lt_cv_to_host_file_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 + ;; + esac + ;; + *-*-cygwin* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin + ;; + esac + ;; + * ) # unhandled hosts (and "normal" native builds) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; +esac + +fi + +to_host_file_cmd=$lt_cv_to_host_file_cmd +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_host_file_cmd" >&5 +$as_echo "$lt_cv_to_host_file_cmd" >&6; } + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to toolchain format" >&5 +$as_echo_n "checking how to convert $build file names to toolchain format... " >&6; } +if ${lt_cv_to_tool_file_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + #assume ordinary cross tools, or native build. +lt_cv_to_tool_file_cmd=func_convert_file_noop +case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 + ;; + esac + ;; +esac + +fi + +to_tool_file_cmd=$lt_cv_to_tool_file_cmd +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_tool_file_cmd" >&5 +$as_echo "$lt_cv_to_tool_file_cmd" >&6; } + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5 +$as_echo_n "checking for $LD option to reload object files... " >&6; } +if ${lt_cv_ld_reload_flag+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_reload_flag='-r' +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5 +$as_echo "$lt_cv_ld_reload_flag" >&6; } +reload_flag=$lt_cv_ld_reload_flag +case $reload_flag in +"" | " "*) ;; +*) reload_flag=" $reload_flag" ;; +esac +reload_cmds='$LD$reload_flag -o $output$reload_objs' +case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + if test yes != "$GCC"; then + reload_cmds=false + fi + ;; + darwin*) + if test yes = "$GCC"; then + reload_cmds='$LTCC $LTCFLAGS -nostdlib $wl-r -o $output$reload_objs' + else + reload_cmds='$LD$reload_flag -o $output$reload_objs' + fi + ;; +esac + + + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. +set dummy ${ac_tool_prefix}objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OBJDUMP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OBJDUMP"; then + ac_cv_prog_OBJDUMP="$OBJDUMP" # 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" + $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 +OBJDUMP=$ac_cv_prog_OBJDUMP +if test -n "$OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 +$as_echo "$OBJDUMP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OBJDUMP"; then + ac_ct_OBJDUMP=$OBJDUMP + # Extract the first word of "objdump", so it can be a program name with args. +set dummy objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OBJDUMP"; then + ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_OBJDUMP="objdump" + $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_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP +if test -n "$ac_ct_OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 +$as_echo "$ac_ct_OBJDUMP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OBJDUMP" = x; then + OBJDUMP="false" + 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 + OBJDUMP=$ac_ct_OBJDUMP + fi +else + OBJDUMP="$ac_cv_prog_OBJDUMP" +fi + +test -z "$OBJDUMP" && OBJDUMP=objdump + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5 +$as_echo_n "checking how to recognize dependent libraries... " >&6; } +if ${lt_cv_deplibs_check_method+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_file_magic_cmd='$MAGIC_CMD' +lt_cv_file_magic_test_file= +lt_cv_deplibs_check_method='unknown' +# Need to set the preceding variable on all platforms that support +# interlibrary dependencies. +# 'none' -- dependencies not supported. +# 'unknown' -- same as none, but documents that we really don't know. +# 'pass_all' -- all dependencies passed with no checks. +# 'test_compile' -- check by making test program. +# 'file_magic [[regex]]' -- check by looking for files in library path +# that responds to the $file_magic_cmd with a given extended regex. +# If you have 'file' or equivalent on your system and you're not sure +# whether 'pass_all' will *always* work, you probably want this one. + +case $host_os in +aix[4-9]*) + lt_cv_deplibs_check_method=pass_all + ;; + +beos*) + lt_cv_deplibs_check_method=pass_all + ;; + +bsdi[45]*) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' + lt_cv_file_magic_cmd='/usr/bin/file -L' + lt_cv_file_magic_test_file=/shlib/libc.so + ;; + +cygwin*) + # func_win32_libid is a shell function defined in ltmain.sh + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + ;; + +mingw* | pw32*) + # Base MSYS/MinGW do not provide the 'file' command needed by + # func_win32_libid shell function, so use a weaker test based on 'objdump', + # unless we find 'file', for example because we are cross-compiling. + if ( file / ) >/dev/null 2>&1; then + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + else + # Keep this pattern in sync with the one in func_win32_libid. + lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' + lt_cv_file_magic_cmd='$OBJDUMP -f' + fi + ;; + +cegcc*) + # use the weaker test based on 'objdump'. See mingw*. + lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + ;; + +darwin* | rhapsody*) + lt_cv_deplibs_check_method=pass_all + ;; + +freebsd* | dragonfly*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +haiku*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case $host_cpu in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]' + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\.[0-9]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +interix[3-9]*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' + ;; + +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +*nto* | *qnx*) + lt_cv_deplibs_check_method=pass_all + ;; + +openbsd* | bitrig*) + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' + fi + ;; + +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + +rdos*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.3*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + pc) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +tpf*) + lt_cv_deplibs_check_method=pass_all + ;; +os2*) + lt_cv_deplibs_check_method=pass_all + ;; +esac + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5 +$as_echo "$lt_cv_deplibs_check_method" >&6; } + +file_magic_glob= +want_nocaseglob=no +if test "$build" = "$host"; then + case $host_os in + mingw* | pw32*) + if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then + want_nocaseglob=yes + else + file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[\1]\/[\1]\/g;/g"` + fi + ;; + esac +fi + +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown + + + + + + + + + + + + + + + + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. +set dummy ${ac_tool_prefix}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 ${ac_cv_prog_DLLTOOL+:} false; 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_DLLTOOL="${ac_tool_prefix}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 + +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 +if test -z "$ac_cv_prog_DLLTOOL"; then + ac_ct_DLLTOOL=$DLLTOOL + # 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 ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DLLTOOL"; then + ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_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 + +fi +fi +ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL +if test -n "$ac_ct_DLLTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5 +$as_echo "$ac_ct_DLLTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_DLLTOOL" = x; then + DLLTOOL="false" + 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 + DLLTOOL=$ac_ct_DLLTOOL + fi +else + DLLTOOL="$ac_cv_prog_DLLTOOL" +fi + +test -z "$DLLTOOL" && DLLTOOL=dlltool + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5 +$as_echo_n "checking how to associate runtime and link libraries... " >&6; } +if ${lt_cv_sharedlib_from_linklib_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_sharedlib_from_linklib_cmd='unknown' + +case $host_os in +cygwin* | mingw* | pw32* | cegcc*) + # two different shell functions defined in ltmain.sh; + # decide which one to use based on capabilities of $DLLTOOL + case `$DLLTOOL --help 2>&1` in + *--identify-strict*) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib + ;; + *) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback + ;; + esac + ;; +*) + # fallback: assume linklib IS sharedlib + lt_cv_sharedlib_from_linklib_cmd=$ECHO + ;; +esac + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sharedlib_from_linklib_cmd" >&5 +$as_echo "$lt_cv_sharedlib_from_linklib_cmd" >&6; } +sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd +test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO + + + + + + + + +if test -n "$ac_tool_prefix"; then + for ac_prog in ar + 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 ${ac_cv_prog_AR+:} false; 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AR="$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 +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 + + + test -n "$AR" && break + done +fi +if test -z "$AR"; then + ac_ct_AR=$AR + for ac_prog in ar +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 ${ac_cv_prog_ac_ct_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_AR"; then + ac_cv_prog_ac_ct_AR="$ac_ct_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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_AR="$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_AR=$ac_cv_prog_ac_ct_AR +if test -n "$ac_ct_AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 +$as_echo "$ac_ct_AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_AR" && break +done + + if test "x$ac_ct_AR" = x; then + AR="false" + 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 + AR=$ac_ct_AR + fi +fi + +: ${AR=ar} +: ${AR_FLAGS=cru} + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for archiver @FILE support" >&5 +$as_echo_n "checking for archiver @FILE support... " >&6; } +if ${lt_cv_ar_at_file+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ar_at_file=no + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + echo conftest.$ac_objext > conftest.lst + lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&5' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 + (eval $lt_ar_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if test 0 -eq "$ac_status"; then + # Ensure the archiver fails upon bogus file names. + rm -f conftest.$ac_objext libconftest.a + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 + (eval $lt_ar_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if test 0 -ne "$ac_status"; then + lt_cv_ar_at_file=@ + fi + fi + rm -f conftest.* libconftest.a + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5 +$as_echo "$lt_cv_ar_at_file" >&6; } + +if test no = "$lt_cv_ar_at_file"; then + archiver_list_spec= +else + archiver_list_spec=$lt_cv_ar_at_file +fi + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + $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 +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_STRIP="strip" + $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_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +$as_echo "$ac_ct_STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + 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 + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + +test -z "$STRIP" && STRIP=: + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. +set dummy ${ac_tool_prefix}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 ${ac_cv_prog_RANLIB+:} false; 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_RANLIB="${ac_tool_prefix}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 + +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 + + +fi +if test -z "$ac_cv_prog_RANLIB"; then + ac_ct_RANLIB=$RANLIB + # 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 ${ac_cv_prog_ac_ct_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_RANLIB"; then + ac_cv_prog_ac_ct_RANLIB="$ac_ct_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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_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 + +fi +fi +ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB +if test -n "$ac_ct_RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 +$as_echo "$ac_ct_RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_RANLIB" = x; then + RANLIB=":" + 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 + RANLIB=$ac_ct_RANLIB + fi +else + RANLIB="$ac_cv_prog_RANLIB" +fi + +test -z "$RANLIB" && RANLIB=: + + + + + + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + bitrig* | openbsd*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" + ;; + *) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" +fi + +case $host_os in + darwin*) + lock_old_archive_extraction=yes ;; + *) + lock_old_archive_extraction=no ;; +esac + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + +# Check for command to grab the raw symbol name followed by C symbol from nm. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5 +$as_echo_n "checking command to parse $NM output from $compiler object... " >&6; } +if ${lt_cv_sys_global_symbol_pipe+:} false; then : + $as_echo_n "(cached) " >&6 +else + +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[BCDEGRST]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([_A-Za-z][_A-Za-z0-9]*\)' + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[BCDT]' + ;; +cygwin* | mingw* | pw32* | cegcc*) + symcode='[ABCDGISTW]' + ;; +hpux*) + if test ia64 = "$host_cpu"; then + symcode='[ABCDEGRST]' + fi + ;; +irix* | nonstopux*) + symcode='[BCDEGRST]' + ;; +osf*) + symcode='[BCDEGQRST]' + ;; +solaris*) + symcode='[BDRT]' + ;; +sco3.2v5*) + symcode='[DT]' + ;; +sysv4.2uw2*) + symcode='[DT]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[ABDT]' + ;; +sysv4) + symcode='[DFNSTU]' + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[ABCDGIRSTW]' ;; +esac + +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Gets list of data symbols to import. + lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'" + # Adjust the below global symbol transforms to fixup imported variables. + lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" + lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" + lt_c_name_lib_hook="\ + -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\ + -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'" +else + # Disable hooks by default. + lt_cv_sys_global_symbol_to_import= + lt_cdecl_hook= + lt_c_name_hook= + lt_c_name_lib_hook= +fi + +# Transform an extracted symbol line into a proper C declaration. +# Some systems (esp. on ia64) link data and code symbols differently, +# so use this general approach. +lt_cv_sys_global_symbol_to_cdecl="sed -n"\ +$lt_cdecl_hook\ +" -e 's/^T .* \(.*\)$/extern int \1();/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n"\ +$lt_c_name_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" + +# Transform an extracted symbol line into symbol name with lib prefix and +# symbol address. +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\ +$lt_c_name_lib_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'" + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# Try without a prefix underscore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Fake it for dumpbin and say T for any non-static function, + # D for any global variable and I for any imported variable. + # Also find C++ and __fastcall symbols from MSVC++, + # which start with @ or ?. + lt_cv_sys_global_symbol_pipe="$AWK '"\ +" {last_section=section; section=\$ 3};"\ +" /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ +" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ +" /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\ +" /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\ +" /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\ +" \$ 0!~/External *\|/{next};"\ +" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ +" {if(hide[section]) next};"\ +" {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\ +" {split(\$ 0,a,/\||\r/); split(a[2],s)};"\ +" s[1]~/^[@?]/{print f,s[1],s[1]; next};"\ +" s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\ +" ' prfx=^$ac_symprfx" + else + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + fi + lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext <<_LT_EOF +#ifdef __cplusplus +extern "C" { +#endif +char nm_test_var; +void nm_test_func(void); +void nm_test_func(void){} +#ifdef __cplusplus +} +#endif +int main(){nm_test_var='a';nm_test_func();return(0);} +_LT_EOF + + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + # Now try to grab the symbols. + nlist=conftest.nm + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist\""; } >&5 + (eval $NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if $GREP ' nm_test_var$' "$nlist" >/dev/null; then + if $GREP ' nm_test_func$' "$nlist" >/dev/null; then + cat <<_LT_EOF > conftest.$ac_ext +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE +/* DATA imports from DLLs on WIN32 can't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT_DLSYM_CONST +#elif defined __osf__ +/* This system does not cope well with relocations in const data. */ +# define LT_DLSYM_CONST +#else +# define LT_DLSYM_CONST const +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +_LT_EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' + + cat <<_LT_EOF >> conftest.$ac_ext + +/* The mapping between symbol names and symbols. */ +LT_DLSYM_CONST struct { + const char *name; + void *address; +} +lt__PROGRAM__LTX_preloaded_symbols[] = +{ + { "@PROGRAM@", (void *) 0 }, +_LT_EOF + $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext + cat <<\_LT_EOF >> conftest.$ac_ext + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt__PROGRAM__LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif +_LT_EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_globsym_save_LIBS=$LIBS + lt_globsym_save_CFLAGS=$CFLAGS + LIBS=conftstm.$ac_objext + CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s conftest$ac_exeext; then + pipe_works=yes + fi + LIBS=$lt_globsym_save_LIBS + CFLAGS=$lt_globsym_save_CFLAGS + else + echo "cannot find nm_test_func in $nlist" >&5 + fi + else + echo "cannot find nm_test_var in $nlist" >&5 + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 + fi + else + echo "$progname: failed program was:" >&5 + cat conftest.$ac_ext >&5 + fi + rm -rf conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test yes = "$pipe_works"; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done + +fi + +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 +$as_echo "failed" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 +$as_echo "ok" >&6; } +fi + +# Response file support. +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + nm_file_list_spec='@' +elif $NM --help 2>/dev/null | grep '[@]FILE' >/dev/null; then + nm_file_list_spec='@' +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5 +$as_echo_n "checking for sysroot... " >&6; } + +# Check whether --with-sysroot was given. +if test "${with_sysroot+set}" = set; then : + withval=$with_sysroot; +else + with_sysroot=no +fi + + +lt_sysroot= +case $with_sysroot in #( + yes) + if test yes = "$GCC"; then + lt_sysroot=`$CC --print-sysroot 2>/dev/null` + fi + ;; #( + /*) + lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` + ;; #( + no|'') + ;; #( + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_sysroot" >&5 +$as_echo "$with_sysroot" >&6; } + as_fn_error $? "The sysroot must be an absolute path." "$LINENO" 5 + ;; +esac + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${lt_sysroot:-no}" >&5 +$as_echo "${lt_sysroot:-no}" >&6; } + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a working dd" >&5 +$as_echo_n "checking for a working dd... " >&6; } +if ${ac_cv_path_lt_DD+:} false; then : + $as_echo_n "(cached) " >&6 +else + printf 0123456789abcdef0123456789abcdef >conftest.i +cat conftest.i conftest.i >conftest2.i +: ${lt_DD:=$DD} +if test -z "$lt_DD"; then + ac_path_lt_DD_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 +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in dd; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_lt_DD="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_lt_DD" || continue +if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=: +fi + $ac_path_lt_DD_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_lt_DD"; then + : + fi +else + ac_cv_path_lt_DD=$lt_DD +fi + +rm -f conftest.i conftest2.i conftest.out +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_lt_DD" >&5 +$as_echo "$ac_cv_path_lt_DD" >&6; } + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to truncate binary pipes" >&5 +$as_echo_n "checking how to truncate binary pipes... " >&6; } +if ${lt_cv_truncate_bin+:} false; then : + $as_echo_n "(cached) " >&6 +else + printf 0123456789abcdef0123456789abcdef >conftest.i +cat conftest.i conftest.i >conftest2.i +lt_cv_truncate_bin= +if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1" +fi +rm -f conftest.i conftest2.i conftest.out +test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q" +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_truncate_bin" >&5 +$as_echo "$lt_cv_truncate_bin" >&6; } + + + + + + + +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +func_cc_basename () +{ + for cc_temp in $*""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac + done + func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` +} + +# Check whether --enable-libtool-lock was given. +if test "${enable_libtool_lock+set}" = set; then : + enableval=$enable_libtool_lock; +fi + +test no = "$enable_libtool_lock" || enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out what ABI is being produced by ac_compile, and set mode + # options accordingly. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE=32 + ;; + *ELF-64*) + HPUX_IA64_MODE=64 + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo '#line '$LINENO' "configure"' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + if test yes = "$lt_cv_prog_gnu_ld"; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +mips64*-*linux*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo '#line '$LINENO' "configure"' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + emul=elf + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + emul="${emul}32" + ;; + *64-bit*) + emul="${emul}64" + ;; + esac + case `/usr/bin/file conftest.$ac_objext` in + *MSB*) + emul="${emul}btsmip" + ;; + *LSB*) + emul="${emul}ltsmip" + ;; + esac + case `/usr/bin/file conftest.$ac_objext` in + *N32*) + emul="${emul}n32" + ;; + esac + LD="${LD-ld} -m $emul" + fi + rm -rf conftest* + ;; + +x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ +s390*-*linux*|s390*-*tpf*|sparc*-*linux*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. Note that the listed cases only cover the + # situations where additional linker options are needed (such as when + # doing 32-bit compilation for a host where ld defaults to 64-bit, or + # vice versa); the common cases where no linker options are needed do + # not appear in the list. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_i386_fbsd" + ;; + x86_64-*linux*) + case `/usr/bin/file conftest.o` in + *x86-64*) + LD="${LD-ld} -m elf32_x86_64" + ;; + *) + LD="${LD-ld} -m elf_i386" + ;; + esac + ;; + powerpc64le-*linux*) + LD="${LD-ld} -m elf32lppclinux" + ;; + powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_x86_64_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + powerpcle-*linux*) + LD="${LD-ld} -m elf64lppc" + ;; + powerpc-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*|s390*-*tpf*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS=$CFLAGS + CFLAGS="$CFLAGS -belf" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5 +$as_echo_n "checking whether the C compiler needs -belf... " >&6; } +if ${lt_cv_cc_needs_belf+:} false; then : + $as_echo_n "(cached) " >&6 +else + 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 + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_cc_needs_belf=yes +else + lt_cv_cc_needs_belf=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + 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 + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5 +$as_echo "$lt_cv_cc_needs_belf" >&6; } + if test yes != "$lt_cv_cc_needs_belf"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS=$SAVE_CFLAGS + fi + ;; +*-*solaris*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) + case $host in + i?86-*-solaris*|x86_64-*-solaris*) + LD="${LD-ld} -m elf_x86_64" + ;; + sparc*-*-solaris*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + # GNU ld 2.21 introduced _sol2 emulations. Use them if available. + if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then + LD=${LD-ld}_sol2 + fi + ;; + *) + if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then + LD="${LD-ld} -64" + fi + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; +esac + +need_locks=$enable_libtool_lock + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}mt", so it can be a program name with args. +set dummy ${ac_tool_prefix}mt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_MANIFEST_TOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$MANIFEST_TOOL"; then + ac_cv_prog_MANIFEST_TOOL="$MANIFEST_TOOL" # 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_MANIFEST_TOOL="${ac_tool_prefix}mt" + $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 +MANIFEST_TOOL=$ac_cv_prog_MANIFEST_TOOL +if test -n "$MANIFEST_TOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MANIFEST_TOOL" >&5 +$as_echo "$MANIFEST_TOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_MANIFEST_TOOL"; then + ac_ct_MANIFEST_TOOL=$MANIFEST_TOOL + # Extract the first word of "mt", so it can be a program name with args. +set dummy mt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_MANIFEST_TOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_MANIFEST_TOOL"; then + ac_cv_prog_ac_ct_MANIFEST_TOOL="$ac_ct_MANIFEST_TOOL" # 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_MANIFEST_TOOL="mt" + $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_MANIFEST_TOOL=$ac_cv_prog_ac_ct_MANIFEST_TOOL +if test -n "$ac_ct_MANIFEST_TOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MANIFEST_TOOL" >&5 +$as_echo "$ac_ct_MANIFEST_TOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_MANIFEST_TOOL" = x; then + MANIFEST_TOOL=":" + 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 + MANIFEST_TOOL=$ac_ct_MANIFEST_TOOL + fi +else + MANIFEST_TOOL="$ac_cv_prog_MANIFEST_TOOL" +fi + +test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $MANIFEST_TOOL is a manifest tool" >&5 +$as_echo_n "checking if $MANIFEST_TOOL is a manifest tool... " >&6; } +if ${lt_cv_path_mainfest_tool+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_path_mainfest_tool=no + echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&5 + $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out + cat conftest.err >&5 + if $GREP 'Manifest Tool' conftest.out > /dev/null; then + lt_cv_path_mainfest_tool=yes + fi + rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5 +$as_echo "$lt_cv_path_mainfest_tool" >&6; } +if test yes != "$lt_cv_path_mainfest_tool"; then + MANIFEST_TOOL=: +fi + + + + + + + case $host_os in + rhapsody* | darwin*) + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args. +set dummy ${ac_tool_prefix}dsymutil; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DSYMUTIL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DSYMUTIL"; then + ac_cv_prog_DSYMUTIL="$DSYMUTIL" # 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil" + $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 +DSYMUTIL=$ac_cv_prog_DSYMUTIL +if test -n "$DSYMUTIL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5 +$as_echo "$DSYMUTIL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_DSYMUTIL"; then + ac_ct_DSYMUTIL=$DSYMUTIL + # Extract the first word of "dsymutil", so it can be a program name with args. +set dummy dsymutil; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DSYMUTIL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DSYMUTIL"; then + ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_DSYMUTIL="dsymutil" + $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_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL +if test -n "$ac_ct_DSYMUTIL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5 +$as_echo "$ac_ct_DSYMUTIL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_DSYMUTIL" = x; then + DSYMUTIL=":" + 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 + DSYMUTIL=$ac_ct_DSYMUTIL + fi +else + DSYMUTIL="$ac_cv_prog_DSYMUTIL" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args. +set dummy ${ac_tool_prefix}nmedit; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_NMEDIT+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$NMEDIT"; then + ac_cv_prog_NMEDIT="$NMEDIT" # 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit" + $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 +NMEDIT=$ac_cv_prog_NMEDIT +if test -n "$NMEDIT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5 +$as_echo "$NMEDIT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_NMEDIT"; then + ac_ct_NMEDIT=$NMEDIT + # Extract the first word of "nmedit", so it can be a program name with args. +set dummy nmedit; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_NMEDIT+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_NMEDIT"; then + ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_NMEDIT="nmedit" + $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_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT +if test -n "$ac_ct_NMEDIT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5 +$as_echo "$ac_ct_NMEDIT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_NMEDIT" = x; then + NMEDIT=":" + 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 + NMEDIT=$ac_ct_NMEDIT + fi +else + NMEDIT="$ac_cv_prog_NMEDIT" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args. +set dummy ${ac_tool_prefix}lipo; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_LIPO+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$LIPO"; then + ac_cv_prog_LIPO="$LIPO" # 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_LIPO="${ac_tool_prefix}lipo" + $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 +LIPO=$ac_cv_prog_LIPO +if test -n "$LIPO"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5 +$as_echo "$LIPO" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_LIPO"; then + ac_ct_LIPO=$LIPO + # Extract the first word of "lipo", so it can be a program name with args. +set dummy lipo; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_LIPO+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_LIPO"; then + ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_LIPO="lipo" + $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_LIPO=$ac_cv_prog_ac_ct_LIPO +if test -n "$ac_ct_LIPO"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5 +$as_echo "$ac_ct_LIPO" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_LIPO" = x; then + LIPO=":" + 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 + LIPO=$ac_ct_LIPO + fi +else + LIPO="$ac_cv_prog_LIPO" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args. +set dummy ${ac_tool_prefix}otool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OTOOL"; then + ac_cv_prog_OTOOL="$OTOOL" # 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_OTOOL="${ac_tool_prefix}otool" + $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 +OTOOL=$ac_cv_prog_OTOOL +if test -n "$OTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5 +$as_echo "$OTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OTOOL"; then + ac_ct_OTOOL=$OTOOL + # Extract the first word of "otool", so it can be a program name with args. +set dummy otool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OTOOL"; then + ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_OTOOL="otool" + $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_OTOOL=$ac_cv_prog_ac_ct_OTOOL +if test -n "$ac_ct_OTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5 +$as_echo "$ac_ct_OTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OTOOL" = x; then + OTOOL=":" + 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 + OTOOL=$ac_ct_OTOOL + fi +else + OTOOL="$ac_cv_prog_OTOOL" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args. +set dummy ${ac_tool_prefix}otool64; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OTOOL64+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OTOOL64"; then + ac_cv_prog_OTOOL64="$OTOOL64" # 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64" + $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 +OTOOL64=$ac_cv_prog_OTOOL64 +if test -n "$OTOOL64"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5 +$as_echo "$OTOOL64" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OTOOL64"; then + ac_ct_OTOOL64=$OTOOL64 + # Extract the first word of "otool64", so it can be a program name with args. +set dummy otool64; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OTOOL64+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OTOOL64"; then + ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_OTOOL64="otool64" + $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_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64 +if test -n "$ac_ct_OTOOL64"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5 +$as_echo "$ac_ct_OTOOL64" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OTOOL64" = x; then + OTOOL64=":" + 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 + OTOOL64=$ac_ct_OTOOL64 + fi +else + OTOOL64="$ac_cv_prog_OTOOL64" +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5 +$as_echo_n "checking for -single_module linker flag... " >&6; } +if ${lt_cv_apple_cc_single_mod+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_apple_cc_single_mod=no + if test -z "$LT_MULTI_MODULE"; then + # By default we will add the -single_module flag. You can override + # by either setting the environment variable LT_MULTI_MODULE + # non-empty at configure time, or by adding -multi_module to the + # link flags. + rm -rf libconftest.dylib* + echo "int foo(void){return 1;}" > conftest.c + echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ +-dynamiclib -Wl,-single_module conftest.c" >&5 + $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ + -dynamiclib -Wl,-single_module conftest.c 2>conftest.err + _lt_result=$? + # If there is a non-empty error log, and "single_module" + # appears in it, assume the flag caused a linker warning + if test -s conftest.err && $GREP single_module conftest.err; then + cat conftest.err >&5 + # Otherwise, if the output was created with a 0 exit code from + # the compiler, it worked. + elif test -f libconftest.dylib && test 0 = "$_lt_result"; then + lt_cv_apple_cc_single_mod=yes + else + cat conftest.err >&5 + fi + rm -rf libconftest.dylib* + rm -f conftest.* + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5 +$as_echo "$lt_cv_apple_cc_single_mod" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5 +$as_echo_n "checking for -exported_symbols_list linker flag... " >&6; } +if ${lt_cv_ld_exported_symbols_list+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_exported_symbols_list=no + save_LDFLAGS=$LDFLAGS + echo "_main" > conftest.sym + LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_ld_exported_symbols_list=yes +else + lt_cv_ld_exported_symbols_list=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$save_LDFLAGS + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5 +$as_echo "$lt_cv_ld_exported_symbols_list" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5 +$as_echo_n "checking for -force_load linker flag... " >&6; } +if ${lt_cv_ld_force_load+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_force_load=no + cat > conftest.c << _LT_EOF +int forced_loaded() { return 2;} +_LT_EOF + echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5 + $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5 + echo "$AR cru libconftest.a conftest.o" >&5 + $AR cru libconftest.a conftest.o 2>&5 + echo "$RANLIB libconftest.a" >&5 + $RANLIB libconftest.a 2>&5 + cat > conftest.c << _LT_EOF +int main() { return 0;} +_LT_EOF + echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5 + $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err + _lt_result=$? + if test -s conftest.err && $GREP force_load conftest.err; then + cat conftest.err >&5 + elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then + lt_cv_ld_force_load=yes + else + cat conftest.err >&5 + fi + rm -f conftest.err libconftest.a conftest conftest.c + rm -rf conftest.dSYM + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5 +$as_echo "$lt_cv_ld_force_load" >&6; } + case $host_os in + rhapsody* | darwin1.[012]) + _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;; + darwin1.*) + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; + darwin*) # darwin 5.x on + # if running on 10.5 or later, the deployment target defaults + # to the OS version, if on x86, and 10.4, the deployment + # target defaults to 10.4. Don't you love it? + case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in + 10.0,*86*-darwin8*|10.0,*-darwin[91]*) + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; + 10.[012][,.]*) + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; + 10.*) + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; + esac + ;; + esac + if test yes = "$lt_cv_apple_cc_single_mod"; then + _lt_dar_single_mod='$single_module' + fi + if test yes = "$lt_cv_ld_exported_symbols_list"; then + _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym' + else + _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib' + fi + if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then + _lt_dsymutil='~$DSYMUTIL $lib || :' + else + _lt_dsymutil= + fi + ;; + esac + +# func_munge_path_list VARIABLE PATH +# ----------------------------------- +# VARIABLE is name of variable containing _space_ separated list of +# directories to be munged by the contents of PATH, which is string +# having a format: +# "DIR[:DIR]:" +# string "DIR[ DIR]" will be prepended to VARIABLE +# ":DIR[:DIR]" +# string "DIR[ DIR]" will be appended to VARIABLE +# "DIRP[:DIRP]::[DIRA:]DIRA" +# string "DIRP[ DIRP]" will be prepended to VARIABLE and string +# "DIRA[ DIRA]" will be appended to VARIABLE +# "DIR[:DIR]" +# VARIABLE will be replaced by "DIR[ DIR]" +func_munge_path_list () +{ + case x$2 in + x) + ;; + *:) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\" + ;; + x:*) + eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\" + ;; + *::*) + eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" + eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\" + ;; + *) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\" + ;; + esac +} + +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 ${ac_cv_prog_CPP+:} false; 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 ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if ${ac_cv_header_stdc+:} false; 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 dlfcn.h +do : + ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default +" +if test "x$ac_cv_header_dlfcn_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_DLFCN_H 1 +_ACEOF + +fi + +done + + + + + +# Set options +enable_win32_dll=yes + +case $host in +*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}as", so it can be a program name with args. +set dummy ${ac_tool_prefix}as; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AS+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AS"; then + ac_cv_prog_AS="$AS" # 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AS="${ac_tool_prefix}as" + $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 +AS=$ac_cv_prog_AS +if test -n "$AS"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AS" >&5 +$as_echo "$AS" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_AS"; then + ac_ct_AS=$AS + # Extract the first word of "as", so it can be a program name with args. +set dummy as; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_AS+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_AS"; then + ac_cv_prog_ac_ct_AS="$ac_ct_AS" # 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_AS="as" + $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_AS=$ac_cv_prog_ac_ct_AS +if test -n "$ac_ct_AS"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AS" >&5 +$as_echo "$ac_ct_AS" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_AS" = x; then + AS="false" + 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 + AS=$ac_ct_AS + fi +else + AS="$ac_cv_prog_AS" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. +set dummy ${ac_tool_prefix}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 ${ac_cv_prog_DLLTOOL+:} false; 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_DLLTOOL="${ac_tool_prefix}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 + +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 +if test -z "$ac_cv_prog_DLLTOOL"; then + ac_ct_DLLTOOL=$DLLTOOL + # 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 ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DLLTOOL"; then + ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_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 + +fi +fi +ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL +if test -n "$ac_ct_DLLTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5 +$as_echo "$ac_ct_DLLTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_DLLTOOL" = x; then + DLLTOOL="false" + 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 + DLLTOOL=$ac_ct_DLLTOOL + fi +else + DLLTOOL="$ac_cv_prog_DLLTOOL" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. +set dummy ${ac_tool_prefix}objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OBJDUMP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OBJDUMP"; then + ac_cv_prog_OBJDUMP="$OBJDUMP" # 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" + $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 +OBJDUMP=$ac_cv_prog_OBJDUMP +if test -n "$OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 +$as_echo "$OBJDUMP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OBJDUMP"; then + ac_ct_OBJDUMP=$OBJDUMP + # Extract the first word of "objdump", so it can be a program name with args. +set dummy objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OBJDUMP"; then + ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_OBJDUMP="objdump" + $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_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP +if test -n "$ac_ct_OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 +$as_echo "$ac_ct_OBJDUMP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OBJDUMP" = x; then + OBJDUMP="false" + 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 + OBJDUMP=$ac_ct_OBJDUMP + fi +else + OBJDUMP="$ac_cv_prog_OBJDUMP" +fi + + ;; +esac + +test -z "$AS" && AS=as + + + + + +test -z "$DLLTOOL" && DLLTOOL=dlltool + + + + + +test -z "$OBJDUMP" && OBJDUMP=objdump + + + + + + + + enable_dlopen=no + + + + # Check whether --enable-shared was given. +if test "${enable_shared+set}" = set; then : + enableval=$enable_shared; p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS=$lt_save_ifs + ;; + esac +else + enable_shared=yes +fi + + + + + + + + + + # Check whether --enable-static was given. +if test "${enable_static+set}" = set; then : + enableval=$enable_static; p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS=$lt_save_ifs + ;; + esac +else + enable_static=yes +fi + + + + + + + + + + +# Check whether --with-pic was given. +if test "${with_pic+set}" = set; then : + withval=$with_pic; lt_p=${PACKAGE-default} + case $withval in + yes|no) pic_mode=$withval ;; + *) + pic_mode=default + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for lt_pkg in $withval; do + IFS=$lt_save_ifs + if test "X$lt_pkg" = "X$lt_p"; then + pic_mode=yes + fi + done + IFS=$lt_save_ifs + ;; + esac +else + pic_mode=default +fi + + + + + + + + + # Check whether --enable-fast-install was given. +if test "${enable_fast_install+set}" = set; then : + enableval=$enable_fast_install; p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS=$lt_save_ifs + ;; + esac +else + enable_fast_install=yes +fi + + + + + + + + + shared_archive_member_spec= +case $host,$enable_shared in +power*-*-aix[5-9]*,yes) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking which variant of shared library versioning to provide" >&5 +$as_echo_n "checking which variant of shared library versioning to provide... " >&6; } + +# Check whether --with-aix-soname was given. +if test "${with_aix_soname+set}" = set; then : + withval=$with_aix_soname; case $withval in + aix|svr4|both) + ;; + *) + as_fn_error $? "Unknown argument to --with-aix-soname" "$LINENO" 5 + ;; + esac + lt_cv_with_aix_soname=$with_aix_soname +else + if ${lt_cv_with_aix_soname+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_with_aix_soname=aix +fi + + with_aix_soname=$lt_cv_with_aix_soname +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_aix_soname" >&5 +$as_echo "$with_aix_soname" >&6; } + if test aix != "$with_aix_soname"; then + # For the AIX way of multilib, we name the shared archive member + # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o', + # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File. + # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag, + # the AIX toolchain works better with OBJECT_MODE set (default 32). + if test 64 = "${OBJECT_MODE-32}"; then + shared_archive_member_spec=shr_64 + else + shared_archive_member_spec=shr + fi + fi + ;; +*) + with_aix_soname=aix + ;; +esac + + + + + + + + + + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS=$ltmain + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +test -z "$LN_S" && LN_S="ln -s" + + + + + + + + + + + + + + +if test -n "${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5 +$as_echo_n "checking for objdir... " >&6; } +if ${lt_cv_objdir+:} false; then : + $as_echo_n "(cached) " >&6 +else + rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5 +$as_echo "$lt_cv_objdir" >&6; } +objdir=$lt_cv_objdir + + + + + +cat >>confdefs.h <<_ACEOF +#define LT_OBJDIR "$lt_cv_objdir/" +_ACEOF + + + + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test set != "${COLLECT_NAMES+set}"; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Global variables: +ofile=libtool +can_build_shared=yes + +# All known linkers require a '.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a + +with_gnu_ld=$lt_cv_prog_gnu_ld + +old_CC=$CC +old_CFLAGS=$CFLAGS + +# Set sane defaults for various variables +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS +test -z "$LD" && LD=ld +test -z "$ac_objext" && ac_objext=o + +func_cc_basename $compiler +cc_basename=$func_cc_basename_result + + +# Only perform the check for file, if the check method requires it +test -z "$MAGIC_CMD" && MAGIC_CMD=file +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5 +$as_echo_n "checking for ${ac_tool_prefix}file... " >&6; } +if ${lt_cv_path_MAGIC_CMD+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $MAGIC_CMD in +[\\/*] | ?:[\\/]*) + lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD=$MAGIC_CMD + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" + for ac_dir in $ac_dummy; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/${ac_tool_prefix}file"; then + lt_cv_path_MAGIC_CMD=$ac_dir/"${ac_tool_prefix}file" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD=$lt_cv_path_MAGIC_CMD + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS=$lt_save_ifs + MAGIC_CMD=$lt_save_MAGIC_CMD + ;; +esac +fi + +MAGIC_CMD=$lt_cv_path_MAGIC_CMD +if test -n "$MAGIC_CMD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 +$as_echo "$MAGIC_CMD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + + + +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5 +$as_echo_n "checking for file... " >&6; } +if ${lt_cv_path_MAGIC_CMD+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $MAGIC_CMD in +[\\/*] | ?:[\\/]*) + lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD=$MAGIC_CMD + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" + for ac_dir in $ac_dummy; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/file"; then + lt_cv_path_MAGIC_CMD=$ac_dir/"file" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD=$lt_cv_path_MAGIC_CMD + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS=$lt_save_ifs + MAGIC_CMD=$lt_save_MAGIC_CMD + ;; +esac +fi + +MAGIC_CMD=$lt_cv_path_MAGIC_CMD +if test -n "$MAGIC_CMD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 +$as_echo "$MAGIC_CMD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + else + MAGIC_CMD=: + fi +fi + + fi + ;; +esac + +# Use C for the default configuration in the libtool script + +lt_save_CC=$CC +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 + + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +objext=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}' + + + + + + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + +# Save the default compiler, since it gets overwritten when the other +# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. +compiler_DEFAULT=$CC + +# save warnings/boilerplate of simple test code +ac_outfile=conftest.$ac_objext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$RM conftest* + +ac_outfile=conftest.$ac_objext +echo "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$RM -r conftest* + + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + +lt_prog_compiler_no_builtin_flag= + +if test yes = "$GCC"; then + case $cc_basename in + nvcc*) + lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;; + *) + lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;; + esac + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 +$as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; } +if ${lt_cv_prog_compiler_rtti_exceptions+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_rtti_exceptions=no + ac_outfile=conftest.$ac_objext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="-fno-rtti -fno-exceptions" ## exclude from sc_useless_quotes_in_assignment + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_rtti_exceptions=yes + fi + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 +$as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; } + +if test yes = "$lt_cv_prog_compiler_rtti_exceptions"; then + lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" +else + : +fi + +fi + + + + + + + lt_prog_compiler_wl= +lt_prog_compiler_pic= +lt_prog_compiler_static= + + + if test yes = "$GCC"; then + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_static='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static='-Bstatic' + fi + lt_prog_compiler_pic='-fPIC' + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + lt_prog_compiler_pic='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the '-m68020' flag to GCC prevents building anything better, + # like '-m68040'. + lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + lt_prog_compiler_pic='-DDLL_EXPORT' + case $host_os in + os2*) + lt_prog_compiler_static='$wl-static' + ;; + esac + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic='-fno-common' + ;; + + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + lt_prog_compiler_static= + ;; + + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic='-fPIC' + ;; + esac + ;; + + interix[3-9]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + lt_prog_compiler_can_build_shared=no + enable_shared=no + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + lt_prog_compiler_pic='-fPIC -shared' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic=-Kconform_pic + fi + ;; + + *) + lt_prog_compiler_pic='-fPIC' + ;; + esac + + case $cc_basename in + nvcc*) # Cuda Compiler Driver 2.2 + lt_prog_compiler_wl='-Xlinker ' + if test -n "$lt_prog_compiler_pic"; then + lt_prog_compiler_pic="-Xcompiler $lt_prog_compiler_pic" + fi + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + lt_prog_compiler_wl='-Wl,' + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static='-Bstatic' + else + lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' + fi + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic='-fno-common' + case $cc_basename in + nagfor*) + # NAG Fortran compiler + lt_prog_compiler_wl='-Wl,-Wl,,' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + esac + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + lt_prog_compiler_pic='-DDLL_EXPORT' + case $host_os in + os2*) + lt_prog_compiler_static='$wl-static' + ;; + esac + ;; + + hpux9* | hpux10* | hpux11*) + lt_prog_compiler_wl='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + lt_prog_compiler_static='$wl-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + lt_prog_compiler_wl='-Wl,' + # PIC (with -KPIC) is the default. + lt_prog_compiler_static='-non_shared' + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + case $cc_basename in + # old Intel for x86_64, which still supported -KPIC. + ecc*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-static' + ;; + # icc used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + icc* | ifort*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fPIC' + lt_prog_compiler_static='-static' + ;; + # Lahey Fortran 8.1. + lf95*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='--shared' + lt_prog_compiler_static='--static' + ;; + nagfor*) + # NAG Fortran compiler + lt_prog_compiler_wl='-Wl,-Wl,,' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fPIC' + lt_prog_compiler_static='-static' + ;; + pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fpic' + lt_prog_compiler_static='-Bstatic' + ;; + ccc*) + lt_prog_compiler_wl='-Wl,' + # All Alpha code is PIC. + lt_prog_compiler_static='-non_shared' + ;; + xl* | bgxl* | bgf* | mpixl*) + # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-qpic' + lt_prog_compiler_static='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [1-7].* | *Sun*Fortran*\ 8.[0-3]*) + # Sun Fortran 8.3 passes all unrecognized flags to the linker + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='' + ;; + *Sun\ F* | *Sun*Fortran*) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='-Qoption ld ' + ;; + *Sun\ C*) + # Sun C 5.9 + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='-Wl,' + ;; + *Intel*\ [CF]*Compiler*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fPIC' + lt_prog_compiler_static='-static' + ;; + *Portland\ Group*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fpic' + lt_prog_compiler_static='-Bstatic' + ;; + esac + ;; + esac + ;; + + newsos6) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + lt_prog_compiler_pic='-fPIC -shared' + ;; + + osf3* | osf4* | osf5*) + lt_prog_compiler_wl='-Wl,' + # All OSF/1 code is PIC. + lt_prog_compiler_static='-non_shared' + ;; + + rdos*) + lt_prog_compiler_static='-non_shared' + ;; + + solaris*) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + case $cc_basename in + f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) + lt_prog_compiler_wl='-Qoption ld ';; + *) + lt_prog_compiler_wl='-Wl,';; + esac + ;; + + sunos4*) + lt_prog_compiler_wl='-Qoption ld ' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic='-Kconform_pic' + lt_prog_compiler_static='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + unicos*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_can_build_shared=no + ;; + + uts4*) + lt_prog_compiler_pic='-pic' + lt_prog_compiler_static='-Bstatic' + ;; + + *) + lt_prog_compiler_can_build_shared=no + ;; + esac + fi + +case $host_os in + # For platforms that do not support PIC, -DPIC is meaningless: + *djgpp*) + lt_prog_compiler_pic= + ;; + *) + lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" + ;; +esac + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 +$as_echo_n "checking for $compiler option to produce PIC... " >&6; } +if ${lt_cv_prog_compiler_pic+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_pic=$lt_prog_compiler_pic +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic" >&5 +$as_echo "$lt_cv_prog_compiler_pic" >&6; } +lt_prog_compiler_pic=$lt_cv_prog_compiler_pic + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$lt_prog_compiler_pic"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 +$as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; } +if ${lt_cv_prog_compiler_pic_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_pic_works=no + ac_outfile=conftest.$ac_objext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$lt_prog_compiler_pic -DPIC" ## exclude from sc_useless_quotes_in_assignment + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_pic_works=yes + fi + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5 +$as_echo "$lt_cv_prog_compiler_pic_works" >&6; } + +if test yes = "$lt_cv_prog_compiler_pic_works"; then + case $lt_prog_compiler_pic in + "" | " "*) ;; + *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; + esac +else + lt_prog_compiler_pic= + lt_prog_compiler_can_build_shared=no +fi + +fi + + + + + + + + + + + +# +# Check to make sure the static flag actually works. +# +wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 +$as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } +if ${lt_cv_prog_compiler_static_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_static_works=no + save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS $lt_tmp_static_flag" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_static_works=yes + fi + else + lt_cv_prog_compiler_static_works=yes + fi + fi + $RM -r conftest* + LDFLAGS=$save_LDFLAGS + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5 +$as_echo "$lt_cv_prog_compiler_static_works" >&6; } + +if test yes = "$lt_cv_prog_compiler_static_works"; then + : +else + lt_prog_compiler_static= +fi + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if ${lt_cv_prog_compiler_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_c_o=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o=yes + fi + fi + chmod u+w . 2>&5 + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 +$as_echo "$lt_cv_prog_compiler_c_o" >&6; } + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if ${lt_cv_prog_compiler_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_c_o=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o=yes + fi + fi + chmod u+w . 2>&5 + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 +$as_echo "$lt_cv_prog_compiler_c_o" >&6; } + + + + +hard_links=nottested +if test no = "$lt_cv_prog_compiler_c_o" && test no != "$need_locks"; then + # do not overwrite the value of need_locks provided by the user + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 +$as_echo_n "checking if we can lock with hard links... " >&6; } + hard_links=yes + $RM conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 +$as_echo "$hard_links" >&6; } + if test no = "$hard_links"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&5 +$as_echo "$as_me: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&2;} + need_locks=warn + fi +else + need_locks=no +fi + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } + + runpath_var= + allow_undefined_flag= + always_export_symbols=no + archive_cmds= + archive_expsym_cmds= + compiler_needs_object=no + enable_shared_with_static_runtimes=no + export_dynamic_flag_spec= + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + hardcode_automatic=no + hardcode_direct=no + hardcode_direct_absolute=no + hardcode_libdir_flag_spec= + hardcode_libdir_separator= + hardcode_minus_L=no + hardcode_shlibpath_var=unsupported + inherit_rpath=no + link_all_deplibs=unknown + module_cmds= + module_expsym_cmds= + old_archive_from_new_cmds= + old_archive_from_expsyms_cmds= + thread_safe_flag_spec= + whole_archive_flag_spec= + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + include_expsyms= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ' (' and ')$', so one must not match beginning or + # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc', + # as well as any symbol that contains 'd'. + exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + # Exclude shared library initialization/finalization symbols. + extract_expsyms_cmds= + + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test yes != "$GCC"; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd* | bitrig*) + with_gnu_ld=no + ;; + linux* | k*bsd*-gnu | gnu*) + link_all_deplibs=no + ;; + esac + + ld_shlibs=yes + + # On some targets, GNU ld is compatible enough with the native linker + # that we're better off using the native interface for both. + lt_use_gnu_ld_interface=no + if test yes = "$with_gnu_ld"; then + case $host_os in + aix*) + # The AIX port of GNU ld has always aspired to compatibility + # with the native linker. However, as the warning in the GNU ld + # block says, versions before 2.19.5* couldn't really create working + # shared libraries, regardless of the interface used. + case `$LD -v 2>&1` in + *\ \(GNU\ Binutils\)\ 2.19.5*) ;; + *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;; + *\ \(GNU\ Binutils\)\ [3-9]*) ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + fi + + if test yes = "$lt_use_gnu_ld_interface"; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='$wl' + + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + runpath_var=LD_RUN_PATH + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + export_dynamic_flag_spec='$wl--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then + whole_archive_flag_spec=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + else + whole_archive_flag_spec= + fi + supports_anon_versioning=no + case `$LD -v | $SED -e 's/(^)\+)\s\+//' 2>&1` in + *GNU\ gold*) supports_anon_versioning=yes ;; + *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix[3-9]*) + # On AIX/PPC, the GNU linker is very broken + if test ia64 != "$host_cpu"; then + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: the GNU linker, at least up to release 2.19, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to install binutils +*** 2.20 or above, or modify your PATH so that a non-GNU linker is found. +*** You will then need to restart the configuration process. + +_LT_EOF + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='' + ;; + m68k) + archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + esac + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + allow_undefined_flag=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + else + ld_shlibs=no + fi + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, + # as there is no search path for DLLs. + hardcode_libdir_flag_spec='-L$libdir' + export_dynamic_flag_spec='$wl--export-all-symbols' + allow_undefined_flag=unsupported + always_export_symbols=no + enable_shared_with_static_runtimes=yes + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' + exclude_expsyms='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file, use it as + # is; otherwise, prepend EXPORTS... + archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + ld_shlibs=no + fi + ;; + + haiku*) + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + link_all_deplibs=yes + ;; + + os2*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + allow_undefined_flag=unsupported + shrext_cmds=.dll + archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + enable_shared_with_static_runtimes=yes + ;; + + interix[3-9]*) + hardcode_direct=no + hardcode_shlibpath_var=no + hardcode_libdir_flag_spec='$wl-rpath,$libdir' + export_dynamic_flag_spec='$wl-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_expsym_cmds='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) + tmp_diet=no + if test linux-dietlibc = "$host_os"; then + case $cc_basename in + diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) + esac + fi + if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ + && test no = "$tmp_diet" + then + tmp_addflag=' $pic_flag' + tmp_sharedflag='-shared' + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group f77 and f90 compilers + whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + lf95*) # Lahey Fortran 8.1 + whole_archive_flag_spec= + tmp_sharedflag='--shared' ;; + nagfor*) # NAGFOR 5.3 + tmp_sharedflag='-Wl,-shared' ;; + xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) + tmp_sharedflag='-qmkshrobj' + tmp_addflag= ;; + nvcc*) # Cuda Compiler Driver 2.2 + whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + compiler_needs_object=yes + ;; + esac + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C 5.9 + whole_archive_flag_spec='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + compiler_needs_object=yes + tmp_sharedflag='-G' ;; + *Sun\ F*) # Sun Fortran 8.3 + tmp_sharedflag='-G' ;; + esac + archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + + if test yes = "$supports_anon_versioning"; then + archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' + fi + + case $cc_basename in + tcc*) + export_dynamic_flag_spec='-rdynamic' + ;; + xlf* | bgf* | bgxlf* | mpixlf*) + # IBM XL Fortran 10.1 on PPC cannot create shared libs itself + whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' + if test yes = "$supports_anon_versioning"; then + archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' + fi + ;; + esac + else + ld_shlibs=no + fi + ;; + + netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + # For security reasons, it is highly recommended that you always + # use absolute paths for naming shared libraries, and exclude the + # DT_RUNPATH tag from executables and libraries. But doing so + # requires that you compile everything twice, which is a pain. + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + esac + ;; + + sunos4*) + archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + *) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + esac + + if test no = "$ld_shlibs"; then + runpath_var= + hardcode_libdir_flag_spec= + export_dynamic_flag_spec= + whole_archive_flag_spec= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + allow_undefined_flag=unsupported + always_export_symbols=yes + archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + hardcode_minus_L=yes + if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + hardcode_direct=unsupported + fi + ;; + + aix[4-9]*) + if test ia64 = "$host_cpu"; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag= + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to GNU nm, but means don't demangle to AIX nm. + # Without the "-l" option, or with the "-B" option, AIX nm treats + # weak defined symbols like other global defined symbols, whereas + # GNU nm marks them as "W". + # While the 'weak' keyword is ignored in the Export File, we need + # it in the Import File for the 'aix-soname' feature, so we have + # to replace the "-B" option with "-P" for AIX nm. + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' + else + export_symbols_cmds='`func_echo_all $NM | $SED -e '\''s/B\([^B]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && (substr(\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # have runtime linking enabled, and use it for executables. + # For shared libraries, we enable/disable runtime linking + # depending on the kind of the shared library created - + # when "with_aix_soname,aix_use_runtimelinking" is: + # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables + # "aix,yes" lib.so shared, rtl:yes, for executables + # lib.a static archive + # "both,no" lib.so.V(shr.o) shared, rtl:yes + # lib.a(lib.so.V) shared, rtl:no, for executables + # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a(lib.so.V) shared, rtl:no + # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a static archive + case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) + for ld_flag in $LDFLAGS; do + if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then + aix_use_runtimelinking=yes + break + fi + done + if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then + # With aix-soname=svr4, we create the lib.so.V shared archives only, + # so we don't have lib.a shared libs to link our executables. + # We have to force runtime linking in this case. + aix_use_runtimelinking=yes + LDFLAGS="$LDFLAGS -Wl,-brtl" + fi + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + archive_cmds='' + hardcode_direct=yes + hardcode_direct_absolute=yes + hardcode_libdir_separator=':' + link_all_deplibs=yes + file_list_spec='$wl-f,' + case $with_aix_soname,$aix_use_runtimelinking in + aix,*) ;; # traditional, no import file + svr4,* | *,yes) # use import file + # The Import File defines what to hardcode. + hardcode_direct=no + hardcode_direct_absolute=no + ;; + esac + + if test yes = "$GCC"; then + case $host_os in aix4.[012]|aix4.[012].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`$CC -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + hardcode_direct=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + hardcode_minus_L=yes + hardcode_libdir_flag_spec='-L$libdir' + hardcode_libdir_separator= + fi + ;; + esac + shared_flag='-shared' + if test yes = "$aix_use_runtimelinking"; then + shared_flag="$shared_flag "'$wl-G' + fi + # Need to ensure runtime linking is disabled for the traditional + # shared library, or the linker may eventually find shared libraries + # /with/ Import File - we do not want to mix them. + shared_flag_aix='-shared' + shared_flag_svr4='-shared $wl-G' + else + # not using gcc + if test ia64 = "$host_cpu"; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test yes = "$aix_use_runtimelinking"; then + shared_flag='$wl-G' + else + shared_flag='$wl-bM:SRE' + fi + shared_flag_aix='$wl-bM:SRE' + shared_flag_svr4='$wl-G' + fi + fi + + export_dynamic_flag_spec='$wl-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + always_export_symbols=yes + if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + allow_undefined_flag='-berok' + # Determine the default libpath from the value encoded in an + # empty executable. + if test set = "${lt_cv_aix_libpath+set}"; then + aix_libpath=$lt_cv_aix_libpath +else + if ${lt_cv_aix_libpath_+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + + lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }' + lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=/usr/lib:/lib + fi + +fi + + aix_libpath=$lt_cv_aix_libpath_ +fi + + hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath" + archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag + else + if test ia64 = "$host_cpu"; then + hardcode_libdir_flag_spec='$wl-R $libdir:/usr/lib:/lib' + allow_undefined_flag="-z nodefs" + archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + if test set = "${lt_cv_aix_libpath+set}"; then + aix_libpath=$lt_cv_aix_libpath +else + if ${lt_cv_aix_libpath_+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + + lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }' + lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=/usr/lib:/lib + fi + +fi + + aix_libpath=$lt_cv_aix_libpath_ +fi + + hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + no_undefined_flag=' $wl-bernotok' + allow_undefined_flag=' $wl-berok' + if test yes = "$with_gnu_ld"; then + # We only use this code for GNU lds that support --whole-archive. + whole_archive_flag_spec='$wl--whole-archive$convenience $wl--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + whole_archive_flag_spec='$convenience' + fi + archive_cmds_need_lc=yes + archive_expsym_cmds='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' + # -brtl affects multiple linker settings, -berok does not and is overridden later + compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([, ]\\)%-berok\\1%g"`' + if test svr4 != "$with_aix_soname"; then + # This is similar to how AIX traditionally builds its shared libraries. + archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' + fi + if test aix != "$with_aix_soname"; then + archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' + else + # used by -dlpreopen to get the symbols + archive_expsym_cmds="$archive_expsym_cmds"'~$MV $output_objdir/$realname.d/$soname $output_objdir' + fi + archive_expsym_cmds="$archive_expsym_cmds"'~$RM -r $output_objdir/$realname.d' + fi + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='' + ;; + m68k) + archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + esac + ;; + + bsdi[45]*) + export_dynamic_flag_spec=-rdynamic + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + case $cc_basename in + cl*) + # Native MSVC + hardcode_libdir_flag_spec=' ' + allow_undefined_flag=unsupported + always_export_symbols=yes + file_list_spec='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' + archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then + cp "$export_symbols" "$output_objdir/$soname.def"; + echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; + else + $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, )='true' + enable_shared_with_static_runtimes=yes + exclude_expsyms='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1,DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' + # Don't use ranlib + old_postinstall_cmds='chmod 644 $oldlib' + postlink_cmds='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile=$lt_outputfile.exe + lt_tool_outputfile=$lt_tool_outputfile.exe + ;; + esac~ + if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # Assume MSVC wrapper + hardcode_libdir_flag_spec=' ' + allow_undefined_flag=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + old_archive_from_new_cmds='true' + # FIXME: Should let the user specify the lib program. + old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs' + enable_shared_with_static_runtimes=yes + ;; + esac + ;; + + darwin* | rhapsody*) + + + archive_cmds_need_lc=no + hardcode_direct=no + hardcode_automatic=yes + hardcode_shlibpath_var=unsupported + if test yes = "$lt_cv_ld_force_load"; then + whole_archive_flag_spec='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + + else + whole_archive_flag_spec='' + fi + link_all_deplibs=yes + allow_undefined_flag=$_lt_dar_allow_undefined + case $cc_basename in + ifort*|nagfor*) _lt_dar_can_shared=yes ;; + *) _lt_dar_can_shared=$GCC ;; + esac + if test yes = "$_lt_dar_can_shared"; then + output_verbose_link_cmd=func_echo_all + archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" + module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" + archive_expsym_cmds="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" + module_expsym_cmds="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" + + else + ld_shlibs=no + fi + + ;; + + dgux*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2.*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | dragonfly*) + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + hpux9*) + if test yes = "$GCC"; then + archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + else + archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + fi + hardcode_libdir_flag_spec='$wl+b $wl$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + export_dynamic_flag_spec='$wl-E' + ;; + + hpux10*) + if test yes,no = "$GCC,$with_gnu_ld"; then + archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test no = "$with_gnu_ld"; then + hardcode_libdir_flag_spec='$wl+b $wl$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + hardcode_direct_absolute=yes + export_dynamic_flag_spec='$wl-E' + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + fi + ;; + + hpux11*) + if test yes,no = "$GCC,$with_gnu_ld"; then + case $host_cpu in + hppa*64*) + archive_cmds='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + archive_cmds='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + + # Older versions of the 11.00 compiler do not understand -b yet + # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5 +$as_echo_n "checking if $CC understands -b... " >&6; } +if ${lt_cv_prog_compiler__b+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler__b=no + save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS -b" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler__b=yes + fi + else + lt_cv_prog_compiler__b=yes + fi + fi + $RM -r conftest* + LDFLAGS=$save_LDFLAGS + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5 +$as_echo "$lt_cv_prog_compiler__b" >&6; } + +if test yes = "$lt_cv_prog_compiler__b"; then + archive_cmds='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' +else + archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' +fi + + ;; + esac + fi + if test no = "$with_gnu_ld"; then + hardcode_libdir_flag_spec='$wl+b $wl$libdir' + hardcode_libdir_separator=: + + case $host_cpu in + hppa*64*|ia64*) + hardcode_direct=no + hardcode_shlibpath_var=no + ;; + *) + hardcode_direct=yes + hardcode_direct_absolute=yes + export_dynamic_flag_spec='$wl-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test yes = "$GCC"; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + # Try to use the -exported_symbol ld option, if it does not + # work, assume that -exports_file does not work either and + # implicitly export all symbols. + # This should be the same for all languages, so no per-tag cache variable. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $host_os linker accepts -exported_symbol" >&5 +$as_echo_n "checking whether the $host_os linker accepts -exported_symbol... " >&6; } +if ${lt_cv_irix_exported_symbol+:} false; then : + $as_echo_n "(cached) " >&6 +else + save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int foo (void) { return 0; } +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_irix_exported_symbol=yes +else + lt_cv_irix_exported_symbol=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$save_LDFLAGS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5 +$as_echo "$lt_cv_irix_exported_symbol" >&6; } + if test yes = "$lt_cv_irix_exported_symbol"; then + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' + fi + link_all_deplibs=no + else + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' + fi + archive_cmds_need_lc='no' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + hardcode_libdir_separator=: + inherit_rpath=yes + link_all_deplibs=yes + ;; + + linux*) + case $cc_basename in + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + ld_shlibs=yes + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + newsos6) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + hardcode_libdir_separator=: + hardcode_shlibpath_var=no + ;; + + *nto* | *qnx*) + ;; + + openbsd* | bitrig*) + if test -f /usr/libexec/ld.so; then + hardcode_direct=yes + hardcode_shlibpath_var=no + hardcode_direct_absolute=yes + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols' + hardcode_libdir_flag_spec='$wl-rpath,$libdir' + export_dynamic_flag_spec='$wl-E' + else + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='$wl-rpath,$libdir' + fi + else + ld_shlibs=no + fi + ;; + + os2*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + allow_undefined_flag=unsupported + shrext_cmds=.dll + archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + enable_shared_with_static_runtimes=yes + ;; + + osf3*) + if test yes = "$GCC"; then + allow_undefined_flag=' $wl-expect_unresolved $wl\*' + archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + fi + archive_cmds_need_lc='no' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + hardcode_libdir_separator=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test yes = "$GCC"; then + allow_undefined_flag=' $wl-expect_unresolved $wl\*' + archive_cmds='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp' + + # Both c and cxx compiler support -rpath directly + hardcode_libdir_flag_spec='-rpath $libdir' + fi + archive_cmds_need_lc='no' + hardcode_libdir_separator=: + ;; + + solaris*) + no_undefined_flag=' -z defs' + if test yes = "$GCC"; then + wlarc='$wl' + archive_cmds='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + else + case `$CC -V 2>&1` in + *"Compilers 5.0"*) + wlarc='' + archive_cmds='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' + ;; + *) + wlarc='$wl' + archive_cmds='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + ;; + esac + fi + hardcode_libdir_flag_spec='-R$libdir' + hardcode_shlibpath_var=no + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands '-z linker_flag'. GCC discards it without '$wl', + # but is careful enough not to reorder. + # Supported since Solaris 2.6 (maybe 2.5.1?) + if test yes = "$GCC"; then + whole_archive_flag_spec='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' + else + whole_archive_flag_spec='-z allextract$convenience -z defaultextract' + fi + ;; + esac + link_all_deplibs=yes + ;; + + sunos4*) + if test sequent = "$host_vendor"; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + archive_cmds='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + hardcode_libdir_flag_spec='-L$libdir' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + sysv4) + case $host_vendor in + sni) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' + reload_cmds='$CC -r -o $output$reload_objs' + hardcode_direct=no + ;; + motorola) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + hardcode_shlibpath_var=no + ;; + + sysv4.3*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + export_dynamic_flag_spec='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + ld_shlibs=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) + no_undefined_flag='$wl-z,text' + archive_cmds_need_lc=no + hardcode_shlibpath_var=no + runpath_var='LD_RUN_PATH' + + if test yes = "$GCC"; then + archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We CANNOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + no_undefined_flag='$wl-z,text' + allow_undefined_flag='$wl-z,nodefs' + archive_cmds_need_lc=no + hardcode_shlibpath_var=no + hardcode_libdir_flag_spec='$wl-R,$libdir' + hardcode_libdir_separator=':' + link_all_deplibs=yes + export_dynamic_flag_spec='$wl-Bexport' + runpath_var='LD_RUN_PATH' + + if test yes = "$GCC"; then + archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + *) + ld_shlibs=no + ;; + esac + + if test sni = "$host_vendor"; then + case $host in + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + export_dynamic_flag_spec='$wl-Blargedynsym' + ;; + esac + fi + fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5 +$as_echo "$ld_shlibs" >&6; } +test no = "$ld_shlibs" && can_build_shared=no + +with_gnu_ld=$with_gnu_ld + + + + + + + + + + + + + + + +# +# Do we need to explicitly link libc? +# +case "x$archive_cmds_need_lc" in +x|xyes) + # Assume -lc should be added + archive_cmds_need_lc=yes + + if test yes,yes = "$GCC,$enable_shared"; then + case $archive_cmds in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 +$as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } +if ${lt_cv_archive_cmds_need_lc+:} false; then : + $as_echo_n "(cached) " >&6 +else + $RM conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$lt_prog_compiler_wl + pic_flag=$lt_prog_compiler_pic + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$allow_undefined_flag + allow_undefined_flag= + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 + (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + then + lt_cv_archive_cmds_need_lc=no + else + lt_cv_archive_cmds_need_lc=yes + fi + allow_undefined_flag=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5 +$as_echo "$lt_cv_archive_cmds_need_lc" >&6; } + archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc + ;; + esac + fi + ;; +esac + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 +$as_echo_n "checking dynamic linker characteristics... " >&6; } + +if test yes = "$GCC"; then + case $host_os in + darwin*) lt_awk_arg='/^libraries:/,/LR/' ;; + *) lt_awk_arg='/^libraries:/' ;; + esac + case $host_os in + mingw* | cegcc*) lt_sed_strip_eq='s|=\([A-Za-z]:\)|\1|g' ;; + *) lt_sed_strip_eq='s|=/|/|g' ;; + esac + lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` + case $lt_search_path_spec in + *\;*) + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` + ;; + *) + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` + ;; + esac + # Ok, now we have the path, separated by spaces, we can step through it + # and add multilib dir if necessary... + lt_tmp_lt_search_path_spec= + lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + # ...but if some path component already ends with the multilib dir we assume + # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer). + case "$lt_multi_os_dir; $lt_search_path_spec " in + "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*) + lt_multi_os_dir= + ;; + esac + for lt_sys_path in $lt_search_path_spec; do + if test -d "$lt_sys_path$lt_multi_os_dir"; then + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir" + elif test -n "$lt_multi_os_dir"; then + test -d "$lt_sys_path" && \ + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" + fi + done + lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' +BEGIN {RS = " "; FS = "/|\n";} { + lt_foo = ""; + lt_count = 0; + for (lt_i = NF; lt_i > 0; lt_i--) { + if ($lt_i != "" && $lt_i != ".") { + if ($lt_i == "..") { + lt_count++; + } else { + if (lt_count == 0) { + lt_foo = "/" $lt_i lt_foo; + } else { + lt_count--; + } + } + } + } + if (lt_foo != "") { lt_freq[lt_foo]++; } + if (lt_freq[lt_foo] == 1) { print lt_foo; } +}'` + # AWK program above erroneously prepends '/' to C:/dos/paths + # for these hosts. + case $host_os in + mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ + $SED 's|/\([A-Za-z]:\)|\1|g'` ;; + esac + sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=.so +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + + + +case $host_os in +aix3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='$libname$release$shared_ext$major' + ;; + +aix[4-9]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test ia64 = "$host_cpu"; then + # AIX 5 supports IA64 + library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line '#! .'. This would cause the generated library to + # depend on '.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[01] | aix4.[01].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # Using Import Files as archive members, it is possible to support + # filename-based versioning of shared library archives on AIX. While + # this would work for both with and without runtime linking, it will + # prevent static linking of such archives. So we do filename-based + # shared library versioning with .so extension only, which is used + # when both runtime linking and shared linking is enabled. + # Unfortunately, runtime linking may impact performance, so we do + # not want this to be the default eventually. Also, we use the + # versioned .so libs for executables only if there is the -brtl + # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. + # To allow for filename-based versioning support, we need to create + # libNAME.so.V as an archive file, containing: + # *) an Import File, referring to the versioned filename of the + # archive as well as the shared archive member, telling the + # bitwidth (32 or 64) of that shared object, and providing the + # list of exported symbols of that shared object, eventually + # decorated with the 'weak' keyword + # *) the shared object with the F_LOADONLY flag set, to really avoid + # it being seen by the linker. + # At run time we better use the real file rather than another symlink, + # but for link time we create the symlink libNAME.so -> libNAME.so.V + + case $with_aix_soname,$aix_use_runtimelinking in + # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + aix,yes) # traditional libtool + dynamic_linker='AIX unversionable lib.so' + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + aix,no) # traditional AIX only + dynamic_linker='AIX lib.a(lib.so.V)' + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + ;; + svr4,*) # full svr4 only + dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o)" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,yes) # both, prefer svr4 + dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o), lib.a(lib.so.V)" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # unpreferred sharedlib libNAME.a needs extra handling + postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' + postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,no) # both, prefer aix + dynamic_linker="AIX lib.a(lib.so.V), lib.so.V($shared_archive_member_spec.o)" + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling + postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' + postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' + ;; + esac + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + case $host_cpu in + powerpc) + # Since July 2007 AmigaOS4 officially supports .so libraries. + # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + m68k) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + esac + ;; + +beos*) + library_names_spec='$libname$shared_ext' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[45]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32* | cegcc*) + version_type=windows + shrext_cmds=.dll + need_version=no + need_lib_prefix=no + + case $GCC,$cc_basename in + yes,*) + # gcc + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api" + ;; + mingw* | cegcc*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + ;; + esac + dynamic_linker='Win32 ld.exe' + ;; + + *,cl*) + # Native MSVC + libname_spec='$name' + soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + library_names_spec='$libname.dll.lib' + + case $build_os in + mingw*) + sys_lib_search_path_spec= + lt_save_ifs=$IFS + IFS=';' + for lt_path in $LIB + do + IFS=$lt_save_ifs + # Let DOS variable expansion print the short 8.3 style file name. + lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` + sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" + done + IFS=$lt_save_ifs + # Convert to MSYS style. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` + ;; + cygwin*) + # Convert to unix form, then to dos form, then back to unix form + # but this time dos style (no spaces!) so that the unix form looks + # like /cygdrive/c/PROGRA~1:/cygdr... + sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` + sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` + sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + ;; + *) + sys_lib_search_path_spec=$LIB + if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then + # It is most probably a Windows format PATH. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + # FIXME: find the short name or the path components, as spaces are + # common. (e.g. "Program Files" -> "PROGRA~1") + ;; + esac + + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + dynamic_linker='Win32 link.exe' + ;; + + *) + # Assume MSVC wrapper + library_names_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext $libname.lib' + dynamic_linker='Win32 ld.exe' + ;; + esac + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' + soname_spec='$libname$release$major$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' + + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib" + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[23].*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2.*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[01]* | freebsdelf3.[01]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ + freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +haiku*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + dynamic_linker="$host_os runtime_loader" + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LIBRARY_PATH + shlibpath_overrides_runpath=no + sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + if test 32 = "$HPUX_IA64_MODE"; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + sys_lib_dlsearch_path_spec=/usr/lib/hpux32 + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + sys_lib_dlsearch_path_spec=/usr/lib/hpux64 + fi + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555, ... + postinstall_cmds='chmod 555 $lib' + # or fails outright, so override atomically: + install_override_mode=555 + ;; + +interix[3-9]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test yes = "$lt_cv_prog_gnu_ld"; then + version_type=linux # correct to gnu/linux during the next big refactor + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" + sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +linux*android*) + version_type=none # Android doesn't support versioned libraries. + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext' + soname_spec='$libname$release$shared_ext' + finish_cmds= + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + dynamic_linker='Android linker' + # Don't embed -rpath directories since the linker doesn't support them. + hardcode_libdir_flag_spec='-L$libdir' + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + + # Some binutils ld are patched to set DT_RUNPATH + if ${lt_cv_shlibpath_overrides_runpath+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_shlibpath_overrides_runpath=no + save_LDFLAGS=$LDFLAGS + save_libdir=$libdir + eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \ + LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\"" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : + lt_cv_shlibpath_overrides_runpath=yes +fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$save_LDFLAGS + libdir=$save_libdir + +fi + + shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Ideally, we could use ldconfig to report *all* directores which are + # searched for libraries, however this is still not possible. Aside from not + # being certain /sbin/ldconfig is available, command + # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, + # even though it is searched at run-time. Try to do the best guess by + # appending ld.so.conf contents (and includes) to the search path. + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsdelf*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='NetBSD ld.elf_so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +*nto* | *qnx*) + version_type=qnx + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='ldqnx.so' + ;; + +openbsd* | bitrig*) + version_type=sunos + sys_lib_dlsearch_path_spec=/usr/lib + need_lib_prefix=no + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + need_version=no + else + need_version=yes + fi + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +os2*) + libname_spec='$name' + version_type=windows + shrext_cmds=.dll + need_version=no + need_lib_prefix=no + # OS/2 can only load a DLL with a base name of 8 characters or less. + soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; + v=$($ECHO $release$versuffix | tr -d .-); + n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); + $ECHO $n$v`$shared_ext' + library_names_spec='${libname}_dll.$libext' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=BEGINLIBPATH + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + +rdos*) + dynamic_linker=no + ;; + +solaris*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test yes = "$with_gnu_ld"; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec; then + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' + soname_spec='$libname$shared_ext.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=sco + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + if test yes = "$with_gnu_ld"; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +tpf*) + # TPF is a cross-target only. Preferred cross-host = GNU/Linux. + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +uts4*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 +$as_echo "$dynamic_linker" >&6; } +test no = "$dynamic_linker" && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test yes = "$GCC"; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then + sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec +fi + +if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then + sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec +fi + +# remember unaugmented sys_lib_dlsearch_path content for libtool script decls... +configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec + +# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code +func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" + +# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool +configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 +$as_echo_n "checking how to hardcode library paths into programs... " >&6; } +hardcode_action= +if test -n "$hardcode_libdir_flag_spec" || + test -n "$runpath_var" || + test yes = "$hardcode_automatic"; then + + # We can hardcode non-existent directories. + if test no != "$hardcode_direct" && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, )" && + test no != "$hardcode_minus_L"; then + # Linking always hardcodes the temporary library directory. + hardcode_action=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + hardcode_action=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + hardcode_action=unsupported +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5 +$as_echo "$hardcode_action" >&6; } + +if test relink = "$hardcode_action" || + test yes = "$inherit_rpath"; then + # Fast installation is not supported + enable_fast_install=no +elif test yes = "$shlibpath_overrides_runpath" || + test no = "$enable_shared"; then + # Fast installation is not necessary + enable_fast_install=needless +fi + + + + + + + if test yes != "$enable_dlopen"; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen=load_add_on + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32* | cegcc*) + lt_cv_dlopen=LoadLibrary + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen=dlopen + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 +$as_echo_n "checking for dlopen in -ldl... " >&6; } +if ${ac_cv_lib_dl_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $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 dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dl_dlopen=yes +else + ac_cv_lib_dl_dlopen=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_dl_dlopen" >&5 +$as_echo "$ac_cv_lib_dl_dlopen" >&6; } +if test "x$ac_cv_lib_dl_dlopen" = xyes; then : + lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl +else + + lt_cv_dlopen=dyld + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + +fi + + ;; + + tpf*) + # Don't try to run any link tests for TPF. We know it's impossible + # because TPF is a cross-compiler, and we know how we open DSOs. + lt_cv_dlopen=dlopen + lt_cv_dlopen_libs= + lt_cv_dlopen_self=no + ;; + + *) + ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load" +if test "x$ac_cv_func_shl_load" = xyes; then : + lt_cv_dlopen=shl_load +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 +$as_echo_n "checking for shl_load in -ldld... " >&6; } +if ${ac_cv_lib_dld_shl_load+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $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 shl_load (); +int +main () +{ +return shl_load (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dld_shl_load=yes +else + ac_cv_lib_dld_shl_load=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_dld_shl_load" >&5 +$as_echo "$ac_cv_lib_dld_shl_load" >&6; } +if test "x$ac_cv_lib_dld_shl_load" = xyes; then : + lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld +else + ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" +if test "x$ac_cv_func_dlopen" = xyes; then : + lt_cv_dlopen=dlopen +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 +$as_echo_n "checking for dlopen in -ldl... " >&6; } +if ${ac_cv_lib_dl_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $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 dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dl_dlopen=yes +else + ac_cv_lib_dl_dlopen=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_dl_dlopen" >&5 +$as_echo "$ac_cv_lib_dl_dlopen" >&6; } +if test "x$ac_cv_lib_dl_dlopen" = xyes; then : + lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5 +$as_echo_n "checking for dlopen in -lsvld... " >&6; } +if ${ac_cv_lib_svld_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsvld $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 dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_svld_dlopen=yes +else + ac_cv_lib_svld_dlopen=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_svld_dlopen" >&5 +$as_echo "$ac_cv_lib_svld_dlopen" >&6; } +if test "x$ac_cv_lib_svld_dlopen" = xyes; then : + lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5 +$as_echo_n "checking for dld_link in -ldld... " >&6; } +if ${ac_cv_lib_dld_dld_link+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $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 dld_link (); +int +main () +{ +return dld_link (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dld_dld_link=yes +else + ac_cv_lib_dld_dld_link=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_dld_dld_link" >&5 +$as_echo "$ac_cv_lib_dld_dld_link" >&6; } +if test "x$ac_cv_lib_dld_dld_link" = xyes; then : + lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld +fi + + +fi + + +fi + + +fi + + +fi + + +fi + + ;; + esac + + if test no = "$lt_cv_dlopen"; then + enable_dlopen=no + else + enable_dlopen=yes + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS=$CPPFLAGS + test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS=$LDFLAGS + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS=$LIBS + LIBS="$lt_cv_dlopen_libs $LIBS" + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5 +$as_echo_n "checking whether a program can dlopen itself... " >&6; } +if ${lt_cv_dlopen_self+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test yes = "$cross_compiling"; then : + lt_cv_dlopen_self=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisibility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +} +_LT_EOF + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then + (./conftest; exit; ) >&5 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; + x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; + x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;; + esac + else : + # compilation failed + lt_cv_dlopen_self=no + fi +fi +rm -fr conftest* + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5 +$as_echo "$lt_cv_dlopen_self" >&6; } + + if test yes = "$lt_cv_dlopen_self"; then + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5 +$as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; } +if ${lt_cv_dlopen_self_static+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test yes = "$cross_compiling"; then : + lt_cv_dlopen_self_static=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisibility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +} +_LT_EOF + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then + (./conftest; exit; ) >&5 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; + x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; + x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;; + esac + else : + # compilation failed + lt_cv_dlopen_self_static=no + fi +fi +rm -fr conftest* + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5 +$as_echo "$lt_cv_dlopen_self_static" >&6; } + fi + + CPPFLAGS=$save_CPPFLAGS + LDFLAGS=$save_LDFLAGS + LIBS=$save_LIBS + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi + + + + + + + + + + + + + + + + + +striplib= +old_striplib= +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5 +$as_echo_n "checking whether stripping libraries is possible... " >&6; } +if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP"; then + striplib="$STRIP -x" + old_striplib="$STRIP -S" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + fi + ;; + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + ;; + esac +fi + + + + + + + + + + + + + # Report what library types will actually be built + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5 +$as_echo_n "checking if libtool supports shared libraries... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5 +$as_echo "$can_build_shared" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5 +$as_echo_n "checking whether to build shared libraries... " >&6; } + test no = "$can_build_shared" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test yes = "$enable_shared" && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + + aix[4-9]*) + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac + fi + ;; + esac + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5 +$as_echo "$enable_shared" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 +$as_echo_n "checking whether to build static libraries... " >&6; } + # Make sure either enable_shared or enable_static is yes. + test yes = "$enable_shared" || enable_static=yes + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5 +$as_echo "$enable_static" >&6; } + + + + +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 + +CC=$lt_save_CC + + + + + + + + + + + + + + + + ac_config_commands="$ac_config_commands libtool" + + + + +# Only expand once: + + + + +GLIB_REQUIRED=2.38.0 +# Check whether --enable-glibtest was given. +if test "${enable_glibtest+set}" = set; then : + enableval=$enable_glibtest; +else + enable_glibtest=yes +fi + + + pkg_config_args=glib-2.0 + for module in . gobject gio + do + case "$module" in + gmodule) + pkg_config_args="$pkg_config_args gmodule-2.0" + ;; + gmodule-no-export) + pkg_config_args="$pkg_config_args gmodule-no-export-2.0" + ;; + gobject) + pkg_config_args="$pkg_config_args gobject-2.0" + ;; + gthread) + pkg_config_args="$pkg_config_args gthread-2.0" + ;; + gio*) + pkg_config_args="$pkg_config_args $module-2.0" + ;; + esac + done + + + + + + + + +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. +set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_PKG_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $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 + + ;; +esac +fi +PKG_CONFIG=$ac_cv_path_PKG_CONFIG +if test -n "$PKG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 +$as_echo "$PKG_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_path_PKG_CONFIG"; then + ac_pt_PKG_CONFIG=$PKG_CONFIG + # Extract the first word of "pkg-config", so it can be a program name with args. +set dummy pkg-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $ac_pt_PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $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 + + ;; +esac +fi +ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG +if test -n "$ac_pt_PKG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5 +$as_echo "$ac_pt_PKG_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_pt_PKG_CONFIG" = x; then + PKG_CONFIG="" + 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 + PKG_CONFIG=$ac_pt_PKG_CONFIG + fi +else + PKG_CONFIG="$ac_cv_path_PKG_CONFIG" +fi + +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=0.16 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5 +$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; } + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + PKG_CONFIG="" + fi +fi + + no_glib="" + + if test "x$PKG_CONFIG" = x ; then + no_glib=yes + PKG_CONFIG=no + fi + + min_glib_version=$GLIB_REQUIRED + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GLIB - version >= $min_glib_version" >&5 +$as_echo_n "checking for GLIB - version >= $min_glib_version... " >&6; } + + if test x$PKG_CONFIG != xno ; then + ## don't try to run the test against uninstalled libtool libs + if $PKG_CONFIG --uninstalled $pkg_config_args; then + echo "Will use uninstalled version of GLib found in PKG_CONFIG_PATH" + enable_glibtest=no + fi + + if $PKG_CONFIG --atleast-version $min_glib_version $pkg_config_args; then + : + else + no_glib=yes + fi + fi + + if test x"$no_glib" = x ; then + GLIB_GENMARSHAL=`$PKG_CONFIG --variable=glib_genmarshal glib-2.0` + GOBJECT_QUERY=`$PKG_CONFIG --variable=gobject_query glib-2.0` + GLIB_MKENUMS=`$PKG_CONFIG --variable=glib_mkenums glib-2.0` + GLIB_COMPILE_RESOURCES=`$PKG_CONFIG --variable=glib_compile_resources gio-2.0` + + GLIB_CFLAGS=`$PKG_CONFIG --cflags $pkg_config_args` + GLIB_LIBS=`$PKG_CONFIG --libs $pkg_config_args` + glib_config_major_version=`$PKG_CONFIG --modversion glib-2.0 | \ + sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\1/'` + glib_config_minor_version=`$PKG_CONFIG --modversion glib-2.0 | \ + sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\2/'` + glib_config_micro_version=`$PKG_CONFIG --modversion glib-2.0 | \ + sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\3/'` + if test "x$enable_glibtest" = "xyes" ; then + ac_save_CFLAGS="$CFLAGS" + ac_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $GLIB_CFLAGS" + LIBS="$GLIB_LIBS $LIBS" + rm -f conf.glibtest + if test "$cross_compiling" = yes; then : + echo $ac_n "cross compiling; assumed OK... $ac_c" +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include +#include + +int +main (void) +{ + unsigned int major, minor, micro; + + fclose (fopen ("conf.glibtest", "w")); + + if (sscanf("$min_glib_version", "%u.%u.%u", &major, &minor, µ) != 3) { + printf("%s, bad version string\n", "$min_glib_version"); + exit(1); + } + + if ((glib_major_version != $glib_config_major_version) || + (glib_minor_version != $glib_config_minor_version) || + (glib_micro_version != $glib_config_micro_version)) + { + printf("\n*** 'pkg-config --modversion glib-2.0' returned %d.%d.%d, but GLIB (%d.%d.%d)\n", + $glib_config_major_version, $glib_config_minor_version, $glib_config_micro_version, + glib_major_version, glib_minor_version, glib_micro_version); + printf ("*** was found! If pkg-config was correct, then it is best\n"); + printf ("*** to remove the old version of GLib. You may also be able to fix the error\n"); + printf("*** by modifying your LD_LIBRARY_PATH enviroment variable, or by editing\n"); + printf("*** /etc/ld.so.conf. Make sure you have run ldconfig if that is\n"); + printf("*** required on your system.\n"); + printf("*** If pkg-config was wrong, set the environment variable PKG_CONFIG_PATH\n"); + printf("*** to point to the correct configuration files\n"); + } + else if ((glib_major_version != GLIB_MAJOR_VERSION) || + (glib_minor_version != GLIB_MINOR_VERSION) || + (glib_micro_version != GLIB_MICRO_VERSION)) + { + printf("*** GLIB header files (version %d.%d.%d) do not match\n", + GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION, GLIB_MICRO_VERSION); + printf("*** library (version %d.%d.%d)\n", + glib_major_version, glib_minor_version, glib_micro_version); + } + else + { + if ((glib_major_version > major) || + ((glib_major_version == major) && (glib_minor_version > minor)) || + ((glib_major_version == major) && (glib_minor_version == minor) && (glib_micro_version >= micro))) + { + return 0; + } + else + { + printf("\n*** An old version of GLIB (%u.%u.%u) was found.\n", + glib_major_version, glib_minor_version, glib_micro_version); + printf("*** You need a version of GLIB newer than %u.%u.%u. The latest version of\n", + major, minor, micro); + printf("*** GLIB is always available from ftp://ftp.gtk.org.\n"); + printf("***\n"); + printf("*** If you have already installed a sufficiently new version, this error\n"); + printf("*** probably means that the wrong copy of the pkg-config shell script is\n"); + printf("*** being found. The easiest way to fix this is to remove the old version\n"); + printf("*** of GLIB, but you can also set the PKG_CONFIG environment to point to the\n"); + printf("*** correct copy of pkg-config. (In this case, you will have to\n"); + printf("*** modify your LD_LIBRARY_PATH enviroment variable, or edit /etc/ld.so.conf\n"); + printf("*** so that the correct libraries are found at run-time))\n"); + } + } + return 1; +} + +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + no_glib=yes +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + fi + fi + if test "x$no_glib" = x ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes (version $glib_config_major_version.$glib_config_minor_version.$glib_config_micro_version)" >&5 +$as_echo "yes (version $glib_config_major_version.$glib_config_minor_version.$glib_config_micro_version)" >&6; } + : + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + if test "$PKG_CONFIG" = "no" ; then + echo "*** A new enough version of pkg-config was not found." + echo "*** See http://www.freedesktop.org/software/pkgconfig/" + else + if test -f conf.glibtest ; then + : + else + echo "*** Could not run GLIB test program, checking why..." + ac_save_CFLAGS="$CFLAGS" + ac_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $GLIB_CFLAGS" + LIBS="$LIBS $GLIB_LIBS" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include + +int +main () +{ + return ((glib_major_version) || (glib_minor_version) || (glib_micro_version)); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + echo "*** The test program compiled, but did not run. This usually means" + echo "*** that the run-time linker is not finding GLIB or finding the wrong" + echo "*** version of GLIB. If it is not finding GLIB, you'll need to set your" + echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" + echo "*** to the installed location Also, make sure you have run ldconfig if that" + echo "*** is required on your system" + echo "***" + echo "*** If you have an old version installed, it is best to remove it, although" + echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH" +else + echo "*** The test program failed to compile or link. See the file config.log for the" + echo "*** exact error that occured. This usually means GLIB is incorrectly installed." +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + fi + fi + GLIB_CFLAGS="" + GLIB_LIBS="" + GLIB_GENMARSHAL="" + GOBJECT_QUERY="" + GLIB_MKENUMS="" + GLIB_COMPILE_RESOURCES="" + : + fi + + + + + + + rm -f conf.glibtest + +if test "$GLIB_LIBS" = ""; then + as_fn_error $? "GLIB $GLIB_REQUIRED or later is required to build libsoup" "$LINENO" 5 +fi +GLIB_CFLAGS="$GLIB_CFLAGS -DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_2_38" + +GLIB_MAKEFILE='$(top_srcdir)/Makefile.glib' + + + + # Check whether --enable-installed-tests was given. +if test "${enable_installed_tests+set}" = set; then : + enableval=$enable_installed_tests; case ${enableval} in + yes) ENABLE_INSTALLED_TESTS="1" ;; + no) ENABLE_INSTALLED_TESTS="" ;; + *) as_fn_error $? "bad value ${enableval} for --enable-installed-tests" "$LINENO" 5 ;; + esac +fi + + if test "$ENABLE_INSTALLED_TESTS" = "1"; then + ENABLE_INSTALLED_TESTS_TRUE= + ENABLE_INSTALLED_TESTS_FALSE='#' +else + ENABLE_INSTALLED_TESTS_TRUE='#' + ENABLE_INSTALLED_TESTS_FALSE= +fi + + # Check whether --enable-always-build-tests was given. +if test "${enable_always_build_tests+set}" = set; then : + enableval=$enable_always_build_tests; case ${enableval} in + yes) ENABLE_ALWAYS_BUILD_TESTS="1" ;; + no) ENABLE_ALWAYS_BUILD_TESTS="" ;; + *) as_fn_error $? "bad value ${enableval} for --enable-always-build-tests" "$LINENO" 5 ;; + esac +fi + + if test "$ENABLE_ALWAYS_BUILD_TESTS" = "1"; then + ENABLE_ALWAYS_BUILD_TESTS_TRUE= + ENABLE_ALWAYS_BUILD_TESTS_FALSE='#' +else + ENABLE_ALWAYS_BUILD_TESTS_TRUE='#' + ENABLE_ALWAYS_BUILD_TESTS_FALSE= +fi + + if test "$ENABLE_INSTALLED_TESTS" = "1"; then + installed_test_metadir=${datadir}/installed-tests/libsoup + + installed_testdir=${libexecdir}/installed-tests/libsoup + + fi + + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for XML" >&5 +$as_echo_n "checking for XML... " >&6; } + +if test -n "$XML_CFLAGS"; then + pkg_cv_XML_CFLAGS="$XML_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libxml-2.0\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libxml-2.0") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_XML_CFLAGS=`$PKG_CONFIG --cflags "libxml-2.0" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$XML_LIBS"; then + pkg_cv_XML_LIBS="$XML_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libxml-2.0\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libxml-2.0") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_XML_LIBS=`$PKG_CONFIG --libs "libxml-2.0" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + XML_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libxml-2.0" 2>&1` + else + XML_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libxml-2.0" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$XML_PKG_ERRORS" >&5 + + as_fn_error $? "Package requirements (libxml-2.0) were not met: + +$XML_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +Alternatively, you may set the environment variables XML_CFLAGS +and XML_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details." "$LINENO" 5 +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +Alternatively, you may set the environment variables XML_CFLAGS +and XML_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details. + +To get pkg-config, see . +See \`config.log' for more details" "$LINENO" 5; } +else + XML_CFLAGS=$pkg_cv_XML_CFLAGS + XML_LIBS=$pkg_cv_XML_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +fi + + + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for SQLITE" >&5 +$as_echo_n "checking for SQLITE... " >&6; } + +if test -n "$SQLITE_CFLAGS"; then + pkg_cv_SQLITE_CFLAGS="$SQLITE_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"sqlite3\""; } >&5 + ($PKG_CONFIG --exists --print-errors "sqlite3") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_SQLITE_CFLAGS=`$PKG_CONFIG --cflags "sqlite3" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$SQLITE_LIBS"; then + pkg_cv_SQLITE_LIBS="$SQLITE_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"sqlite3\""; } >&5 + ($PKG_CONFIG --exists --print-errors "sqlite3") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_SQLITE_LIBS=`$PKG_CONFIG --libs "sqlite3" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + SQLITE_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "sqlite3" 2>&1` + else + SQLITE_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "sqlite3" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$SQLITE_PKG_ERRORS" >&5 + + as_fn_error $? "Package requirements (sqlite3) were not met: + +$SQLITE_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +Alternatively, you may set the environment variables SQLITE_CFLAGS +and SQLITE_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details." "$LINENO" 5 +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +Alternatively, you may set the environment variables SQLITE_CFLAGS +and SQLITE_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details. + +To get pkg-config, see . +See \`config.log' for more details" "$LINENO" 5; } +else + SQLITE_CFLAGS=$pkg_cv_SQLITE_CFLAGS + SQLITE_LIBS=$pkg_cv_SQLITE_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +fi + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for Win32" >&5 +$as_echo_n "checking for Win32... " >&6; } +case "$host" in + *-*-mingw*) + os_win32=yes + os_linux=yes + CFLAGS="$CFLAGS -D_REENTRANT" + ;; + *-*-linux*) + os_win32=no + os_linux=yes + ;; + *) + os_win32=no + os_linux=no + ;; +esac +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $os_win32" >&5 +$as_echo "$os_win32" >&6; } + if test $os_win32 = yes; then + OS_WIN32_TRUE= + OS_WIN32_FALSE='#' +else + OS_WIN32_TRUE='#' + OS_WIN32_FALSE= +fi + + if test $os_linux = yes; then + OS_LINUX_TRUE= + OS_LINUX_FALSE='#' +else + OS_LINUX_TRUE='#' + OS_LINUX_FALSE= +fi + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether NLS is requested" >&5 +$as_echo_n "checking whether NLS is requested... " >&6; } + # Check whether --enable-nls was given. +if test "${enable_nls+set}" = set; then : + enableval=$enable_nls; USE_NLS=$enableval +else + USE_NLS=yes +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_NLS" >&5 +$as_echo "$USE_NLS" >&6; } + + + + +case "$am__api_version" in + 1.01234) + as_fn_error $? "Automake 1.5 or newer is required to use intltool" "$LINENO" 5 + ;; + *) + ;; +esac + +INTLTOOL_REQUIRED_VERSION_AS_INT=`echo 0.35.0 | awk -F. '{ print $ 1 * 1000 + $ 2 * 100 + $ 3; }'` +INTLTOOL_APPLIED_VERSION=`intltool-update --version | head -1 | cut -d" " -f3` +INTLTOOL_APPLIED_VERSION_AS_INT=`echo $INTLTOOL_APPLIED_VERSION | awk -F. '{ print $ 1 * 1000 + $ 2 * 100 + $ 3; }'` +if test -n "0.35.0"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for intltool >= 0.35.0" >&5 +$as_echo_n "checking for intltool >= 0.35.0... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $INTLTOOL_APPLIED_VERSION found" >&5 +$as_echo "$INTLTOOL_APPLIED_VERSION found" >&6; } + test "$INTLTOOL_APPLIED_VERSION_AS_INT" -ge "$INTLTOOL_REQUIRED_VERSION_AS_INT" || + as_fn_error $? "Your intltool is too old. You need intltool 0.35.0 or later." "$LINENO" 5 +fi + +# Extract the first word of "intltool-update", so it can be a program name with args. +set dummy intltool-update; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_INTLTOOL_UPDATE+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $INTLTOOL_UPDATE in + [\\/]* | ?:[\\/]*) + ac_cv_path_INTLTOOL_UPDATE="$INTLTOOL_UPDATE" # Let the user override the test with a path. + ;; + *) + 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_INTLTOOL_UPDATE="$as_dir/$ac_word$ac_exec_ext" + $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 + + ;; +esac +fi +INTLTOOL_UPDATE=$ac_cv_path_INTLTOOL_UPDATE +if test -n "$INTLTOOL_UPDATE"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $INTLTOOL_UPDATE" >&5 +$as_echo "$INTLTOOL_UPDATE" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +# Extract the first word of "intltool-merge", so it can be a program name with args. +set dummy intltool-merge; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_INTLTOOL_MERGE+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $INTLTOOL_MERGE in + [\\/]* | ?:[\\/]*) + ac_cv_path_INTLTOOL_MERGE="$INTLTOOL_MERGE" # Let the user override the test with a path. + ;; + *) + 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_INTLTOOL_MERGE="$as_dir/$ac_word$ac_exec_ext" + $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 + + ;; +esac +fi +INTLTOOL_MERGE=$ac_cv_path_INTLTOOL_MERGE +if test -n "$INTLTOOL_MERGE"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $INTLTOOL_MERGE" >&5 +$as_echo "$INTLTOOL_MERGE" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +# Extract the first word of "intltool-extract", so it can be a program name with args. +set dummy intltool-extract; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_INTLTOOL_EXTRACT+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $INTLTOOL_EXTRACT in + [\\/]* | ?:[\\/]*) + ac_cv_path_INTLTOOL_EXTRACT="$INTLTOOL_EXTRACT" # Let the user override the test with a path. + ;; + *) + 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_INTLTOOL_EXTRACT="$as_dir/$ac_word$ac_exec_ext" + $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 + + ;; +esac +fi +INTLTOOL_EXTRACT=$ac_cv_path_INTLTOOL_EXTRACT +if test -n "$INTLTOOL_EXTRACT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $INTLTOOL_EXTRACT" >&5 +$as_echo "$INTLTOOL_EXTRACT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +if test -z "$INTLTOOL_UPDATE" -o -z "$INTLTOOL_MERGE" -o -z "$INTLTOOL_EXTRACT"; then + as_fn_error $? "The intltool scripts were not found. Please install intltool." "$LINENO" 5 +fi + +if test -z "$AM_DEFAULT_VERBOSITY"; then + AM_DEFAULT_VERBOSITY=1 +fi + + +INTLTOOL_V_MERGE='$(INTLTOOL__v_MERGE_$(V))' +INTLTOOL__v_MERGE_='$(INTLTOOL__v_MERGE_$(AM_DEFAULT_VERBOSITY))' +INTLTOOL__v_MERGE_0='@echo " ITMRG " $@;' + + + + +INTLTOOL_V_MERGE_OPTIONS='$(intltool__v_merge_options_$(V))' +intltool__v_merge_options_='$(intltool__v_merge_options_$(AM_DEFAULT_VERBOSITY))' +intltool__v_merge_options_0='-q' + + + + + INTLTOOL_DESKTOP_RULE='%.desktop: %.desktop.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@' +INTLTOOL_DIRECTORY_RULE='%.directory: %.directory.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@' + INTLTOOL_KEYS_RULE='%.keys: %.keys.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -k -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@' + INTLTOOL_PROP_RULE='%.prop: %.prop.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@' + INTLTOOL_OAF_RULE='%.oaf: %.oaf.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -o -p $(top_srcdir)/po $< $@' + INTLTOOL_PONG_RULE='%.pong: %.pong.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@' + INTLTOOL_SERVER_RULE='%.server: %.server.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -o -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@' + INTLTOOL_SHEET_RULE='%.sheet: %.sheet.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@' +INTLTOOL_SOUNDLIST_RULE='%.soundlist: %.soundlist.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@' + INTLTOOL_UI_RULE='%.ui: %.ui.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@' + INTLTOOL_XML_RULE='%.xml: %.xml.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@' +if test "$INTLTOOL_APPLIED_VERSION_AS_INT" -ge 5000; then + INTLTOOL_XML_NOMERGE_RULE='%.xml: %.xml.in $(INTLTOOL_MERGE) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u --no-translations $< $@' +else + INTLTOOL_XML_NOMERGE_RULE='%.xml: %.xml.in $(INTLTOOL_MERGE) ; $(INTLTOOL_V_MERGE)_it_tmp_dir=tmp.intltool.$$RANDOM && mkdir $$_it_tmp_dir && LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u $$_it_tmp_dir $< $@ && rmdir $$_it_tmp_dir' +fi + INTLTOOL_XAM_RULE='%.xam: %.xml.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@' + INTLTOOL_KBD_RULE='%.kbd: %.kbd.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u -m -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@' + INTLTOOL_CAVES_RULE='%.caves: %.caves.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@' + INTLTOOL_SCHEMAS_RULE='%.schemas: %.schemas.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -s -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@' + INTLTOOL_THEME_RULE='%.theme: %.theme.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@' + INTLTOOL_SERVICE_RULE='%.service: %.service.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@' + INTLTOOL_POLICY_RULE='%.policy: %.policy.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +# Check the gettext tools to make sure they are GNU +# Extract the first word of "xgettext", so it can be a program name with args. +set dummy xgettext; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_XGETTEXT+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $XGETTEXT in + [\\/]* | ?:[\\/]*) + ac_cv_path_XGETTEXT="$XGETTEXT" # Let the user override the test with a path. + ;; + *) + 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_XGETTEXT="$as_dir/$ac_word$ac_exec_ext" + $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 + + ;; +esac +fi +XGETTEXT=$ac_cv_path_XGETTEXT +if test -n "$XGETTEXT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $XGETTEXT" >&5 +$as_echo "$XGETTEXT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +# Extract the first word of "msgmerge", so it can be a program name with args. +set dummy msgmerge; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_MSGMERGE+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $MSGMERGE in + [\\/]* | ?:[\\/]*) + ac_cv_path_MSGMERGE="$MSGMERGE" # Let the user override the test with a path. + ;; + *) + 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_MSGMERGE="$as_dir/$ac_word$ac_exec_ext" + $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 + + ;; +esac +fi +MSGMERGE=$ac_cv_path_MSGMERGE +if test -n "$MSGMERGE"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MSGMERGE" >&5 +$as_echo "$MSGMERGE" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +# Extract the first word of "msgfmt", so it can be a program name with args. +set dummy msgfmt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_MSGFMT+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $MSGFMT in + [\\/]* | ?:[\\/]*) + ac_cv_path_MSGFMT="$MSGFMT" # Let the user override the test with a path. + ;; + *) + 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_MSGFMT="$as_dir/$ac_word$ac_exec_ext" + $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 + + ;; +esac +fi +MSGFMT=$ac_cv_path_MSGFMT +if test -n "$MSGFMT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MSGFMT" >&5 +$as_echo "$MSGFMT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +# Extract the first word of "gmsgfmt", so it can be a program name with args. +set dummy gmsgfmt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_GMSGFMT+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $GMSGFMT in + [\\/]* | ?:[\\/]*) + ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a path. + ;; + *) + 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_GMSGFMT="$as_dir/$ac_word$ac_exec_ext" + $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_path_GMSGFMT" && ac_cv_path_GMSGFMT="$MSGFMT" + ;; +esac +fi +GMSGFMT=$ac_cv_path_GMSGFMT +if test -n "$GMSGFMT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GMSGFMT" >&5 +$as_echo "$GMSGFMT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +if test -z "$XGETTEXT" -o -z "$MSGMERGE" -o -z "$MSGFMT"; then + as_fn_error $? "GNU gettext tools not found; required for intltool" "$LINENO" 5 +fi +xgversion="`$XGETTEXT --version|grep '(GNU ' 2> /dev/null`" +mmversion="`$MSGMERGE --version|grep '(GNU ' 2> /dev/null`" +mfversion="`$MSGFMT --version|grep '(GNU ' 2> /dev/null`" +if test -z "$xgversion" -o -z "$mmversion" -o -z "$mfversion"; then + as_fn_error $? "GNU gettext tools not found; required for intltool" "$LINENO" 5 +fi + +# Extract the first word of "perl", so it can be a program name with args. +set dummy perl; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_INTLTOOL_PERL+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $INTLTOOL_PERL in + [\\/]* | ?:[\\/]*) + ac_cv_path_INTLTOOL_PERL="$INTLTOOL_PERL" # Let the user override the test with a path. + ;; + *) + 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_INTLTOOL_PERL="$as_dir/$ac_word$ac_exec_ext" + $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 + + ;; +esac +fi +INTLTOOL_PERL=$ac_cv_path_INTLTOOL_PERL +if test -n "$INTLTOOL_PERL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $INTLTOOL_PERL" >&5 +$as_echo "$INTLTOOL_PERL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +if test -z "$INTLTOOL_PERL"; then + as_fn_error $? "perl not found" "$LINENO" 5 +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for perl >= 5.8.1" >&5 +$as_echo_n "checking for perl >= 5.8.1... " >&6; } +$INTLTOOL_PERL -e "use 5.8.1;" > /dev/null 2>&1 +if test $? -ne 0; then + as_fn_error $? "perl 5.8.1 is required for intltool" "$LINENO" 5 +else + IT_PERL_VERSION=`$INTLTOOL_PERL -e "printf '%vd', $^V"` + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $IT_PERL_VERSION" >&5 +$as_echo "$IT_PERL_VERSION" >&6; } +fi +if test "x" != "xno-xml"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for XML::Parser" >&5 +$as_echo_n "checking for XML::Parser... " >&6; } + if `$INTLTOOL_PERL -e "require XML::Parser" 2>/dev/null`; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 +$as_echo "ok" >&6; } + else + as_fn_error $? "XML::Parser perl module is required for intltool" "$LINENO" 5 + fi +fi + +# Substitute ALL_LINGUAS so we can use it in po/Makefile + + + + + +GETTEXT_PACKAGE=libsoup + + +cat >>confdefs.h <<_ACEOF +#define GETTEXT_PACKAGE "$GETTEXT_PACKAGE" +_ACEOF + + +for ac_func in gmtime_r +do : + ac_fn_c_check_func "$LINENO" "gmtime_r" "ac_cv_func_gmtime_r" +if test "x$ac_cv_func_gmtime_r" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_GMTIME_R 1 +_ACEOF + +fi +done + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build libsoup-gnome" >&5 +$as_echo_n "checking whether to build libsoup-gnome... " >&6; } + +# Check whether --with-gnome was given. +if test "${with_gnome+set}" = set; then : + withval=$with_gnome; : +else + if test $os_win32 = yes; then with_gnome=no; else with_gnome=yes; fi +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_gnome" >&5 +$as_echo "$with_gnome" >&6; } + + if test $with_gnome != no; then + BUILD_LIBSOUP_GNOME_TRUE= + BUILD_LIBSOUP_GNOME_FALSE='#' +else + BUILD_LIBSOUP_GNOME_TRUE='#' + BUILD_LIBSOUP_GNOME_FALSE= +fi + + +if test $with_gnome != no; then + +$as_echo "#define HAVE_GNOME 1" >>confdefs.h + +fi + + + +# gtkdocize greps for ^GTK_DOC_CHECK and parses it, so you need to have +# it on it's own line. + + + + + gtk_doc_requires="gtk-doc >= 1.20" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gtk-doc" >&5 +$as_echo_n "checking for gtk-doc... " >&6; } + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$gtk_doc_requires\""; } >&5 + ($PKG_CONFIG --exists --print-errors "$gtk_doc_requires") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + have_gtk_doc=yes +else + have_gtk_doc=no +fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_gtk_doc" >&5 +$as_echo "$have_gtk_doc" >&6; } + + if test "$have_gtk_doc" = "no"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: + You will not be able to create source packages with 'make dist' + because $gtk_doc_requires is not found." >&5 +$as_echo "$as_me: WARNING: + You will not be able to create source packages with 'make dist' + because $gtk_doc_requires is not found." >&2;} + fi + + # Extract the first word of "gtkdoc-check", so it can be a program name with args. +set dummy gtkdoc-check; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_GTKDOC_CHECK+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$GTKDOC_CHECK"; then + ac_cv_prog_GTKDOC_CHECK="$GTKDOC_CHECK" # 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_GTKDOC_CHECK="gtkdoc-check.test" + $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 +GTKDOC_CHECK=$ac_cv_prog_GTKDOC_CHECK +if test -n "$GTKDOC_CHECK"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GTKDOC_CHECK" >&5 +$as_echo "$GTKDOC_CHECK" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + # Extract the first word of "gtkdoc-check", so it can be a program name with args. +set dummy gtkdoc-check; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_GTKDOC_CHECK_PATH+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $GTKDOC_CHECK_PATH in + [\\/]* | ?:[\\/]*) + ac_cv_path_GTKDOC_CHECK_PATH="$GTKDOC_CHECK_PATH" # Let the user override the test with a path. + ;; + *) + 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_GTKDOC_CHECK_PATH="$as_dir/$ac_word$ac_exec_ext" + $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 + + ;; +esac +fi +GTKDOC_CHECK_PATH=$ac_cv_path_GTKDOC_CHECK_PATH +if test -n "$GTKDOC_CHECK_PATH"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GTKDOC_CHECK_PATH" >&5 +$as_echo "$GTKDOC_CHECK_PATH" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + for ac_prog in gtkdoc-rebase +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 ${ac_cv_path_GTKDOC_REBASE+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $GTKDOC_REBASE in + [\\/]* | ?:[\\/]*) + ac_cv_path_GTKDOC_REBASE="$GTKDOC_REBASE" # Let the user override the test with a path. + ;; + *) + 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_GTKDOC_REBASE="$as_dir/$ac_word$ac_exec_ext" + $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 + + ;; +esac +fi +GTKDOC_REBASE=$ac_cv_path_GTKDOC_REBASE +if test -n "$GTKDOC_REBASE"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GTKDOC_REBASE" >&5 +$as_echo "$GTKDOC_REBASE" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$GTKDOC_REBASE" && break +done +test -n "$GTKDOC_REBASE" || GTKDOC_REBASE="true" + + # Extract the first word of "gtkdoc-mkpdf", so it can be a program name with args. +set dummy gtkdoc-mkpdf; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_GTKDOC_MKPDF+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $GTKDOC_MKPDF in + [\\/]* | ?:[\\/]*) + ac_cv_path_GTKDOC_MKPDF="$GTKDOC_MKPDF" # Let the user override the test with a path. + ;; + *) + 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_GTKDOC_MKPDF="$as_dir/$ac_word$ac_exec_ext" + $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 + + ;; +esac +fi +GTKDOC_MKPDF=$ac_cv_path_GTKDOC_MKPDF +if test -n "$GTKDOC_MKPDF"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GTKDOC_MKPDF" >&5 +$as_echo "$GTKDOC_MKPDF" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + + +# Check whether --with-html-dir was given. +if test "${with_html_dir+set}" = set; then : + withval=$with_html_dir; +else + with_html_dir='${datadir}/gtk-doc/html' +fi + + HTML_DIR="$with_html_dir" + + + # Check whether --enable-gtk-doc was given. +if test "${enable_gtk_doc+set}" = set; then : + enableval=$enable_gtk_doc; +else + enable_gtk_doc=no +fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build gtk-doc documentation" >&5 +$as_echo_n "checking whether to build gtk-doc documentation... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_gtk_doc" >&5 +$as_echo "$enable_gtk_doc" >&6; } + + if test "x$enable_gtk_doc" = "xyes" && test "$have_gtk_doc" = "no"; then + as_fn_error $? " + You must have $gtk_doc_requires installed to build documentation for + $PACKAGE_NAME. Please install gtk-doc or disable building the + documentation by adding '--disable-gtk-doc' to '$0'." "$LINENO" 5 + fi + + if test "x$PACKAGE_NAME" != "xglib"; then + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GTKDOC_DEPS" >&5 +$as_echo_n "checking for GTKDOC_DEPS... " >&6; } + +if test -n "$GTKDOC_DEPS_CFLAGS"; then + pkg_cv_GTKDOC_DEPS_CFLAGS="$GTKDOC_DEPS_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"glib-2.0 >= 2.10.0 gobject-2.0 >= 2.10.0\""; } >&5 + ($PKG_CONFIG --exists --print-errors "glib-2.0 >= 2.10.0 gobject-2.0 >= 2.10.0") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_GTKDOC_DEPS_CFLAGS=`$PKG_CONFIG --cflags "glib-2.0 >= 2.10.0 gobject-2.0 >= 2.10.0" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$GTKDOC_DEPS_LIBS"; then + pkg_cv_GTKDOC_DEPS_LIBS="$GTKDOC_DEPS_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"glib-2.0 >= 2.10.0 gobject-2.0 >= 2.10.0\""; } >&5 + ($PKG_CONFIG --exists --print-errors "glib-2.0 >= 2.10.0 gobject-2.0 >= 2.10.0") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_GTKDOC_DEPS_LIBS=`$PKG_CONFIG --libs "glib-2.0 >= 2.10.0 gobject-2.0 >= 2.10.0" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + GTKDOC_DEPS_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "glib-2.0 >= 2.10.0 gobject-2.0 >= 2.10.0" 2>&1` + else + GTKDOC_DEPS_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "glib-2.0 >= 2.10.0 gobject-2.0 >= 2.10.0" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$GTKDOC_DEPS_PKG_ERRORS" >&5 + + : +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + : +else + GTKDOC_DEPS_CFLAGS=$pkg_cv_GTKDOC_DEPS_CFLAGS + GTKDOC_DEPS_LIBS=$pkg_cv_GTKDOC_DEPS_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +fi + fi + + # Check whether --enable-gtk-doc-html was given. +if test "${enable_gtk_doc_html+set}" = set; then : + enableval=$enable_gtk_doc_html; +else + enable_gtk_doc_html=yes +fi + + # Check whether --enable-gtk-doc-pdf was given. +if test "${enable_gtk_doc_pdf+set}" = set; then : + enableval=$enable_gtk_doc_pdf; +else + enable_gtk_doc_pdf=no +fi + + + if test -z "$GTKDOC_MKPDF"; then + enable_gtk_doc_pdf=no + fi + + if test -z "$AM_DEFAULT_VERBOSITY"; then + AM_DEFAULT_VERBOSITY=1 + fi + + + if test x$have_gtk_doc = xyes; then + HAVE_GTK_DOC_TRUE= + HAVE_GTK_DOC_FALSE='#' +else + HAVE_GTK_DOC_TRUE='#' + HAVE_GTK_DOC_FALSE= +fi + + if test x$enable_gtk_doc = xyes; then + ENABLE_GTK_DOC_TRUE= + ENABLE_GTK_DOC_FALSE='#' +else + ENABLE_GTK_DOC_TRUE='#' + ENABLE_GTK_DOC_FALSE= +fi + + if test x$enable_gtk_doc_html = xyes; then + GTK_DOC_BUILD_HTML_TRUE= + GTK_DOC_BUILD_HTML_FALSE='#' +else + GTK_DOC_BUILD_HTML_TRUE='#' + GTK_DOC_BUILD_HTML_FALSE= +fi + + if test x$enable_gtk_doc_pdf = xyes; then + GTK_DOC_BUILD_PDF_TRUE= + GTK_DOC_BUILD_PDF_FALSE='#' +else + GTK_DOC_BUILD_PDF_TRUE='#' + GTK_DOC_BUILD_PDF_FALSE= +fi + + if test -n "$LIBTOOL"; then + GTK_DOC_USE_LIBTOOL_TRUE= + GTK_DOC_USE_LIBTOOL_FALSE='#' +else + GTK_DOC_USE_LIBTOOL_TRUE='#' + GTK_DOC_USE_LIBTOOL_FALSE= +fi + + if test -n "$GTKDOC_REBASE"; then + GTK_DOC_USE_REBASE_TRUE= + GTK_DOC_USE_REBASE_FALSE='#' +else + GTK_DOC_USE_REBASE_TRUE='#' + GTK_DOC_USE_REBASE_FALSE= +fi + + + + + + + + # Check whether --enable-introspection was given. +if test "${enable_introspection+set}" = set; then : + enableval=$enable_introspection; +else + enable_introspection=auto +fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gobject-introspection" >&5 +$as_echo_n "checking for gobject-introspection... " >&6; } + + case $enable_introspection in #( + no) : + found_introspection="no (disabled, use --enable-introspection to enable)" + ;; #( + yes) : + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gobject-introspection-1.0\""; } >&5 + ($PKG_CONFIG --exists --print-errors "gobject-introspection-1.0") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + : +else + as_fn_error $? "gobject-introspection-1.0 is not installed" "$LINENO" 5 +fi + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gobject-introspection-1.0 >= 0.9.5\""; } >&5 + ($PKG_CONFIG --exists --print-errors "gobject-introspection-1.0 >= 0.9.5") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + found_introspection=yes +else + as_fn_error $? "You need to have gobject-introspection >= 0.9.5 installed to build libsoup" "$LINENO" 5 +fi + ;; #( + auto) : + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gobject-introspection-1.0 >= 0.9.5\""; } >&5 + ($PKG_CONFIG --exists --print-errors "gobject-introspection-1.0 >= 0.9.5") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + found_introspection=yes +else + found_introspection=no +fi + ;; #( + *) : + as_fn_error $? "invalid argument passed to --enable-introspection, should be one of [no/auto/yes]" "$LINENO" 5 + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $found_introspection" >&5 +$as_echo "$found_introspection" >&6; } + + INTROSPECTION_SCANNER= + INTROSPECTION_COMPILER= + INTROSPECTION_GENERATE= + INTROSPECTION_GIRDIR= + INTROSPECTION_TYPELIBDIR= + if test "x$found_introspection" = "xyes"; then + INTROSPECTION_SCANNER=`$PKG_CONFIG --variable=g_ir_scanner gobject-introspection-1.0` + INTROSPECTION_COMPILER=`$PKG_CONFIG --variable=g_ir_compiler gobject-introspection-1.0` + INTROSPECTION_GENERATE=`$PKG_CONFIG --variable=g_ir_generate gobject-introspection-1.0` + INTROSPECTION_GIRDIR=`$PKG_CONFIG --variable=girdir gobject-introspection-1.0` + INTROSPECTION_TYPELIBDIR="$($PKG_CONFIG --variable=typelibdir gobject-introspection-1.0)" + INTROSPECTION_CFLAGS=`$PKG_CONFIG --cflags gobject-introspection-1.0` + INTROSPECTION_LIBS=`$PKG_CONFIG --libs gobject-introspection-1.0` + INTROSPECTION_MAKEFILE=`$PKG_CONFIG --variable=datadir gobject-introspection-1.0`/gobject-introspection-1.0/Makefile.introspection + fi + + + + + + + + + + if test "x$found_introspection" = "xyes"; then + HAVE_INTROSPECTION_TRUE= + HAVE_INTROSPECTION_FALSE='#' +else + HAVE_INTROSPECTION_TRUE='#' + HAVE_INTROSPECTION_FALSE= +fi + + + + +if test "$found_introspection" != "yes" -a "$enable_vala" = ""; then + enable_vala=no +fi +# Extract the first word of "valac", so it can be a program name with args. +set dummy valac; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_VALAC+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $VALAC in + [\\/]* | ?:[\\/]*) + ac_cv_path_VALAC="$VALAC" # Let the user override the test with a path. + ;; + *) + 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_VALAC="$as_dir/$ac_word$ac_exec_ext" + $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_path_VALAC" && ac_cv_path_VALAC="valac" + ;; +esac +fi +VALAC=$ac_cv_path_VALAC +if test -n "$VALAC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $VALAC" >&5 +$as_echo "$VALAC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + if test "$VALAC" != valac && test -n ""; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $VALAC is at least version " >&5 +$as_echo_n "checking whether $VALAC is at least version ... " >&6; } + am__vala_version=`$VALAC --version | sed 's/Vala *//'` + as_arg_v1= +as_arg_v2="$am__vala_version" +awk "$as_awk_strverscmp" v1="$as_arg_v1" v2="$as_arg_v2" /dev/null +case $? in #( + 1) : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } ;; #( + 0) : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } ;; #( + 2) : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + VALAC=valac ;; #( + *) : + ;; +esac +fi + if test "$VALAC" = valac; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: no proper vala compiler found" >&5 +$as_echo "$as_me: WARNING: no proper vala compiler found" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: you will not be able to compile vala source files" >&5 +$as_echo "$as_me: WARNING: you will not be able to compile vala source files" >&2;} + else + : + fi + + + + + # Check whether --enable-vala was given. +if test "${enable_vala+set}" = set; then : + enableval=$enable_vala; +else + + if test "x" = "x"; then : + + enable_vala=auto + +else + + enable_vala= + +fi + +fi + + if test "x$enable_vala" = "xyes" -o "x$enable_vala" = "xauto"; then : + + if test "x" != "xyes" -a "x$found_introspection" != "xyes"; then : + + as_fn_error $? "Vala bindings require GObject Introspection" "$LINENO" 5 + +fi + +else + + if test "x$enable_vala" != "no"; then : + + vapigen_pkg_found=no + +else + + as_fn_error $? "Invalid argument passed to --enable-vala, should be one of [no/auto/yes]" "$LINENO" 5 + +fi + +fi + if test "x" = "x"; then : + + vapigen_pkg_name=vapigen + +else + + vapigen_pkg_name=vapigen- + +fi + if test "x" = "x"; then : + + vapigen_pkg="$vapigen_pkg_name" + +else + + vapigen_pkg="$vapigen_pkg_name >= " + +fi + if test "x$enable_vala" = "xyes" -o "x$enable_vala" = "xauto"; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for vapigen $vapigen_pkg_name" >&5 +$as_echo_n "checking for vapigen $vapigen_pkg_name... " >&6; } + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \" \$vapigen_pkg \""; } >&5 + ($PKG_CONFIG --exists --print-errors " $vapigen_pkg ") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + + vapigen_pkg_found=yes + +else + + vapigen_pkg_found=no + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: Searching for $vapigen_pkg_name program..." >&5 +$as_echo "$as_me: Searching for $vapigen_pkg_name program..." >&6;} + # Extract the first word of "$vapigen_pkg_name", so it can be a program name with args. +set dummy $vapigen_pkg_name; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_VAPIGEN+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $VAPIGEN in + [\\/]* | ?:[\\/]*) + ac_cv_path_VAPIGEN="$VAPIGEN" # Let the user override the test with a path. + ;; + *) + 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_VAPIGEN="$as_dir/$ac_word$ac_exec_ext" + $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_path_VAPIGEN" && ac_cv_path_VAPIGEN="no" + ;; +esac +fi +VAPIGEN=$ac_cv_path_VAPIGEN +if test -n "$VAPIGEN"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $VAPIGEN" >&5 +$as_echo "$VAPIGEN" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + if test "x$VAPIGEN" = "xno" + then + check_prog=no + else + check_prog=yes + fi + +fi + + case $vapigen_pkg_found in #( + yes) : + + VAPIGEN=`$PKG_CONFIG --variable=vapigen vapigen` + VAPIGEN_MAKEFILE=`$PKG_CONFIG --variable=datadir vapigen`/vala/Makefile.vapigen + VAPIDIR=`$PKG_CONFIG --variable=vapidir vapigen` + if test "x" = "x"; then : + + VAPIGEN_VAPIDIR=`$PKG_CONFIG --variable=vapidir vapigen` + +else + + VAPIGEN_VAPIDIR=`$PKG_CONFIG --variable=vapidir_versioned vapigen` + +fi + ;; #( + no) : + + case $check_prog in #( + no) : + + as_fn_error $? "Can't locate $vapigen_pkg program" "$LINENO" 5 + ;; #( + yes) : + + if test "x" = "x"; then : + + vala_pkg_name=libvala + +else + + vala_pkg_name=libvala- + +fi + if test "x" = "x"; then : + + vala_pkg="$vala_pkg_name" + +else + + vala_pkg="$vala_pkg_name >= " + +fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $vala_pkg" >&5 +$as_echo_n "checking for $vala_pkg... " >&6; } + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$vala_pkg\""; } >&5 + ($PKG_CONFIG --exists --print-errors "$vala_pkg") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + + VALA_DATADIR=`pkg-config $vala_pkg --variable=datadir` + VAPIDIR="$VALA_DATADIR/vala/vapi" + VAPIGEN_MAKEFILE="$VALA_DATADIR/vala/Makefile.vapigen" + if test "x" = "x"; then : + + VAPIGEN_VAPIDIR=`$PKG_CONFIG --variable=vapidir vapigen` + +else + + VAPIGEN_VAPIDIR=`$PKG_CONFIG --variable=vapidir_versioned vapigen` + +fi + vapigen_pkg_found=yes + +else + + case $enable_vala in #( + yes) : + + as_fn_error $? "$vala_pkg not found" "$LINENO" 5 + ;; #( + auto) : + + vapigen_pkg_found=no + ;; #( + *) : + ;; +esac + +fi + ;; #( + *) : + ;; +esac + ;; #( + *) : + ;; +esac + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $vapigen_pkg_found" >&5 +$as_echo "$vapigen_pkg_found" >&6; } + + + +fi + + + + + + if test "x$vapigen_pkg_found" = "xyes"; then + ENABLE_VAPIGEN_TRUE= + ENABLE_VAPIGEN_FALSE='#' +else + ENABLE_VAPIGEN_TRUE='#' + ENABLE_VAPIGEN_FALSE= +fi + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for glib-networking (glib TLS implementation)" >&5 +$as_echo_n "checking for glib-networking (glib TLS implementation)... " >&6; } +save_CFLAGS="$CFLAGS" +save_LIBS="$LIBS" +CFLAGS="$CFLAGS $GLIB_CFLAGS" +LIBS="$LIBS $GLIB_LIBS" +if test "$cross_compiling" = yes; then : + have_glib_networking="unknown (cross-compiling)" +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +return !g_tls_backend_supports_tls (g_tls_backend_get_default ()); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + have_glib_networking=yes +else + have_glib_networking=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +CFLAGS="$save_CFLAGS" +LIBS="$save_LIBS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_glib_networking" >&5 +$as_echo "$have_glib_networking" >&6; } + +# Check whether --enable-tls-check was given. +if test "${enable_tls_check+set}" = set; then : + enableval=$enable_tls_check; +fi + +if test "$enable_tls_check" != "no" -a "$have_glib_networking" = "no"; then + as_fn_error $? "libsoup requires glib-networking for TLS support. + +If you are building a package, you can pass --disable-tls-check to +allow building libsoup anyway (since glib-networking is not actually +required at compile time), but you should be sure to add a runtime +dependency on it." "$LINENO" 5 +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for programs needed for regression tests" >&5 +$as_echo "$as_me: checking for programs needed for regression tests" >&6;} + + +# Check whether --with-apache-httpd was given. +if test "${with_apache_httpd+set}" = set; then : + withval=$with_apache_httpd; APACHE_HTTPD="$withval" +else + for ac_prog in httpd2 httpd apache2 apache +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 ${ac_cv_path_APACHE_HTTPD+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $APACHE_HTTPD in + [\\/]* | ?:[\\/]*) + ac_cv_path_APACHE_HTTPD="$APACHE_HTTPD" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_dummy="${PATH}:/usr/sbin" +for as_dir in $as_dummy +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_APACHE_HTTPD="$as_dir/$ac_word$ac_exec_ext" + $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 + + ;; +esac +fi +APACHE_HTTPD=$ac_cv_path_APACHE_HTTPD +if test -n "$APACHE_HTTPD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $APACHE_HTTPD" >&5 +$as_echo "$APACHE_HTTPD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$APACHE_HTTPD" && break +done +test -n "$APACHE_HTTPD" || APACHE_HTTPD="no" + +fi + +if test "$APACHE_HTTPD" != "no"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking Apache version" >&5 +$as_echo_n "checking Apache version... " >&6; } + apache_version=`$APACHE_HTTPD -v 2>/dev/null | sed -ne 's/Server version: Apache\///p'` + case $apache_version in + 2.4.*) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $apache_version (ok)" >&5 +$as_echo "$apache_version (ok)" >&6; } + ;; + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $apache_version (ignoring)" >&5 +$as_echo "$apache_version (ignoring)" >&6; } + APACHE_HTTPD="no" + ;; + esac +fi + + +cat >>confdefs.h <<_ACEOF +#define APACHE_HTTPD "$APACHE_HTTPD" +_ACEOF + + +if test "$APACHE_HTTPD" != "no"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Apache module directory" >&5 +$as_echo_n "checking for Apache module directory... " >&6; } + +# Check whether --with-apache-module-dir was given. +if test "${with_apache_module_dir+set}" = set; then : + withval=$with_apache_module_dir; apache_module_dirs="$withval" +else + apache_prefix=`dirname \`dirname $APACHE_HTTPD\`` + mpm=`$APACHE_HTTPD -V -C "ServerName localhost" | sed -ne 's/^Server MPM: */-/p' | tr 'A-Z' 'a-z'` + # This only works with bash, but should fail harmlessly in sh + apache_module_dirs=`echo $apache_prefix/lib{64,}/{apache,apache2,http,http2,httpd}{$mpm,}{/modules,}` +fi + + for dir in $apache_module_dirs; do + if test -f $dir/mod_auth_digest.so; then + APACHE_MODULE_DIR="$dir" + fi + if test -f $dir/mod_ssl.so; then + APACHE_SSL_MODULE_DIR="$dir" + IF_HAVE_APACHE_SSL="" + fi + if test -f $dir/libphp7.so; then + APACHE_PHP_MODULE_DIR="$dir" + fi + done + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $APACHE_MODULE_DIR" >&5 +$as_echo "$APACHE_MODULE_DIR" >&6; } + + + +fi + +if test "$APACHE_HTTPD" != "no" -a -n "$APACHE_MODULE_DIR" -a -n "$APACHE_SSL_MODULE_DIR"; then + +$as_echo "#define HAVE_APACHE 1" >>confdefs.h + + have_apache=1 +else + have_apache=0 +fi + if test "$have_apache" = 1; then + HAVE_APACHE_TRUE= + HAVE_APACHE_FALSE='#' +else + HAVE_APACHE_TRUE='#' + HAVE_APACHE_FALSE= +fi + + +if test "$have_apache" = 1; then + for ac_prog in php +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 ${ac_cv_prog_PHP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$PHP"; then + ac_cv_prog_PHP="$PHP" # 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_PHP="$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 +PHP=$ac_cv_prog_PHP +if test -n "$PHP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PHP" >&5 +$as_echo "$PHP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$PHP" && break +done + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Apache PHP module" >&5 +$as_echo_n "checking for Apache PHP module... " >&6; } + if test -d "$APACHE_PHP_MODULE_DIR"; then + have_php="yes" + IF_HAVE_PHP="" + else + have_php="no" + IF_HAVE_PHP="#" + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_php" >&5 +$as_echo "$have_php" >&6; } + + + if test "$have_php" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for php-xmlrpc" >&5 +$as_echo_n "checking for php-xmlrpc... " >&6; } + if $PHP --rf xmlrpc_server_create | grep -q "does not exist"; then + have_php_xmlrpc=no + else + have_php_xmlrpc=yes + +$as_echo "#define HAVE_PHP_XMLRPC 1" >>confdefs.h + + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_php_xmlrpc" >&5 +$as_echo "$have_php_xmlrpc" >&6; } + fi + + if test -f "$APACHE_MODULE_DIR/mod_unixd.so"; then + IF_HAVE_MOD_UNIXD="" + else + IF_HAVE_MOD_UNIXD="#" + fi + +fi + +# Extract the first word of "curl", so it can be a program name with args. +set dummy curl; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_CURL+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $CURL in + [\\/]* | ?:[\\/]*) + ac_cv_path_CURL="$CURL" # Let the user override the test with a path. + ;; + *) + 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_CURL="$as_dir/$ac_word$ac_exec_ext" + $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_path_CURL" && ac_cv_path_CURL="no" + ;; +esac +fi +CURL=$ac_cv_path_CURL +if test -n "$CURL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CURL" >&5 +$as_echo "$CURL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +if test "$CURL" != no; then + +$as_echo "#define HAVE_CURL 1" >>confdefs.h + +fi + + +# Check whether --with-ntlm-auth was given. +if test "${with_ntlm_auth+set}" = set; then : + withval=$with_ntlm_auth; ntlm_auth="$withval" +else + if test $os_win32 = yes; then ntlm_auth="no"; else ntlm_auth="/usr/bin/ntlm_auth"; fi +fi + +if test "$ntlm_auth" != "no"; then + +$as_echo "#define USE_NTLM_AUTH 1" >>confdefs.h + + if test "$ntlm_auth" = "yes"; then + ntlm_auth="/usr/bin/ntlm_auth" + fi +fi + + +cat >>confdefs.h <<_ACEOF +#define NTLM_AUTH "$ntlm_auth" +_ACEOF + + + + + + # allow to override gcov location + +# Check whether --with-gcov was given. +if test "${with_gcov+set}" = set; then : + withval=$with_gcov; _AX_CODE_COVERAGE_GCOV_PROG_WITH=$with_gcov +else + _AX_CODE_COVERAGE_GCOV_PROG_WITH=gcov +fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build with code coverage support" >&5 +$as_echo_n "checking whether to build with code coverage support... " >&6; } + # Check whether --enable-code-coverage was given. +if test "${enable_code_coverage+set}" = set; then : + enableval=$enable_code_coverage; +else + enable_code_coverage=no +fi + + + if test x$enable_code_coverage = xyes; then + CODE_COVERAGE_ENABLED_TRUE= + CODE_COVERAGE_ENABLED_FALSE='#' +else + CODE_COVERAGE_ENABLED_TRUE='#' + CODE_COVERAGE_ENABLED_FALSE= +fi + + CODE_COVERAGE_ENABLED=$enable_code_coverage + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_code_coverage" >&5 +$as_echo "$enable_code_coverage" >&6; } + + if test "$enable_code_coverage" = "yes" ; then : + + # check for gcov + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}$_AX_CODE_COVERAGE_GCOV_PROG_WITH", so it can be a program name with args. +set dummy ${ac_tool_prefix}$_AX_CODE_COVERAGE_GCOV_PROG_WITH; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_GCOV+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$GCOV"; then + ac_cv_prog_GCOV="$GCOV" # 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_GCOV="${ac_tool_prefix}$_AX_CODE_COVERAGE_GCOV_PROG_WITH" + $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 +GCOV=$ac_cv_prog_GCOV +if test -n "$GCOV"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GCOV" >&5 +$as_echo "$GCOV" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_GCOV"; then + ac_ct_GCOV=$GCOV + # Extract the first word of "$_AX_CODE_COVERAGE_GCOV_PROG_WITH", so it can be a program name with args. +set dummy $_AX_CODE_COVERAGE_GCOV_PROG_WITH; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_GCOV+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_GCOV"; then + ac_cv_prog_ac_ct_GCOV="$ac_ct_GCOV" # 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_GCOV="$_AX_CODE_COVERAGE_GCOV_PROG_WITH" + $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_GCOV=$ac_cv_prog_ac_ct_GCOV +if test -n "$ac_ct_GCOV"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_GCOV" >&5 +$as_echo "$ac_ct_GCOV" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_GCOV" = x; then + GCOV=":" + 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 + GCOV=$ac_ct_GCOV + fi +else + GCOV="$ac_cv_prog_GCOV" +fi + + if test "X$GCOV" = "X:"; then : + as_fn_error $? "gcov is needed to do coverage" "$LINENO" 5 +fi + + + if test "$GCC" = "no" ; then : + + as_fn_error $? "not compiling with gcc, which is required for gcov code coverage" "$LINENO" 5 + +fi + + # List of supported lcov versions. + lcov_version_list="1.6 1.7 1.8 1.9 1.10 1.11 1.12" + + # Extract the first word of "lcov", so it can be a program name with args. +set dummy lcov; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_LCOV+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$LCOV"; then + ac_cv_prog_LCOV="$LCOV" # 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_LCOV="lcov" + $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 +LCOV=$ac_cv_prog_LCOV +if test -n "$LCOV"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LCOV" >&5 +$as_echo "$LCOV" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + # Extract the first word of "genhtml", so it can be a program name with args. +set dummy genhtml; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_GENHTML+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$GENHTML"; then + ac_cv_prog_GENHTML="$GENHTML" # 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_GENHTML="genhtml" + $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 +GENHTML=$ac_cv_prog_GENHTML +if test -n "$GENHTML"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GENHTML" >&5 +$as_echo "$GENHTML" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + + if test "$LCOV" ; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for lcov version" >&5 +$as_echo_n "checking for lcov version... " >&6; } +if ${ax_cv_lcov_version+:} false; then : + $as_echo_n "(cached) " >&6 +else + + ax_cv_lcov_version=invalid + lcov_version=`$LCOV -v 2>/dev/null | $SED -e 's/^.* //'` + for lcov_check_version in $lcov_version_list; do + if test "$lcov_version" = "$lcov_check_version"; then + ax_cv_lcov_version="$lcov_check_version (ok)" + fi + done + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_lcov_version" >&5 +$as_echo "$ax_cv_lcov_version" >&6; } + +else + + lcov_msg="To enable code coverage reporting you must have one of the following lcov versions installed: $lcov_version_list" + as_fn_error $? "$lcov_msg" "$LINENO" 5 + +fi + + case $ax_cv_lcov_version in + ""|invalid) + lcov_msg="You must have one of the following versions of lcov: $lcov_version_list (found: $lcov_version)." + as_fn_error $? "$lcov_msg" "$LINENO" 5 + LCOV="exit 0;" + ;; + esac + + if test -z "$GENHTML" ; then : + + as_fn_error $? "Could not find genhtml from the lcov package" "$LINENO" 5 + +fi + + CODE_COVERAGE_CPPFLAGS="-DNDEBUG" + CODE_COVERAGE_CFLAGS="-O0 -g -fprofile-arcs -ftest-coverage" + CODE_COVERAGE_CXXFLAGS="-O0 -g -fprofile-arcs -ftest-coverage" + CODE_COVERAGE_LDFLAGS="-lgcov" + + + + + + +fi + +CODE_COVERAGE_RULES=' +# Code coverage +# +# Optional: +# - CODE_COVERAGE_DIRECTORY: Top-level directory for code coverage reporting. +# Multiple directories may be specified, separated by whitespace. +# (Default: $(top_builddir)) +# - CODE_COVERAGE_OUTPUT_FILE: Filename and path for the .info file generated +# by lcov for code coverage. (Default: +# $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage.info) +# - CODE_COVERAGE_OUTPUT_DIRECTORY: Directory for generated code coverage +# reports to be created. (Default: +# $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage) +# - CODE_COVERAGE_BRANCH_COVERAGE: Set to 1 to enforce branch coverage, +# set to 0 to disable it and leave empty to stay with the default. +# (Default: empty) +# - CODE_COVERAGE_LCOV_SHOPTS_DEFAULT: Extra options shared between both lcov +# instances. (Default: based on $CODE_COVERAGE_BRANCH_COVERAGE) +# - CODE_COVERAGE_LCOV_SHOPTS: Extra options to shared between both lcov +# instances. (Default: $CODE_COVERAGE_LCOV_SHOPTS_DEFAULT) +# - CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH: --gcov-tool pathtogcov +# - CODE_COVERAGE_LCOV_OPTIONS_DEFAULT: Extra options to pass to the +# collecting lcov instance. (Default: $CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH) +# - CODE_COVERAGE_LCOV_OPTIONS: Extra options to pass to the collecting lcov +# instance. (Default: $CODE_COVERAGE_LCOV_OPTIONS_DEFAULT) +# - CODE_COVERAGE_LCOV_RMOPTS_DEFAULT: Extra options to pass to the filtering +# lcov instance. (Default: empty) +# - CODE_COVERAGE_LCOV_RMOPTS: Extra options to pass to the filtering lcov +# instance. (Default: $CODE_COVERAGE_LCOV_RMOPTS_DEFAULT) +# - CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT: Extra options to pass to the +# genhtml instance. (Default: based on $CODE_COVERAGE_BRANCH_COVERAGE) +# - CODE_COVERAGE_GENHTML_OPTIONS: Extra options to pass to the genhtml +# instance. (Default: $CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT) +# - CODE_COVERAGE_IGNORE_PATTERN: Extra glob pattern of files to ignore +# +# The generated report will be titled using the $(PACKAGE_NAME) and +# $(PACKAGE_VERSION). In order to add the current git hash to the title, +# use the git-version-gen script, available online. + +# Optional variables +CODE_COVERAGE_DIRECTORY ?= $(top_builddir) +CODE_COVERAGE_OUTPUT_FILE ?= $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage.info +CODE_COVERAGE_OUTPUT_DIRECTORY ?= $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage +CODE_COVERAGE_BRANCH_COVERAGE ?= +CODE_COVERAGE_LCOV_SHOPTS_DEFAULT ?= $(if $(CODE_COVERAGE_BRANCH_COVERAGE),\ +--rc lcov_branch_coverage=$(CODE_COVERAGE_BRANCH_COVERAGE)) +CODE_COVERAGE_LCOV_SHOPTS ?= $(CODE_COVERAGE_LCOV_SHOPTS_DEFAULT) +CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH ?= --gcov-tool "$(GCOV)" +CODE_COVERAGE_LCOV_OPTIONS_DEFAULT ?= $(CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH) +CODE_COVERAGE_LCOV_OPTIONS ?= $(CODE_COVERAGE_LCOV_OPTIONS_DEFAULT) +CODE_COVERAGE_LCOV_RMOPTS_DEFAULT ?= +CODE_COVERAGE_LCOV_RMOPTS ?= $(CODE_COVERAGE_LCOV_RMOPTS_DEFAULT) +CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT ?=\ +$(if $(CODE_COVERAGE_BRANCH_COVERAGE),\ +--rc genhtml_branch_coverage=$(CODE_COVERAGE_BRANCH_COVERAGE)) +CODE_COVERAGE_GENHTML_OPTIONS ?= $(CODE_COVERAGE_GENHTML_OPTIONS_DEFAULTS) +CODE_COVERAGE_IGNORE_PATTERN ?= + +code_coverage_v_lcov_cap = $(code_coverage_v_lcov_cap_$(V)) +code_coverage_v_lcov_cap_ = $(code_coverage_v_lcov_cap_$(AM_DEFAULT_VERBOSITY)) +code_coverage_v_lcov_cap_0 = @echo " LCOV --capture"\ + $(CODE_COVERAGE_OUTPUT_FILE); +code_coverage_v_lcov_ign = $(code_coverage_v_lcov_ign_$(V)) +code_coverage_v_lcov_ign_ = $(code_coverage_v_lcov_ign_$(AM_DEFAULT_VERBOSITY)) +code_coverage_v_lcov_ign_0 = @echo " LCOV --remove /tmp/*"\ + $(CODE_COVERAGE_IGNORE_PATTERN); +code_coverage_v_genhtml = $(code_coverage_v_genhtml_$(V)) +code_coverage_v_genhtml_ = $(code_coverage_v_genhtml_$(AM_DEFAULT_VERBOSITY)) +code_coverage_v_genhtml_0 = @echo " GEN " $(CODE_COVERAGE_OUTPUT_DIRECTORY); +code_coverage_quiet = $(code_coverage_quiet_$(V)) +code_coverage_quiet_ = $(code_coverage_quiet_$(AM_DEFAULT_VERBOSITY)) +code_coverage_quiet_0 = --quiet + +# sanitizes the test-name: replaces with underscores: dashes and dots +code_coverage_sanitize = $(subst -,_,$(subst .,_,$(1))) + +# Use recursive makes in order to ignore errors during check +check-code-coverage: +ifeq ($(CODE_COVERAGE_ENABLED),yes) + -$(A''M_V_at)$(MAKE) $(AM_MAKEFLAGS) -k check + $(A''M_V_at)$(MAKE) $(AM_MAKEFLAGS) code-coverage-capture +else + @echo "Need to reconfigure with --enable-code-coverage" +endif + +# Capture code coverage data +code-coverage-capture: code-coverage-capture-hook +ifeq ($(CODE_COVERAGE_ENABLED),yes) + $(code_coverage_v_lcov_cap)$(LCOV) $(code_coverage_quiet) $(addprefix --directory ,$(CODE_COVERAGE_DIRECTORY)) --capture --output-file "$(CODE_COVERAGE_OUTPUT_FILE).tmp" --test-name "$(call code_coverage_sanitize,$(PACKAGE_NAME)-$(PACKAGE_VERSION))" --no-checksum --compat-libtool $(CODE_COVERAGE_LCOV_SHOPTS) $(CODE_COVERAGE_LCOV_OPTIONS) + $(code_coverage_v_lcov_ign)$(LCOV) $(code_coverage_quiet) $(addprefix --directory ,$(CODE_COVERAGE_DIRECTORY)) --remove "$(CODE_COVERAGE_OUTPUT_FILE).tmp" "/tmp/*" $(CODE_COVERAGE_IGNORE_PATTERN) --output-file "$(CODE_COVERAGE_OUTPUT_FILE)" $(CODE_COVERAGE_LCOV_SHOPTS) $(CODE_COVERAGE_LCOV_RMOPTS) + -@rm -f $(CODE_COVERAGE_OUTPUT_FILE).tmp + $(code_coverage_v_genhtml)LANG=C $(GENHTML) $(code_coverage_quiet) $(addprefix --prefix ,$(CODE_COVERAGE_DIRECTORY)) --output-directory "$(CODE_COVERAGE_OUTPUT_DIRECTORY)" --title "$(PACKAGE_NAME)-$(PACKAGE_VERSION) Code Coverage" --legend --show-details "$(CODE_COVERAGE_OUTPUT_FILE)" $(CODE_COVERAGE_GENHTML_OPTIONS) + @echo "file://$(abs_builddir)/$(CODE_COVERAGE_OUTPUT_DIRECTORY)/index.html" +else + @echo "Need to reconfigure with --enable-code-coverage" +endif + +# Hook rule executed before code-coverage-capture, overridable by the user +code-coverage-capture-hook: + +ifeq ($(CODE_COVERAGE_ENABLED),yes) +clean: code-coverage-clean +distclean: code-coverage-clean +code-coverage-clean: + -$(LCOV) --directory $(top_builddir) -z + -rm -rf $(CODE_COVERAGE_OUTPUT_FILE) $(CODE_COVERAGE_OUTPUT_FILE).tmp $(CODE_COVERAGE_OUTPUT_DIRECTORY) + -find . \( -name "*.gcda" -o -name "*.gcno" -o -name "*.gcov" \) -delete +endif + +GITIGNOREFILES ?= +GITIGNOREFILES += $(CODE_COVERAGE_OUTPUT_FILE) $(CODE_COVERAGE_OUTPUT_DIRECTORY) + +A''M_DISTCHECK_CONFIGURE_FLAGS ?= +A''M_DISTCHECK_CONFIGURE_FLAGS += --disable-code-coverage + +.PHONY: check-code-coverage code-coverage-capture code-coverage-capture-hook code-coverage-clean +' + + + + + + +# Check whether --with-gssapi was given. +if test "${with_gssapi+set}" = set; then : + withval=$with_gssapi; +fi + + +if test "$with_gssapi" != "no"; then + +# Check whether --with-krb5-config was given. +if test "${with_krb5_config+set}" = set; then : + withval=$with_krb5_config; KRB5_CONFIG="$withval" +else + for ac_prog in krb5-config +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 ${ac_cv_path_KRB5_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $KRB5_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_KRB5_CONFIG="$KRB5_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_dummy="${PATH}:/usr/kerberos/bin" +for as_dir in $as_dummy +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_KRB5_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $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 + + ;; +esac +fi +KRB5_CONFIG=$ac_cv_path_KRB5_CONFIG +if test -n "$KRB5_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $KRB5_CONFIG" >&5 +$as_echo "$KRB5_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$KRB5_CONFIG" && break +done +test -n "$KRB5_CONFIG" || KRB5_CONFIG="no" + +fi + + + if test "$KRB5_CONFIG" != "no"; then + KRB5_LIBS="`${KRB5_CONFIG} --libs gssapi`" + KRB5_CFLAGS="`${KRB5_CONFIG} --cflags gssapi`" + + + if test "$KRB5_CONFIG" != none; then + +$as_echo "#define LIBSOUP_HAVE_GSSAPI 1" >>confdefs.h + + fi + else + if test "$with_gssapi" = "yes"; then + as_fn_error $? "GSSAPI support requested but failed to found krb5-config. Try to set KRB5_CONFIG." "$LINENO" 5 + fi + fi +fi + + +# Check whether --enable-more-warnings was given. +if test "${enable_more_warnings+set}" = set; then : + enableval=$enable_more_warnings; set_more_warnings=no +fi + + +if test "$GCC" = "yes" -a "$set_more_warnings" != "no"; then + CFLAGS="$CFLAGS \ + -Wall -Wstrict-prototypes -Werror=missing-prototypes \ + -Werror=implicit-function-declaration \ + -Werror=pointer-arith -Werror=init-self -Werror=format=2 \ + -Wno-format-zero-length \ + -Werror=missing-include-dirs -Werror=aggregate-return \ + -Werror=declaration-after-statement" +fi + +################################################## +# Visibility handling +################################################## + +SOUP_HIDDEN_VISIBILITY_CFLAGS="" +case "$host" in + *-*-mingw*) + +$as_echo "#define _SOUP_EXTERN __attribute__((visibility(\"default\"))) __declspec(dllexport) extern" >>confdefs.h + + SOUP_HIDDEN_VISIBILITY_CFLAGS="-fvisibility=hidden" + ;; + *) + SAVED_CFLAGS="${CFLAGS}" + CFLAGS="-fvisibility=hidden" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -fvisibility=hidden compiler flag" >&5 +$as_echo_n "checking for -fvisibility=hidden compiler flag... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +return 0 + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + enable_fvisibility_hidden=yes +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + enable_fvisibility_hidden=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS="${SAVED_CFLAGS}" + + if test "${enable_fvisibility_hidden}" = "yes"; then : + + +$as_echo "#define _SOUP_EXTERN __attribute__((visibility(\"default\"))) extern" >>confdefs.h + + SOUP_HIDDEN_VISIBILITY_CFLAGS="-fvisibility=hidden" + +fi + ;; +esac + + + if test x$MSVC_BASE_TOOLSET = x; then + MSVC_BASE_NO_TOOLSET_SET_TRUE= + MSVC_BASE_NO_TOOLSET_SET_FALSE='#' +else + MSVC_BASE_NO_TOOLSET_SET_TRUE='#' + MSVC_BASE_NO_TOOLSET_SET_FALSE= +fi + + if test x$MSVC_TOOLSET = x; then + MSVC_NO_TOOLSET_SET_TRUE= + MSVC_NO_TOOLSET_SET_FALSE='#' +else + MSVC_NO_TOOLSET_SET_TRUE='#' + MSVC_NO_TOOLSET_SET_FALSE= +fi + + + + +ac_config_headers="$ac_config_headers config.h" + +ac_config_files="$ac_config_files libsoup-2.4.pc libsoup-gnome-2.4.pc Makefile libsoup-zip libsoup/Makefile po/Makefile.in po/Makefile tests/Makefile tests/httpd.conf examples/Makefile docs/Makefile docs/reference/Makefile libsoup/soup-version.h config.h.win32 win32/Makefile win32/vs9/Makefile win32/vs9/soup-version-paths.vsprops win32/vs10/Makefile win32/vs10/soup-version-paths.props win32/vs11/Makefile win32/vs12/Makefile win32/vs14/Makefile win32/vs15/Makefile" + +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 + if test "x$cache_file" != "x/dev/null"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} + if test ! -f "$cache_file" || test -h "$cache_file"; then + cat confcache >"$cache_file" + else + case $cache_file in #( + */* | ?:*) + mv -f confcache "$cache_file"$$ && + mv -f "$cache_file"$$ "$cache_file" ;; #( + *) + mv -f confcache "$cache_file" ;; + esac + fi + fi + 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 + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5 +$as_echo_n "checking that generated files are newer than configure... " >&6; } + if test -n "$am_sleep_pid"; then + # Hide warnings about reused PIDs. + wait $am_sleep_pid 2>/dev/null + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5 +$as_echo "done" >&6; } + if test -n "$EXEEXT"; then + am__EXEEXT_TRUE= + am__EXEEXT_FALSE='#' +else + am__EXEEXT_TRUE='#' + am__EXEEXT_FALSE= +fi + +if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then + as_fn_error $? "conditional \"AMDEP\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then + as_fn_error $? "conditional \"am__fastdepCC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${ENABLE_INSTALLED_TESTS_TRUE}" && test -z "${ENABLE_INSTALLED_TESTS_FALSE}"; then + as_fn_error $? "conditional \"ENABLE_INSTALLED_TESTS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${ENABLE_ALWAYS_BUILD_TESTS_TRUE}" && test -z "${ENABLE_ALWAYS_BUILD_TESTS_FALSE}"; then + as_fn_error $? "conditional \"ENABLE_ALWAYS_BUILD_TESTS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${OS_WIN32_TRUE}" && test -z "${OS_WIN32_FALSE}"; then + as_fn_error $? "conditional \"OS_WIN32\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${OS_LINUX_TRUE}" && test -z "${OS_LINUX_FALSE}"; then + as_fn_error $? "conditional \"OS_LINUX\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi + + ac_config_commands="$ac_config_commands po/stamp-it" + + +if test -z "${BUILD_LIBSOUP_GNOME_TRUE}" && test -z "${BUILD_LIBSOUP_GNOME_FALSE}"; then + as_fn_error $? "conditional \"BUILD_LIBSOUP_GNOME\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_GTK_DOC_TRUE}" && test -z "${HAVE_GTK_DOC_FALSE}"; then + as_fn_error $? "conditional \"HAVE_GTK_DOC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${ENABLE_GTK_DOC_TRUE}" && test -z "${ENABLE_GTK_DOC_FALSE}"; then + as_fn_error $? "conditional \"ENABLE_GTK_DOC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${GTK_DOC_BUILD_HTML_TRUE}" && test -z "${GTK_DOC_BUILD_HTML_FALSE}"; then + as_fn_error $? "conditional \"GTK_DOC_BUILD_HTML\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${GTK_DOC_BUILD_PDF_TRUE}" && test -z "${GTK_DOC_BUILD_PDF_FALSE}"; then + as_fn_error $? "conditional \"GTK_DOC_BUILD_PDF\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${GTK_DOC_USE_LIBTOOL_TRUE}" && test -z "${GTK_DOC_USE_LIBTOOL_FALSE}"; then + as_fn_error $? "conditional \"GTK_DOC_USE_LIBTOOL\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${GTK_DOC_USE_REBASE_TRUE}" && test -z "${GTK_DOC_USE_REBASE_FALSE}"; then + as_fn_error $? "conditional \"GTK_DOC_USE_REBASE\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_INTROSPECTION_TRUE}" && test -z "${HAVE_INTROSPECTION_FALSE}"; then + as_fn_error $? "conditional \"HAVE_INTROSPECTION\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${ENABLE_VAPIGEN_TRUE}" && test -z "${ENABLE_VAPIGEN_FALSE}"; then + as_fn_error $? "conditional \"ENABLE_VAPIGEN\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_APACHE_TRUE}" && test -z "${HAVE_APACHE_FALSE}"; then + as_fn_error $? "conditional \"HAVE_APACHE\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${CODE_COVERAGE_ENABLED_TRUE}" && test -z "${CODE_COVERAGE_ENABLED_FALSE}"; then + as_fn_error $? "conditional \"CODE_COVERAGE_ENABLED\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MSVC_BASE_NO_TOOLSET_SET_TRUE}" && test -z "${MSVC_BASE_NO_TOOLSET_SET_FALSE}"; then + as_fn_error $? "conditional \"MSVC_BASE_NO_TOOLSET_SET\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MSVC_NO_TOOLSET_SET_TRUE}" && test -z "${MSVC_NO_TOOLSET_SET_FALSE}"; then + as_fn_error $? "conditional \"MSVC_NO_TOOLSET_SET\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi + +: "${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. +as_myself= +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 -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +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 + + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# 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 libsoup $as_me 2.62.3, which was +generated by GNU Autoconf 2.69. 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_files in *" +"*) set x $ac_config_files; shift; ac_config_files=$*;; +esac + +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_files="$ac_config_files" +config_headers="$ac_config_headers" +config_commands="$ac_config_commands" + +_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 + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Configuration commands: +$config_commands + +Report bugs to ." + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" +ac_cs_version="\\ +libsoup config.status 2.62.3 +configured by $0, generated by GNU Autoconf 2.69, + with options \\"\$ac_cs_config\\" + +Copyright (C) 2012 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' +INSTALL='$INSTALL' +MKDIR_P='$MKDIR_P' +AWK='$AWK' +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=: ;; + --file | --fil | --fi | --f ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + '') as_fn_error $? "missing file argument" ;; + esac + as_fn_append CONFIG_FILES " '$ac_optarg'" + ac_need_defaults=false;; + --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 +# +# INIT-COMMANDS +# +AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" + + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +sed_quote_subst='$sed_quote_subst' +double_quote_subst='$double_quote_subst' +delay_variable_subst='$delay_variable_subst' +macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`' +macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`' +AS='`$ECHO "$AS" | $SED "$delay_single_quote_subst"`' +DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`' +OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`' +enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`' +enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`' +pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`' +enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`' +shared_archive_member_spec='`$ECHO "$shared_archive_member_spec" | $SED "$delay_single_quote_subst"`' +SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`' +ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`' +PATH_SEPARATOR='`$ECHO "$PATH_SEPARATOR" | $SED "$delay_single_quote_subst"`' +host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`' +host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`' +host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`' +build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`' +build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`' +build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`' +SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`' +Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`' +GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`' +EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`' +FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`' +LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`' +NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`' +LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`' +max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`' +ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`' +exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`' +lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`' +lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`' +lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`' +lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_quote_subst"`' +lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`' +reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`' +reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`' +deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`' +file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`' +file_magic_glob='`$ECHO "$file_magic_glob" | $SED "$delay_single_quote_subst"`' +want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`' +sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`' +AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`' +AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`' +archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`' +STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`' +RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`' +old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`' +old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`' +old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`' +lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`' +CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`' +CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`' +compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`' +GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_import='`$ECHO "$lt_cv_sys_global_symbol_to_import" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`' +lt_cv_nm_interface='`$ECHO "$lt_cv_nm_interface" | $SED "$delay_single_quote_subst"`' +nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`' +lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`' +lt_cv_truncate_bin='`$ECHO "$lt_cv_truncate_bin" | $SED "$delay_single_quote_subst"`' +objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`' +MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`' +lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`' +need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`' +MANIFEST_TOOL='`$ECHO "$MANIFEST_TOOL" | $SED "$delay_single_quote_subst"`' +DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`' +NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`' +LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`' +OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`' +OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`' +libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`' +shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`' +extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`' +archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`' +enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`' +export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`' +whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`' +compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`' +old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`' +old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`' +archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`' +archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`' +module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`' +module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`' +with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`' +allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`' +no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`' +hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`' +hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`' +hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`' +hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`' +hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`' +inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`' +link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`' +always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`' +export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`' +exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`' +include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`' +prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`' +postlink_cmds='`$ECHO "$postlink_cmds" | $SED "$delay_single_quote_subst"`' +file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`' +variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`' +need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`' +need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`' +version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`' +runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`' +shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`' +shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`' +libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`' +library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`' +soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`' +install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`' +postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`' +postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`' +finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`' +finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`' +hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`' +sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`' +configure_time_dlsearch_path='`$ECHO "$configure_time_dlsearch_path" | $SED "$delay_single_quote_subst"`' +configure_time_lt_sys_library_path='`$ECHO "$configure_time_lt_sys_library_path" | $SED "$delay_single_quote_subst"`' +hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`' +enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`' +enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`' +enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`' +old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`' +striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`' + +LTCC='$LTCC' +LTCFLAGS='$LTCFLAGS' +compiler='$compiler_DEFAULT' + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$1 +_LTECHO_EOF' +} + +# Quote evaled strings. +for var in AS \ +DLLTOOL \ +OBJDUMP \ +SHELL \ +ECHO \ +PATH_SEPARATOR \ +SED \ +GREP \ +EGREP \ +FGREP \ +LD \ +NM \ +LN_S \ +lt_SP2NL \ +lt_NL2SP \ +reload_flag \ +deplibs_check_method \ +file_magic_cmd \ +file_magic_glob \ +want_nocaseglob \ +sharedlib_from_linklib_cmd \ +AR \ +AR_FLAGS \ +archiver_list_spec \ +STRIP \ +RANLIB \ +CC \ +CFLAGS \ +compiler \ +lt_cv_sys_global_symbol_pipe \ +lt_cv_sys_global_symbol_to_cdecl \ +lt_cv_sys_global_symbol_to_import \ +lt_cv_sys_global_symbol_to_c_name_address \ +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \ +lt_cv_nm_interface \ +nm_file_list_spec \ +lt_cv_truncate_bin \ +lt_prog_compiler_no_builtin_flag \ +lt_prog_compiler_pic \ +lt_prog_compiler_wl \ +lt_prog_compiler_static \ +lt_cv_prog_compiler_c_o \ +need_locks \ +MANIFEST_TOOL \ +DSYMUTIL \ +NMEDIT \ +LIPO \ +OTOOL \ +OTOOL64 \ +shrext_cmds \ +export_dynamic_flag_spec \ +whole_archive_flag_spec \ +compiler_needs_object \ +with_gnu_ld \ +allow_undefined_flag \ +no_undefined_flag \ +hardcode_libdir_flag_spec \ +hardcode_libdir_separator \ +exclude_expsyms \ +include_expsyms \ +file_list_spec \ +variables_saved_for_relink \ +libname_spec \ +library_names_spec \ +soname_spec \ +install_override_mode \ +finish_eval \ +old_striplib \ +striplib; do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[\\\\\\\`\\"\\\$]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +# Double-quote double-evaled strings. +for var in reload_cmds \ +old_postinstall_cmds \ +old_postuninstall_cmds \ +old_archive_cmds \ +extract_expsyms_cmds \ +old_archive_from_new_cmds \ +old_archive_from_expsyms_cmds \ +archive_cmds \ +archive_expsym_cmds \ +module_cmds \ +module_expsym_cmds \ +export_symbols_cmds \ +prelink_cmds \ +postlink_cmds \ +postinstall_cmds \ +postuninstall_cmds \ +finish_cmds \ +sys_lib_search_path_spec \ +configure_time_dlsearch_path \ +configure_time_lt_sys_library_path; do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[\\\\\\\`\\"\\\$]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +ac_aux_dir='$ac_aux_dir' + +# See if we are running on zsh, and set the options that allow our +# commands through without removal of \ escapes INIT. +if test -n "\${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST +fi + + + PACKAGE='$PACKAGE' + VERSION='$VERSION' + RM='$RM' + ofile='$ofile' + + + + +_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 + "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; + "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; + "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; + "libsoup-2.4.pc") CONFIG_FILES="$CONFIG_FILES libsoup-2.4.pc" ;; + "libsoup-gnome-2.4.pc") CONFIG_FILES="$CONFIG_FILES libsoup-gnome-2.4.pc" ;; + "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "libsoup-zip") CONFIG_FILES="$CONFIG_FILES libsoup-zip" ;; + "libsoup/Makefile") CONFIG_FILES="$CONFIG_FILES libsoup/Makefile" ;; + "po/Makefile.in") CONFIG_FILES="$CONFIG_FILES po/Makefile.in" ;; + "po/Makefile") CONFIG_FILES="$CONFIG_FILES po/Makefile" ;; + "tests/Makefile") CONFIG_FILES="$CONFIG_FILES tests/Makefile" ;; + "tests/httpd.conf") CONFIG_FILES="$CONFIG_FILES tests/httpd.conf" ;; + "examples/Makefile") CONFIG_FILES="$CONFIG_FILES examples/Makefile" ;; + "docs/Makefile") CONFIG_FILES="$CONFIG_FILES docs/Makefile" ;; + "docs/reference/Makefile") CONFIG_FILES="$CONFIG_FILES docs/reference/Makefile" ;; + "libsoup/soup-version.h") CONFIG_FILES="$CONFIG_FILES libsoup/soup-version.h" ;; + "config.h.win32") CONFIG_FILES="$CONFIG_FILES config.h.win32" ;; + "win32/Makefile") CONFIG_FILES="$CONFIG_FILES win32/Makefile" ;; + "win32/vs9/Makefile") CONFIG_FILES="$CONFIG_FILES win32/vs9/Makefile" ;; + "win32/vs9/soup-version-paths.vsprops") CONFIG_FILES="$CONFIG_FILES win32/vs9/soup-version-paths.vsprops" ;; + "win32/vs10/Makefile") CONFIG_FILES="$CONFIG_FILES win32/vs10/Makefile" ;; + "win32/vs10/soup-version-paths.props") CONFIG_FILES="$CONFIG_FILES win32/vs10/soup-version-paths.props" ;; + "win32/vs11/Makefile") CONFIG_FILES="$CONFIG_FILES win32/vs11/Makefile" ;; + "win32/vs12/Makefile") CONFIG_FILES="$CONFIG_FILES win32/vs12/Makefile" ;; + "win32/vs14/Makefile") CONFIG_FILES="$CONFIG_FILES win32/vs14/Makefile" ;; + "win32/vs15/Makefile") CONFIG_FILES="$CONFIG_FILES win32/vs15/Makefile" ;; + "po/stamp-it") CONFIG_COMMANDS="$CONFIG_COMMANDS po/stamp-it" ;; + + *) 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_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers + test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands +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= ac_tmp= + trap 'exit_status=$? + : "${ac_tmp:=$tmp}" + { test ! -d "$ac_tmp" || rm -fr "$ac_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 -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +ac_tmp=$tmp + +# Set up the scripts for CONFIG_FILES section. +# No need to generate them if there are no CONFIG_FILES. +# This happens for instance with `./config.status config.h'. +if test -n "$CONFIG_FILES"; then + + +ac_cr=`echo X | tr X '\015'` +# On cygwin, bash can eat \r inside `` if the user requested igncr. +# But we know of no other shell where ac_cr would be empty at this +# point, so we can use a bashism as a fallback. +if test "x$ac_cr" = x; then + eval ac_cr=\$\'\\r\' +fi +ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` +if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then + ac_cs_awk_cr='\\r' +else + ac_cs_awk_cr=$ac_cr +fi + +echo 'BEGIN {' >"$ac_tmp/subs1.awk" && +_ACEOF + + +{ + echo "cat >conf$$subs.awk <<_ACEOF" && + echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && + echo "_ACEOF" +} >conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + . ./conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + + ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` + if test $ac_delim_n = $ac_delim_num; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done +rm -f conf$$subs.sh + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && +_ACEOF +sed -n ' +h +s/^/S["/; s/!.*/"]=/ +p +g +s/^[^!]*!// +:repl +t repl +s/'"$ac_delim"'$// +t delim +:nl +h +s/\(.\{148\}\)..*/\1/ +t more1 +s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ +p +n +b repl +:more1 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t nl +:delim +h +s/\(.\{148\}\)..*/\1/ +t more2 +s/["\\]/\\&/g; s/^/"/; s/$/"/ +p +b +:more2 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t delim +' >$CONFIG_STATUS || ac_write_fail=1 +rm -f conf$$subs.awk +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACAWK +cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && + for (key in S) S_is_set[key] = 1 + FS = "" + +} +{ + line = $ 0 + nfields = split(line, field, "@") + substed = 0 + len = length(field[1]) + for (i = 2; i < nfields; i++) { + key = field[i] + keylen = length(key) + if (S_is_set[key]) { + value = S[key] + line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) + len += length(value) + length(field[++i]) + substed = 1 + } else + len += 1 + keylen + } + + print line +} + +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then + sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" +else + cat +fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ + || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 +_ACEOF + +# VPATH may cause trouble with some makes, so we remove sole $(srcdir), +# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ +h +s/// +s/^/:/ +s/[ ]*$/:/ +s/:\$(srcdir):/:/g +s/:\${srcdir}:/:/g +s/:@srcdir@:/:/g +s/^:*// +s/:*$// +x +s/\(=[ ]*\).*/\1/ +G +s/\n// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +fi # test -n "$CONFIG_FILES" + +# 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 >"$ac_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_tt=`sed -n "/$ac_delim/p" confdefs.h` + if test -z "$ac_tt"; 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 " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" +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="$ac_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 >"$ac_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 + :F) + # + # CONFIG_FILE + # + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; + esac + ac_MKDIR_P=$MKDIR_P + case $MKDIR_P in + [\\/$]* | ?:[\\/]* ) ;; + */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; + esac +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= +ac_sed_dataroot=' +/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p' +case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_sed_extra="$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s|@configure_input@|$ac_sed_conf_input|;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@top_build_prefix@&$ac_top_build_prefix&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +s&@INSTALL@&$ac_INSTALL&;t t +s&@MKDIR_P@&$ac_MKDIR_P&;t t +$ac_datarootdir_hack +" +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ + >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ + "$ac_tmp/out"`; test -z "$ac_out"; } && + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&5 +$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&2;} + + rm -f "$ac_tmp/stdin" + case $ac_file in + -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; + *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; + esac \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + ;; + :H) + # + # CONFIG_HEADER + # + if test x"$ac_file" != x-; then + { + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" + } >"$ac_tmp/config.h" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + if diff "$ac_file" "$ac_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 "$ac_tmp/config.h" "$ac_file" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + fi + else + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ + || as_fn_error $? "could not create -" "$LINENO" 5 + fi +# Compute "$ac_file"'s index in $config_headers. +_am_arg="$ac_file" +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $_am_arg | $_am_arg:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" || +$as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$_am_arg" : 'X\(//\)[^/]' \| \ + X"$_am_arg" : 'X\(//\)$' \| \ + X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$_am_arg" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'`/stamp-h$_am_stamp_count + ;; + + :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 +$as_echo "$as_me: executing $ac_file commands" >&6;} + ;; + esac + + + case $ac_file$ac_mode in + "depfiles":C) test x"$AMDEP_TRUE" != x"" || { + # Older Autoconf quotes --file arguments for eval, but not when files + # are listed without --file. Let's play safe and only enable the eval + # if we detect the quoting. + case $CONFIG_FILES in + *\'*) eval set x "$CONFIG_FILES" ;; + *) set x $CONFIG_FILES ;; + esac + shift + for mf + do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named 'Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # Grep'ing the whole file is not good either: AIX grep has a line + # limit of 2048, but all sed's we know have understand at least 4000. + if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then + dirpart=`$as_dirname -- "$mf" || +$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$mf" : 'X\(//\)[^/]' \| \ + X"$mf" : 'X\(//\)$' \| \ + X"$mf" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$mf" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + else + continue + fi + # Extract the definition of DEPDIR, am__include, and am__quote + # from the Makefile without running 'make'. + DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` + test -z "$DEPDIR" && continue + am__include=`sed -n 's/^am__include = //p' < "$mf"` + test -z "$am__include" && continue + am__quote=`sed -n 's/^am__quote = //p' < "$mf"` + # Find all dependency output files, they are included files with + # $(DEPDIR) in their names. We invoke sed twice because it is the + # simplest approach to changing $(DEPDIR) to its actual value in the + # expansion. + for file in `sed -n " + s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`$as_dirname -- "$file" || +$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$file" : 'X\(//\)[^/]' \| \ + X"$file" : 'X\(//\)$' \| \ + X"$file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir=$dirpart/$fdir; as_fn_mkdir_p + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done + done +} + ;; + "libtool":C) + + # See if we are running on zsh, and set the options that allow our + # commands through without removal of \ escapes. + if test -n "${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST + fi + + cfgfile=${ofile}T + trap "$RM \"$cfgfile\"; exit 1" 1 2 15 + $RM "$cfgfile" + + cat <<_LT_EOF >> "$cfgfile" +#! $SHELL +# Generated automatically by $as_me ($PACKAGE) $VERSION +# NOTE: Changes made to this file will be lost: look at ltmain.sh. + +# Provide generalized library-building support services. +# Written by Gordon Matzigkeit, 1996 + +# Copyright (C) 2014 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. + +# GNU Libtool 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 of the License, or +# (at your option) any later version. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program or library that is built +# using GNU Libtool, you may include this file under the same +# distribution terms that you use for the rest of that program. +# +# GNU Libtool is distributed in the hope that 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 . + + +# The names of the tagged configurations supported by this script. +available_tags='' + +# Configured defaults for sys_lib_dlsearch_path munging. +: \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} + +# ### BEGIN LIBTOOL CONFIG + +# Which release of libtool.m4 was used? +macro_version=$macro_version +macro_revision=$macro_revision + +# Assembler program. +AS=$lt_AS + +# DLL creation program. +DLLTOOL=$lt_DLLTOOL + +# Object dumper program. +OBJDUMP=$lt_OBJDUMP + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# What type of objects to build. +pic_mode=$pic_mode + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# Shared archive member basename,for filename based shared library versioning on AIX. +shared_archive_member_spec=$shared_archive_member_spec + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# An echo program that protects backslashes. +ECHO=$lt_ECHO + +# The PATH separator for the build system. +PATH_SEPARATOR=$lt_PATH_SEPARATOR + +# The host system. +host_alias=$host_alias +host=$host +host_os=$host_os + +# The build system. +build_alias=$build_alias +build=$build +build_os=$build_os + +# A sed program that does not truncate output. +SED=$lt_SED + +# Sed that helps us avoid accidentally triggering echo(1) options like -n. +Xsed="\$SED -e 1s/^X//" + +# A grep program that handles long lines. +GREP=$lt_GREP + +# An ERE matcher. +EGREP=$lt_EGREP + +# A literal string matcher. +FGREP=$lt_FGREP + +# A BSD- or MS-compatible name lister. +NM=$lt_NM + +# Whether we need soft or hard links. +LN_S=$lt_LN_S + +# What is the maximum length of a command? +max_cmd_len=$max_cmd_len + +# Object file suffix (normally "o"). +objext=$ac_objext + +# Executable file suffix (normally ""). +exeext=$exeext + +# whether the shell understands "unset". +lt_unset=$lt_unset + +# turn spaces into newlines. +SP2NL=$lt_lt_SP2NL + +# turn newlines into spaces. +NL2SP=$lt_lt_NL2SP + +# convert \$build file names to \$host format. +to_host_file_cmd=$lt_cv_to_host_file_cmd + +# convert \$build files to toolchain format. +to_tool_file_cmd=$lt_cv_to_tool_file_cmd + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$lt_deplibs_check_method + +# Command to use when deplibs_check_method = "file_magic". +file_magic_cmd=$lt_file_magic_cmd + +# How to find potential files when deplibs_check_method = "file_magic". +file_magic_glob=$lt_file_magic_glob + +# Find potential files using nocaseglob when deplibs_check_method = "file_magic". +want_nocaseglob=$lt_want_nocaseglob + +# Command to associate shared and link libraries. +sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd + +# The archiver. +AR=$lt_AR + +# Flags to create an archive. +AR_FLAGS=$lt_AR_FLAGS + +# How to feed a file listing to the archiver. +archiver_list_spec=$lt_archiver_list_spec + +# A symbol stripping program. +STRIP=$lt_STRIP + +# Commands used to install an old-style archive. +RANLIB=$lt_RANLIB +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Whether to use a lock for old archive extraction. +lock_old_archive_extraction=$lock_old_archive_extraction + +# A C compiler. +LTCC=$lt_CC + +# LTCC compiler flags. +LTCFLAGS=$lt_CFLAGS + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe + +# Transform the output of nm in a proper C declaration. +global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl + +# Transform the output of nm into a list of symbols to manually relocate. +global_symbol_to_import=$lt_lt_cv_sys_global_symbol_to_import + +# Transform the output of nm in a C name address pair. +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# Transform the output of nm in a C name address pair when lib prefix is needed. +global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix + +# The name lister interface. +nm_interface=$lt_lt_cv_nm_interface + +# Specify filename containing input files for \$NM. +nm_file_list_spec=$lt_nm_file_list_spec + +# The root where to search for dependent libraries,and where our libraries should be installed. +lt_sysroot=$lt_sysroot + +# Command to truncate a binary pipe. +lt_truncate_bin=$lt_lt_cv_truncate_bin + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# Used to examine libraries when file_magic_cmd begins with "file". +MAGIC_CMD=$MAGIC_CMD + +# Must we lock files when doing compilation? +need_locks=$lt_need_locks + +# Manifest tool. +MANIFEST_TOOL=$lt_MANIFEST_TOOL + +# Tool to manipulate archived DWARF debug symbol files on Mac OS X. +DSYMUTIL=$lt_DSYMUTIL + +# Tool to change global to local symbols on Mac OS X. +NMEDIT=$lt_NMEDIT + +# Tool to manipulate fat objects and archives on Mac OS X. +LIPO=$lt_LIPO + +# ldd/readelf like tool for Mach-O binaries on Mac OS X. +OTOOL=$lt_OTOOL + +# ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4. +OTOOL64=$lt_OTOOL64 + +# Old archive suffix (normally "a"). +libext=$libext + +# Shared library suffix (normally ".so"). +shrext_cmds=$lt_shrext_cmds + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at link time. +variables_saved_for_relink=$lt_variables_saved_for_relink + +# Do we need the "lib" prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Library versioning type. +version_type=$version_type + +# Shared library runtime path variable. +runpath_var=$runpath_var + +# Shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Permission mode override for installation of shared libraries. +install_override_mode=$lt_install_override_mode + +# Command to use after installation of a shared archive. +postinstall_cmds=$lt_postinstall_cmds + +# Command to use after uninstallation of a shared archive. +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# As "finish_cmds", except a single script fragment to be evaled but +# not shown. +finish_eval=$lt_finish_eval + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Compile-time system search path for libraries. +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Detected run-time system search path for libraries. +sys_lib_dlsearch_path_spec=$lt_configure_time_dlsearch_path + +# Explicit LT_SYS_LIBRARY_PATH set during ./configure time. +configure_time_lt_sys_library_path=$lt_configure_time_lt_sys_library_path + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + + +# The linker used to build libraries. +LD=$lt_LD + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# Commands used to build an old-style archive. +old_archive_cmds=$lt_old_archive_cmds + +# A language specific compiler. +CC=$lt_compiler + +# Is the compiler the GNU compiler? +with_gcc=$GCC + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag + +# Additional compiler flags for building library objects. +pic_flag=$lt_lt_prog_compiler_pic + +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_lt_prog_compiler_static + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_lt_cv_prog_compiler_c_o + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$archive_cmds_need_lc + +# Whether or not to disallow shared libs when runtime libs are static. +allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_export_dynamic_flag_spec + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_whole_archive_flag_spec + +# Whether the compiler copes with passing no objects directly. +compiler_needs_object=$lt_compiler_needs_object + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_old_archive_from_new_cmds + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds + +# Commands used to build a shared archive. +archive_cmds=$lt_archive_cmds +archive_expsym_cmds=$lt_archive_expsym_cmds + +# Commands used to build a loadable module if different from building +# a shared archive. +module_cmds=$lt_module_cmds +module_expsym_cmds=$lt_module_expsym_cmds + +# Whether we are building with GNU ld or not. +with_gnu_ld=$lt_with_gnu_ld + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_allow_undefined_flag + +# Flag that enforces no undefined symbols. +no_undefined_flag=$lt_no_undefined_flag + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist +hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec + +# Whether we need a single "-rpath" flag with a separated argument. +hardcode_libdir_separator=$lt_hardcode_libdir_separator + +# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes +# DIR into the resulting binary. +hardcode_direct=$hardcode_direct + +# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes +# DIR into the resulting binary and the resulting library dependency is +# "absolute",i.e impossible to change by setting \$shlibpath_var if the +# library is relocated. +hardcode_direct_absolute=$hardcode_direct_absolute + +# Set to "yes" if using the -LDIR flag during linking hardcodes DIR +# into the resulting binary. +hardcode_minus_L=$hardcode_minus_L + +# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR +# into the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var + +# Set to "yes" if building a shared library automatically hardcodes DIR +# into the library and all subsequent libraries and executables linked +# against it. +hardcode_automatic=$hardcode_automatic + +# Set to yes if linker adds runtime paths of dependent libraries +# to runtime path list. +inherit_rpath=$inherit_rpath + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$link_all_deplibs + +# Set to "yes" if exported symbols are required. +always_export_symbols=$always_export_symbols + +# The commands to list exported symbols. +export_symbols_cmds=$lt_export_symbols_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_exclude_expsyms + +# Symbols that must always be exported. +include_expsyms=$lt_include_expsyms + +# Commands necessary for linking programs (against libraries) with templates. +prelink_cmds=$lt_prelink_cmds + +# Commands necessary for finishing linking programs. +postlink_cmds=$lt_postlink_cmds + +# Specify filename containing input files. +file_list_spec=$lt_file_list_spec + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action + +# ### END LIBTOOL CONFIG + +_LT_EOF + + cat <<'_LT_EOF' >> "$cfgfile" + +# ### BEGIN FUNCTIONS SHARED WITH CONFIGURE + +# func_munge_path_list VARIABLE PATH +# ----------------------------------- +# VARIABLE is name of variable containing _space_ separated list of +# directories to be munged by the contents of PATH, which is string +# having a format: +# "DIR[:DIR]:" +# string "DIR[ DIR]" will be prepended to VARIABLE +# ":DIR[:DIR]" +# string "DIR[ DIR]" will be appended to VARIABLE +# "DIRP[:DIRP]::[DIRA:]DIRA" +# string "DIRP[ DIRP]" will be prepended to VARIABLE and string +# "DIRA[ DIRA]" will be appended to VARIABLE +# "DIR[:DIR]" +# VARIABLE will be replaced by "DIR[ DIR]" +func_munge_path_list () +{ + case x$2 in + x) + ;; + *:) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\" + ;; + x:*) + eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\" + ;; + *::*) + eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" + eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\" + ;; + *) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\" + ;; + esac +} + + +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +func_cc_basename () +{ + for cc_temp in $*""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac + done + func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` +} + + +# ### END FUNCTIONS SHARED WITH CONFIGURE + +_LT_EOF + + case $host_os in + aix3*) + cat <<\_LT_EOF >> "$cfgfile" +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test set != "${COLLECT_NAMES+set}"; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +_LT_EOF + ;; + esac + + +ltmain=$ac_aux_dir/ltmain.sh + + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '$q' "$ltmain" >> "$cfgfile" \ + || (rm -f "$cfgfile"; exit 1) + + mv -f "$cfgfile" "$ofile" || + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" + + ;; + "po/stamp-it":C) + if ! grep "^# INTLTOOL_MAKEFILE$" "po/Makefile.in" > /dev/null ; then + as_fn_error $? "po/Makefile.in.in was not created by intltoolize." "$LINENO" 5 + fi + rm -f "po/stamp-it" "po/stamp-it.tmp" "po/POTFILES" "po/Makefile.tmp" + >"po/stamp-it.tmp" + sed '/^#/d + s/^[[].*] *// + /^[ ]*$/d + '"s|^| $ac_top_srcdir/|" \ + "$srcdir/po/POTFILES.in" | sed '$!s/$/ \\/' >"po/POTFILES" + + sed '/^POTFILES =/,/[^\\]$/ { + /^POTFILES =/!d + r po/POTFILES + } + ' "po/Makefile.in" >"po/Makefile" + rm -f "po/Makefile.tmp" + mv "po/stamp-it.tmp" "po/stamp-it" + ;; + + 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 + diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..82fa424 --- /dev/null +++ b/configure.ac @@ -0,0 +1,433 @@ +dnl ******************************************* +dnl *** Initialize automake and set version *** +dnl ******************************************* + +m4_define([soup_major_version], [2]) +m4_define([soup_minor_version], [62]) +m4_define([soup_micro_version], [3]) + +AC_PREREQ(2.63) +AC_INIT([libsoup],[soup_major_version.soup_minor_version.soup_micro_version],[http://bugzilla.gnome.org/enter_bug.cgi?product=libsoup]) +AC_CONFIG_SRCDIR([libsoup-2.4.pc.in]) +AC_CONFIG_MACRO_DIR([m4]) +AC_CONFIG_AUX_DIR([build-aux]) + +AM_INIT_AUTOMAKE([1.11 foreign no-dist-gzip dist-xz -Wno-portability]) +m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])],) + +AC_PROG_MAKE_SET + +SOUP_MAJOR_VERSION=soup_major_version +SOUP_MINOR_VERSION=soup_minor_version +SOUP_MICRO_VERSION=soup_micro_version +AC_SUBST(SOUP_MAJOR_VERSION) +AC_SUBST(SOUP_MINOR_VERSION) +AC_SUBST(SOUP_MICRO_VERSION) + +SOUP_API_VERSION=2.4 +AC_SUBST(SOUP_API_VERSION) + +# Increment on interface addition. Reset on removal. +SOUP_AGE=8 + +# Increment on interface add, remove, or change. +SOUP_CURRENT=9 + +# Increment on source change. Reset when CURRENT changes. +SOUP_REVISION=0 + +AC_SUBST(SOUP_CURRENT) +AC_SUBST(SOUP_REVISION) +AC_SUBST(SOUP_AGE) + +dnl *************************** +dnl *** Set debugging flags *** +dnl *************************** + +debug_default=minimum + +# Declare --enable-* args and collect ac_help strings +AC_ARG_ENABLE(debug, + AS_HELP_STRING([--enable-debug=[no/minimum/yes]], + [turn on debugging (default=$debug_default)]),, + enable_debug=$debug_default) + +# Set the debug flags +if test "x$enable_debug" = "xyes"; then + test "$cflags_set" = set || CFLAGS="$CFLAGS -g" + SOUP_DEBUG_FLAGS="-DG_ENABLE_DEBUG" +else + if test "x$enable_debug" = "xno"; then + SOUP_DEBUG_FLAGS="-DG_DISABLE_ASSERT -DG_DISABLE_CHECKS" + fi +fi + +AC_SUBST(SOUP_DEBUG_FLAGS) + +dnl *************************** +dnl *** Checks for programs *** +dnl *************************** + +AC_PROG_CC +AC_PROG_INSTALL + +# Initialize libtool +LT_INIT([win32-dll]) + +dnl *********************** +dnl *** Checks for glib *** +dnl *********************** + +GLIB_REQUIRED=2.38.0 +AM_PATH_GLIB_2_0($GLIB_REQUIRED,,,gobject gio) +if test "$GLIB_LIBS" = ""; then + AC_MSG_ERROR(GLIB $GLIB_REQUIRED or later is required to build libsoup) +fi +GLIB_CFLAGS="$GLIB_CFLAGS -DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_2_38" + +GLIB_MAKEFILE='$(top_srcdir)/Makefile.glib' +AC_SUBST(GLIB_MAKEFILE) + +GLIB_TESTS + +PKG_CHECK_MODULES(XML, libxml-2.0) +AC_SUBST(XML_CFLAGS) +AC_SUBST(XML_LIBS) + +PKG_CHECK_MODULES(SQLITE, sqlite3) +AC_SUBST(SQLITE_CFLAGS) +AC_SUBST(SQLITE_LIBS) + +dnl *********************** +dnl *** Check for Win32 *** +dnl *********************** + +AC_MSG_CHECKING([for Win32]) +case "$host" in + *-*-mingw*) + os_win32=yes + os_linux=yes + CFLAGS="$CFLAGS -D_REENTRANT" + ;; + *-*-linux*) + os_win32=no + os_linux=yes + ;; + *) + os_win32=no + os_linux=no + ;; +esac +AC_MSG_RESULT([$os_win32]) +AM_CONDITIONAL(OS_WIN32, [test $os_win32 = yes]) +AM_CONDITIONAL(OS_LINUX, [test $os_linux = yes]) + +dnl ************************ +dnl *** gettext/intltool *** +dnl ************************ +IT_PROG_INTLTOOL([0.35.0]) +GETTEXT_PACKAGE=libsoup +AC_SUBST([GETTEXT_PACKAGE]) +AC_DEFINE_UNQUOTED([GETTEXT_PACKAGE],["$GETTEXT_PACKAGE"],[The gettext domain name]) + +dnl ******************* +dnl *** Misc checks *** +dnl ******************* +AC_CHECK_FUNCS(gmtime_r) + +dnl ********************* +dnl *** GNOME support *** +dnl ********************* +AC_MSG_CHECKING(whether to build libsoup-gnome) +AC_ARG_WITH(gnome, + AS_HELP_STRING([--without-gnome], [Do not build libsoup-gnome]), + :, [if test $os_win32 = yes; then with_gnome=no; else with_gnome=yes; fi]) +AC_MSG_RESULT($with_gnome) + +AM_CONDITIONAL(BUILD_LIBSOUP_GNOME, test $with_gnome != no) + +if test $with_gnome != no; then + AC_DEFINE(HAVE_GNOME, 1, [Defined if GNOME support is enabled]) +fi +AC_SUBST(HAVE_GNOME) + + +dnl *************** +dnl *** gtk-doc *** +dnl *************** +# gtkdocize greps for ^GTK_DOC_CHECK and parses it, so you need to have +# it on it's own line. +m4_ifdef([GTK_DOC_CHECK], [ +GTK_DOC_CHECK([1.20], [--flavour no-tmpl]) +],[]) + +dnl ***************************** +dnl *** gobject-introspection *** +dnl ***************************** +GOBJECT_INTROSPECTION_CHECK([0.9.5]) + +if test "$found_introspection" != "yes" -a "$enable_vala" = ""; then + enable_vala=no +fi +VAPIGEN_CHECK() + +AC_MSG_CHECKING([for glib-networking (glib TLS implementation)]) +save_CFLAGS="$CFLAGS" +save_LIBS="$LIBS" +CFLAGS="$CFLAGS $GLIB_CFLAGS" +LIBS="$LIBS $GLIB_LIBS" +AC_RUN_IFELSE([AC_LANG_PROGRAM([#include ], + [return !g_tls_backend_supports_tls (g_tls_backend_get_default ());])], + [have_glib_networking=yes], + [have_glib_networking=no], + [have_glib_networking="unknown (cross-compiling)"]) +CFLAGS="$save_CFLAGS" +LIBS="$save_LIBS" +AC_MSG_RESULT($have_glib_networking) + +AC_ARG_ENABLE(tls-check, + AS_HELP_STRING([--disable-tls-check], [Don't error out if glib-networking is unavailable])) +if test "$enable_tls_check" != "no" -a "$have_glib_networking" = "no"; then + AC_MSG_ERROR([libsoup requires glib-networking for TLS support. + +If you are building a package, you can pass --disable-tls-check to +allow building libsoup anyway (since glib-networking is not actually +required at compile time), but you should be sure to add a runtime +dependency on it.]) +fi + +dnl ****************************** +dnl *** Stuff for regression tests +dnl ****************************** +AC_MSG_NOTICE([checking for programs needed for regression tests]) + +AC_ARG_WITH(apache-httpd, + AS_HELP_STRING([--with-apache-httpd], [Path to apache httpd (for tests)]), + APACHE_HTTPD="$withval", + [AC_PATH_PROGS(APACHE_HTTPD, httpd2 httpd apache2 apache, no, ${PATH}:/usr/sbin)]) +if test "$APACHE_HTTPD" != "no"; then + AC_MSG_CHECKING([Apache version]) + apache_version=`$APACHE_HTTPD -v 2>/dev/null | sed -ne 's/Server version: Apache\///p'` + case $apache_version in + 2.4.*) + AC_MSG_RESULT([$apache_version (ok)]) + ;; + *) + AC_MSG_RESULT([$apache_version (ignoring)]) + APACHE_HTTPD="no" + ;; + esac +fi +AC_SUBST(APACHE_HTTPD) +AC_DEFINE_UNQUOTED(APACHE_HTTPD, "$APACHE_HTTPD", [Apache httpd]) + +if test "$APACHE_HTTPD" != "no"; then + AC_MSG_CHECKING([for Apache module directory]) + AC_ARG_WITH(apache-module-dir, + AS_HELP_STRING([--with-apache-module-dir], [Apache modules dirs (for tests)]), + apache_module_dirs="$withval", + [apache_prefix=`dirname \`dirname $APACHE_HTTPD\`` + mpm=`$APACHE_HTTPD -V -C "ServerName localhost" | sed -ne 's/^Server MPM: */-/p' | tr 'A-Z' 'a-z'` + # This only works with bash, but should fail harmlessly in sh + apache_module_dirs=`echo $apache_prefix/lib{64,}/{apache,apache2,http,http2,httpd}{$mpm,}{/modules,}`]) + for dir in $apache_module_dirs; do + if test -f $dir/mod_auth_digest.so; then + APACHE_MODULE_DIR="$dir" + fi + if test -f $dir/mod_ssl.so; then + APACHE_SSL_MODULE_DIR="$dir" + IF_HAVE_APACHE_SSL="" + fi + if test -f $dir/libphp7.so; then + APACHE_PHP_MODULE_DIR="$dir" + fi + done + AC_MSG_RESULT($APACHE_MODULE_DIR) + AC_SUBST(APACHE_MODULE_DIR) + AC_SUBST(APACHE_SSL_MODULE_DIR) + AC_SUBST(APACHE_PHP_MODULE_DIR) +fi + +if test "$APACHE_HTTPD" != "no" -a -n "$APACHE_MODULE_DIR" -a -n "$APACHE_SSL_MODULE_DIR"; then + AC_DEFINE(HAVE_APACHE, 1, [Whether or not apache can be used for tests]) + have_apache=1 +else + have_apache=0 +fi +AM_CONDITIONAL(HAVE_APACHE, test "$have_apache" = 1) + +if test "$have_apache" = 1; then + AC_CHECK_PROGS(PHP, php) + + AC_MSG_CHECKING([for Apache PHP module]) + if test -d "$APACHE_PHP_MODULE_DIR"; then + have_php="yes" + IF_HAVE_PHP="" + else + have_php="no" + IF_HAVE_PHP="#" + fi + AC_MSG_RESULT($have_php) + AC_SUBST(IF_HAVE_PHP) + + if test "$have_php" = yes; then + AC_MSG_CHECKING([for php-xmlrpc]) + if $PHP --rf xmlrpc_server_create | grep -q "does not exist"; then + have_php_xmlrpc=no + else + have_php_xmlrpc=yes + AC_DEFINE(HAVE_PHP_XMLRPC, 1, [Have php-xmlrpc]) + fi + AC_MSG_RESULT($have_php_xmlrpc) + fi + + if test -f "$APACHE_MODULE_DIR/mod_unixd.so"; then + IF_HAVE_MOD_UNIXD="" + else + IF_HAVE_MOD_UNIXD="#" + fi + AC_SUBST(IF_HAVE_MOD_UNIXD) +fi + +AC_PATH_PROG(CURL, curl, no) +if test "$CURL" != no; then + AC_DEFINE(HAVE_CURL, 1, [Whether or not curl can be used for tests]) +fi + +dnl ********************************************************** +dnl *** path of NTLM single-sign-on helper ntlm_auth +dnl ********************************************************** +AC_ARG_WITH(ntlm-auth, + AC_HELP_STRING([--with-ntlm-auth=PATH],[Where to look for ntlm_auth, path points to ntlm_auth installation (default: /usr/bin/ntlm_auth)]), + ntlm_auth="$withval", + [if test $os_win32 = yes; then ntlm_auth="no"; else ntlm_auth="/usr/bin/ntlm_auth"; fi]) +if test "$ntlm_auth" != "no"; then + AC_DEFINE(USE_NTLM_AUTH, 1, [Whether or not use Samba's 'winbind' daemon helper 'ntlm_auth' for NTLM single-sign-on]) + if test "$ntlm_auth" = "yes"; then + dnl --with-ntlm-auth (without path) used, use default path + ntlm_auth="/usr/bin/ntlm_auth" + fi +fi +AC_SUBST(ntlm_auth) +AC_DEFINE_UNQUOTED(NTLM_AUTH, "$ntlm_auth", [Samba's 'winbind' daemon helper 'ntlm_auth' which can be used for NTLM single-sign-on]) + +AX_CODE_COVERAGE + +dnl ********************** +dnl *** GSSAPI support *** +dnl ********************** +AC_ARG_WITH(gssapi, + AS_HELP_STRING([--with-gssapi], + [Build with GSSAPI support [default=auto]])) + +if test "$with_gssapi" != "no"; then + AC_ARG_WITH(krb5-config, + AS_HELP_STRING([--with-krb5-config=PATH],[Where to look for krb5-config, path points to krb5-config installation (default: /usr/kerberos/bin/)]), + KRB5_CONFIG="$withval", + [AC_PATH_PROGS(KRB5_CONFIG, krb5-config, no, ${PATH}:/usr/kerberos/bin)]) + + if test "$KRB5_CONFIG" != "no"; then + KRB5_LIBS="`${KRB5_CONFIG} --libs gssapi`" + KRB5_CFLAGS="`${KRB5_CONFIG} --cflags gssapi`" + AC_SUBST(KRB5_CFLAGS) + AC_SUBST(KRB5_LIBS) + if test "$KRB5_CONFIG" != none; then + AC_DEFINE(LIBSOUP_HAVE_GSSAPI, 1, [Whether or not GSSAPI libs are available]) + fi + else + if test "$with_gssapi" = "yes"; then + AC_MSG_ERROR([GSSAPI support requested but failed to found krb5-config. Try to set KRB5_CONFIG.]) + fi + fi +fi + +dnl **************************************************** +dnl *** Warnings to show if using GCC *** +dnl *** (do this last so -Werror won't mess up tests *** +dnl **************************************************** + +AC_ARG_ENABLE(more-warnings, + AS_HELP_STRING([--disable-more-warnings], [Inhibit compiler warnings]), + set_more_warnings=no) + +if test "$GCC" = "yes" -a "$set_more_warnings" != "no"; then + CFLAGS="$CFLAGS \ + -Wall -Wstrict-prototypes -Werror=missing-prototypes \ + -Werror=implicit-function-declaration \ + -Werror=pointer-arith -Werror=init-self -Werror=format=2 \ + -Wno-format-zero-length \ + -Werror=missing-include-dirs -Werror=aggregate-return \ + -Werror=declaration-after-statement" +fi + +################################################## +# Visibility handling +################################################## + +SOUP_HIDDEN_VISIBILITY_CFLAGS="" +case "$host" in + *-*-mingw*) + dnl on mingw32 we do -fvisibility=hidden and __declspec(dllexport) + AC_DEFINE([_SOUP_EXTERN], [__attribute__((visibility("default"))) __declspec(dllexport) extern], + [defines how to decorate public symbols while building]) + SOUP_HIDDEN_VISIBILITY_CFLAGS="-fvisibility=hidden" + ;; + *) + dnl on other compilers, check if we can do -fvisibility=hidden + SAVED_CFLAGS="${CFLAGS}" + CFLAGS="-fvisibility=hidden" + AC_MSG_CHECKING([for -fvisibility=hidden compiler flag]) + AC_TRY_COMPILE([], [return 0], + AC_MSG_RESULT(yes) + enable_fvisibility_hidden=yes, + AC_MSG_RESULT(no) + enable_fvisibility_hidden=no) + CFLAGS="${SAVED_CFLAGS}" + + AS_IF([test "${enable_fvisibility_hidden}" = "yes"], [ + AC_DEFINE([_SOUP_EXTERN], [__attribute__((visibility("default"))) extern], + [defines how to decorate public symbols while building]) + SOUP_HIDDEN_VISIBILITY_CFLAGS="-fvisibility=hidden" + ]) + ;; +esac +AC_SUBST(SOUP_HIDDEN_VISIBILITY_CFLAGS) + +dnl **************************************************** +dnl *** Check whether MSVC toolset is explicitly set *** +dnl **************************************************** +AM_CONDITIONAL(MSVC_BASE_NO_TOOLSET_SET, [test x$MSVC_BASE_TOOLSET = x]) +AM_CONDITIONAL(MSVC_NO_TOOLSET_SET, [test x$MSVC_TOOLSET = x]) + + +dnl ************************* +dnl *** Output Everything *** +dnl ************************* + +AC_CONFIG_HEADERS([config.h]) +AC_CONFIG_FILES([ + libsoup-2.4.pc + libsoup-gnome-2.4.pc + Makefile + libsoup-zip + libsoup/Makefile + po/Makefile.in + po/Makefile + tests/Makefile + tests/httpd.conf + examples/Makefile + docs/Makefile + docs/reference/Makefile + libsoup/soup-version.h + config.h.win32 + win32/Makefile + win32/vs9/Makefile + win32/vs9/soup-version-paths.vsprops + win32/vs10/Makefile + win32/vs10/soup-version-paths.props + win32/vs11/Makefile + win32/vs12/Makefile + win32/vs14/Makefile + win32/vs15/Makefile + ]) +AC_OUTPUT diff --git a/data/effective_tld_names.dat b/data/effective_tld_names.dat new file mode 100644 index 0000000..b2d261e --- /dev/null +++ b/data/effective_tld_names.dat @@ -0,0 +1,12370 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +// Please pull this list from, and only from https://publicsuffix.org/list/public_suffix_list.dat, +// rather than any other VCS sites. Pulling from any other URL is not guaranteed to be supported. + +// Instructions on pulling and using this list can be found at https://publicsuffix.org/list/. + +// ===BEGIN ICANN DOMAINS=== + +// ac : https://en.wikipedia.org/wiki/.ac +ac +com.ac +edu.ac +gov.ac +net.ac +mil.ac +org.ac + +// ad : https://en.wikipedia.org/wiki/.ad +ad +nom.ad + +// ae : https://en.wikipedia.org/wiki/.ae +// see also: "Domain Name Eligibility Policy" at http://www.aeda.ae/eng/aepolicy.php +ae +co.ae +net.ae +org.ae +sch.ae +ac.ae +gov.ae +mil.ae + +// aero : see https://www.information.aero/index.php?id=66 +aero +accident-investigation.aero +accident-prevention.aero +aerobatic.aero +aeroclub.aero +aerodrome.aero +agents.aero +aircraft.aero +airline.aero +airport.aero +air-surveillance.aero +airtraffic.aero +air-traffic-control.aero +ambulance.aero +amusement.aero +association.aero +author.aero +ballooning.aero +broker.aero +caa.aero +cargo.aero +catering.aero +certification.aero +championship.aero +charter.aero +civilaviation.aero +club.aero +conference.aero +consultant.aero +consulting.aero +control.aero +council.aero +crew.aero +design.aero +dgca.aero +educator.aero +emergency.aero +engine.aero +engineer.aero +entertainment.aero +equipment.aero +exchange.aero +express.aero +federation.aero +flight.aero +freight.aero +fuel.aero +gliding.aero +government.aero +groundhandling.aero +group.aero +hanggliding.aero +homebuilt.aero +insurance.aero +journal.aero +journalist.aero +leasing.aero +logistics.aero +magazine.aero +maintenance.aero +media.aero +microlight.aero +modelling.aero +navigation.aero +parachuting.aero +paragliding.aero +passenger-association.aero +pilot.aero +press.aero +production.aero +recreation.aero +repbody.aero +res.aero +research.aero +rotorcraft.aero +safety.aero +scientist.aero +services.aero +show.aero +skydiving.aero +software.aero +student.aero +trader.aero +trading.aero +trainer.aero +union.aero +workinggroup.aero +works.aero + +// af : http://www.nic.af/help.jsp +af +gov.af +com.af +org.af +net.af +edu.af + +// ag : http://www.nic.ag/prices.htm +ag +com.ag +org.ag +net.ag +co.ag +nom.ag + +// ai : http://nic.com.ai/ +ai +off.ai +com.ai +net.ai +org.ai + +// al : http://www.ert.gov.al/ert_alb/faq_det.html?Id=31 +al +com.al +edu.al +gov.al +mil.al +net.al +org.al + +// am : https://en.wikipedia.org/wiki/.am +am + +// ao : https://en.wikipedia.org/wiki/.ao +// http://www.dns.ao/REGISTR.DOC +ao +ed.ao +gv.ao +og.ao +co.ao +pb.ao +it.ao + +// aq : https://en.wikipedia.org/wiki/.aq +aq + +// ar : https://nic.ar/nic-argentina/normativa-vigente +ar +com.ar +edu.ar +gob.ar +gov.ar +int.ar +mil.ar +musica.ar +net.ar +org.ar +tur.ar + +// arpa : https://en.wikipedia.org/wiki/.arpa +// Confirmed by registry 2008-06-18 +arpa +e164.arpa +in-addr.arpa +ip6.arpa +iris.arpa +uri.arpa +urn.arpa + +// as : https://en.wikipedia.org/wiki/.as +as +gov.as + +// asia : https://en.wikipedia.org/wiki/.asia +asia + +// at : https://en.wikipedia.org/wiki/.at +// Confirmed by registry 2008-06-17 +at +ac.at +co.at +gv.at +or.at + +// au : https://en.wikipedia.org/wiki/.au +// http://www.auda.org.au/ +au +// 2LDs +com.au +net.au +org.au +edu.au +gov.au +asn.au +id.au +// Historic 2LDs (closed to new registration, but sites still exist) +info.au +conf.au +oz.au +// CGDNs - http://www.cgdn.org.au/ +act.au +nsw.au +nt.au +qld.au +sa.au +tas.au +vic.au +wa.au +// 3LDs +act.edu.au +nsw.edu.au +nt.edu.au +qld.edu.au +sa.edu.au +tas.edu.au +vic.edu.au +wa.edu.au +// act.gov.au Bug 984824 - Removed at request of Greg Tankard +// nsw.gov.au Bug 547985 - Removed at request of +// nt.gov.au Bug 940478 - Removed at request of Greg Connors +qld.gov.au +sa.gov.au +tas.gov.au +vic.gov.au +wa.gov.au + +// aw : https://en.wikipedia.org/wiki/.aw +aw +com.aw + +// ax : https://en.wikipedia.org/wiki/.ax +ax + +// az : https://en.wikipedia.org/wiki/.az +az +com.az +net.az +int.az +gov.az +org.az +edu.az +info.az +pp.az +mil.az +name.az +pro.az +biz.az + +// ba : http://nic.ba/users_data/files/pravilnik_o_registraciji.pdf +ba +com.ba +edu.ba +gov.ba +mil.ba +net.ba +org.ba + +// bb : https://en.wikipedia.org/wiki/.bb +bb +biz.bb +co.bb +com.bb +edu.bb +gov.bb +info.bb +net.bb +org.bb +store.bb +tv.bb + +// bd : https://en.wikipedia.org/wiki/.bd +*.bd + +// be : https://en.wikipedia.org/wiki/.be +// Confirmed by registry 2008-06-08 +be +ac.be + +// bf : https://en.wikipedia.org/wiki/.bf +bf +gov.bf + +// bg : https://en.wikipedia.org/wiki/.bg +// https://www.register.bg/user/static/rules/en/index.html +bg +a.bg +b.bg +c.bg +d.bg +e.bg +f.bg +g.bg +h.bg +i.bg +j.bg +k.bg +l.bg +m.bg +n.bg +o.bg +p.bg +q.bg +r.bg +s.bg +t.bg +u.bg +v.bg +w.bg +x.bg +y.bg +z.bg +0.bg +1.bg +2.bg +3.bg +4.bg +5.bg +6.bg +7.bg +8.bg +9.bg + +// bh : https://en.wikipedia.org/wiki/.bh +bh +com.bh +edu.bh +net.bh +org.bh +gov.bh + +// bi : https://en.wikipedia.org/wiki/.bi +// http://whois.nic.bi/ +bi +co.bi +com.bi +edu.bi +or.bi +org.bi + +// biz : https://en.wikipedia.org/wiki/.biz +biz + +// bj : https://en.wikipedia.org/wiki/.bj +bj +asso.bj +barreau.bj +gouv.bj + +// bm : http://www.bermudanic.bm/dnr-text.txt +bm +com.bm +edu.bm +gov.bm +net.bm +org.bm + +// bn : https://en.wikipedia.org/wiki/.bn +*.bn + +// bo : https://nic.bo/delegacion2015.php#h-1.10 +bo +com.bo +edu.bo +gob.bo +int.bo +org.bo +net.bo +mil.bo +tv.bo +web.bo +// Social Domains +academia.bo +agro.bo +arte.bo +blog.bo +bolivia.bo +ciencia.bo +cooperativa.bo +democracia.bo +deporte.bo +ecologia.bo +economia.bo +empresa.bo +indigena.bo +industria.bo +info.bo +medicina.bo +movimiento.bo +musica.bo +natural.bo +nombre.bo +noticias.bo +patria.bo +politica.bo +profesional.bo +plurinacional.bo +pueblo.bo +revista.bo +salud.bo +tecnologia.bo +tksat.bo +transporte.bo +wiki.bo + +// br : http://registro.br/dominio/categoria.html +// Submitted by registry +br +9guacu.br +abc.br +adm.br +adv.br +agr.br +aju.br +am.br +anani.br +aparecida.br +arq.br +art.br +ato.br +b.br +belem.br +bhz.br +bio.br +blog.br +bmd.br +boavista.br +bsb.br +campinagrande.br +campinas.br +caxias.br +cim.br +cng.br +cnt.br +com.br +contagem.br +coop.br +cri.br +cuiaba.br +curitiba.br +def.br +ecn.br +eco.br +edu.br +emp.br +eng.br +esp.br +etc.br +eti.br +far.br +feira.br +flog.br +floripa.br +fm.br +fnd.br +fortal.br +fot.br +foz.br +fst.br +g12.br +ggf.br +goiania.br +gov.br +// gov.br 26 states + df https://en.wikipedia.org/wiki/States_of_Brazil +ac.gov.br +al.gov.br +am.gov.br +ap.gov.br +ba.gov.br +ce.gov.br +df.gov.br +es.gov.br +go.gov.br +ma.gov.br +mg.gov.br +ms.gov.br +mt.gov.br +pa.gov.br +pb.gov.br +pe.gov.br +pi.gov.br +pr.gov.br +rj.gov.br +rn.gov.br +ro.gov.br +rr.gov.br +rs.gov.br +sc.gov.br +se.gov.br +sp.gov.br +to.gov.br +gru.br +imb.br +ind.br +inf.br +jab.br +jampa.br +jdf.br +joinville.br +jor.br +jus.br +leg.br +lel.br +londrina.br +macapa.br +maceio.br +manaus.br +maringa.br +mat.br +med.br +mil.br +morena.br +mp.br +mus.br +natal.br +net.br +niteroi.br +*.nom.br +not.br +ntr.br +odo.br +org.br +osasco.br +palmas.br +poa.br +ppg.br +pro.br +psc.br +psi.br +pvh.br +qsl.br +radio.br +rec.br +recife.br +ribeirao.br +rio.br +riobranco.br +riopreto.br +salvador.br +sampa.br +santamaria.br +santoandre.br +saobernardo.br +saogonca.br +sjc.br +slg.br +slz.br +sorocaba.br +srv.br +taxi.br +teo.br +the.br +tmp.br +trd.br +tur.br +tv.br +udi.br +vet.br +vix.br +vlog.br +wiki.br +zlg.br + +// bs : http://www.nic.bs/rules.html +bs +com.bs +net.bs +org.bs +edu.bs +gov.bs + +// bt : https://en.wikipedia.org/wiki/.bt +bt +com.bt +edu.bt +gov.bt +net.bt +org.bt + +// bv : No registrations at this time. +// Submitted by registry +bv + +// bw : https://en.wikipedia.org/wiki/.bw +// http://www.gobin.info/domainname/bw.doc +// list of other 2nd level tlds ? +bw +co.bw +org.bw + +// by : https://en.wikipedia.org/wiki/.by +// http://tld.by/rules_2006_en.html +// list of other 2nd level tlds ? +by +gov.by +mil.by +// Official information does not indicate that com.by is a reserved +// second-level domain, but it's being used as one (see www.google.com.by and +// www.yahoo.com.by, for example), so we list it here for safety's sake. +com.by + +// http://hoster.by/ +of.by + +// bz : https://en.wikipedia.org/wiki/.bz +// http://www.belizenic.bz/ +bz +com.bz +net.bz +org.bz +edu.bz +gov.bz + +// ca : https://en.wikipedia.org/wiki/.ca +ca +// ca geographical names +ab.ca +bc.ca +mb.ca +nb.ca +nf.ca +nl.ca +ns.ca +nt.ca +nu.ca +on.ca +pe.ca +qc.ca +sk.ca +yk.ca +// gc.ca: https://en.wikipedia.org/wiki/.gc.ca +// see also: http://registry.gc.ca/en/SubdomainFAQ +gc.ca + +// cat : https://en.wikipedia.org/wiki/.cat +cat + +// cc : https://en.wikipedia.org/wiki/.cc +cc + +// cd : https://en.wikipedia.org/wiki/.cd +// see also: https://www.nic.cd/domain/insertDomain_2.jsp?act=1 +cd +gov.cd + +// cf : https://en.wikipedia.org/wiki/.cf +cf + +// cg : https://en.wikipedia.org/wiki/.cg +cg + +// ch : https://en.wikipedia.org/wiki/.ch +ch + +// ci : https://en.wikipedia.org/wiki/.ci +// http://www.nic.ci/index.php?page=charte +ci +org.ci +or.ci +com.ci +co.ci +edu.ci +ed.ci +ac.ci +net.ci +go.ci +asso.ci +aéroport.ci +int.ci +presse.ci +md.ci +gouv.ci + +// ck : https://en.wikipedia.org/wiki/.ck +*.ck +!www.ck + +// cl : https://en.wikipedia.org/wiki/.cl +cl +gov.cl +gob.cl +co.cl +mil.cl + +// cm : https://en.wikipedia.org/wiki/.cm plus bug 981927 +cm +co.cm +com.cm +gov.cm +net.cm + +// cn : https://en.wikipedia.org/wiki/.cn +// Submitted by registry +cn +ac.cn +com.cn +edu.cn +gov.cn +net.cn +org.cn +mil.cn +公司.cn +网络.cn +網絡.cn +// cn geographic names +ah.cn +bj.cn +cq.cn +fj.cn +gd.cn +gs.cn +gz.cn +gx.cn +ha.cn +hb.cn +he.cn +hi.cn +hl.cn +hn.cn +jl.cn +js.cn +jx.cn +ln.cn +nm.cn +nx.cn +qh.cn +sc.cn +sd.cn +sh.cn +sn.cn +sx.cn +tj.cn +xj.cn +xz.cn +yn.cn +zj.cn +hk.cn +mo.cn +tw.cn + +// co : https://en.wikipedia.org/wiki/.co +// Submitted by registry +co +arts.co +com.co +edu.co +firm.co +gov.co +info.co +int.co +mil.co +net.co +nom.co +org.co +rec.co +web.co + +// com : https://en.wikipedia.org/wiki/.com +com + +// coop : https://en.wikipedia.org/wiki/.coop +coop + +// cr : http://www.nic.cr/niccr_publico/showRegistroDominiosScreen.do +cr +ac.cr +co.cr +ed.cr +fi.cr +go.cr +or.cr +sa.cr + +// cu : https://en.wikipedia.org/wiki/.cu +cu +com.cu +edu.cu +org.cu +net.cu +gov.cu +inf.cu + +// cv : https://en.wikipedia.org/wiki/.cv +cv + +// cw : http://www.una.cw/cw_registry/ +// Confirmed by registry 2013-03-26 +cw +com.cw +edu.cw +net.cw +org.cw + +// cx : https://en.wikipedia.org/wiki/.cx +// list of other 2nd level tlds ? +cx +gov.cx + +// cy : http://www.nic.cy/ +// Submitted by registry Panayiotou Fotia +cy +ac.cy +biz.cy +com.cy +ekloges.cy +gov.cy +ltd.cy +name.cy +net.cy +org.cy +parliament.cy +press.cy +pro.cy +tm.cy + +// cz : https://en.wikipedia.org/wiki/.cz +cz + +// de : https://en.wikipedia.org/wiki/.de +// Confirmed by registry (with technical +// reservations) 2008-07-01 +de + +// dj : https://en.wikipedia.org/wiki/.dj +dj + +// dk : https://en.wikipedia.org/wiki/.dk +// Confirmed by registry 2008-06-17 +dk + +// dm : https://en.wikipedia.org/wiki/.dm +dm +com.dm +net.dm +org.dm +edu.dm +gov.dm + +// do : https://en.wikipedia.org/wiki/.do +do +art.do +com.do +edu.do +gob.do +gov.do +mil.do +net.do +org.do +sld.do +web.do + +// dz : https://en.wikipedia.org/wiki/.dz +dz +com.dz +org.dz +net.dz +gov.dz +edu.dz +asso.dz +pol.dz +art.dz + +// ec : http://www.nic.ec/reg/paso1.asp +// Submitted by registry +ec +com.ec +info.ec +net.ec +fin.ec +k12.ec +med.ec +pro.ec +org.ec +edu.ec +gov.ec +gob.ec +mil.ec + +// edu : https://en.wikipedia.org/wiki/.edu +edu + +// ee : http://www.eenet.ee/EENet/dom_reeglid.html#lisa_B +ee +edu.ee +gov.ee +riik.ee +lib.ee +med.ee +com.ee +pri.ee +aip.ee +org.ee +fie.ee + +// eg : https://en.wikipedia.org/wiki/.eg +eg +com.eg +edu.eg +eun.eg +gov.eg +mil.eg +name.eg +net.eg +org.eg +sci.eg + +// er : https://en.wikipedia.org/wiki/.er +*.er + +// es : https://www.nic.es/site_ingles/ingles/dominios/index.html +es +com.es +nom.es +org.es +gob.es +edu.es + +// et : https://en.wikipedia.org/wiki/.et +et +com.et +gov.et +org.et +edu.et +biz.et +name.et +info.et +net.et + +// eu : https://en.wikipedia.org/wiki/.eu +eu + +// fi : https://en.wikipedia.org/wiki/.fi +fi +// aland.fi : https://en.wikipedia.org/wiki/.ax +// This domain is being phased out in favor of .ax. As there are still many +// domains under aland.fi, we still keep it on the list until aland.fi is +// completely removed. +// TODO: Check for updates (expected to be phased out around Q1/2009) +aland.fi + +// fj : https://en.wikipedia.org/wiki/.fj +*.fj + +// fk : https://en.wikipedia.org/wiki/.fk +*.fk + +// fm : https://en.wikipedia.org/wiki/.fm +fm + +// fo : https://en.wikipedia.org/wiki/.fo +fo + +// fr : http://www.afnic.fr/ +// domaines descriptifs : http://www.afnic.fr/obtenir/chartes/nommage-fr/annexe-descriptifs +fr +com.fr +asso.fr +nom.fr +prd.fr +presse.fr +tm.fr +// domaines sectoriels : http://www.afnic.fr/obtenir/chartes/nommage-fr/annexe-sectoriels +aeroport.fr +assedic.fr +avocat.fr +avoues.fr +cci.fr +chambagri.fr +chirurgiens-dentistes.fr +experts-comptables.fr +geometre-expert.fr +gouv.fr +greta.fr +huissier-justice.fr +medecin.fr +notaires.fr +pharmacien.fr +port.fr +veterinaire.fr + +// ga : https://en.wikipedia.org/wiki/.ga +ga + +// gb : This registry is effectively dormant +// Submitted by registry +gb + +// gd : https://en.wikipedia.org/wiki/.gd +gd + +// ge : http://www.nic.net.ge/policy_en.pdf +ge +com.ge +edu.ge +gov.ge +org.ge +mil.ge +net.ge +pvt.ge + +// gf : https://en.wikipedia.org/wiki/.gf +gf + +// gg : http://www.channelisles.net/register-domains/ +// Confirmed by registry 2013-11-28 +gg +co.gg +net.gg +org.gg + +// gh : https://en.wikipedia.org/wiki/.gh +// see also: http://www.nic.gh/reg_now.php +// Although domains directly at second level are not possible at the moment, +// they have been possible for some time and may come back. +gh +com.gh +edu.gh +gov.gh +org.gh +mil.gh + +// gi : http://www.nic.gi/rules.html +gi +com.gi +ltd.gi +gov.gi +mod.gi +edu.gi +org.gi + +// gl : https://en.wikipedia.org/wiki/.gl +// http://nic.gl +gl +co.gl +com.gl +edu.gl +net.gl +org.gl + +// gm : http://www.nic.gm/htmlpages%5Cgm-policy.htm +gm + +// gn : http://psg.com/dns/gn/gn.txt +// Submitted by registry +gn +ac.gn +com.gn +edu.gn +gov.gn +org.gn +net.gn + +// gov : https://en.wikipedia.org/wiki/.gov +gov + +// gp : http://www.nic.gp/index.php?lang=en +gp +com.gp +net.gp +mobi.gp +edu.gp +org.gp +asso.gp + +// gq : https://en.wikipedia.org/wiki/.gq +gq + +// gr : https://grweb.ics.forth.gr/english/1617-B-2005.html +// Submitted by registry +gr +com.gr +edu.gr +net.gr +org.gr +gov.gr + +// gs : https://en.wikipedia.org/wiki/.gs +gs + +// gt : http://www.gt/politicas_de_registro.html +gt +com.gt +edu.gt +gob.gt +ind.gt +mil.gt +net.gt +org.gt + +// gu : http://gadao.gov.gu/registration.txt +*.gu + +// gw : https://en.wikipedia.org/wiki/.gw +gw + +// gy : https://en.wikipedia.org/wiki/.gy +// http://registry.gy/ +gy +co.gy +com.gy +edu.gy +gov.gy +net.gy +org.gy + +// hk : https://www.hkdnr.hk +// Submitted by registry +hk +com.hk +edu.hk +gov.hk +idv.hk +net.hk +org.hk +公司.hk +教育.hk +敎育.hk +政府.hk +個人.hk +个人.hk +箇人.hk +網络.hk +网络.hk +组織.hk +網絡.hk +网絡.hk +组织.hk +組織.hk +組织.hk + +// hm : https://en.wikipedia.org/wiki/.hm +hm + +// hn : http://www.nic.hn/politicas/ps02,,05.html +hn +com.hn +edu.hn +org.hn +net.hn +mil.hn +gob.hn + +// hr : http://www.dns.hr/documents/pdf/HRTLD-regulations.pdf +hr +iz.hr +from.hr +name.hr +com.hr + +// ht : http://www.nic.ht/info/charte.cfm +ht +com.ht +shop.ht +firm.ht +info.ht +adult.ht +net.ht +pro.ht +org.ht +med.ht +art.ht +coop.ht +pol.ht +asso.ht +edu.ht +rel.ht +gouv.ht +perso.ht + +// hu : http://www.domain.hu/domain/English/sld.html +// Confirmed by registry 2008-06-12 +hu +co.hu +info.hu +org.hu +priv.hu +sport.hu +tm.hu +2000.hu +agrar.hu +bolt.hu +casino.hu +city.hu +erotica.hu +erotika.hu +film.hu +forum.hu +games.hu +hotel.hu +ingatlan.hu +jogasz.hu +konyvelo.hu +lakas.hu +media.hu +news.hu +reklam.hu +sex.hu +shop.hu +suli.hu +szex.hu +tozsde.hu +utazas.hu +video.hu + +// id : https://register.pandi.or.id/ +id +ac.id +biz.id +co.id +desa.id +go.id +mil.id +my.id +net.id +or.id +sch.id +web.id + +// ie : https://en.wikipedia.org/wiki/.ie +ie +gov.ie + +// il : http://www.isoc.org.il/domains/ +il +ac.il +co.il +gov.il +idf.il +k12.il +muni.il +net.il +org.il + +// im : https://www.nic.im/ +// Submitted by registry +im +ac.im +co.im +com.im +ltd.co.im +net.im +org.im +plc.co.im +tt.im +tv.im + +// in : https://en.wikipedia.org/wiki/.in +// see also: https://registry.in/Policies +// Please note, that nic.in is not an official eTLD, but used by most +// government institutions. +in +co.in +firm.in +net.in +org.in +gen.in +ind.in +nic.in +ac.in +edu.in +res.in +gov.in +mil.in + +// info : https://en.wikipedia.org/wiki/.info +info + +// int : https://en.wikipedia.org/wiki/.int +// Confirmed by registry 2008-06-18 +int +eu.int + +// io : http://www.nic.io/rules.html +// list of other 2nd level tlds ? +io +com.io + +// iq : http://www.cmc.iq/english/iq/iqregister1.htm +iq +gov.iq +edu.iq +mil.iq +com.iq +org.iq +net.iq + +// ir : http://www.nic.ir/Terms_and_Conditions_ir,_Appendix_1_Domain_Rules +// Also see http://www.nic.ir/Internationalized_Domain_Names +// Two .ir entries added at request of , 2010-04-16 +ir +ac.ir +co.ir +gov.ir +id.ir +net.ir +org.ir +sch.ir +// xn--mgba3a4f16a.ir (.ir, Persian YEH) +ایران.ir +// xn--mgba3a4fra.ir (.ir, Arabic YEH) +ايران.ir + +// is : http://www.isnic.is/domain/rules.php +// Confirmed by registry 2008-12-06 +is +net.is +com.is +edu.is +gov.is +org.is +int.is + +// it : https://en.wikipedia.org/wiki/.it +it +gov.it +edu.it +// Reserved geo-names: +// http://www.nic.it/documenti/regolamenti-e-linee-guida/regolamento-assegnazione-versione-6.0.pdf +// There is also a list of reserved geo-names corresponding to Italian municipalities +// http://www.nic.it/documenti/appendice-c.pdf, but it is not included here. +// Regions +abr.it +abruzzo.it +aosta-valley.it +aostavalley.it +bas.it +basilicata.it +cal.it +calabria.it +cam.it +campania.it +emilia-romagna.it +emiliaromagna.it +emr.it +friuli-v-giulia.it +friuli-ve-giulia.it +friuli-vegiulia.it +friuli-venezia-giulia.it +friuli-veneziagiulia.it +friuli-vgiulia.it +friuliv-giulia.it +friulive-giulia.it +friulivegiulia.it +friulivenezia-giulia.it +friuliveneziagiulia.it +friulivgiulia.it +fvg.it +laz.it +lazio.it +lig.it +liguria.it +lom.it +lombardia.it +lombardy.it +lucania.it +mar.it +marche.it +mol.it +molise.it +piedmont.it +piemonte.it +pmn.it +pug.it +puglia.it +sar.it +sardegna.it +sardinia.it +sic.it +sicilia.it +sicily.it +taa.it +tos.it +toscana.it +trentino-a-adige.it +trentino-aadige.it +trentino-alto-adige.it +trentino-altoadige.it +trentino-s-tirol.it +trentino-stirol.it +trentino-sud-tirol.it +trentino-sudtirol.it +trentino-sued-tirol.it +trentino-suedtirol.it +trentinoa-adige.it +trentinoaadige.it +trentinoalto-adige.it +trentinoaltoadige.it +trentinos-tirol.it +trentinostirol.it +trentinosud-tirol.it +trentinosudtirol.it +trentinosued-tirol.it +trentinosuedtirol.it +tuscany.it +umb.it +umbria.it +val-d-aosta.it +val-daosta.it +vald-aosta.it +valdaosta.it +valle-aosta.it +valle-d-aosta.it +valle-daosta.it +valleaosta.it +valled-aosta.it +valledaosta.it +vallee-aoste.it +valleeaoste.it +vao.it +vda.it +ven.it +veneto.it +// Provinces +ag.it +agrigento.it +al.it +alessandria.it +alto-adige.it +altoadige.it +an.it +ancona.it +andria-barletta-trani.it +andria-trani-barletta.it +andriabarlettatrani.it +andriatranibarletta.it +ao.it +aosta.it +aoste.it +ap.it +aq.it +aquila.it +ar.it +arezzo.it +ascoli-piceno.it +ascolipiceno.it +asti.it +at.it +av.it +avellino.it +ba.it +balsan.it +bari.it +barletta-trani-andria.it +barlettatraniandria.it +belluno.it +benevento.it +bergamo.it +bg.it +bi.it +biella.it +bl.it +bn.it +bo.it +bologna.it +bolzano.it +bozen.it +br.it +brescia.it +brindisi.it +bs.it +bt.it +bz.it +ca.it +cagliari.it +caltanissetta.it +campidano-medio.it +campidanomedio.it +campobasso.it +carbonia-iglesias.it +carboniaiglesias.it +carrara-massa.it +carraramassa.it +caserta.it +catania.it +catanzaro.it +cb.it +ce.it +cesena-forli.it +cesenaforli.it +ch.it +chieti.it +ci.it +cl.it +cn.it +co.it +como.it +cosenza.it +cr.it +cremona.it +crotone.it +cs.it +ct.it +cuneo.it +cz.it +dell-ogliastra.it +dellogliastra.it +en.it +enna.it +fc.it +fe.it +fermo.it +ferrara.it +fg.it +fi.it +firenze.it +florence.it +fm.it +foggia.it +forli-cesena.it +forlicesena.it +fr.it +frosinone.it +ge.it +genoa.it +genova.it +go.it +gorizia.it +gr.it +grosseto.it +iglesias-carbonia.it +iglesiascarbonia.it +im.it +imperia.it +is.it +isernia.it +kr.it +la-spezia.it +laquila.it +laspezia.it +latina.it +lc.it +le.it +lecce.it +lecco.it +li.it +livorno.it +lo.it +lodi.it +lt.it +lu.it +lucca.it +macerata.it +mantova.it +massa-carrara.it +massacarrara.it +matera.it +mb.it +mc.it +me.it +medio-campidano.it +mediocampidano.it +messina.it +mi.it +milan.it +milano.it +mn.it +mo.it +modena.it +monza-brianza.it +monza-e-della-brianza.it +monza.it +monzabrianza.it +monzaebrianza.it +monzaedellabrianza.it +ms.it +mt.it +na.it +naples.it +napoli.it +no.it +novara.it +nu.it +nuoro.it +og.it +ogliastra.it +olbia-tempio.it +olbiatempio.it +or.it +oristano.it +ot.it +pa.it +padova.it +padua.it +palermo.it +parma.it +pavia.it +pc.it +pd.it +pe.it +perugia.it +pesaro-urbino.it +pesarourbino.it +pescara.it +pg.it +pi.it +piacenza.it +pisa.it +pistoia.it +pn.it +po.it +pordenone.it +potenza.it +pr.it +prato.it +pt.it +pu.it +pv.it +pz.it +ra.it +ragusa.it +ravenna.it +rc.it +re.it +reggio-calabria.it +reggio-emilia.it +reggiocalabria.it +reggioemilia.it +rg.it +ri.it +rieti.it +rimini.it +rm.it +rn.it +ro.it +roma.it +rome.it +rovigo.it +sa.it +salerno.it +sassari.it +savona.it +si.it +siena.it +siracusa.it +so.it +sondrio.it +sp.it +sr.it +ss.it +suedtirol.it +sv.it +ta.it +taranto.it +te.it +tempio-olbia.it +tempioolbia.it +teramo.it +terni.it +tn.it +to.it +torino.it +tp.it +tr.it +trani-andria-barletta.it +trani-barletta-andria.it +traniandriabarletta.it +tranibarlettaandria.it +trapani.it +trentino.it +trento.it +treviso.it +trieste.it +ts.it +turin.it +tv.it +ud.it +udine.it +urbino-pesaro.it +urbinopesaro.it +va.it +varese.it +vb.it +vc.it +ve.it +venezia.it +venice.it +verbania.it +vercelli.it +verona.it +vi.it +vibo-valentia.it +vibovalentia.it +vicenza.it +viterbo.it +vr.it +vs.it +vt.it +vv.it + +// je : http://www.channelisles.net/register-domains/ +// Confirmed by registry 2013-11-28 +je +co.je +net.je +org.je + +// jm : http://www.com.jm/register.html +*.jm + +// jo : http://www.dns.jo/Registration_policy.aspx +jo +com.jo +org.jo +net.jo +edu.jo +sch.jo +gov.jo +mil.jo +name.jo + +// jobs : https://en.wikipedia.org/wiki/.jobs +jobs + +// jp : https://en.wikipedia.org/wiki/.jp +// http://jprs.co.jp/en/jpdomain.html +// Submitted by registry +jp +// jp organizational type names +ac.jp +ad.jp +co.jp +ed.jp +go.jp +gr.jp +lg.jp +ne.jp +or.jp +// jp prefecture type names +aichi.jp +akita.jp +aomori.jp +chiba.jp +ehime.jp +fukui.jp +fukuoka.jp +fukushima.jp +gifu.jp +gunma.jp +hiroshima.jp +hokkaido.jp +hyogo.jp +ibaraki.jp +ishikawa.jp +iwate.jp +kagawa.jp +kagoshima.jp +kanagawa.jp +kochi.jp +kumamoto.jp +kyoto.jp +mie.jp +miyagi.jp +miyazaki.jp +nagano.jp +nagasaki.jp +nara.jp +niigata.jp +oita.jp +okayama.jp +okinawa.jp +osaka.jp +saga.jp +saitama.jp +shiga.jp +shimane.jp +shizuoka.jp +tochigi.jp +tokushima.jp +tokyo.jp +tottori.jp +toyama.jp +wakayama.jp +yamagata.jp +yamaguchi.jp +yamanashi.jp +栃木.jp +愛知.jp +愛媛.jp +兵庫.jp +熊本.jp +茨城.jp +北海道.jp +千葉.jp +和歌山.jp +長崎.jp +長野.jp +新潟.jp +青森.jp +静岡.jp +東京.jp +石川.jp +埼玉.jp +三重.jp +京都.jp +佐賀.jp +大分.jp +大阪.jp +奈良.jp +宮城.jp +宮崎.jp +富山.jp +山口.jp +山形.jp +山梨.jp +岩手.jp +岐阜.jp +岡山.jp +島根.jp +広島.jp +徳島.jp +沖縄.jp +滋賀.jp +神奈川.jp +福井.jp +福岡.jp +福島.jp +秋田.jp +群馬.jp +香川.jp +高知.jp +鳥取.jp +鹿児島.jp +// jp geographic type names +// http://jprs.jp/doc/rule/saisoku-1.html +*.kawasaki.jp +*.kitakyushu.jp +*.kobe.jp +*.nagoya.jp +*.sapporo.jp +*.sendai.jp +*.yokohama.jp +!city.kawasaki.jp +!city.kitakyushu.jp +!city.kobe.jp +!city.nagoya.jp +!city.sapporo.jp +!city.sendai.jp +!city.yokohama.jp +// 4th level registration +aisai.aichi.jp +ama.aichi.jp +anjo.aichi.jp +asuke.aichi.jp +chiryu.aichi.jp +chita.aichi.jp +fuso.aichi.jp +gamagori.aichi.jp +handa.aichi.jp +hazu.aichi.jp +hekinan.aichi.jp +higashiura.aichi.jp +ichinomiya.aichi.jp +inazawa.aichi.jp +inuyama.aichi.jp +isshiki.aichi.jp +iwakura.aichi.jp +kanie.aichi.jp +kariya.aichi.jp +kasugai.aichi.jp +kira.aichi.jp +kiyosu.aichi.jp +komaki.aichi.jp +konan.aichi.jp +kota.aichi.jp +mihama.aichi.jp +miyoshi.aichi.jp +nishio.aichi.jp +nisshin.aichi.jp +obu.aichi.jp +oguchi.aichi.jp +oharu.aichi.jp +okazaki.aichi.jp +owariasahi.aichi.jp +seto.aichi.jp +shikatsu.aichi.jp +shinshiro.aichi.jp +shitara.aichi.jp +tahara.aichi.jp +takahama.aichi.jp +tobishima.aichi.jp +toei.aichi.jp +togo.aichi.jp +tokai.aichi.jp +tokoname.aichi.jp +toyoake.aichi.jp +toyohashi.aichi.jp +toyokawa.aichi.jp +toyone.aichi.jp +toyota.aichi.jp +tsushima.aichi.jp +yatomi.aichi.jp +akita.akita.jp +daisen.akita.jp +fujisato.akita.jp +gojome.akita.jp +hachirogata.akita.jp +happou.akita.jp +higashinaruse.akita.jp +honjo.akita.jp +honjyo.akita.jp +ikawa.akita.jp +kamikoani.akita.jp +kamioka.akita.jp +katagami.akita.jp +kazuno.akita.jp +kitaakita.akita.jp +kosaka.akita.jp +kyowa.akita.jp +misato.akita.jp +mitane.akita.jp +moriyoshi.akita.jp +nikaho.akita.jp +noshiro.akita.jp +odate.akita.jp +oga.akita.jp +ogata.akita.jp +semboku.akita.jp +yokote.akita.jp +yurihonjo.akita.jp +aomori.aomori.jp +gonohe.aomori.jp +hachinohe.aomori.jp +hashikami.aomori.jp +hiranai.aomori.jp +hirosaki.aomori.jp +itayanagi.aomori.jp +kuroishi.aomori.jp +misawa.aomori.jp +mutsu.aomori.jp +nakadomari.aomori.jp +noheji.aomori.jp +oirase.aomori.jp +owani.aomori.jp +rokunohe.aomori.jp +sannohe.aomori.jp +shichinohe.aomori.jp +shingo.aomori.jp +takko.aomori.jp +towada.aomori.jp +tsugaru.aomori.jp +tsuruta.aomori.jp +abiko.chiba.jp +asahi.chiba.jp +chonan.chiba.jp +chosei.chiba.jp +choshi.chiba.jp +chuo.chiba.jp +funabashi.chiba.jp +futtsu.chiba.jp +hanamigawa.chiba.jp +ichihara.chiba.jp +ichikawa.chiba.jp +ichinomiya.chiba.jp +inzai.chiba.jp +isumi.chiba.jp +kamagaya.chiba.jp +kamogawa.chiba.jp +kashiwa.chiba.jp +katori.chiba.jp +katsuura.chiba.jp +kimitsu.chiba.jp +kisarazu.chiba.jp +kozaki.chiba.jp +kujukuri.chiba.jp +kyonan.chiba.jp +matsudo.chiba.jp +midori.chiba.jp +mihama.chiba.jp +minamiboso.chiba.jp +mobara.chiba.jp +mutsuzawa.chiba.jp +nagara.chiba.jp +nagareyama.chiba.jp +narashino.chiba.jp +narita.chiba.jp +noda.chiba.jp +oamishirasato.chiba.jp +omigawa.chiba.jp +onjuku.chiba.jp +otaki.chiba.jp +sakae.chiba.jp +sakura.chiba.jp +shimofusa.chiba.jp +shirako.chiba.jp +shiroi.chiba.jp +shisui.chiba.jp +sodegaura.chiba.jp +sosa.chiba.jp +tako.chiba.jp +tateyama.chiba.jp +togane.chiba.jp +tohnosho.chiba.jp +tomisato.chiba.jp +urayasu.chiba.jp +yachimata.chiba.jp +yachiyo.chiba.jp +yokaichiba.chiba.jp +yokoshibahikari.chiba.jp +yotsukaido.chiba.jp +ainan.ehime.jp +honai.ehime.jp +ikata.ehime.jp +imabari.ehime.jp +iyo.ehime.jp +kamijima.ehime.jp +kihoku.ehime.jp +kumakogen.ehime.jp +masaki.ehime.jp +matsuno.ehime.jp +matsuyama.ehime.jp +namikata.ehime.jp +niihama.ehime.jp +ozu.ehime.jp +saijo.ehime.jp +seiyo.ehime.jp +shikokuchuo.ehime.jp +tobe.ehime.jp +toon.ehime.jp +uchiko.ehime.jp +uwajima.ehime.jp +yawatahama.ehime.jp +echizen.fukui.jp +eiheiji.fukui.jp +fukui.fukui.jp +ikeda.fukui.jp +katsuyama.fukui.jp +mihama.fukui.jp +minamiechizen.fukui.jp +obama.fukui.jp +ohi.fukui.jp +ono.fukui.jp +sabae.fukui.jp +sakai.fukui.jp +takahama.fukui.jp +tsuruga.fukui.jp +wakasa.fukui.jp +ashiya.fukuoka.jp +buzen.fukuoka.jp +chikugo.fukuoka.jp +chikuho.fukuoka.jp +chikujo.fukuoka.jp +chikushino.fukuoka.jp +chikuzen.fukuoka.jp +chuo.fukuoka.jp +dazaifu.fukuoka.jp +fukuchi.fukuoka.jp +hakata.fukuoka.jp +higashi.fukuoka.jp +hirokawa.fukuoka.jp +hisayama.fukuoka.jp +iizuka.fukuoka.jp +inatsuki.fukuoka.jp +kaho.fukuoka.jp +kasuga.fukuoka.jp +kasuya.fukuoka.jp +kawara.fukuoka.jp +keisen.fukuoka.jp +koga.fukuoka.jp +kurate.fukuoka.jp +kurogi.fukuoka.jp +kurume.fukuoka.jp +minami.fukuoka.jp +miyako.fukuoka.jp +miyama.fukuoka.jp +miyawaka.fukuoka.jp +mizumaki.fukuoka.jp +munakata.fukuoka.jp +nakagawa.fukuoka.jp +nakama.fukuoka.jp +nishi.fukuoka.jp +nogata.fukuoka.jp +ogori.fukuoka.jp +okagaki.fukuoka.jp +okawa.fukuoka.jp +oki.fukuoka.jp +omuta.fukuoka.jp +onga.fukuoka.jp +onojo.fukuoka.jp +oto.fukuoka.jp +saigawa.fukuoka.jp +sasaguri.fukuoka.jp +shingu.fukuoka.jp +shinyoshitomi.fukuoka.jp +shonai.fukuoka.jp +soeda.fukuoka.jp +sue.fukuoka.jp +tachiarai.fukuoka.jp +tagawa.fukuoka.jp +takata.fukuoka.jp +toho.fukuoka.jp +toyotsu.fukuoka.jp +tsuiki.fukuoka.jp +ukiha.fukuoka.jp +umi.fukuoka.jp +usui.fukuoka.jp +yamada.fukuoka.jp +yame.fukuoka.jp +yanagawa.fukuoka.jp +yukuhashi.fukuoka.jp +aizubange.fukushima.jp +aizumisato.fukushima.jp +aizuwakamatsu.fukushima.jp +asakawa.fukushima.jp +bandai.fukushima.jp +date.fukushima.jp +fukushima.fukushima.jp +furudono.fukushima.jp +futaba.fukushima.jp +hanawa.fukushima.jp +higashi.fukushima.jp +hirata.fukushima.jp +hirono.fukushima.jp +iitate.fukushima.jp +inawashiro.fukushima.jp +ishikawa.fukushima.jp +iwaki.fukushima.jp +izumizaki.fukushima.jp +kagamiishi.fukushima.jp +kaneyama.fukushima.jp +kawamata.fukushima.jp +kitakata.fukushima.jp +kitashiobara.fukushima.jp +koori.fukushima.jp +koriyama.fukushima.jp +kunimi.fukushima.jp +miharu.fukushima.jp +mishima.fukushima.jp +namie.fukushima.jp +nango.fukushima.jp +nishiaizu.fukushima.jp +nishigo.fukushima.jp +okuma.fukushima.jp +omotego.fukushima.jp +ono.fukushima.jp +otama.fukushima.jp +samegawa.fukushima.jp +shimogo.fukushima.jp +shirakawa.fukushima.jp +showa.fukushima.jp +soma.fukushima.jp +sukagawa.fukushima.jp +taishin.fukushima.jp +tamakawa.fukushima.jp +tanagura.fukushima.jp +tenei.fukushima.jp +yabuki.fukushima.jp +yamato.fukushima.jp +yamatsuri.fukushima.jp +yanaizu.fukushima.jp +yugawa.fukushima.jp +anpachi.gifu.jp +ena.gifu.jp +gifu.gifu.jp +ginan.gifu.jp +godo.gifu.jp +gujo.gifu.jp +hashima.gifu.jp +hichiso.gifu.jp +hida.gifu.jp +higashishirakawa.gifu.jp +ibigawa.gifu.jp +ikeda.gifu.jp +kakamigahara.gifu.jp +kani.gifu.jp +kasahara.gifu.jp +kasamatsu.gifu.jp +kawaue.gifu.jp +kitagata.gifu.jp +mino.gifu.jp +minokamo.gifu.jp +mitake.gifu.jp +mizunami.gifu.jp +motosu.gifu.jp +nakatsugawa.gifu.jp +ogaki.gifu.jp +sakahogi.gifu.jp +seki.gifu.jp +sekigahara.gifu.jp +shirakawa.gifu.jp +tajimi.gifu.jp +takayama.gifu.jp +tarui.gifu.jp +toki.gifu.jp +tomika.gifu.jp +wanouchi.gifu.jp +yamagata.gifu.jp +yaotsu.gifu.jp +yoro.gifu.jp +annaka.gunma.jp +chiyoda.gunma.jp +fujioka.gunma.jp +higashiagatsuma.gunma.jp +isesaki.gunma.jp +itakura.gunma.jp +kanna.gunma.jp +kanra.gunma.jp +katashina.gunma.jp +kawaba.gunma.jp +kiryu.gunma.jp +kusatsu.gunma.jp +maebashi.gunma.jp +meiwa.gunma.jp +midori.gunma.jp +minakami.gunma.jp +naganohara.gunma.jp +nakanojo.gunma.jp +nanmoku.gunma.jp +numata.gunma.jp +oizumi.gunma.jp +ora.gunma.jp +ota.gunma.jp +shibukawa.gunma.jp +shimonita.gunma.jp +shinto.gunma.jp +showa.gunma.jp +takasaki.gunma.jp +takayama.gunma.jp +tamamura.gunma.jp +tatebayashi.gunma.jp +tomioka.gunma.jp +tsukiyono.gunma.jp +tsumagoi.gunma.jp +ueno.gunma.jp +yoshioka.gunma.jp +asaminami.hiroshima.jp +daiwa.hiroshima.jp +etajima.hiroshima.jp +fuchu.hiroshima.jp +fukuyama.hiroshima.jp +hatsukaichi.hiroshima.jp +higashihiroshima.hiroshima.jp +hongo.hiroshima.jp +jinsekikogen.hiroshima.jp +kaita.hiroshima.jp +kui.hiroshima.jp +kumano.hiroshima.jp +kure.hiroshima.jp +mihara.hiroshima.jp +miyoshi.hiroshima.jp +naka.hiroshima.jp +onomichi.hiroshima.jp +osakikamijima.hiroshima.jp +otake.hiroshima.jp +saka.hiroshima.jp +sera.hiroshima.jp +seranishi.hiroshima.jp +shinichi.hiroshima.jp +shobara.hiroshima.jp +takehara.hiroshima.jp +abashiri.hokkaido.jp +abira.hokkaido.jp +aibetsu.hokkaido.jp +akabira.hokkaido.jp +akkeshi.hokkaido.jp +asahikawa.hokkaido.jp +ashibetsu.hokkaido.jp +ashoro.hokkaido.jp +assabu.hokkaido.jp +atsuma.hokkaido.jp +bibai.hokkaido.jp +biei.hokkaido.jp +bifuka.hokkaido.jp +bihoro.hokkaido.jp +biratori.hokkaido.jp +chippubetsu.hokkaido.jp +chitose.hokkaido.jp +date.hokkaido.jp +ebetsu.hokkaido.jp +embetsu.hokkaido.jp +eniwa.hokkaido.jp +erimo.hokkaido.jp +esan.hokkaido.jp +esashi.hokkaido.jp +fukagawa.hokkaido.jp +fukushima.hokkaido.jp +furano.hokkaido.jp +furubira.hokkaido.jp +haboro.hokkaido.jp +hakodate.hokkaido.jp +hamatonbetsu.hokkaido.jp +hidaka.hokkaido.jp +higashikagura.hokkaido.jp +higashikawa.hokkaido.jp +hiroo.hokkaido.jp +hokuryu.hokkaido.jp +hokuto.hokkaido.jp +honbetsu.hokkaido.jp +horokanai.hokkaido.jp +horonobe.hokkaido.jp +ikeda.hokkaido.jp +imakane.hokkaido.jp +ishikari.hokkaido.jp +iwamizawa.hokkaido.jp +iwanai.hokkaido.jp +kamifurano.hokkaido.jp +kamikawa.hokkaido.jp +kamishihoro.hokkaido.jp +kamisunagawa.hokkaido.jp +kamoenai.hokkaido.jp +kayabe.hokkaido.jp +kembuchi.hokkaido.jp +kikonai.hokkaido.jp +kimobetsu.hokkaido.jp +kitahiroshima.hokkaido.jp +kitami.hokkaido.jp +kiyosato.hokkaido.jp +koshimizu.hokkaido.jp +kunneppu.hokkaido.jp +kuriyama.hokkaido.jp +kuromatsunai.hokkaido.jp +kushiro.hokkaido.jp +kutchan.hokkaido.jp +kyowa.hokkaido.jp +mashike.hokkaido.jp +matsumae.hokkaido.jp +mikasa.hokkaido.jp +minamifurano.hokkaido.jp +mombetsu.hokkaido.jp +moseushi.hokkaido.jp +mukawa.hokkaido.jp +muroran.hokkaido.jp +naie.hokkaido.jp +nakagawa.hokkaido.jp +nakasatsunai.hokkaido.jp +nakatombetsu.hokkaido.jp +nanae.hokkaido.jp +nanporo.hokkaido.jp +nayoro.hokkaido.jp +nemuro.hokkaido.jp +niikappu.hokkaido.jp +niki.hokkaido.jp +nishiokoppe.hokkaido.jp +noboribetsu.hokkaido.jp +numata.hokkaido.jp +obihiro.hokkaido.jp +obira.hokkaido.jp +oketo.hokkaido.jp +okoppe.hokkaido.jp +otaru.hokkaido.jp +otobe.hokkaido.jp +otofuke.hokkaido.jp +otoineppu.hokkaido.jp +oumu.hokkaido.jp +ozora.hokkaido.jp +pippu.hokkaido.jp +rankoshi.hokkaido.jp +rebun.hokkaido.jp +rikubetsu.hokkaido.jp +rishiri.hokkaido.jp +rishirifuji.hokkaido.jp +saroma.hokkaido.jp +sarufutsu.hokkaido.jp +shakotan.hokkaido.jp +shari.hokkaido.jp +shibecha.hokkaido.jp +shibetsu.hokkaido.jp +shikabe.hokkaido.jp +shikaoi.hokkaido.jp +shimamaki.hokkaido.jp +shimizu.hokkaido.jp +shimokawa.hokkaido.jp +shinshinotsu.hokkaido.jp +shintoku.hokkaido.jp +shiranuka.hokkaido.jp +shiraoi.hokkaido.jp +shiriuchi.hokkaido.jp +sobetsu.hokkaido.jp +sunagawa.hokkaido.jp +taiki.hokkaido.jp +takasu.hokkaido.jp +takikawa.hokkaido.jp +takinoue.hokkaido.jp +teshikaga.hokkaido.jp +tobetsu.hokkaido.jp +tohma.hokkaido.jp +tomakomai.hokkaido.jp +tomari.hokkaido.jp +toya.hokkaido.jp +toyako.hokkaido.jp +toyotomi.hokkaido.jp +toyoura.hokkaido.jp +tsubetsu.hokkaido.jp +tsukigata.hokkaido.jp +urakawa.hokkaido.jp +urausu.hokkaido.jp +uryu.hokkaido.jp +utashinai.hokkaido.jp +wakkanai.hokkaido.jp +wassamu.hokkaido.jp +yakumo.hokkaido.jp +yoichi.hokkaido.jp +aioi.hyogo.jp +akashi.hyogo.jp +ako.hyogo.jp +amagasaki.hyogo.jp +aogaki.hyogo.jp +asago.hyogo.jp +ashiya.hyogo.jp +awaji.hyogo.jp +fukusaki.hyogo.jp +goshiki.hyogo.jp +harima.hyogo.jp +himeji.hyogo.jp +ichikawa.hyogo.jp +inagawa.hyogo.jp +itami.hyogo.jp +kakogawa.hyogo.jp +kamigori.hyogo.jp +kamikawa.hyogo.jp +kasai.hyogo.jp +kasuga.hyogo.jp +kawanishi.hyogo.jp +miki.hyogo.jp +minamiawaji.hyogo.jp +nishinomiya.hyogo.jp +nishiwaki.hyogo.jp +ono.hyogo.jp +sanda.hyogo.jp +sannan.hyogo.jp +sasayama.hyogo.jp +sayo.hyogo.jp +shingu.hyogo.jp +shinonsen.hyogo.jp +shiso.hyogo.jp +sumoto.hyogo.jp +taishi.hyogo.jp +taka.hyogo.jp +takarazuka.hyogo.jp +takasago.hyogo.jp +takino.hyogo.jp +tamba.hyogo.jp +tatsuno.hyogo.jp +toyooka.hyogo.jp +yabu.hyogo.jp +yashiro.hyogo.jp +yoka.hyogo.jp +yokawa.hyogo.jp +ami.ibaraki.jp +asahi.ibaraki.jp +bando.ibaraki.jp +chikusei.ibaraki.jp +daigo.ibaraki.jp +fujishiro.ibaraki.jp +hitachi.ibaraki.jp +hitachinaka.ibaraki.jp +hitachiomiya.ibaraki.jp +hitachiota.ibaraki.jp +ibaraki.ibaraki.jp +ina.ibaraki.jp +inashiki.ibaraki.jp +itako.ibaraki.jp +iwama.ibaraki.jp +joso.ibaraki.jp +kamisu.ibaraki.jp +kasama.ibaraki.jp +kashima.ibaraki.jp +kasumigaura.ibaraki.jp +koga.ibaraki.jp +miho.ibaraki.jp +mito.ibaraki.jp +moriya.ibaraki.jp +naka.ibaraki.jp +namegata.ibaraki.jp +oarai.ibaraki.jp +ogawa.ibaraki.jp +omitama.ibaraki.jp +ryugasaki.ibaraki.jp +sakai.ibaraki.jp +sakuragawa.ibaraki.jp +shimodate.ibaraki.jp +shimotsuma.ibaraki.jp +shirosato.ibaraki.jp +sowa.ibaraki.jp +suifu.ibaraki.jp +takahagi.ibaraki.jp +tamatsukuri.ibaraki.jp +tokai.ibaraki.jp +tomobe.ibaraki.jp +tone.ibaraki.jp +toride.ibaraki.jp +tsuchiura.ibaraki.jp +tsukuba.ibaraki.jp +uchihara.ibaraki.jp +ushiku.ibaraki.jp +yachiyo.ibaraki.jp +yamagata.ibaraki.jp +yawara.ibaraki.jp +yuki.ibaraki.jp +anamizu.ishikawa.jp +hakui.ishikawa.jp +hakusan.ishikawa.jp +kaga.ishikawa.jp +kahoku.ishikawa.jp +kanazawa.ishikawa.jp +kawakita.ishikawa.jp +komatsu.ishikawa.jp +nakanoto.ishikawa.jp +nanao.ishikawa.jp +nomi.ishikawa.jp +nonoichi.ishikawa.jp +noto.ishikawa.jp +shika.ishikawa.jp +suzu.ishikawa.jp +tsubata.ishikawa.jp +tsurugi.ishikawa.jp +uchinada.ishikawa.jp +wajima.ishikawa.jp +fudai.iwate.jp +fujisawa.iwate.jp +hanamaki.iwate.jp +hiraizumi.iwate.jp +hirono.iwate.jp +ichinohe.iwate.jp +ichinoseki.iwate.jp +iwaizumi.iwate.jp +iwate.iwate.jp +joboji.iwate.jp +kamaishi.iwate.jp +kanegasaki.iwate.jp +karumai.iwate.jp +kawai.iwate.jp +kitakami.iwate.jp +kuji.iwate.jp +kunohe.iwate.jp +kuzumaki.iwate.jp +miyako.iwate.jp +mizusawa.iwate.jp +morioka.iwate.jp +ninohe.iwate.jp +noda.iwate.jp +ofunato.iwate.jp +oshu.iwate.jp +otsuchi.iwate.jp +rikuzentakata.iwate.jp +shiwa.iwate.jp +shizukuishi.iwate.jp +sumita.iwate.jp +tanohata.iwate.jp +tono.iwate.jp +yahaba.iwate.jp +yamada.iwate.jp +ayagawa.kagawa.jp +higashikagawa.kagawa.jp +kanonji.kagawa.jp +kotohira.kagawa.jp +manno.kagawa.jp +marugame.kagawa.jp +mitoyo.kagawa.jp +naoshima.kagawa.jp +sanuki.kagawa.jp +tadotsu.kagawa.jp +takamatsu.kagawa.jp +tonosho.kagawa.jp +uchinomi.kagawa.jp +utazu.kagawa.jp +zentsuji.kagawa.jp +akune.kagoshima.jp +amami.kagoshima.jp +hioki.kagoshima.jp +isa.kagoshima.jp +isen.kagoshima.jp +izumi.kagoshima.jp +kagoshima.kagoshima.jp +kanoya.kagoshima.jp +kawanabe.kagoshima.jp +kinko.kagoshima.jp +kouyama.kagoshima.jp +makurazaki.kagoshima.jp +matsumoto.kagoshima.jp +minamitane.kagoshima.jp +nakatane.kagoshima.jp +nishinoomote.kagoshima.jp +satsumasendai.kagoshima.jp +soo.kagoshima.jp +tarumizu.kagoshima.jp +yusui.kagoshima.jp +aikawa.kanagawa.jp +atsugi.kanagawa.jp +ayase.kanagawa.jp +chigasaki.kanagawa.jp +ebina.kanagawa.jp +fujisawa.kanagawa.jp +hadano.kanagawa.jp +hakone.kanagawa.jp +hiratsuka.kanagawa.jp +isehara.kanagawa.jp +kaisei.kanagawa.jp +kamakura.kanagawa.jp +kiyokawa.kanagawa.jp +matsuda.kanagawa.jp +minamiashigara.kanagawa.jp +miura.kanagawa.jp +nakai.kanagawa.jp +ninomiya.kanagawa.jp +odawara.kanagawa.jp +oi.kanagawa.jp +oiso.kanagawa.jp +sagamihara.kanagawa.jp +samukawa.kanagawa.jp +tsukui.kanagawa.jp +yamakita.kanagawa.jp +yamato.kanagawa.jp +yokosuka.kanagawa.jp +yugawara.kanagawa.jp +zama.kanagawa.jp +zushi.kanagawa.jp +aki.kochi.jp +geisei.kochi.jp +hidaka.kochi.jp +higashitsuno.kochi.jp +ino.kochi.jp +kagami.kochi.jp +kami.kochi.jp +kitagawa.kochi.jp +kochi.kochi.jp +mihara.kochi.jp +motoyama.kochi.jp +muroto.kochi.jp +nahari.kochi.jp +nakamura.kochi.jp +nankoku.kochi.jp +nishitosa.kochi.jp +niyodogawa.kochi.jp +ochi.kochi.jp +okawa.kochi.jp +otoyo.kochi.jp +otsuki.kochi.jp +sakawa.kochi.jp +sukumo.kochi.jp +susaki.kochi.jp +tosa.kochi.jp +tosashimizu.kochi.jp +toyo.kochi.jp +tsuno.kochi.jp +umaji.kochi.jp +yasuda.kochi.jp +yusuhara.kochi.jp +amakusa.kumamoto.jp +arao.kumamoto.jp +aso.kumamoto.jp +choyo.kumamoto.jp +gyokuto.kumamoto.jp +kamiamakusa.kumamoto.jp +kikuchi.kumamoto.jp +kumamoto.kumamoto.jp +mashiki.kumamoto.jp +mifune.kumamoto.jp +minamata.kumamoto.jp +minamioguni.kumamoto.jp +nagasu.kumamoto.jp +nishihara.kumamoto.jp +oguni.kumamoto.jp +ozu.kumamoto.jp +sumoto.kumamoto.jp +takamori.kumamoto.jp +uki.kumamoto.jp +uto.kumamoto.jp +yamaga.kumamoto.jp +yamato.kumamoto.jp +yatsushiro.kumamoto.jp +ayabe.kyoto.jp +fukuchiyama.kyoto.jp +higashiyama.kyoto.jp +ide.kyoto.jp +ine.kyoto.jp +joyo.kyoto.jp +kameoka.kyoto.jp +kamo.kyoto.jp +kita.kyoto.jp +kizu.kyoto.jp +kumiyama.kyoto.jp +kyotamba.kyoto.jp +kyotanabe.kyoto.jp +kyotango.kyoto.jp +maizuru.kyoto.jp +minami.kyoto.jp +minamiyamashiro.kyoto.jp +miyazu.kyoto.jp +muko.kyoto.jp +nagaokakyo.kyoto.jp +nakagyo.kyoto.jp +nantan.kyoto.jp +oyamazaki.kyoto.jp +sakyo.kyoto.jp +seika.kyoto.jp +tanabe.kyoto.jp +uji.kyoto.jp +ujitawara.kyoto.jp +wazuka.kyoto.jp +yamashina.kyoto.jp +yawata.kyoto.jp +asahi.mie.jp +inabe.mie.jp +ise.mie.jp +kameyama.mie.jp +kawagoe.mie.jp +kiho.mie.jp +kisosaki.mie.jp +kiwa.mie.jp +komono.mie.jp +kumano.mie.jp +kuwana.mie.jp +matsusaka.mie.jp +meiwa.mie.jp +mihama.mie.jp +minamiise.mie.jp +misugi.mie.jp +miyama.mie.jp +nabari.mie.jp +shima.mie.jp +suzuka.mie.jp +tado.mie.jp +taiki.mie.jp +taki.mie.jp +tamaki.mie.jp +toba.mie.jp +tsu.mie.jp +udono.mie.jp +ureshino.mie.jp +watarai.mie.jp +yokkaichi.mie.jp +furukawa.miyagi.jp +higashimatsushima.miyagi.jp +ishinomaki.miyagi.jp +iwanuma.miyagi.jp +kakuda.miyagi.jp +kami.miyagi.jp +kawasaki.miyagi.jp +marumori.miyagi.jp +matsushima.miyagi.jp +minamisanriku.miyagi.jp +misato.miyagi.jp +murata.miyagi.jp +natori.miyagi.jp +ogawara.miyagi.jp +ohira.miyagi.jp +onagawa.miyagi.jp +osaki.miyagi.jp +rifu.miyagi.jp +semine.miyagi.jp +shibata.miyagi.jp +shichikashuku.miyagi.jp +shikama.miyagi.jp +shiogama.miyagi.jp +shiroishi.miyagi.jp +tagajo.miyagi.jp +taiwa.miyagi.jp +tome.miyagi.jp +tomiya.miyagi.jp +wakuya.miyagi.jp +watari.miyagi.jp +yamamoto.miyagi.jp +zao.miyagi.jp +aya.miyazaki.jp +ebino.miyazaki.jp +gokase.miyazaki.jp +hyuga.miyazaki.jp +kadogawa.miyazaki.jp +kawaminami.miyazaki.jp +kijo.miyazaki.jp +kitagawa.miyazaki.jp +kitakata.miyazaki.jp +kitaura.miyazaki.jp +kobayashi.miyazaki.jp +kunitomi.miyazaki.jp +kushima.miyazaki.jp +mimata.miyazaki.jp +miyakonojo.miyazaki.jp +miyazaki.miyazaki.jp +morotsuka.miyazaki.jp +nichinan.miyazaki.jp +nishimera.miyazaki.jp +nobeoka.miyazaki.jp +saito.miyazaki.jp +shiiba.miyazaki.jp +shintomi.miyazaki.jp +takaharu.miyazaki.jp +takanabe.miyazaki.jp +takazaki.miyazaki.jp +tsuno.miyazaki.jp +achi.nagano.jp +agematsu.nagano.jp +anan.nagano.jp +aoki.nagano.jp +asahi.nagano.jp +azumino.nagano.jp +chikuhoku.nagano.jp +chikuma.nagano.jp +chino.nagano.jp +fujimi.nagano.jp +hakuba.nagano.jp +hara.nagano.jp +hiraya.nagano.jp +iida.nagano.jp +iijima.nagano.jp +iiyama.nagano.jp +iizuna.nagano.jp +ikeda.nagano.jp +ikusaka.nagano.jp +ina.nagano.jp +karuizawa.nagano.jp +kawakami.nagano.jp +kiso.nagano.jp +kisofukushima.nagano.jp +kitaaiki.nagano.jp +komagane.nagano.jp +komoro.nagano.jp +matsukawa.nagano.jp +matsumoto.nagano.jp +miasa.nagano.jp +minamiaiki.nagano.jp +minamimaki.nagano.jp +minamiminowa.nagano.jp +minowa.nagano.jp +miyada.nagano.jp +miyota.nagano.jp +mochizuki.nagano.jp +nagano.nagano.jp +nagawa.nagano.jp +nagiso.nagano.jp +nakagawa.nagano.jp +nakano.nagano.jp +nozawaonsen.nagano.jp +obuse.nagano.jp +ogawa.nagano.jp +okaya.nagano.jp +omachi.nagano.jp +omi.nagano.jp +ookuwa.nagano.jp +ooshika.nagano.jp +otaki.nagano.jp +otari.nagano.jp +sakae.nagano.jp +sakaki.nagano.jp +saku.nagano.jp +sakuho.nagano.jp +shimosuwa.nagano.jp +shinanomachi.nagano.jp +shiojiri.nagano.jp +suwa.nagano.jp +suzaka.nagano.jp +takagi.nagano.jp +takamori.nagano.jp +takayama.nagano.jp +tateshina.nagano.jp +tatsuno.nagano.jp +togakushi.nagano.jp +togura.nagano.jp +tomi.nagano.jp +ueda.nagano.jp +wada.nagano.jp +yamagata.nagano.jp +yamanouchi.nagano.jp +yasaka.nagano.jp +yasuoka.nagano.jp +chijiwa.nagasaki.jp +futsu.nagasaki.jp +goto.nagasaki.jp +hasami.nagasaki.jp +hirado.nagasaki.jp +iki.nagasaki.jp +isahaya.nagasaki.jp +kawatana.nagasaki.jp +kuchinotsu.nagasaki.jp +matsuura.nagasaki.jp +nagasaki.nagasaki.jp +obama.nagasaki.jp +omura.nagasaki.jp +oseto.nagasaki.jp +saikai.nagasaki.jp +sasebo.nagasaki.jp +seihi.nagasaki.jp +shimabara.nagasaki.jp +shinkamigoto.nagasaki.jp +togitsu.nagasaki.jp +tsushima.nagasaki.jp +unzen.nagasaki.jp +ando.nara.jp +gose.nara.jp +heguri.nara.jp +higashiyoshino.nara.jp +ikaruga.nara.jp +ikoma.nara.jp +kamikitayama.nara.jp +kanmaki.nara.jp +kashiba.nara.jp +kashihara.nara.jp +katsuragi.nara.jp +kawai.nara.jp +kawakami.nara.jp +kawanishi.nara.jp +koryo.nara.jp +kurotaki.nara.jp +mitsue.nara.jp +miyake.nara.jp +nara.nara.jp +nosegawa.nara.jp +oji.nara.jp +ouda.nara.jp +oyodo.nara.jp +sakurai.nara.jp +sango.nara.jp +shimoichi.nara.jp +shimokitayama.nara.jp +shinjo.nara.jp +soni.nara.jp +takatori.nara.jp +tawaramoto.nara.jp +tenkawa.nara.jp +tenri.nara.jp +uda.nara.jp +yamatokoriyama.nara.jp +yamatotakada.nara.jp +yamazoe.nara.jp +yoshino.nara.jp +aga.niigata.jp +agano.niigata.jp +gosen.niigata.jp +itoigawa.niigata.jp +izumozaki.niigata.jp +joetsu.niigata.jp +kamo.niigata.jp +kariwa.niigata.jp +kashiwazaki.niigata.jp +minamiuonuma.niigata.jp +mitsuke.niigata.jp +muika.niigata.jp +murakami.niigata.jp +myoko.niigata.jp +nagaoka.niigata.jp +niigata.niigata.jp +ojiya.niigata.jp +omi.niigata.jp +sado.niigata.jp +sanjo.niigata.jp +seiro.niigata.jp +seirou.niigata.jp +sekikawa.niigata.jp +shibata.niigata.jp +tagami.niigata.jp +tainai.niigata.jp +tochio.niigata.jp +tokamachi.niigata.jp +tsubame.niigata.jp +tsunan.niigata.jp +uonuma.niigata.jp +yahiko.niigata.jp +yoita.niigata.jp +yuzawa.niigata.jp +beppu.oita.jp +bungoono.oita.jp +bungotakada.oita.jp +hasama.oita.jp +hiji.oita.jp +himeshima.oita.jp +hita.oita.jp +kamitsue.oita.jp +kokonoe.oita.jp +kuju.oita.jp +kunisaki.oita.jp +kusu.oita.jp +oita.oita.jp +saiki.oita.jp +taketa.oita.jp +tsukumi.oita.jp +usa.oita.jp +usuki.oita.jp +yufu.oita.jp +akaiwa.okayama.jp +asakuchi.okayama.jp +bizen.okayama.jp +hayashima.okayama.jp +ibara.okayama.jp +kagamino.okayama.jp +kasaoka.okayama.jp +kibichuo.okayama.jp +kumenan.okayama.jp +kurashiki.okayama.jp +maniwa.okayama.jp +misaki.okayama.jp +nagi.okayama.jp +niimi.okayama.jp +nishiawakura.okayama.jp +okayama.okayama.jp +satosho.okayama.jp +setouchi.okayama.jp +shinjo.okayama.jp +shoo.okayama.jp +soja.okayama.jp +takahashi.okayama.jp +tamano.okayama.jp +tsuyama.okayama.jp +wake.okayama.jp +yakage.okayama.jp +aguni.okinawa.jp +ginowan.okinawa.jp +ginoza.okinawa.jp +gushikami.okinawa.jp +haebaru.okinawa.jp +higashi.okinawa.jp +hirara.okinawa.jp +iheya.okinawa.jp +ishigaki.okinawa.jp +ishikawa.okinawa.jp +itoman.okinawa.jp +izena.okinawa.jp +kadena.okinawa.jp +kin.okinawa.jp +kitadaito.okinawa.jp +kitanakagusuku.okinawa.jp +kumejima.okinawa.jp +kunigami.okinawa.jp +minamidaito.okinawa.jp +motobu.okinawa.jp +nago.okinawa.jp +naha.okinawa.jp +nakagusuku.okinawa.jp +nakijin.okinawa.jp +nanjo.okinawa.jp +nishihara.okinawa.jp +ogimi.okinawa.jp +okinawa.okinawa.jp +onna.okinawa.jp +shimoji.okinawa.jp +taketomi.okinawa.jp +tarama.okinawa.jp +tokashiki.okinawa.jp +tomigusuku.okinawa.jp +tonaki.okinawa.jp +urasoe.okinawa.jp +uruma.okinawa.jp +yaese.okinawa.jp +yomitan.okinawa.jp +yonabaru.okinawa.jp +yonaguni.okinawa.jp +zamami.okinawa.jp +abeno.osaka.jp +chihayaakasaka.osaka.jp +chuo.osaka.jp +daito.osaka.jp +fujiidera.osaka.jp +habikino.osaka.jp +hannan.osaka.jp +higashiosaka.osaka.jp +higashisumiyoshi.osaka.jp +higashiyodogawa.osaka.jp +hirakata.osaka.jp +ibaraki.osaka.jp +ikeda.osaka.jp +izumi.osaka.jp +izumiotsu.osaka.jp +izumisano.osaka.jp +kadoma.osaka.jp +kaizuka.osaka.jp +kanan.osaka.jp +kashiwara.osaka.jp +katano.osaka.jp +kawachinagano.osaka.jp +kishiwada.osaka.jp +kita.osaka.jp +kumatori.osaka.jp +matsubara.osaka.jp +minato.osaka.jp +minoh.osaka.jp +misaki.osaka.jp +moriguchi.osaka.jp +neyagawa.osaka.jp +nishi.osaka.jp +nose.osaka.jp +osakasayama.osaka.jp +sakai.osaka.jp +sayama.osaka.jp +sennan.osaka.jp +settsu.osaka.jp +shijonawate.osaka.jp +shimamoto.osaka.jp +suita.osaka.jp +tadaoka.osaka.jp +taishi.osaka.jp +tajiri.osaka.jp +takaishi.osaka.jp +takatsuki.osaka.jp +tondabayashi.osaka.jp +toyonaka.osaka.jp +toyono.osaka.jp +yao.osaka.jp +ariake.saga.jp +arita.saga.jp +fukudomi.saga.jp +genkai.saga.jp +hamatama.saga.jp +hizen.saga.jp +imari.saga.jp +kamimine.saga.jp +kanzaki.saga.jp +karatsu.saga.jp +kashima.saga.jp +kitagata.saga.jp +kitahata.saga.jp +kiyama.saga.jp +kouhoku.saga.jp +kyuragi.saga.jp +nishiarita.saga.jp +ogi.saga.jp +omachi.saga.jp +ouchi.saga.jp +saga.saga.jp +shiroishi.saga.jp +taku.saga.jp +tara.saga.jp +tosu.saga.jp +yoshinogari.saga.jp +arakawa.saitama.jp +asaka.saitama.jp +chichibu.saitama.jp +fujimi.saitama.jp +fujimino.saitama.jp +fukaya.saitama.jp +hanno.saitama.jp +hanyu.saitama.jp +hasuda.saitama.jp +hatogaya.saitama.jp +hatoyama.saitama.jp +hidaka.saitama.jp +higashichichibu.saitama.jp +higashimatsuyama.saitama.jp +honjo.saitama.jp +ina.saitama.jp +iruma.saitama.jp +iwatsuki.saitama.jp +kamiizumi.saitama.jp +kamikawa.saitama.jp +kamisato.saitama.jp +kasukabe.saitama.jp +kawagoe.saitama.jp +kawaguchi.saitama.jp +kawajima.saitama.jp +kazo.saitama.jp +kitamoto.saitama.jp +koshigaya.saitama.jp +kounosu.saitama.jp +kuki.saitama.jp +kumagaya.saitama.jp +matsubushi.saitama.jp +minano.saitama.jp +misato.saitama.jp +miyashiro.saitama.jp +miyoshi.saitama.jp +moroyama.saitama.jp +nagatoro.saitama.jp +namegawa.saitama.jp +niiza.saitama.jp +ogano.saitama.jp +ogawa.saitama.jp +ogose.saitama.jp +okegawa.saitama.jp +omiya.saitama.jp +otaki.saitama.jp +ranzan.saitama.jp +ryokami.saitama.jp +saitama.saitama.jp +sakado.saitama.jp +satte.saitama.jp +sayama.saitama.jp +shiki.saitama.jp +shiraoka.saitama.jp +soka.saitama.jp +sugito.saitama.jp +toda.saitama.jp +tokigawa.saitama.jp +tokorozawa.saitama.jp +tsurugashima.saitama.jp +urawa.saitama.jp +warabi.saitama.jp +yashio.saitama.jp +yokoze.saitama.jp +yono.saitama.jp +yorii.saitama.jp +yoshida.saitama.jp +yoshikawa.saitama.jp +yoshimi.saitama.jp +aisho.shiga.jp +gamo.shiga.jp +higashiomi.shiga.jp +hikone.shiga.jp +koka.shiga.jp +konan.shiga.jp +kosei.shiga.jp +koto.shiga.jp +kusatsu.shiga.jp +maibara.shiga.jp +moriyama.shiga.jp +nagahama.shiga.jp +nishiazai.shiga.jp +notogawa.shiga.jp +omihachiman.shiga.jp +otsu.shiga.jp +ritto.shiga.jp +ryuoh.shiga.jp +takashima.shiga.jp +takatsuki.shiga.jp +torahime.shiga.jp +toyosato.shiga.jp +yasu.shiga.jp +akagi.shimane.jp +ama.shimane.jp +gotsu.shimane.jp +hamada.shimane.jp +higashiizumo.shimane.jp +hikawa.shimane.jp +hikimi.shimane.jp +izumo.shimane.jp +kakinoki.shimane.jp +masuda.shimane.jp +matsue.shimane.jp +misato.shimane.jp +nishinoshima.shimane.jp +ohda.shimane.jp +okinoshima.shimane.jp +okuizumo.shimane.jp +shimane.shimane.jp +tamayu.shimane.jp +tsuwano.shimane.jp +unnan.shimane.jp +yakumo.shimane.jp +yasugi.shimane.jp +yatsuka.shimane.jp +arai.shizuoka.jp +atami.shizuoka.jp +fuji.shizuoka.jp +fujieda.shizuoka.jp +fujikawa.shizuoka.jp +fujinomiya.shizuoka.jp +fukuroi.shizuoka.jp +gotemba.shizuoka.jp +haibara.shizuoka.jp +hamamatsu.shizuoka.jp +higashiizu.shizuoka.jp +ito.shizuoka.jp +iwata.shizuoka.jp +izu.shizuoka.jp +izunokuni.shizuoka.jp +kakegawa.shizuoka.jp +kannami.shizuoka.jp +kawanehon.shizuoka.jp +kawazu.shizuoka.jp +kikugawa.shizuoka.jp +kosai.shizuoka.jp +makinohara.shizuoka.jp +matsuzaki.shizuoka.jp +minamiizu.shizuoka.jp +mishima.shizuoka.jp +morimachi.shizuoka.jp +nishiizu.shizuoka.jp +numazu.shizuoka.jp +omaezaki.shizuoka.jp +shimada.shizuoka.jp +shimizu.shizuoka.jp +shimoda.shizuoka.jp +shizuoka.shizuoka.jp +susono.shizuoka.jp +yaizu.shizuoka.jp +yoshida.shizuoka.jp +ashikaga.tochigi.jp +bato.tochigi.jp +haga.tochigi.jp +ichikai.tochigi.jp +iwafune.tochigi.jp +kaminokawa.tochigi.jp +kanuma.tochigi.jp +karasuyama.tochigi.jp +kuroiso.tochigi.jp +mashiko.tochigi.jp +mibu.tochigi.jp +moka.tochigi.jp +motegi.tochigi.jp +nasu.tochigi.jp +nasushiobara.tochigi.jp +nikko.tochigi.jp +nishikata.tochigi.jp +nogi.tochigi.jp +ohira.tochigi.jp +ohtawara.tochigi.jp +oyama.tochigi.jp +sakura.tochigi.jp +sano.tochigi.jp +shimotsuke.tochigi.jp +shioya.tochigi.jp +takanezawa.tochigi.jp +tochigi.tochigi.jp +tsuga.tochigi.jp +ujiie.tochigi.jp +utsunomiya.tochigi.jp +yaita.tochigi.jp +aizumi.tokushima.jp +anan.tokushima.jp +ichiba.tokushima.jp +itano.tokushima.jp +kainan.tokushima.jp +komatsushima.tokushima.jp +matsushige.tokushima.jp +mima.tokushima.jp +minami.tokushima.jp +miyoshi.tokushima.jp +mugi.tokushima.jp +nakagawa.tokushima.jp +naruto.tokushima.jp +sanagochi.tokushima.jp +shishikui.tokushima.jp +tokushima.tokushima.jp +wajiki.tokushima.jp +adachi.tokyo.jp +akiruno.tokyo.jp +akishima.tokyo.jp +aogashima.tokyo.jp +arakawa.tokyo.jp +bunkyo.tokyo.jp +chiyoda.tokyo.jp +chofu.tokyo.jp +chuo.tokyo.jp +edogawa.tokyo.jp +fuchu.tokyo.jp +fussa.tokyo.jp +hachijo.tokyo.jp +hachioji.tokyo.jp +hamura.tokyo.jp +higashikurume.tokyo.jp +higashimurayama.tokyo.jp +higashiyamato.tokyo.jp +hino.tokyo.jp +hinode.tokyo.jp +hinohara.tokyo.jp +inagi.tokyo.jp +itabashi.tokyo.jp +katsushika.tokyo.jp +kita.tokyo.jp +kiyose.tokyo.jp +kodaira.tokyo.jp +koganei.tokyo.jp +kokubunji.tokyo.jp +komae.tokyo.jp +koto.tokyo.jp +kouzushima.tokyo.jp +kunitachi.tokyo.jp +machida.tokyo.jp +meguro.tokyo.jp +minato.tokyo.jp +mitaka.tokyo.jp +mizuho.tokyo.jp +musashimurayama.tokyo.jp +musashino.tokyo.jp +nakano.tokyo.jp +nerima.tokyo.jp +ogasawara.tokyo.jp +okutama.tokyo.jp +ome.tokyo.jp +oshima.tokyo.jp +ota.tokyo.jp +setagaya.tokyo.jp +shibuya.tokyo.jp +shinagawa.tokyo.jp +shinjuku.tokyo.jp +suginami.tokyo.jp +sumida.tokyo.jp +tachikawa.tokyo.jp +taito.tokyo.jp +tama.tokyo.jp +toshima.tokyo.jp +chizu.tottori.jp +hino.tottori.jp +kawahara.tottori.jp +koge.tottori.jp +kotoura.tottori.jp +misasa.tottori.jp +nanbu.tottori.jp +nichinan.tottori.jp +sakaiminato.tottori.jp +tottori.tottori.jp +wakasa.tottori.jp +yazu.tottori.jp +yonago.tottori.jp +asahi.toyama.jp +fuchu.toyama.jp +fukumitsu.toyama.jp +funahashi.toyama.jp +himi.toyama.jp +imizu.toyama.jp +inami.toyama.jp +johana.toyama.jp +kamiichi.toyama.jp +kurobe.toyama.jp +nakaniikawa.toyama.jp +namerikawa.toyama.jp +nanto.toyama.jp +nyuzen.toyama.jp +oyabe.toyama.jp +taira.toyama.jp +takaoka.toyama.jp +tateyama.toyama.jp +toga.toyama.jp +tonami.toyama.jp +toyama.toyama.jp +unazuki.toyama.jp +uozu.toyama.jp +yamada.toyama.jp +arida.wakayama.jp +aridagawa.wakayama.jp +gobo.wakayama.jp +hashimoto.wakayama.jp +hidaka.wakayama.jp +hirogawa.wakayama.jp +inami.wakayama.jp +iwade.wakayama.jp +kainan.wakayama.jp +kamitonda.wakayama.jp +katsuragi.wakayama.jp +kimino.wakayama.jp +kinokawa.wakayama.jp +kitayama.wakayama.jp +koya.wakayama.jp +koza.wakayama.jp +kozagawa.wakayama.jp +kudoyama.wakayama.jp +kushimoto.wakayama.jp +mihama.wakayama.jp +misato.wakayama.jp +nachikatsuura.wakayama.jp +shingu.wakayama.jp +shirahama.wakayama.jp +taiji.wakayama.jp +tanabe.wakayama.jp +wakayama.wakayama.jp +yuasa.wakayama.jp +yura.wakayama.jp +asahi.yamagata.jp +funagata.yamagata.jp +higashine.yamagata.jp +iide.yamagata.jp +kahoku.yamagata.jp +kaminoyama.yamagata.jp +kaneyama.yamagata.jp +kawanishi.yamagata.jp +mamurogawa.yamagata.jp +mikawa.yamagata.jp +murayama.yamagata.jp +nagai.yamagata.jp +nakayama.yamagata.jp +nanyo.yamagata.jp +nishikawa.yamagata.jp +obanazawa.yamagata.jp +oe.yamagata.jp +oguni.yamagata.jp +ohkura.yamagata.jp +oishida.yamagata.jp +sagae.yamagata.jp +sakata.yamagata.jp +sakegawa.yamagata.jp +shinjo.yamagata.jp +shirataka.yamagata.jp +shonai.yamagata.jp +takahata.yamagata.jp +tendo.yamagata.jp +tozawa.yamagata.jp +tsuruoka.yamagata.jp +yamagata.yamagata.jp +yamanobe.yamagata.jp +yonezawa.yamagata.jp +yuza.yamagata.jp +abu.yamaguchi.jp +hagi.yamaguchi.jp +hikari.yamaguchi.jp +hofu.yamaguchi.jp +iwakuni.yamaguchi.jp +kudamatsu.yamaguchi.jp +mitou.yamaguchi.jp +nagato.yamaguchi.jp +oshima.yamaguchi.jp +shimonoseki.yamaguchi.jp +shunan.yamaguchi.jp +tabuse.yamaguchi.jp +tokuyama.yamaguchi.jp +toyota.yamaguchi.jp +ube.yamaguchi.jp +yuu.yamaguchi.jp +chuo.yamanashi.jp +doshi.yamanashi.jp +fuefuki.yamanashi.jp +fujikawa.yamanashi.jp +fujikawaguchiko.yamanashi.jp +fujiyoshida.yamanashi.jp +hayakawa.yamanashi.jp +hokuto.yamanashi.jp +ichikawamisato.yamanashi.jp +kai.yamanashi.jp +kofu.yamanashi.jp +koshu.yamanashi.jp +kosuge.yamanashi.jp +minami-alps.yamanashi.jp +minobu.yamanashi.jp +nakamichi.yamanashi.jp +nanbu.yamanashi.jp +narusawa.yamanashi.jp +nirasaki.yamanashi.jp +nishikatsura.yamanashi.jp +oshino.yamanashi.jp +otsuki.yamanashi.jp +showa.yamanashi.jp +tabayama.yamanashi.jp +tsuru.yamanashi.jp +uenohara.yamanashi.jp +yamanakako.yamanashi.jp +yamanashi.yamanashi.jp + +// ke : http://www.kenic.or.ke/index.php/en/ke-domains/ke-domains +ke +ac.ke +co.ke +go.ke +info.ke +me.ke +mobi.ke +ne.ke +or.ke +sc.ke + +// kg : http://www.domain.kg/dmn_n.html +kg +org.kg +net.kg +com.kg +edu.kg +gov.kg +mil.kg + +// kh : http://www.mptc.gov.kh/dns_registration.htm +*.kh + +// ki : http://www.ki/dns/index.html +ki +edu.ki +biz.ki +net.ki +org.ki +gov.ki +info.ki +com.ki + +// km : https://en.wikipedia.org/wiki/.km +// http://www.domaine.km/documents/charte.doc +km +org.km +nom.km +gov.km +prd.km +tm.km +edu.km +mil.km +ass.km +com.km +// These are only mentioned as proposed suggestions at domaine.km, but +// https://en.wikipedia.org/wiki/.km says they're available for registration: +coop.km +asso.km +presse.km +medecin.km +notaires.km +pharmaciens.km +veterinaire.km +gouv.km + +// kn : https://en.wikipedia.org/wiki/.kn +// http://www.dot.kn/domainRules.html +kn +net.kn +org.kn +edu.kn +gov.kn + +// kp : http://www.kcce.kp/en_index.php +kp +com.kp +edu.kp +gov.kp +org.kp +rep.kp +tra.kp + +// kr : https://en.wikipedia.org/wiki/.kr +// see also: http://domain.nida.or.kr/eng/registration.jsp +kr +ac.kr +co.kr +es.kr +go.kr +hs.kr +kg.kr +mil.kr +ms.kr +ne.kr +or.kr +pe.kr +re.kr +sc.kr +// kr geographical names +busan.kr +chungbuk.kr +chungnam.kr +daegu.kr +daejeon.kr +gangwon.kr +gwangju.kr +gyeongbuk.kr +gyeonggi.kr +gyeongnam.kr +incheon.kr +jeju.kr +jeonbuk.kr +jeonnam.kr +seoul.kr +ulsan.kr + +// kw : https://en.wikipedia.org/wiki/.kw +*.kw + +// ky : http://www.icta.ky/da_ky_reg_dom.php +// Confirmed by registry 2008-06-17 +ky +edu.ky +gov.ky +com.ky +org.ky +net.ky + +// kz : https://en.wikipedia.org/wiki/.kz +// see also: http://www.nic.kz/rules/index.jsp +kz +org.kz +edu.kz +net.kz +gov.kz +mil.kz +com.kz + +// la : https://en.wikipedia.org/wiki/.la +// Submitted by registry +la +int.la +net.la +info.la +edu.la +gov.la +per.la +com.la +org.la + +// lb : https://en.wikipedia.org/wiki/.lb +// Submitted by registry +lb +com.lb +edu.lb +gov.lb +net.lb +org.lb + +// lc : https://en.wikipedia.org/wiki/.lc +// see also: http://www.nic.lc/rules.htm +lc +com.lc +net.lc +co.lc +org.lc +edu.lc +gov.lc + +// li : https://en.wikipedia.org/wiki/.li +li + +// lk : http://www.nic.lk/seclevpr.html +lk +gov.lk +sch.lk +net.lk +int.lk +com.lk +org.lk +edu.lk +ngo.lk +soc.lk +web.lk +ltd.lk +assn.lk +grp.lk +hotel.lk +ac.lk + +// lr : http://psg.com/dns/lr/lr.txt +// Submitted by registry +lr +com.lr +edu.lr +gov.lr +org.lr +net.lr + +// ls : https://en.wikipedia.org/wiki/.ls +ls +co.ls +org.ls + +// lt : https://en.wikipedia.org/wiki/.lt +lt +// gov.lt : http://www.gov.lt/index_en.php +gov.lt + +// lu : http://www.dns.lu/en/ +lu + +// lv : http://www.nic.lv/DNS/En/generic.php +lv +com.lv +edu.lv +gov.lv +org.lv +mil.lv +id.lv +net.lv +asn.lv +conf.lv + +// ly : http://www.nic.ly/regulations.php +ly +com.ly +net.ly +gov.ly +plc.ly +edu.ly +sch.ly +med.ly +org.ly +id.ly + +// ma : https://en.wikipedia.org/wiki/.ma +// http://www.anrt.ma/fr/admin/download/upload/file_fr782.pdf +ma +co.ma +net.ma +gov.ma +org.ma +ac.ma +press.ma + +// mc : http://www.nic.mc/ +mc +tm.mc +asso.mc + +// md : https://en.wikipedia.org/wiki/.md +md + +// me : https://en.wikipedia.org/wiki/.me +me +co.me +net.me +org.me +edu.me +ac.me +gov.me +its.me +priv.me + +// mg : http://nic.mg/nicmg/?page_id=39 +mg +org.mg +nom.mg +gov.mg +prd.mg +tm.mg +edu.mg +mil.mg +com.mg +co.mg + +// mh : https://en.wikipedia.org/wiki/.mh +mh + +// mil : https://en.wikipedia.org/wiki/.mil +mil + +// mk : https://en.wikipedia.org/wiki/.mk +// see also: http://dns.marnet.net.mk/postapka.php +mk +com.mk +org.mk +net.mk +edu.mk +gov.mk +inf.mk +name.mk + +// ml : http://www.gobin.info/domainname/ml-template.doc +// see also: https://en.wikipedia.org/wiki/.ml +ml +com.ml +edu.ml +gouv.ml +gov.ml +net.ml +org.ml +presse.ml + +// mm : https://en.wikipedia.org/wiki/.mm +*.mm + +// mn : https://en.wikipedia.org/wiki/.mn +mn +gov.mn +edu.mn +org.mn + +// mo : http://www.monic.net.mo/ +mo +com.mo +net.mo +org.mo +edu.mo +gov.mo + +// mobi : https://en.wikipedia.org/wiki/.mobi +mobi + +// mp : http://www.dot.mp/ +// Confirmed by registry 2008-06-17 +mp + +// mq : https://en.wikipedia.org/wiki/.mq +mq + +// mr : https://en.wikipedia.org/wiki/.mr +mr +gov.mr + +// ms : http://www.nic.ms/pdf/MS_Domain_Name_Rules.pdf +ms +com.ms +edu.ms +gov.ms +net.ms +org.ms + +// mt : https://www.nic.org.mt/go/policy +// Submitted by registry +mt +com.mt +edu.mt +net.mt +org.mt + +// mu : https://en.wikipedia.org/wiki/.mu +mu +com.mu +net.mu +org.mu +gov.mu +ac.mu +co.mu +or.mu + +// museum : http://about.museum/naming/ +// http://index.museum/ +museum +academy.museum +agriculture.museum +air.museum +airguard.museum +alabama.museum +alaska.museum +amber.museum +ambulance.museum +american.museum +americana.museum +americanantiques.museum +americanart.museum +amsterdam.museum +and.museum +annefrank.museum +anthro.museum +anthropology.museum +antiques.museum +aquarium.museum +arboretum.museum +archaeological.museum +archaeology.museum +architecture.museum +art.museum +artanddesign.museum +artcenter.museum +artdeco.museum +arteducation.museum +artgallery.museum +arts.museum +artsandcrafts.museum +asmatart.museum +assassination.museum +assisi.museum +association.museum +astronomy.museum +atlanta.museum +austin.museum +australia.museum +automotive.museum +aviation.museum +axis.museum +badajoz.museum +baghdad.museum +bahn.museum +bale.museum +baltimore.museum +barcelona.museum +baseball.museum +basel.museum +baths.museum +bauern.museum +beauxarts.museum +beeldengeluid.museum +bellevue.museum +bergbau.museum +berkeley.museum +berlin.museum +bern.museum +bible.museum +bilbao.museum +bill.museum +birdart.museum +birthplace.museum +bonn.museum +boston.museum +botanical.museum +botanicalgarden.museum +botanicgarden.museum +botany.museum +brandywinevalley.museum +brasil.museum +bristol.museum +british.museum +britishcolumbia.museum +broadcast.museum +brunel.museum +brussel.museum +brussels.museum +bruxelles.museum +building.museum +burghof.museum +bus.museum +bushey.museum +cadaques.museum +california.museum +cambridge.museum +can.museum +canada.museum +capebreton.museum +carrier.museum +cartoonart.museum +casadelamoneda.museum +castle.museum +castres.museum +celtic.museum +center.museum +chattanooga.museum +cheltenham.museum +chesapeakebay.museum +chicago.museum +children.museum +childrens.museum +childrensgarden.museum +chiropractic.museum +chocolate.museum +christiansburg.museum +cincinnati.museum +cinema.museum +circus.museum +civilisation.museum +civilization.museum +civilwar.museum +clinton.museum +clock.museum +coal.museum +coastaldefence.museum +cody.museum +coldwar.museum +collection.museum +colonialwilliamsburg.museum +coloradoplateau.museum +columbia.museum +columbus.museum +communication.museum +communications.museum +community.museum +computer.museum +computerhistory.museum +comunicações.museum +contemporary.museum +contemporaryart.museum +convent.museum +copenhagen.museum +corporation.museum +correios-e-telecomunicações.museum +corvette.museum +costume.museum +countryestate.museum +county.museum +crafts.museum +cranbrook.museum +creation.museum +cultural.museum +culturalcenter.museum +culture.museum +cyber.museum +cymru.museum +dali.museum +dallas.museum +database.museum +ddr.museum +decorativearts.museum +delaware.museum +delmenhorst.museum +denmark.museum +depot.museum +design.museum +detroit.museum +dinosaur.museum +discovery.museum +dolls.museum +donostia.museum +durham.museum +eastafrica.museum +eastcoast.museum +education.museum +educational.museum +egyptian.museum +eisenbahn.museum +elburg.museum +elvendrell.museum +embroidery.museum +encyclopedic.museum +england.museum +entomology.museum +environment.museum +environmentalconservation.museum +epilepsy.museum +essex.museum +estate.museum +ethnology.museum +exeter.museum +exhibition.museum +family.museum +farm.museum +farmequipment.museum +farmers.museum +farmstead.museum +field.museum +figueres.museum +filatelia.museum +film.museum +fineart.museum +finearts.museum +finland.museum +flanders.museum +florida.museum +force.museum +fortmissoula.museum +fortworth.museum +foundation.museum +francaise.museum +frankfurt.museum +franziskaner.museum +freemasonry.museum +freiburg.museum +fribourg.museum +frog.museum +fundacio.museum +furniture.museum +gallery.museum +garden.museum +gateway.museum +geelvinck.museum +gemological.museum +geology.museum +georgia.museum +giessen.museum +glas.museum +glass.museum +gorge.museum +grandrapids.museum +graz.museum +guernsey.museum +halloffame.museum +hamburg.museum +handson.museum +harvestcelebration.museum +hawaii.museum +health.museum +heimatunduhren.museum +hellas.museum +helsinki.museum +hembygdsforbund.museum +heritage.museum +histoire.museum +historical.museum +historicalsociety.museum +historichouses.museum +historisch.museum +historisches.museum +history.museum +historyofscience.museum +horology.museum +house.museum +humanities.museum +illustration.museum +imageandsound.museum +indian.museum +indiana.museum +indianapolis.museum +indianmarket.museum +intelligence.museum +interactive.museum +iraq.museum +iron.museum +isleofman.museum +jamison.museum +jefferson.museum +jerusalem.museum +jewelry.museum +jewish.museum +jewishart.museum +jfk.museum +journalism.museum +judaica.museum +judygarland.museum +juedisches.museum +juif.museum +karate.museum +karikatur.museum +kids.museum +koebenhavn.museum +koeln.museum +kunst.museum +kunstsammlung.museum +kunstunddesign.museum +labor.museum +labour.museum +lajolla.museum +lancashire.museum +landes.museum +lans.museum +läns.museum +larsson.museum +lewismiller.museum +lincoln.museum +linz.museum +living.museum +livinghistory.museum +localhistory.museum +london.museum +losangeles.museum +louvre.museum +loyalist.museum +lucerne.museum +luxembourg.museum +luzern.museum +mad.museum +madrid.museum +mallorca.museum +manchester.museum +mansion.museum +mansions.museum +manx.museum +marburg.museum +maritime.museum +maritimo.museum +maryland.museum +marylhurst.museum +media.museum +medical.museum +medizinhistorisches.museum +meeres.museum +memorial.museum +mesaverde.museum +michigan.museum +midatlantic.museum +military.museum +mill.museum +miners.museum +mining.museum +minnesota.museum +missile.museum +missoula.museum +modern.museum +moma.museum +money.museum +monmouth.museum +monticello.museum +montreal.museum +moscow.museum +motorcycle.museum +muenchen.museum +muenster.museum +mulhouse.museum +muncie.museum +museet.museum +museumcenter.museum +museumvereniging.museum +music.museum +national.museum +nationalfirearms.museum +nationalheritage.museum +nativeamerican.museum +naturalhistory.museum +naturalhistorymuseum.museum +naturalsciences.museum +nature.museum +naturhistorisches.museum +natuurwetenschappen.museum +naumburg.museum +naval.museum +nebraska.museum +neues.museum +newhampshire.museum +newjersey.museum +newmexico.museum +newport.museum +newspaper.museum +newyork.museum +niepce.museum +norfolk.museum +north.museum +nrw.museum +nuernberg.museum +nuremberg.museum +nyc.museum +nyny.museum +oceanographic.museum +oceanographique.museum +omaha.museum +online.museum +ontario.museum +openair.museum +oregon.museum +oregontrail.museum +otago.museum +oxford.museum +pacific.museum +paderborn.museum +palace.museum +paleo.museum +palmsprings.museum +panama.museum +paris.museum +pasadena.museum +pharmacy.museum +philadelphia.museum +philadelphiaarea.museum +philately.museum +phoenix.museum +photography.museum +pilots.museum +pittsburgh.museum +planetarium.museum +plantation.museum +plants.museum +plaza.museum +portal.museum +portland.museum +portlligat.museum +posts-and-telecommunications.museum +preservation.museum +presidio.museum +press.museum +project.museum +public.museum +pubol.museum +quebec.museum +railroad.museum +railway.museum +research.museum +resistance.museum +riodejaneiro.museum +rochester.museum +rockart.museum +roma.museum +russia.museum +saintlouis.museum +salem.museum +salvadordali.museum +salzburg.museum +sandiego.museum +sanfrancisco.museum +santabarbara.museum +santacruz.museum +santafe.museum +saskatchewan.museum +satx.museum +savannahga.museum +schlesisches.museum +schoenbrunn.museum +schokoladen.museum +school.museum +schweiz.museum +science.museum +scienceandhistory.museum +scienceandindustry.museum +sciencecenter.museum +sciencecenters.museum +science-fiction.museum +sciencehistory.museum +sciences.museum +sciencesnaturelles.museum +scotland.museum +seaport.museum +settlement.museum +settlers.museum +shell.museum +sherbrooke.museum +sibenik.museum +silk.museum +ski.museum +skole.museum +society.museum +sologne.museum +soundandvision.museum +southcarolina.museum +southwest.museum +space.museum +spy.museum +square.museum +stadt.museum +stalbans.museum +starnberg.museum +state.museum +stateofdelaware.museum +station.museum +steam.museum +steiermark.museum +stjohn.museum +stockholm.museum +stpetersburg.museum +stuttgart.museum +suisse.museum +surgeonshall.museum +surrey.museum +svizzera.museum +sweden.museum +sydney.museum +tank.museum +tcm.museum +technology.museum +telekommunikation.museum +television.museum +texas.museum +textile.museum +theater.museum +time.museum +timekeeping.museum +topology.museum +torino.museum +touch.museum +town.museum +transport.museum +tree.museum +trolley.museum +trust.museum +trustee.museum +uhren.museum +ulm.museum +undersea.museum +university.museum +usa.museum +usantiques.museum +usarts.museum +uscountryestate.museum +usculture.museum +usdecorativearts.museum +usgarden.museum +ushistory.museum +ushuaia.museum +uslivinghistory.museum +utah.museum +uvic.museum +valley.museum +vantaa.museum +versailles.museum +viking.museum +village.museum +virginia.museum +virtual.museum +virtuel.museum +vlaanderen.museum +volkenkunde.museum +wales.museum +wallonie.museum +war.museum +washingtondc.museum +watchandclock.museum +watch-and-clock.museum +western.museum +westfalen.museum +whaling.museum +wildlife.museum +williamsburg.museum +windmill.museum +workshop.museum +york.museum +yorkshire.museum +yosemite.museum +youth.museum +zoological.museum +zoology.museum +ירושלים.museum +иком.museum + +// mv : https://en.wikipedia.org/wiki/.mv +// "mv" included because, contra Wikipedia, google.mv exists. +mv +aero.mv +biz.mv +com.mv +coop.mv +edu.mv +gov.mv +info.mv +int.mv +mil.mv +museum.mv +name.mv +net.mv +org.mv +pro.mv + +// mw : http://www.registrar.mw/ +mw +ac.mw +biz.mw +co.mw +com.mw +coop.mw +edu.mw +gov.mw +int.mw +museum.mw +net.mw +org.mw + +// mx : http://www.nic.mx/ +// Submitted by registry +mx +com.mx +org.mx +gob.mx +edu.mx +net.mx + +// my : http://www.mynic.net.my/ +my +com.my +net.my +org.my +gov.my +edu.my +mil.my +name.my + +// mz : http://www.uem.mz/ +// Submitted by registry +mz +ac.mz +adv.mz +co.mz +edu.mz +gov.mz +mil.mz +net.mz +org.mz + +// na : http://www.na-nic.com.na/ +// http://www.info.na/domain/ +na +info.na +pro.na +name.na +school.na +or.na +dr.na +us.na +mx.na +ca.na +in.na +cc.na +tv.na +ws.na +mobi.na +co.na +com.na +org.na + +// name : has 2nd-level tlds, but there's no list of them +name + +// nc : http://www.cctld.nc/ +nc +asso.nc +nom.nc + +// ne : https://en.wikipedia.org/wiki/.ne +ne + +// net : https://en.wikipedia.org/wiki/.net +net + +// nf : https://en.wikipedia.org/wiki/.nf +nf +com.nf +net.nf +per.nf +rec.nf +web.nf +arts.nf +firm.nf +info.nf +other.nf +store.nf + +// ng : http://www.nira.org.ng/index.php/join-us/register-ng-domain/189-nira-slds +ng +com.ng +edu.ng +gov.ng +i.ng +mil.ng +mobi.ng +name.ng +net.ng +org.ng +sch.ng + +// ni : http://www.nic.ni/ +ni +ac.ni +biz.ni +co.ni +com.ni +edu.ni +gob.ni +in.ni +info.ni +int.ni +mil.ni +net.ni +nom.ni +org.ni +web.ni + +// nl : https://en.wikipedia.org/wiki/.nl +// https://www.sidn.nl/ +// ccTLD for the Netherlands +nl + +// BV.nl will be a registry for dutch BV's (besloten vennootschap) +bv.nl + +// no : http://www.norid.no/regelverk/index.en.html +// The Norwegian registry has declined to notify us of updates. The web pages +// referenced below are the official source of the data. There is also an +// announce mailing list: +// https://postlister.uninett.no/sympa/info/norid-diskusjon +no +// Norid generic domains : http://www.norid.no/regelverk/vedlegg-c.en.html +fhs.no +vgs.no +fylkesbibl.no +folkebibl.no +museum.no +idrett.no +priv.no +// Non-Norid generic domains : http://www.norid.no/regelverk/vedlegg-d.en.html +mil.no +stat.no +dep.no +kommune.no +herad.no +// no geographical names : http://www.norid.no/regelverk/vedlegg-b.en.html +// counties +aa.no +ah.no +bu.no +fm.no +hl.no +hm.no +jan-mayen.no +mr.no +nl.no +nt.no +of.no +ol.no +oslo.no +rl.no +sf.no +st.no +svalbard.no +tm.no +tr.no +va.no +vf.no +// primary and lower secondary schools per county +gs.aa.no +gs.ah.no +gs.bu.no +gs.fm.no +gs.hl.no +gs.hm.no +gs.jan-mayen.no +gs.mr.no +gs.nl.no +gs.nt.no +gs.of.no +gs.ol.no +gs.oslo.no +gs.rl.no +gs.sf.no +gs.st.no +gs.svalbard.no +gs.tm.no +gs.tr.no +gs.va.no +gs.vf.no +// cities +akrehamn.no +åkrehamn.no +algard.no +ålgård.no +arna.no +brumunddal.no +bryne.no +bronnoysund.no +brønnøysund.no +drobak.no +drøbak.no +egersund.no +fetsund.no +floro.no +florø.no +fredrikstad.no +hokksund.no +honefoss.no +hønefoss.no +jessheim.no +jorpeland.no +jørpeland.no +kirkenes.no +kopervik.no +krokstadelva.no +langevag.no +langevåg.no +leirvik.no +mjondalen.no +mjøndalen.no +mo-i-rana.no +mosjoen.no +mosjøen.no +nesoddtangen.no +orkanger.no +osoyro.no +osøyro.no +raholt.no +råholt.no +sandnessjoen.no +sandnessjøen.no +skedsmokorset.no +slattum.no +spjelkavik.no +stathelle.no +stavern.no +stjordalshalsen.no +stjørdalshalsen.no +tananger.no +tranby.no +vossevangen.no +// communities +afjord.no +åfjord.no +agdenes.no +al.no +ål.no +alesund.no +ålesund.no +alstahaug.no +alta.no +áltá.no +alaheadju.no +álaheadju.no +alvdal.no +amli.no +åmli.no +amot.no +åmot.no +andebu.no +andoy.no +andøy.no +andasuolo.no +ardal.no +årdal.no +aremark.no +arendal.no +ås.no +aseral.no +åseral.no +asker.no +askim.no +askvoll.no +askoy.no +askøy.no +asnes.no +åsnes.no +audnedaln.no +aukra.no +aure.no +aurland.no +aurskog-holand.no +aurskog-høland.no +austevoll.no +austrheim.no +averoy.no +averøy.no +balestrand.no +ballangen.no +balat.no +bálát.no +balsfjord.no +bahccavuotna.no +báhccavuotna.no +bamble.no +bardu.no +beardu.no +beiarn.no +bajddar.no +bájddar.no +baidar.no +báidár.no +berg.no +bergen.no +berlevag.no +berlevåg.no +bearalvahki.no +bearalváhki.no +bindal.no +birkenes.no +bjarkoy.no +bjarkøy.no +bjerkreim.no +bjugn.no +bodo.no +bodø.no +badaddja.no +bådåddjå.no +budejju.no +bokn.no +bremanger.no +bronnoy.no +brønnøy.no +bygland.no +bykle.no +barum.no +bærum.no +bo.telemark.no +bø.telemark.no +bo.nordland.no +bø.nordland.no +bievat.no +bievát.no +bomlo.no +bømlo.no +batsfjord.no +båtsfjord.no +bahcavuotna.no +báhcavuotna.no +dovre.no +drammen.no +drangedal.no +dyroy.no +dyrøy.no +donna.no +dønna.no +eid.no +eidfjord.no +eidsberg.no +eidskog.no +eidsvoll.no +eigersund.no +elverum.no +enebakk.no +engerdal.no +etne.no +etnedal.no +evenes.no +evenassi.no +evenášši.no +evje-og-hornnes.no +farsund.no +fauske.no +fuossko.no +fuoisku.no +fedje.no +fet.no +finnoy.no +finnøy.no +fitjar.no +fjaler.no +fjell.no +flakstad.no +flatanger.no +flekkefjord.no +flesberg.no +flora.no +fla.no +flå.no +folldal.no +forsand.no +fosnes.no +frei.no +frogn.no +froland.no +frosta.no +frana.no +fræna.no +froya.no +frøya.no +fusa.no +fyresdal.no +forde.no +førde.no +gamvik.no +gangaviika.no +gáŋgaviika.no +gaular.no +gausdal.no +gildeskal.no +gildeskål.no +giske.no +gjemnes.no +gjerdrum.no +gjerstad.no +gjesdal.no +gjovik.no +gjøvik.no +gloppen.no +gol.no +gran.no +grane.no +granvin.no +gratangen.no +grimstad.no +grong.no +kraanghke.no +kråanghke.no +grue.no +gulen.no +hadsel.no +halden.no +halsa.no +hamar.no +hamaroy.no +habmer.no +hábmer.no +hapmir.no +hápmir.no +hammerfest.no +hammarfeasta.no +hámmárfeasta.no +haram.no +hareid.no +harstad.no +hasvik.no +aknoluokta.no +ákŋoluokta.no +hattfjelldal.no +aarborte.no +haugesund.no +hemne.no +hemnes.no +hemsedal.no +heroy.more-og-romsdal.no +herøy.møre-og-romsdal.no +heroy.nordland.no +herøy.nordland.no +hitra.no +hjartdal.no +hjelmeland.no +hobol.no +hobøl.no +hof.no +hol.no +hole.no +holmestrand.no +holtalen.no +holtålen.no +hornindal.no +horten.no +hurdal.no +hurum.no +hvaler.no +hyllestad.no +hagebostad.no +hægebostad.no +hoyanger.no +høyanger.no +hoylandet.no +høylandet.no +ha.no +hå.no +ibestad.no +inderoy.no +inderøy.no +iveland.no +jevnaker.no +jondal.no +jolster.no +jølster.no +karasjok.no +karasjohka.no +kárášjohka.no +karlsoy.no +galsa.no +gálsá.no +karmoy.no +karmøy.no +kautokeino.no +guovdageaidnu.no +klepp.no +klabu.no +klæbu.no +kongsberg.no +kongsvinger.no +kragero.no +kragerø.no +kristiansand.no +kristiansund.no +krodsherad.no +krødsherad.no +kvalsund.no +rahkkeravju.no +ráhkkerávju.no +kvam.no +kvinesdal.no +kvinnherad.no +kviteseid.no +kvitsoy.no +kvitsøy.no +kvafjord.no +kvæfjord.no +giehtavuoatna.no +kvanangen.no +kvænangen.no +navuotna.no +návuotna.no +kafjord.no +kåfjord.no +gaivuotna.no +gáivuotna.no +larvik.no +lavangen.no +lavagis.no +loabat.no +loabát.no +lebesby.no +davvesiida.no +leikanger.no +leirfjord.no +leka.no +leksvik.no +lenvik.no +leangaviika.no +leaŋgaviika.no +lesja.no +levanger.no +lier.no +lierne.no +lillehammer.no +lillesand.no +lindesnes.no +lindas.no +lindås.no +lom.no +loppa.no +lahppi.no +láhppi.no +lund.no +lunner.no +luroy.no +lurøy.no +luster.no +lyngdal.no +lyngen.no +ivgu.no +lardal.no +lerdal.no +lærdal.no +lodingen.no +lødingen.no +lorenskog.no +lørenskog.no +loten.no +løten.no +malvik.no +masoy.no +måsøy.no +muosat.no +muosát.no +mandal.no +marker.no +marnardal.no +masfjorden.no +meland.no +meldal.no +melhus.no +meloy.no +meløy.no +meraker.no +meråker.no +moareke.no +moåreke.no +midsund.no +midtre-gauldal.no +modalen.no +modum.no +molde.no +moskenes.no +moss.no +mosvik.no +malselv.no +målselv.no +malatvuopmi.no +málatvuopmi.no +namdalseid.no +aejrie.no +namsos.no +namsskogan.no +naamesjevuemie.no +nååmesjevuemie.no +laakesvuemie.no +nannestad.no +narvik.no +narviika.no +naustdal.no +nedre-eiker.no +nes.akershus.no +nes.buskerud.no +nesna.no +nesodden.no +nesseby.no +unjarga.no +unjárga.no +nesset.no +nissedal.no +nittedal.no +nord-aurdal.no +nord-fron.no +nord-odal.no +norddal.no +nordkapp.no +davvenjarga.no +davvenjárga.no +nordre-land.no +nordreisa.no +raisa.no +ráisa.no +nore-og-uvdal.no +notodden.no +naroy.no +nærøy.no +notteroy.no +nøtterøy.no +odda.no +oksnes.no +øksnes.no +oppdal.no +oppegard.no +oppegård.no +orkdal.no +orland.no +ørland.no +orskog.no +ørskog.no +orsta.no +ørsta.no +os.hedmark.no +os.hordaland.no +osen.no +osteroy.no +osterøy.no +ostre-toten.no +østre-toten.no +overhalla.no +ovre-eiker.no +øvre-eiker.no +oyer.no +øyer.no +oygarden.no +øygarden.no +oystre-slidre.no +øystre-slidre.no +porsanger.no +porsangu.no +porsáŋgu.no +porsgrunn.no +radoy.no +radøy.no +rakkestad.no +rana.no +ruovat.no +randaberg.no +rauma.no +rendalen.no +rennebu.no +rennesoy.no +rennesøy.no +rindal.no +ringebu.no +ringerike.no +ringsaker.no +rissa.no +risor.no +risør.no +roan.no +rollag.no +rygge.no +ralingen.no +rælingen.no +rodoy.no +rødøy.no +romskog.no +rømskog.no +roros.no +røros.no +rost.no +røst.no +royken.no +røyken.no +royrvik.no +røyrvik.no +rade.no +råde.no +salangen.no +siellak.no +saltdal.no +salat.no +sálát.no +sálat.no +samnanger.no +sande.more-og-romsdal.no +sande.møre-og-romsdal.no +sande.vestfold.no +sandefjord.no +sandnes.no +sandoy.no +sandøy.no +sarpsborg.no +sauda.no +sauherad.no +sel.no +selbu.no +selje.no +seljord.no +sigdal.no +siljan.no +sirdal.no +skaun.no +skedsmo.no +ski.no +skien.no +skiptvet.no +skjervoy.no +skjervøy.no +skierva.no +skiervá.no +skjak.no +skjåk.no +skodje.no +skanland.no +skånland.no +skanit.no +skánit.no +smola.no +smøla.no +snillfjord.no +snasa.no +snåsa.no +snoasa.no +snaase.no +snåase.no +sogndal.no +sokndal.no +sola.no +solund.no +songdalen.no +sortland.no +spydeberg.no +stange.no +stavanger.no +steigen.no +steinkjer.no +stjordal.no +stjørdal.no +stokke.no +stor-elvdal.no +stord.no +stordal.no +storfjord.no +omasvuotna.no +strand.no +stranda.no +stryn.no +sula.no +suldal.no +sund.no +sunndal.no +surnadal.no +sveio.no +svelvik.no +sykkylven.no +sogne.no +søgne.no +somna.no +sømna.no +sondre-land.no +søndre-land.no +sor-aurdal.no +sør-aurdal.no +sor-fron.no +sør-fron.no +sor-odal.no +sør-odal.no +sor-varanger.no +sør-varanger.no +matta-varjjat.no +mátta-várjjat.no +sorfold.no +sørfold.no +sorreisa.no +sørreisa.no +sorum.no +sørum.no +tana.no +deatnu.no +time.no +tingvoll.no +tinn.no +tjeldsund.no +dielddanuorri.no +tjome.no +tjøme.no +tokke.no +tolga.no +torsken.no +tranoy.no +tranøy.no +tromso.no +tromsø.no +tromsa.no +romsa.no +trondheim.no +troandin.no +trysil.no +trana.no +træna.no +trogstad.no +trøgstad.no +tvedestrand.no +tydal.no +tynset.no +tysfjord.no +divtasvuodna.no +divttasvuotna.no +tysnes.no +tysvar.no +tysvær.no +tonsberg.no +tønsberg.no +ullensaker.no +ullensvang.no +ulvik.no +utsira.no +vadso.no +vadsø.no +cahcesuolo.no +čáhcesuolo.no +vaksdal.no +valle.no +vang.no +vanylven.no +vardo.no +vardø.no +varggat.no +várggát.no +vefsn.no +vaapste.no +vega.no +vegarshei.no +vegårshei.no +vennesla.no +verdal.no +verran.no +vestby.no +vestnes.no +vestre-slidre.no +vestre-toten.no +vestvagoy.no +vestvågøy.no +vevelstad.no +vik.no +vikna.no +vindafjord.no +volda.no +voss.no +varoy.no +værøy.no +vagan.no +vågan.no +voagat.no +vagsoy.no +vågsøy.no +vaga.no +vågå.no +valer.ostfold.no +våler.østfold.no +valer.hedmark.no +våler.hedmark.no + +// np : http://www.mos.com.np/register.html +*.np + +// nr : http://cenpac.net.nr/dns/index.html +// Submitted by registry +nr +biz.nr +info.nr +gov.nr +edu.nr +org.nr +net.nr +com.nr + +// nu : https://en.wikipedia.org/wiki/.nu +nu + +// nz : https://en.wikipedia.org/wiki/.nz +// Submitted by registry +nz +ac.nz +co.nz +cri.nz +geek.nz +gen.nz +govt.nz +health.nz +iwi.nz +kiwi.nz +maori.nz +mil.nz +māori.nz +net.nz +org.nz +parliament.nz +school.nz + +// om : https://en.wikipedia.org/wiki/.om +om +co.om +com.om +edu.om +gov.om +med.om +museum.om +net.om +org.om +pro.om + +// onion : https://tools.ietf.org/html/rfc7686 +onion + +// org : https://en.wikipedia.org/wiki/.org +org + +// pa : http://www.nic.pa/ +// Some additional second level "domains" resolve directly as hostnames, such as +// pannet.pa, so we add a rule for "pa". +pa +ac.pa +gob.pa +com.pa +org.pa +sld.pa +edu.pa +net.pa +ing.pa +abo.pa +med.pa +nom.pa + +// pe : https://www.nic.pe/InformeFinalComision.pdf +pe +edu.pe +gob.pe +nom.pe +mil.pe +org.pe +com.pe +net.pe + +// pf : http://www.gobin.info/domainname/formulaire-pf.pdf +pf +com.pf +org.pf +edu.pf + +// pg : https://en.wikipedia.org/wiki/.pg +*.pg + +// ph : http://www.domains.ph/FAQ2.asp +// Submitted by registry +ph +com.ph +net.ph +org.ph +gov.ph +edu.ph +ngo.ph +mil.ph +i.ph + +// pk : http://pk5.pknic.net.pk/pk5/msgNamepk.PK +pk +com.pk +net.pk +edu.pk +org.pk +fam.pk +biz.pk +web.pk +gov.pk +gob.pk +gok.pk +gon.pk +gop.pk +gos.pk +info.pk + +// pl http://www.dns.pl/english/index.html +// Submitted by registry +pl +com.pl +net.pl +org.pl +// pl functional domains (http://www.dns.pl/english/index.html) +aid.pl +agro.pl +atm.pl +auto.pl +biz.pl +edu.pl +gmina.pl +gsm.pl +info.pl +mail.pl +miasta.pl +media.pl +mil.pl +nieruchomosci.pl +nom.pl +pc.pl +powiat.pl +priv.pl +realestate.pl +rel.pl +sex.pl +shop.pl +sklep.pl +sos.pl +szkola.pl +targi.pl +tm.pl +tourism.pl +travel.pl +turystyka.pl +// Government domains +gov.pl +ap.gov.pl +ic.gov.pl +is.gov.pl +us.gov.pl +kmpsp.gov.pl +kppsp.gov.pl +kwpsp.gov.pl +psp.gov.pl +wskr.gov.pl +kwp.gov.pl +mw.gov.pl +ug.gov.pl +um.gov.pl +umig.gov.pl +ugim.gov.pl +upow.gov.pl +uw.gov.pl +starostwo.gov.pl +pa.gov.pl +po.gov.pl +psse.gov.pl +pup.gov.pl +rzgw.gov.pl +sa.gov.pl +so.gov.pl +sr.gov.pl +wsa.gov.pl +sko.gov.pl +uzs.gov.pl +wiih.gov.pl +winb.gov.pl +pinb.gov.pl +wios.gov.pl +witd.gov.pl +wzmiuw.gov.pl +piw.gov.pl +wiw.gov.pl +griw.gov.pl +wif.gov.pl +oum.gov.pl +sdn.gov.pl +zp.gov.pl +uppo.gov.pl +mup.gov.pl +wuoz.gov.pl +konsulat.gov.pl +oirm.gov.pl +// pl regional domains (http://www.dns.pl/english/index.html) +augustow.pl +babia-gora.pl +bedzin.pl +beskidy.pl +bialowieza.pl +bialystok.pl +bielawa.pl +bieszczady.pl +boleslawiec.pl +bydgoszcz.pl +bytom.pl +cieszyn.pl +czeladz.pl +czest.pl +dlugoleka.pl +elblag.pl +elk.pl +glogow.pl +gniezno.pl +gorlice.pl +grajewo.pl +ilawa.pl +jaworzno.pl +jelenia-gora.pl +jgora.pl +kalisz.pl +kazimierz-dolny.pl +karpacz.pl +kartuzy.pl +kaszuby.pl +katowice.pl +kepno.pl +ketrzyn.pl +klodzko.pl +kobierzyce.pl +kolobrzeg.pl +konin.pl +konskowola.pl +kutno.pl +lapy.pl +lebork.pl +legnica.pl +lezajsk.pl +limanowa.pl +lomza.pl +lowicz.pl +lubin.pl +lukow.pl +malbork.pl +malopolska.pl +mazowsze.pl +mazury.pl +mielec.pl +mielno.pl +mragowo.pl +naklo.pl +nowaruda.pl +nysa.pl +olawa.pl +olecko.pl +olkusz.pl +olsztyn.pl +opoczno.pl +opole.pl +ostroda.pl +ostroleka.pl +ostrowiec.pl +ostrowwlkp.pl +pila.pl +pisz.pl +podhale.pl +podlasie.pl +polkowice.pl +pomorze.pl +pomorskie.pl +prochowice.pl +pruszkow.pl +przeworsk.pl +pulawy.pl +radom.pl +rawa-maz.pl +rybnik.pl +rzeszow.pl +sanok.pl +sejny.pl +slask.pl +slupsk.pl +sosnowiec.pl +stalowa-wola.pl +skoczow.pl +starachowice.pl +stargard.pl +suwalki.pl +swidnica.pl +swiebodzin.pl +swinoujscie.pl +szczecin.pl +szczytno.pl +tarnobrzeg.pl +tgory.pl +turek.pl +tychy.pl +ustka.pl +walbrzych.pl +warmia.pl +warszawa.pl +waw.pl +wegrow.pl +wielun.pl +wlocl.pl +wloclawek.pl +wodzislaw.pl +wolomin.pl +wroclaw.pl +zachpomor.pl +zagan.pl +zarow.pl +zgora.pl +zgorzelec.pl + +// pm : http://www.afnic.fr/medias/documents/AFNIC-naming-policy2012.pdf +pm + +// pn : http://www.government.pn/PnRegistry/policies.htm +pn +gov.pn +co.pn +org.pn +edu.pn +net.pn + +// post : https://en.wikipedia.org/wiki/.post +post + +// pr : http://www.nic.pr/index.asp?f=1 +pr +com.pr +net.pr +org.pr +gov.pr +edu.pr +isla.pr +pro.pr +biz.pr +info.pr +name.pr +// these aren't mentioned on nic.pr, but on https://en.wikipedia.org/wiki/.pr +est.pr +prof.pr +ac.pr + +// pro : http://registry.pro/get-pro +pro +aaa.pro +aca.pro +acct.pro +avocat.pro +bar.pro +cpa.pro +eng.pro +jur.pro +law.pro +med.pro +recht.pro + +// ps : https://en.wikipedia.org/wiki/.ps +// http://www.nic.ps/registration/policy.html#reg +ps +edu.ps +gov.ps +sec.ps +plo.ps +com.ps +org.ps +net.ps + +// pt : http://online.dns.pt/dns/start_dns +pt +net.pt +gov.pt +org.pt +edu.pt +int.pt +publ.pt +com.pt +nome.pt + +// pw : https://en.wikipedia.org/wiki/.pw +pw +co.pw +ne.pw +or.pw +ed.pw +go.pw +belau.pw + +// py : http://www.nic.py/pautas.html#seccion_9 +// Submitted by registry +py +com.py +coop.py +edu.py +gov.py +mil.py +net.py +org.py + +// qa : http://domains.qa/en/ +qa +com.qa +edu.qa +gov.qa +mil.qa +name.qa +net.qa +org.qa +sch.qa + +// re : http://www.afnic.re/obtenir/chartes/nommage-re/annexe-descriptifs +re +asso.re +com.re +nom.re + +// ro : http://www.rotld.ro/ +ro +arts.ro +com.ro +firm.ro +info.ro +nom.ro +nt.ro +org.ro +rec.ro +store.ro +tm.ro +www.ro + +// rs : https://www.rnids.rs/en/domains/national-domains +rs +ac.rs +co.rs +edu.rs +gov.rs +in.rs +org.rs + +// ru : https://cctld.ru/en/domains/domens_ru/reserved/ +ru +ac.ru +edu.ru +gov.ru +int.ru +mil.ru +test.ru + +// rw : http://www.nic.rw/cgi-bin/policy.pl +rw +gov.rw +net.rw +edu.rw +ac.rw +com.rw +co.rw +int.rw +mil.rw +gouv.rw + +// sa : http://www.nic.net.sa/ +sa +com.sa +net.sa +org.sa +gov.sa +med.sa +pub.sa +edu.sa +sch.sa + +// sb : http://www.sbnic.net.sb/ +// Submitted by registry +sb +com.sb +edu.sb +gov.sb +net.sb +org.sb + +// sc : http://www.nic.sc/ +sc +com.sc +gov.sc +net.sc +org.sc +edu.sc + +// sd : http://www.isoc.sd/sudanic.isoc.sd/billing_pricing.htm +// Submitted by registry +sd +com.sd +net.sd +org.sd +edu.sd +med.sd +tv.sd +gov.sd +info.sd + +// se : https://en.wikipedia.org/wiki/.se +// Submitted by registry +se +a.se +ac.se +b.se +bd.se +brand.se +c.se +d.se +e.se +f.se +fh.se +fhsk.se +fhv.se +g.se +h.se +i.se +k.se +komforb.se +kommunalforbund.se +komvux.se +l.se +lanbib.se +m.se +n.se +naturbruksgymn.se +o.se +org.se +p.se +parti.se +pp.se +press.se +r.se +s.se +t.se +tm.se +u.se +w.se +x.se +y.se +z.se + +// sg : http://www.nic.net.sg/page/registration-policies-procedures-and-guidelines +sg +com.sg +net.sg +org.sg +gov.sg +edu.sg +per.sg + +// sh : http://www.nic.sh/registrar.html +sh +com.sh +net.sh +gov.sh +org.sh +mil.sh + +// si : https://en.wikipedia.org/wiki/.si +si + +// sj : No registrations at this time. +// Submitted by registry +sj + +// sk : https://en.wikipedia.org/wiki/.sk +// list of 2nd level domains ? +sk + +// sl : http://www.nic.sl +// Submitted by registry +sl +com.sl +net.sl +edu.sl +gov.sl +org.sl + +// sm : https://en.wikipedia.org/wiki/.sm +sm + +// sn : https://en.wikipedia.org/wiki/.sn +sn +art.sn +com.sn +edu.sn +gouv.sn +org.sn +perso.sn +univ.sn + +// so : http://www.soregistry.com/ +so +com.so +net.so +org.so + +// sr : https://en.wikipedia.org/wiki/.sr +sr + +// st : http://www.nic.st/html/policyrules/ +st +co.st +com.st +consulado.st +edu.st +embaixada.st +gov.st +mil.st +net.st +org.st +principe.st +saotome.st +store.st + +// su : https://en.wikipedia.org/wiki/.su +su + +// sv : http://www.svnet.org.sv/niveldos.pdf +sv +com.sv +edu.sv +gob.sv +org.sv +red.sv + +// sx : https://en.wikipedia.org/wiki/.sx +// Submitted by registry +sx +gov.sx + +// sy : https://en.wikipedia.org/wiki/.sy +// see also: http://www.gobin.info/domainname/sy.doc +sy +edu.sy +gov.sy +net.sy +mil.sy +com.sy +org.sy + +// sz : https://en.wikipedia.org/wiki/.sz +// http://www.sispa.org.sz/ +sz +co.sz +ac.sz +org.sz + +// tc : https://en.wikipedia.org/wiki/.tc +tc + +// td : https://en.wikipedia.org/wiki/.td +td + +// tel: https://en.wikipedia.org/wiki/.tel +// http://www.telnic.org/ +tel + +// tf : https://en.wikipedia.org/wiki/.tf +tf + +// tg : https://en.wikipedia.org/wiki/.tg +// http://www.nic.tg/ +tg + +// th : https://en.wikipedia.org/wiki/.th +// Submitted by registry +th +ac.th +co.th +go.th +in.th +mi.th +net.th +or.th + +// tj : http://www.nic.tj/policy.html +tj +ac.tj +biz.tj +co.tj +com.tj +edu.tj +go.tj +gov.tj +int.tj +mil.tj +name.tj +net.tj +nic.tj +org.tj +test.tj +web.tj + +// tk : https://en.wikipedia.org/wiki/.tk +tk + +// tl : https://en.wikipedia.org/wiki/.tl +tl +gov.tl + +// tm : http://www.nic.tm/local.html +tm +com.tm +co.tm +org.tm +net.tm +nom.tm +gov.tm +mil.tm +edu.tm + +// tn : https://en.wikipedia.org/wiki/.tn +// http://whois.ati.tn/ +tn +com.tn +ens.tn +fin.tn +gov.tn +ind.tn +intl.tn +nat.tn +net.tn +org.tn +info.tn +perso.tn +tourism.tn +edunet.tn +rnrt.tn +rns.tn +rnu.tn +mincom.tn +agrinet.tn +defense.tn +turen.tn + +// to : https://en.wikipedia.org/wiki/.to +// Submitted by registry +to +com.to +gov.to +net.to +org.to +edu.to +mil.to + +// subTLDs: https://www.nic.tr/forms/eng/policies.pdf +// and: https://www.nic.tr/forms/politikalar.pdf +// Submitted by +tr +com.tr +info.tr +biz.tr +net.tr +org.tr +web.tr +gen.tr +tv.tr +av.tr +dr.tr +bbs.tr +name.tr +tel.tr +gov.tr +bel.tr +pol.tr +mil.tr +k12.tr +edu.tr +kep.tr + +// Used by Northern Cyprus +nc.tr + +// Used by government agencies of Northern Cyprus +gov.nc.tr + +// travel : https://en.wikipedia.org/wiki/.travel +travel + +// tt : http://www.nic.tt/ +tt +co.tt +com.tt +org.tt +net.tt +biz.tt +info.tt +pro.tt +int.tt +coop.tt +jobs.tt +mobi.tt +travel.tt +museum.tt +aero.tt +name.tt +gov.tt +edu.tt + +// tv : https://en.wikipedia.org/wiki/.tv +// Not listing any 2LDs as reserved since none seem to exist in practice, +// Wikipedia notwithstanding. +tv + +// tw : https://en.wikipedia.org/wiki/.tw +tw +edu.tw +gov.tw +mil.tw +com.tw +net.tw +org.tw +idv.tw +game.tw +ebiz.tw +club.tw +網路.tw +組織.tw +商業.tw + +// tz : http://www.tznic.or.tz/index.php/domains +// Submitted by registry +tz +ac.tz +co.tz +go.tz +hotel.tz +info.tz +me.tz +mil.tz +mobi.tz +ne.tz +or.tz +sc.tz +tv.tz + +// ua : https://hostmaster.ua/policy/?ua +// Submitted by registry +ua +// ua 2LD +com.ua +edu.ua +gov.ua +in.ua +net.ua +org.ua +// ua geographic names +// https://hostmaster.ua/2ld/ +cherkassy.ua +cherkasy.ua +chernigov.ua +chernihiv.ua +chernivtsi.ua +chernovtsy.ua +ck.ua +cn.ua +cr.ua +crimea.ua +cv.ua +dn.ua +dnepropetrovsk.ua +dnipropetrovsk.ua +dominic.ua +donetsk.ua +dp.ua +if.ua +ivano-frankivsk.ua +kh.ua +kharkiv.ua +kharkov.ua +kherson.ua +khmelnitskiy.ua +khmelnytskyi.ua +kiev.ua +kirovograd.ua +km.ua +kr.ua +krym.ua +ks.ua +kv.ua +kyiv.ua +lg.ua +lt.ua +lugansk.ua +lutsk.ua +lv.ua +lviv.ua +mk.ua +mykolaiv.ua +nikolaev.ua +od.ua +odesa.ua +odessa.ua +pl.ua +poltava.ua +rivne.ua +rovno.ua +rv.ua +sb.ua +sebastopol.ua +sevastopol.ua +sm.ua +sumy.ua +te.ua +ternopil.ua +uz.ua +uzhgorod.ua +vinnica.ua +vinnytsia.ua +vn.ua +volyn.ua +yalta.ua +zaporizhzhe.ua +zaporizhzhia.ua +zhitomir.ua +zhytomyr.ua +zp.ua +zt.ua + +// ug : https://www.registry.co.ug/ +ug +co.ug +or.ug +ac.ug +sc.ug +go.ug +ne.ug +com.ug +org.ug + +// uk : https://en.wikipedia.org/wiki/.uk +// Submitted by registry +uk +ac.uk +co.uk +gov.uk +ltd.uk +me.uk +net.uk +nhs.uk +org.uk +plc.uk +police.uk +*.sch.uk + +// us : https://en.wikipedia.org/wiki/.us +us +dni.us +fed.us +isa.us +kids.us +nsn.us +// us geographic names +ak.us +al.us +ar.us +as.us +az.us +ca.us +co.us +ct.us +dc.us +de.us +fl.us +ga.us +gu.us +hi.us +ia.us +id.us +il.us +in.us +ks.us +ky.us +la.us +ma.us +md.us +me.us +mi.us +mn.us +mo.us +ms.us +mt.us +nc.us +nd.us +ne.us +nh.us +nj.us +nm.us +nv.us +ny.us +oh.us +ok.us +or.us +pa.us +pr.us +ri.us +sc.us +sd.us +tn.us +tx.us +ut.us +vi.us +vt.us +va.us +wa.us +wi.us +wv.us +wy.us +// The registrar notes several more specific domains available in each state, +// such as state.*.us, dst.*.us, etc., but resolution of these is somewhat +// haphazard; in some states these domains resolve as addresses, while in others +// only subdomains are available, or even nothing at all. We include the +// most common ones where it's clear that different sites are different +// entities. +k12.ak.us +k12.al.us +k12.ar.us +k12.as.us +k12.az.us +k12.ca.us +k12.co.us +k12.ct.us +k12.dc.us +k12.de.us +k12.fl.us +k12.ga.us +k12.gu.us +// k12.hi.us Bug 614565 - Hawaii has a state-wide DOE login +k12.ia.us +k12.id.us +k12.il.us +k12.in.us +k12.ks.us +k12.ky.us +k12.la.us +k12.ma.us +k12.md.us +k12.me.us +k12.mi.us +k12.mn.us +k12.mo.us +k12.ms.us +k12.mt.us +k12.nc.us +// k12.nd.us Bug 1028347 - Removed at request of Travis Rosso +k12.ne.us +k12.nh.us +k12.nj.us +k12.nm.us +k12.nv.us +k12.ny.us +k12.oh.us +k12.ok.us +k12.or.us +k12.pa.us +k12.pr.us +k12.ri.us +k12.sc.us +// k12.sd.us Bug 934131 - Removed at request of James Booze +k12.tn.us +k12.tx.us +k12.ut.us +k12.vi.us +k12.vt.us +k12.va.us +k12.wa.us +k12.wi.us +// k12.wv.us Bug 947705 - Removed at request of Verne Britton +k12.wy.us +cc.ak.us +cc.al.us +cc.ar.us +cc.as.us +cc.az.us +cc.ca.us +cc.co.us +cc.ct.us +cc.dc.us +cc.de.us +cc.fl.us +cc.ga.us +cc.gu.us +cc.hi.us +cc.ia.us +cc.id.us +cc.il.us +cc.in.us +cc.ks.us +cc.ky.us +cc.la.us +cc.ma.us +cc.md.us +cc.me.us +cc.mi.us +cc.mn.us +cc.mo.us +cc.ms.us +cc.mt.us +cc.nc.us +cc.nd.us +cc.ne.us +cc.nh.us +cc.nj.us +cc.nm.us +cc.nv.us +cc.ny.us +cc.oh.us +cc.ok.us +cc.or.us +cc.pa.us +cc.pr.us +cc.ri.us +cc.sc.us +cc.sd.us +cc.tn.us +cc.tx.us +cc.ut.us +cc.vi.us +cc.vt.us +cc.va.us +cc.wa.us +cc.wi.us +cc.wv.us +cc.wy.us +lib.ak.us +lib.al.us +lib.ar.us +lib.as.us +lib.az.us +lib.ca.us +lib.co.us +lib.ct.us +lib.dc.us +// lib.de.us Issue #243 - Moved to Private section at request of Ed Moore +lib.fl.us +lib.ga.us +lib.gu.us +lib.hi.us +lib.ia.us +lib.id.us +lib.il.us +lib.in.us +lib.ks.us +lib.ky.us +lib.la.us +lib.ma.us +lib.md.us +lib.me.us +lib.mi.us +lib.mn.us +lib.mo.us +lib.ms.us +lib.mt.us +lib.nc.us +lib.nd.us +lib.ne.us +lib.nh.us +lib.nj.us +lib.nm.us +lib.nv.us +lib.ny.us +lib.oh.us +lib.ok.us +lib.or.us +lib.pa.us +lib.pr.us +lib.ri.us +lib.sc.us +lib.sd.us +lib.tn.us +lib.tx.us +lib.ut.us +lib.vi.us +lib.vt.us +lib.va.us +lib.wa.us +lib.wi.us +// lib.wv.us Bug 941670 - Removed at request of Larry W Arnold +lib.wy.us +// k12.ma.us contains school districts in Massachusetts. The 4LDs are +// managed independently except for private (PVT), charter (CHTR) and +// parochial (PAROCH) schools. Those are delegated directly to the +// 5LD operators. +pvt.k12.ma.us +chtr.k12.ma.us +paroch.k12.ma.us +// Merit Network, Inc. maintains the registry for =~ /(k12|cc|lib).mi.us/ and the following +// see also: http://domreg.merit.edu +// see also: whois -h whois.domreg.merit.edu help +ann-arbor.mi.us +cog.mi.us +dst.mi.us +eaton.mi.us +gen.mi.us +mus.mi.us +tec.mi.us +washtenaw.mi.us + +// uy : http://www.nic.org.uy/ +uy +com.uy +edu.uy +gub.uy +mil.uy +net.uy +org.uy + +// uz : http://www.reg.uz/ +uz +co.uz +com.uz +net.uz +org.uz + +// va : https://en.wikipedia.org/wiki/.va +va + +// vc : https://en.wikipedia.org/wiki/.vc +// Submitted by registry +vc +com.vc +net.vc +org.vc +gov.vc +mil.vc +edu.vc + +// ve : https://registro.nic.ve/ +// Submitted by registry +ve +arts.ve +co.ve +com.ve +e12.ve +edu.ve +firm.ve +gob.ve +gov.ve +info.ve +int.ve +mil.ve +net.ve +org.ve +rec.ve +store.ve +tec.ve +web.ve + +// vg : https://en.wikipedia.org/wiki/.vg +vg + +// vi : http://www.nic.vi/newdomainform.htm +// http://www.nic.vi/Domain_Rules/body_domain_rules.html indicates some other +// TLDs are "reserved", such as edu.vi and gov.vi, but doesn't actually say they +// are available for registration (which they do not seem to be). +vi +co.vi +com.vi +k12.vi +net.vi +org.vi + +// vn : https://www.dot.vn/vnnic/vnnic/domainregistration.jsp +vn +com.vn +net.vn +org.vn +edu.vn +gov.vn +int.vn +ac.vn +biz.vn +info.vn +name.vn +pro.vn +health.vn + +// vu : https://en.wikipedia.org/wiki/.vu +// http://www.vunic.vu/ +vu +com.vu +edu.vu +net.vu +org.vu + +// wf : http://www.afnic.fr/medias/documents/AFNIC-naming-policy2012.pdf +wf + +// ws : https://en.wikipedia.org/wiki/.ws +// http://samoanic.ws/index.dhtml +ws +com.ws +net.ws +org.ws +gov.ws +edu.ws + +// yt : http://www.afnic.fr/medias/documents/AFNIC-naming-policy2012.pdf +yt + +// IDN ccTLDs +// When submitting patches, please maintain a sort by ISO 3166 ccTLD, then +// U-label, and follow this format: +// // A-Label ("", [, variant info]) : +// // [sponsoring org] +// U-Label + +// xn--mgbaam7a8h ("Emerat", Arabic) : AE +// http://nic.ae/english/arabicdomain/rules.jsp +امارات + +// xn--y9a3aq ("hye", Armenian) : AM +// ISOC AM (operated by .am Registry) +հայ + +// xn--54b7fta0cc ("Bangla", Bangla) : BD +বাংলা + +// xn--90ae ("bg", Bulgarian) : BG +бг + +// xn--90ais ("bel", Belarusian/Russian Cyrillic) : BY +// Operated by .by registry +бел + +// xn--fiqs8s ("Zhongguo/China", Chinese, Simplified) : CN +// CNNIC +// http://cnnic.cn/html/Dir/2005/10/11/3218.htm +中国 + +// xn--fiqz9s ("Zhongguo/China", Chinese, Traditional) : CN +// CNNIC +// http://cnnic.cn/html/Dir/2005/10/11/3218.htm +中國 + +// xn--lgbbat1ad8j ("Algeria/Al Jazair", Arabic) : DZ +الجزائر + +// xn--wgbh1c ("Egypt/Masr", Arabic) : EG +// http://www.dotmasr.eg/ +مصر + +// xn--e1a4c ("eu", Cyrillic) : EU +ею + +// xn--node ("ge", Georgian Mkhedruli) : GE +გე + +// xn--qxam ("el", Greek) : GR +// Hellenic Ministry of Infrastructure, Transport, and Networks +ελ + +// xn--j6w193g ("Hong Kong", Chinese) : HK +// https://www2.hkirc.hk/register/rules.jsp +香港 + +// xn--2scrj9c ("Bharat", Kannada) : IN +// India +ಭಾರತ + +// xn--3hcrj9c ("Bharat", Oriya) : IN +// India +ଭାରତ + +// xn--45br5cyl ("Bharatam", Assamese) : IN +// India +ভাৰত + +// xn--h2breg3eve ("Bharatam", Sanskrit) : IN +// India +भारतम् + +// xn--h2brj9c8c ("Bharot", Santali) : IN +// India +भारोत + +// xn--mgbgu82a ("Bharat", Sindhi) : IN +// India +ڀارت + +// xn--rvc1e0am3e ("Bharatam", Malayalam) : IN +// India +ഭാരതം + +// xn--h2brj9c ("Bharat", Devanagari) : IN +// India +भारत + +// xn--mgbbh1a71e ("Bharat", Arabic) : IN +// India +بھارت + +// xn--fpcrj9c3d ("Bharat", Telugu) : IN +// India +భారత్ + +// xn--gecrj9c ("Bharat", Gujarati) : IN +// India +ભારત + +// xn--s9brj9c ("Bharat", Gurmukhi) : IN +// India +ਭਾਰਤ + +// xn--45brj9c ("Bharat", Bengali) : IN +// India +ভারত + +// xn--xkc2dl3a5ee0h ("India", Tamil) : IN +// India +இந்தியா + +// xn--mgba3a4f16a ("Iran", Persian) : IR +ایران + +// xn--mgba3a4fra ("Iran", Arabic) : IR +ايران + +// xn--mgbtx2b ("Iraq", Arabic) : IQ +// Communications and Media Commission +عراق + +// xn--mgbayh7gpa ("al-Ordon", Arabic) : JO +// National Information Technology Center (NITC) +// Royal Scientific Society, Al-Jubeiha +الاردن + +// xn--3e0b707e ("Republic of Korea", Hangul) : KR +한국 + +// xn--80ao21a ("Kaz", Kazakh) : KZ +қаз + +// xn--fzc2c9e2c ("Lanka", Sinhalese-Sinhala) : LK +// http://nic.lk +ලංකා + +// xn--xkc2al3hye2a ("Ilangai", Tamil) : LK +// http://nic.lk +இலங்கை + +// xn--mgbc0a9azcg ("Morocco/al-Maghrib", Arabic) : MA +المغرب + +// xn--d1alf ("mkd", Macedonian) : MK +// MARnet +мкд + +// xn--l1acc ("mon", Mongolian) : MN +мон + +// xn--mix891f ("Macao", Chinese, Traditional) : MO +// MONIC / HNET Asia (Registry Operator for .mo) +澳門 + +// xn--mix082f ("Macao", Chinese, Simplified) : MO +澳门 + +// xn--mgbx4cd0ab ("Malaysia", Malay) : MY +مليسيا + +// xn--mgb9awbf ("Oman", Arabic) : OM +عمان + +// xn--mgbai9azgqp6j ("Pakistan", Urdu/Arabic) : PK +پاکستان + +// xn--mgbai9a5eva00b ("Pakistan", Urdu/Arabic, variant) : PK +پاكستان + +// xn--ygbi2ammx ("Falasteen", Arabic) : PS +// The Palestinian National Internet Naming Authority (PNINA) +// http://www.pnina.ps +فلسطين + +// xn--90a3ac ("srb", Cyrillic) : RS +// https://www.rnids.rs/en/domains/national-domains +срб +пр.срб +орг.срб +обр.срб +од.срб +упр.срб +ак.срб + +// xn--p1ai ("rf", Russian-Cyrillic) : RU +// http://www.cctld.ru/en/docs/rulesrf.php +рф + +// xn--wgbl6a ("Qatar", Arabic) : QA +// http://www.ict.gov.qa/ +قطر + +// xn--mgberp4a5d4ar ("AlSaudiah", Arabic) : SA +// http://www.nic.net.sa/ +السعودية + +// xn--mgberp4a5d4a87g ("AlSaudiah", Arabic, variant) : SA +السعودیة + +// xn--mgbqly7c0a67fbc ("AlSaudiah", Arabic, variant) : SA +السعودیۃ + +// xn--mgbqly7cvafr ("AlSaudiah", Arabic, variant) : SA +السعوديه + +// xn--mgbpl2fh ("sudan", Arabic) : SD +// Operated by .sd registry +سودان + +// xn--yfro4i67o Singapore ("Singapore", Chinese) : SG +新加坡 + +// xn--clchc0ea0b2g2a9gcd ("Singapore", Tamil) : SG +சிங்கப்பூர் + +// xn--ogbpf8fl ("Syria", Arabic) : SY +سورية + +// xn--mgbtf8fl ("Syria", Arabic, variant) : SY +سوريا + +// xn--o3cw4h ("Thai", Thai) : TH +// http://www.thnic.co.th +ไทย +ศึกษา.ไทย +ธุรกิจ.ไทย +รัฐบาล.ไทย +ทหาร.ไทย +เน็ต.ไทย +องค์กร.ไทย + +// xn--pgbs0dh ("Tunisia", Arabic) : TN +// http://nic.tn +تونس + +// xn--kpry57d ("Taiwan", Chinese, Traditional) : TW +// http://www.twnic.net/english/dn/dn_07a.htm +台灣 + +// xn--kprw13d ("Taiwan", Chinese, Simplified) : TW +// http://www.twnic.net/english/dn/dn_07a.htm +台湾 + +// xn--nnx388a ("Taiwan", Chinese, variant) : TW +臺灣 + +// xn--j1amh ("ukr", Cyrillic) : UA +укр + +// xn--mgb2ddes ("AlYemen", Arabic) : YE +اليمن + +// xxx : http://icmregistry.com +xxx + +// ye : http://www.y.net.ye/services/domain_name.htm +*.ye + +// za : http://www.zadna.org.za/content/page/domain-information +ac.za +agric.za +alt.za +co.za +edu.za +gov.za +grondar.za +law.za +mil.za +net.za +ngo.za +nis.za +nom.za +org.za +school.za +tm.za +web.za + +// zm : https://zicta.zm/ +// Submitted by registry +zm +ac.zm +biz.zm +co.zm +com.zm +edu.zm +gov.zm +info.zm +mil.zm +net.zm +org.zm +sch.zm + +// zw : https://www.potraz.gov.zw/ +// Confirmed by registry 2017-01-25 +zw +ac.zw +co.zw +gov.zw +mil.zw +org.zw + +// List of new gTLDs imported from https://newgtlds.icann.org/newgtlds.csv on 2017-02-23T00:46:09Z + +// aaa : 2015-02-26 American Automobile Association, Inc. +aaa + +// aarp : 2015-05-21 AARP +aarp + +// abarth : 2015-07-30 Fiat Chrysler Automobiles N.V. +abarth + +// abb : 2014-10-24 ABB Ltd +abb + +// abbott : 2014-07-24 Abbott Laboratories, Inc. +abbott + +// abbvie : 2015-07-30 AbbVie Inc. +abbvie + +// abc : 2015-07-30 Disney Enterprises, Inc. +abc + +// able : 2015-06-25 Able Inc. +able + +// abogado : 2014-04-24 Top Level Domain Holdings Limited +abogado + +// abudhabi : 2015-07-30 Abu Dhabi Systems and Information Centre +abudhabi + +// academy : 2013-11-07 Half Oaks, LLC +academy + +// accenture : 2014-08-15 Accenture plc +accenture + +// accountant : 2014-11-20 dot Accountant Limited +accountant + +// accountants : 2014-03-20 Knob Town, LLC +accountants + +// aco : 2015-01-08 ACO Severin Ahlmann GmbH & Co. KG +aco + +// active : 2014-05-01 The Active Network, Inc +active + +// actor : 2013-12-12 United TLD Holdco Ltd. +actor + +// adac : 2015-07-16 Allgemeiner Deutscher Automobil-Club e.V. (ADAC) +adac + +// ads : 2014-12-04 Charleston Road Registry Inc. +ads + +// adult : 2014-10-16 ICM Registry AD LLC +adult + +// aeg : 2015-03-19 Aktiebolaget Electrolux +aeg + +// aetna : 2015-05-21 Aetna Life Insurance Company +aetna + +// afamilycompany : 2015-07-23 Johnson Shareholdings, Inc. +afamilycompany + +// afl : 2014-10-02 Australian Football League +afl + +// africa : 2014-03-24 ZA Central Registry NPC trading as Registry.Africa +africa + +// agakhan : 2015-04-23 Fondation Aga Khan (Aga Khan Foundation) +agakhan + +// agency : 2013-11-14 Steel Falls, LLC +agency + +// aig : 2014-12-18 American International Group, Inc. +aig + +// aigo : 2015-08-06 aigo Digital Technology Co,Ltd. +aigo + +// airbus : 2015-07-30 Airbus S.A.S. +airbus + +// airforce : 2014-03-06 United TLD Holdco Ltd. +airforce + +// airtel : 2014-10-24 Bharti Airtel Limited +airtel + +// akdn : 2015-04-23 Fondation Aga Khan (Aga Khan Foundation) +akdn + +// alfaromeo : 2015-07-31 Fiat Chrysler Automobiles N.V. +alfaromeo + +// alibaba : 2015-01-15 Alibaba Group Holding Limited +alibaba + +// alipay : 2015-01-15 Alibaba Group Holding Limited +alipay + +// allfinanz : 2014-07-03 Allfinanz Deutsche Vermögensberatung Aktiengesellschaft +allfinanz + +// allstate : 2015-07-31 Allstate Fire and Casualty Insurance Company +allstate + +// ally : 2015-06-18 Ally Financial Inc. +ally + +// alsace : 2014-07-02 REGION D ALSACE +alsace + +// alstom : 2015-07-30 ALSTOM +alstom + +// americanexpress : 2015-07-31 American Express Travel Related Services Company, Inc. +americanexpress + +// americanfamily : 2015-07-23 AmFam, Inc. +americanfamily + +// amex : 2015-07-31 American Express Travel Related Services Company, Inc. +amex + +// amfam : 2015-07-23 AmFam, Inc. +amfam + +// amica : 2015-05-28 Amica Mutual Insurance Company +amica + +// amsterdam : 2014-07-24 Gemeente Amsterdam +amsterdam + +// analytics : 2014-12-18 Campus IP LLC +analytics + +// android : 2014-08-07 Charleston Road Registry Inc. +android + +// anquan : 2015-01-08 QIHOO 360 TECHNOLOGY CO. LTD. +anquan + +// anz : 2015-07-31 Australia and New Zealand Banking Group Limited +anz + +// aol : 2015-09-17 AOL Inc. +aol + +// apartments : 2014-12-11 June Maple, LLC +apartments + +// app : 2015-05-14 Charleston Road Registry Inc. +app + +// apple : 2015-05-14 Apple Inc. +apple + +// aquarelle : 2014-07-24 Aquarelle.com +aquarelle + +// arab : 2015-11-12 League of Arab States +arab + +// aramco : 2014-11-20 Aramco Services Company +aramco + +// archi : 2014-02-06 STARTING DOT LIMITED +archi + +// army : 2014-03-06 United TLD Holdco Ltd. +army + +// art : 2016-03-24 UK Creative Ideas Limited +art + +// arte : 2014-12-11 Association Relative à la Télévision Européenne G.E.I.E. +arte + +// asda : 2015-07-31 Wal-Mart Stores, Inc. +asda + +// associates : 2014-03-06 Baxter Hill, LLC +associates + +// athleta : 2015-07-30 The Gap, Inc. +athleta + +// attorney : 2014-03-20 +attorney + +// auction : 2014-03-20 +auction + +// audi : 2015-05-21 AUDI Aktiengesellschaft +audi + +// audible : 2015-06-25 Amazon EU S.à r.l. +audible + +// audio : 2014-03-20 Uniregistry, Corp. +audio + +// auspost : 2015-08-13 Australian Postal Corporation +auspost + +// author : 2014-12-18 Amazon EU S.à r.l. +author + +// auto : 2014-11-13 +auto + +// autos : 2014-01-09 DERAutos, LLC +autos + +// avianca : 2015-01-08 Aerovias del Continente Americano S.A. Avianca +avianca + +// aws : 2015-06-25 Amazon EU S.à r.l. +aws + +// axa : 2013-12-19 AXA SA +axa + +// azure : 2014-12-18 Microsoft Corporation +azure + +// baby : 2015-04-09 Johnson & Johnson Services, Inc. +baby + +// baidu : 2015-01-08 Baidu, Inc. +baidu + +// banamex : 2015-07-30 Citigroup Inc. +banamex + +// bananarepublic : 2015-07-31 The Gap, Inc. +bananarepublic + +// band : 2014-06-12 +band + +// bank : 2014-09-25 fTLD Registry Services LLC +bank + +// bar : 2013-12-12 Punto 2012 Sociedad Anonima Promotora de Inversion de Capital Variable +bar + +// barcelona : 2014-07-24 Municipi de Barcelona +barcelona + +// barclaycard : 2014-11-20 Barclays Bank PLC +barclaycard + +// barclays : 2014-11-20 Barclays Bank PLC +barclays + +// barefoot : 2015-06-11 Gallo Vineyards, Inc. +barefoot + +// bargains : 2013-11-14 Half Hallow, LLC +bargains + +// baseball : 2015-10-29 MLB Advanced Media DH, LLC +baseball + +// basketball : 2015-08-20 Fédération Internationale de Basketball (FIBA) +basketball + +// bauhaus : 2014-04-17 Werkhaus GmbH +bauhaus + +// bayern : 2014-01-23 Bayern Connect GmbH +bayern + +// bbc : 2014-12-18 British Broadcasting Corporation +bbc + +// bbt : 2015-07-23 BB&T Corporation +bbt + +// bbva : 2014-10-02 BANCO BILBAO VIZCAYA ARGENTARIA, S.A. +bbva + +// bcg : 2015-04-02 The Boston Consulting Group, Inc. +bcg + +// bcn : 2014-07-24 Municipi de Barcelona +bcn + +// beats : 2015-05-14 Beats Electronics, LLC +beats + +// beauty : 2015-12-03 L'Oréal +beauty + +// beer : 2014-01-09 Top Level Domain Holdings Limited +beer + +// bentley : 2014-12-18 Bentley Motors Limited +bentley + +// berlin : 2013-10-31 dotBERLIN GmbH & Co. KG +berlin + +// best : 2013-12-19 BestTLD Pty Ltd +best + +// bestbuy : 2015-07-31 BBY Solutions, Inc. +bestbuy + +// bet : 2015-05-07 Afilias plc +bet + +// bharti : 2014-01-09 Bharti Enterprises (Holding) Private Limited +bharti + +// bible : 2014-06-19 American Bible Society +bible + +// bid : 2013-12-19 dot Bid Limited +bid + +// bike : 2013-08-27 Grand Hollow, LLC +bike + +// bing : 2014-12-18 Microsoft Corporation +bing + +// bingo : 2014-12-04 Sand Cedar, LLC +bingo + +// bio : 2014-03-06 STARTING DOT LIMITED +bio + +// black : 2014-01-16 Afilias Limited +black + +// blackfriday : 2014-01-16 Uniregistry, Corp. +blackfriday + +// blanco : 2015-07-16 BLANCO GmbH + Co KG +blanco + +// blockbuster : 2015-07-30 Dish DBS Corporation +blockbuster + +// blog : 2015-05-14 +blog + +// bloomberg : 2014-07-17 Bloomberg IP Holdings LLC +bloomberg + +// blue : 2013-11-07 Afilias Limited +blue + +// bms : 2014-10-30 Bristol-Myers Squibb Company +bms + +// bmw : 2014-01-09 Bayerische Motoren Werke Aktiengesellschaft +bmw + +// bnl : 2014-07-24 Banca Nazionale del Lavoro +bnl + +// bnpparibas : 2014-05-29 BNP Paribas +bnpparibas + +// boats : 2014-12-04 DERBoats, LLC +boats + +// boehringer : 2015-07-09 Boehringer Ingelheim International GmbH +boehringer + +// bofa : 2015-07-31 NMS Services, Inc. +bofa + +// bom : 2014-10-16 Núcleo de Informação e Coordenação do Ponto BR - NIC.br +bom + +// bond : 2014-06-05 Bond University Limited +bond + +// boo : 2014-01-30 Charleston Road Registry Inc. +boo + +// book : 2015-08-27 Amazon EU S.à r.l. +book + +// booking : 2015-07-16 Booking.com B.V. +booking + +// boots : 2015-01-08 THE BOOTS COMPANY PLC +boots + +// bosch : 2015-06-18 Robert Bosch GMBH +bosch + +// bostik : 2015-05-28 Bostik SA +bostik + +// boston : 2015-12-10 +boston + +// bot : 2014-12-18 Amazon EU S.à r.l. +bot + +// boutique : 2013-11-14 Over Galley, LLC +boutique + +// box : 2015-11-12 NS1 Limited +box + +// bradesco : 2014-12-18 Banco Bradesco S.A. +bradesco + +// bridgestone : 2014-12-18 Bridgestone Corporation +bridgestone + +// broadway : 2014-12-22 Celebrate Broadway, Inc. +broadway + +// broker : 2014-12-11 IG Group Holdings PLC +broker + +// brother : 2015-01-29 Brother Industries, Ltd. +brother + +// brussels : 2014-02-06 DNS.be vzw +brussels + +// budapest : 2013-11-21 Top Level Domain Holdings Limited +budapest + +// bugatti : 2015-07-23 Bugatti International SA +bugatti + +// build : 2013-11-07 Plan Bee LLC +build + +// builders : 2013-11-07 Atomic Madison, LLC +builders + +// business : 2013-11-07 Spring Cross, LLC +business + +// buy : 2014-12-18 Amazon EU S.à r.l. +buy + +// buzz : 2013-10-02 DOTSTRATEGY CO. +buzz + +// bzh : 2014-02-27 Association www.bzh +bzh + +// cab : 2013-10-24 Half Sunset, LLC +cab + +// cafe : 2015-02-11 Pioneer Canyon, LLC +cafe + +// cal : 2014-07-24 Charleston Road Registry Inc. +cal + +// call : 2014-12-18 Amazon EU S.à r.l. +call + +// calvinklein : 2015-07-30 PVH gTLD Holdings LLC +calvinklein + +// cam : 2016-04-21 AC Webconnecting Holding B.V. +cam + +// camera : 2013-08-27 Atomic Maple, LLC +camera + +// camp : 2013-11-07 Delta Dynamite, LLC +camp + +// cancerresearch : 2014-05-15 Australian Cancer Research Foundation +cancerresearch + +// canon : 2014-09-12 Canon Inc. +canon + +// capetown : 2014-03-24 ZA Central Registry NPC trading as ZA Central Registry +capetown + +// capital : 2014-03-06 Delta Mill, LLC +capital + +// capitalone : 2015-08-06 Capital One Financial Corporation +capitalone + +// car : 2015-01-22 +car + +// caravan : 2013-12-12 Caravan International, Inc. +caravan + +// cards : 2013-12-05 Foggy Hollow, LLC +cards + +// care : 2014-03-06 Goose Cross +care + +// career : 2013-10-09 dotCareer LLC +career + +// careers : 2013-10-02 Wild Corner, LLC +careers + +// cars : 2014-11-13 +cars + +// cartier : 2014-06-23 Richemont DNS Inc. +cartier + +// casa : 2013-11-21 Top Level Domain Holdings Limited +casa + +// case : 2015-09-03 CNH Industrial N.V. +case + +// caseih : 2015-09-03 CNH Industrial N.V. +caseih + +// cash : 2014-03-06 Delta Lake, LLC +cash + +// casino : 2014-12-18 Binky Sky, LLC +casino + +// catering : 2013-12-05 New Falls. LLC +catering + +// catholic : 2015-10-21 Pontificium Consilium de Comunicationibus Socialibus (PCCS) (Pontifical Council for Social Communication) +catholic + +// cba : 2014-06-26 COMMONWEALTH BANK OF AUSTRALIA +cba + +// cbn : 2014-08-22 The Christian Broadcasting Network, Inc. +cbn + +// cbre : 2015-07-02 CBRE, Inc. +cbre + +// cbs : 2015-08-06 CBS Domains Inc. +cbs + +// ceb : 2015-04-09 The Corporate Executive Board Company +ceb + +// center : 2013-11-07 Tin Mill, LLC +center + +// ceo : 2013-11-07 CEOTLD Pty Ltd +ceo + +// cern : 2014-06-05 European Organization for Nuclear Research ("CERN") +cern + +// cfa : 2014-08-28 CFA Institute +cfa + +// cfd : 2014-12-11 IG Group Holdings PLC +cfd + +// chanel : 2015-04-09 Chanel International B.V. +chanel + +// channel : 2014-05-08 Charleston Road Registry Inc. +channel + +// chase : 2015-04-30 JPMorgan Chase & Co. +chase + +// chat : 2014-12-04 Sand Fields, LLC +chat + +// cheap : 2013-11-14 Sand Cover, LLC +cheap + +// chintai : 2015-06-11 CHINTAI Corporation +chintai + +// christmas : 2013-11-21 Uniregistry, Corp. +christmas + +// chrome : 2014-07-24 Charleston Road Registry Inc. +chrome + +// chrysler : 2015-07-30 FCA US LLC. +chrysler + +// church : 2014-02-06 Holly Fields, LLC +church + +// cipriani : 2015-02-19 Hotel Cipriani Srl +cipriani + +// circle : 2014-12-18 Amazon EU S.à r.l. +circle + +// cisco : 2014-12-22 Cisco Technology, Inc. +cisco + +// citadel : 2015-07-23 Citadel Domain LLC +citadel + +// citi : 2015-07-30 Citigroup Inc. +citi + +// citic : 2014-01-09 CITIC Group Corporation +citic + +// city : 2014-05-29 Snow Sky, LLC +city + +// cityeats : 2014-12-11 Lifestyle Domain Holdings, Inc. +cityeats + +// claims : 2014-03-20 Black Corner, LLC +claims + +// cleaning : 2013-12-05 Fox Shadow, LLC +cleaning + +// click : 2014-06-05 Uniregistry, Corp. +click + +// clinic : 2014-03-20 Goose Park, LLC +clinic + +// clinique : 2015-10-01 The Estée Lauder Companies Inc. +clinique + +// clothing : 2013-08-27 Steel Lake, LLC +clothing + +// cloud : 2015-04-16 ARUBA S.p.A. +cloud + +// club : 2013-11-08 .CLUB DOMAINS, LLC +club + +// clubmed : 2015-06-25 Club Méditerranée S.A. +clubmed + +// coach : 2014-10-09 Koko Island, LLC +coach + +// codes : 2013-10-31 Puff Willow, LLC +codes + +// coffee : 2013-10-17 Trixy Cover, LLC +coffee + +// college : 2014-01-16 XYZ.COM LLC +college + +// cologne : 2014-02-05 NetCologne Gesellschaft für Telekommunikation mbH +cologne + +// comcast : 2015-07-23 Comcast IP Holdings I, LLC +comcast + +// commbank : 2014-06-26 COMMONWEALTH BANK OF AUSTRALIA +commbank + +// community : 2013-12-05 Fox Orchard, LLC +community + +// company : 2013-11-07 Silver Avenue, LLC +company + +// compare : 2015-10-08 iSelect Ltd +compare + +// computer : 2013-10-24 Pine Mill, LLC +computer + +// comsec : 2015-01-08 VeriSign, Inc. +comsec + +// condos : 2013-12-05 Pine House, LLC +condos + +// construction : 2013-09-16 Fox Dynamite, LLC +construction + +// consulting : 2013-12-05 +consulting + +// contact : 2015-01-08 Top Level Spectrum, Inc. +contact + +// contractors : 2013-09-10 Magic Woods, LLC +contractors + +// cooking : 2013-11-21 Top Level Domain Holdings Limited +cooking + +// cookingchannel : 2015-07-02 Lifestyle Domain Holdings, Inc. +cookingchannel + +// cool : 2013-11-14 Koko Lake, LLC +cool + +// corsica : 2014-09-25 Collectivité Territoriale de Corse +corsica + +// country : 2013-12-19 Top Level Domain Holdings Limited +country + +// coupon : 2015-02-26 Amazon EU S.à r.l. +coupon + +// coupons : 2015-03-26 Black Island, LLC +coupons + +// courses : 2014-12-04 OPEN UNIVERSITIES AUSTRALIA PTY LTD +courses + +// credit : 2014-03-20 Snow Shadow, LLC +credit + +// creditcard : 2014-03-20 Binky Frostbite, LLC +creditcard + +// creditunion : 2015-01-22 CUNA Performance Resources, LLC +creditunion + +// cricket : 2014-10-09 dot Cricket Limited +cricket + +// crown : 2014-10-24 Crown Equipment Corporation +crown + +// crs : 2014-04-03 Federated Co-operatives Limited +crs + +// cruise : 2015-12-10 Viking River Cruises (Bermuda) Ltd. +cruise + +// cruises : 2013-12-05 Spring Way, LLC +cruises + +// csc : 2014-09-25 Alliance-One Services, Inc. +csc + +// cuisinella : 2014-04-03 SALM S.A.S. +cuisinella + +// cymru : 2014-05-08 Nominet UK +cymru + +// cyou : 2015-01-22 Beijing Gamease Age Digital Technology Co., Ltd. +cyou + +// dabur : 2014-02-06 Dabur India Limited +dabur + +// dad : 2014-01-23 Charleston Road Registry Inc. +dad + +// dance : 2013-10-24 United TLD Holdco Ltd. +dance + +// data : 2016-06-02 Dish DBS Corporation +data + +// date : 2014-11-20 dot Date Limited +date + +// dating : 2013-12-05 Pine Fest, LLC +dating + +// datsun : 2014-03-27 NISSAN MOTOR CO., LTD. +datsun + +// day : 2014-01-30 Charleston Road Registry Inc. +day + +// dclk : 2014-11-20 Charleston Road Registry Inc. +dclk + +// dds : 2015-05-07 Top Level Domain Holdings Limited +dds + +// deal : 2015-06-25 Amazon EU S.à r.l. +deal + +// dealer : 2014-12-22 Dealer Dot Com, Inc. +dealer + +// deals : 2014-05-22 Sand Sunset, LLC +deals + +// degree : 2014-03-06 +degree + +// delivery : 2014-09-11 Steel Station, LLC +delivery + +// dell : 2014-10-24 Dell Inc. +dell + +// deloitte : 2015-07-31 Deloitte Touche Tohmatsu +deloitte + +// delta : 2015-02-19 Delta Air Lines, Inc. +delta + +// democrat : 2013-10-24 United TLD Holdco Ltd. +democrat + +// dental : 2014-03-20 Tin Birch, LLC +dental + +// dentist : 2014-03-20 +dentist + +// desi : 2013-11-14 Desi Networks LLC +desi + +// design : 2014-11-07 Top Level Design, LLC +design + +// dev : 2014-10-16 Charleston Road Registry Inc. +dev + +// dhl : 2015-07-23 Deutsche Post AG +dhl + +// diamonds : 2013-09-22 John Edge, LLC +diamonds + +// diet : 2014-06-26 Uniregistry, Corp. +diet + +// digital : 2014-03-06 Dash Park, LLC +digital + +// direct : 2014-04-10 Half Trail, LLC +direct + +// directory : 2013-09-20 Extra Madison, LLC +directory + +// discount : 2014-03-06 Holly Hill, LLC +discount + +// discover : 2015-07-23 Discover Financial Services +discover + +// dish : 2015-07-30 Dish DBS Corporation +dish + +// diy : 2015-11-05 Lifestyle Domain Holdings, Inc. +diy + +// dnp : 2013-12-13 Dai Nippon Printing Co., Ltd. +dnp + +// docs : 2014-10-16 Charleston Road Registry Inc. +docs + +// doctor : 2016-06-02 Brice Trail, LLC +doctor + +// dodge : 2015-07-30 FCA US LLC. +dodge + +// dog : 2014-12-04 Koko Mill, LLC +dog + +// doha : 2014-09-18 Communications Regulatory Authority (CRA) +doha + +// domains : 2013-10-17 Sugar Cross, LLC +domains + +// dot : 2015-05-21 Dish DBS Corporation +dot + +// download : 2014-11-20 dot Support Limited +download + +// drive : 2015-03-05 Charleston Road Registry Inc. +drive + +// dtv : 2015-06-04 Dish DBS Corporation +dtv + +// dubai : 2015-01-01 Dubai Smart Government Department +dubai + +// duck : 2015-07-23 Johnson Shareholdings, Inc. +duck + +// dunlop : 2015-07-02 The Goodyear Tire & Rubber Company +dunlop + +// duns : 2015-08-06 The Dun & Bradstreet Corporation +duns + +// dupont : 2015-06-25 E. I. du Pont de Nemours and Company +dupont + +// durban : 2014-03-24 ZA Central Registry NPC trading as ZA Central Registry +durban + +// dvag : 2014-06-23 Deutsche Vermögensberatung Aktiengesellschaft DVAG +dvag + +// dvr : 2016-05-26 Hughes Satellite Systems Corporation +dvr + +// earth : 2014-12-04 Interlink Co., Ltd. +earth + +// eat : 2014-01-23 Charleston Road Registry Inc. +eat + +// eco : 2016-07-08 Big Room Inc. +eco + +// edeka : 2014-12-18 EDEKA Verband kaufmännischer Genossenschaften e.V. +edeka + +// education : 2013-11-07 Brice Way, LLC +education + +// email : 2013-10-31 Spring Madison, LLC +email + +// emerck : 2014-04-03 Merck KGaA +emerck + +// energy : 2014-09-11 Binky Birch, LLC +energy + +// engineer : 2014-03-06 United TLD Holdco Ltd. +engineer + +// engineering : 2014-03-06 Romeo Canyon +engineering + +// enterprises : 2013-09-20 Snow Oaks, LLC +enterprises + +// epost : 2015-07-23 Deutsche Post AG +epost + +// epson : 2014-12-04 Seiko Epson Corporation +epson + +// equipment : 2013-08-27 Corn Station, LLC +equipment + +// ericsson : 2015-07-09 Telefonaktiebolaget L M Ericsson +ericsson + +// erni : 2014-04-03 ERNI Group Holding AG +erni + +// esq : 2014-05-08 Charleston Road Registry Inc. +esq + +// estate : 2013-08-27 Trixy Park, LLC +estate + +// esurance : 2015-07-23 Esurance Insurance Company +esurance + +// etisalat : 2015-09-03 Emirates Telecommunications Corporation (trading as Etisalat) +etisalat + +// eurovision : 2014-04-24 European Broadcasting Union (EBU) +eurovision + +// eus : 2013-12-12 Puntueus Fundazioa +eus + +// events : 2013-12-05 Pioneer Maple, LLC +events + +// everbank : 2014-05-15 EverBank +everbank + +// exchange : 2014-03-06 Spring Falls, LLC +exchange + +// expert : 2013-11-21 Magic Pass, LLC +expert + +// exposed : 2013-12-05 Victor Beach, LLC +exposed + +// express : 2015-02-11 Sea Sunset, LLC +express + +// extraspace : 2015-05-14 Extra Space Storage LLC +extraspace + +// fage : 2014-12-18 Fage International S.A. +fage + +// fail : 2014-03-06 Atomic Pipe, LLC +fail + +// fairwinds : 2014-11-13 FairWinds Partners, LLC +fairwinds + +// faith : 2014-11-20 dot Faith Limited +faith + +// family : 2015-04-02 +family + +// fan : 2014-03-06 +fan + +// fans : 2014-11-07 Asiamix Digital Limited +fans + +// farm : 2013-11-07 Just Maple, LLC +farm + +// farmers : 2015-07-09 Farmers Insurance Exchange +farmers + +// fashion : 2014-07-03 Top Level Domain Holdings Limited +fashion + +// fast : 2014-12-18 Amazon EU S.à r.l. +fast + +// fedex : 2015-08-06 Federal Express Corporation +fedex + +// feedback : 2013-12-19 Top Level Spectrum, Inc. +feedback + +// ferrari : 2015-07-31 Fiat Chrysler Automobiles N.V. +ferrari + +// ferrero : 2014-12-18 Ferrero Trading Lux S.A. +ferrero + +// fiat : 2015-07-31 Fiat Chrysler Automobiles N.V. +fiat + +// fidelity : 2015-07-30 Fidelity Brokerage Services LLC +fidelity + +// fido : 2015-08-06 Rogers Communications Partnership +fido + +// film : 2015-01-08 Motion Picture Domain Registry Pty Ltd +film + +// final : 2014-10-16 Núcleo de Informação e Coordenação do Ponto BR - NIC.br +final + +// finance : 2014-03-20 Cotton Cypress, LLC +finance + +// financial : 2014-03-06 Just Cover, LLC +financial + +// fire : 2015-06-25 Amazon EU S.à r.l. +fire + +// firestone : 2014-12-18 Bridgestone Corporation +firestone + +// firmdale : 2014-03-27 Firmdale Holdings Limited +firmdale + +// fish : 2013-12-12 Fox Woods, LLC +fish + +// fishing : 2013-11-21 Top Level Domain Holdings Limited +fishing + +// fit : 2014-11-07 Top Level Domain Holdings Limited +fit + +// fitness : 2014-03-06 Brice Orchard, LLC +fitness + +// flickr : 2015-04-02 Yahoo! Domain Services Inc. +flickr + +// flights : 2013-12-05 Fox Station, LLC +flights + +// flir : 2015-07-23 FLIR Systems, Inc. +flir + +// florist : 2013-11-07 Half Cypress, LLC +florist + +// flowers : 2014-10-09 Uniregistry, Corp. +flowers + +// fly : 2014-05-08 Charleston Road Registry Inc. +fly + +// foo : 2014-01-23 Charleston Road Registry Inc. +foo + +// food : 2016-04-21 Lifestyle Domain Holdings, Inc. +food + +// foodnetwork : 2015-07-02 Lifestyle Domain Holdings, Inc. +foodnetwork + +// football : 2014-12-18 Foggy Farms, LLC +football + +// ford : 2014-11-13 Ford Motor Company +ford + +// forex : 2014-12-11 IG Group Holdings PLC +forex + +// forsale : 2014-05-22 +forsale + +// forum : 2015-04-02 Fegistry, LLC +forum + +// foundation : 2013-12-05 John Dale, LLC +foundation + +// fox : 2015-09-11 FOX Registry, LLC +fox + +// free : 2015-12-10 Amazon EU S.à r.l. +free + +// fresenius : 2015-07-30 Fresenius Immobilien-Verwaltungs-GmbH +fresenius + +// frl : 2014-05-15 FRLregistry B.V. +frl + +// frogans : 2013-12-19 OP3FT +frogans + +// frontdoor : 2015-07-02 Lifestyle Domain Holdings, Inc. +frontdoor + +// frontier : 2015-02-05 Frontier Communications Corporation +frontier + +// ftr : 2015-07-16 Frontier Communications Corporation +ftr + +// fujitsu : 2015-07-30 Fujitsu Limited +fujitsu + +// fujixerox : 2015-07-23 Xerox DNHC LLC +fujixerox + +// fun : 2016-01-14 +fun + +// fund : 2014-03-20 John Castle, LLC +fund + +// furniture : 2014-03-20 Lone Fields, LLC +furniture + +// futbol : 2013-09-20 +futbol + +// fyi : 2015-04-02 Silver Tigers, LLC +fyi + +// gal : 2013-11-07 Asociación puntoGAL +gal + +// gallery : 2013-09-13 Sugar House, LLC +gallery + +// gallo : 2015-06-11 Gallo Vineyards, Inc. +gallo + +// gallup : 2015-02-19 Gallup, Inc. +gallup + +// game : 2015-05-28 Uniregistry, Corp. +game + +// games : 2015-05-28 +games + +// gap : 2015-07-31 The Gap, Inc. +gap + +// garden : 2014-06-26 Top Level Domain Holdings Limited +garden + +// gbiz : 2014-07-17 Charleston Road Registry Inc. +gbiz + +// gdn : 2014-07-31 Joint Stock Company "Navigation-information systems" +gdn + +// gea : 2014-12-04 GEA Group Aktiengesellschaft +gea + +// gent : 2014-01-23 COMBELL GROUP NV/SA +gent + +// genting : 2015-03-12 Resorts World Inc Pte. Ltd. +genting + +// george : 2015-07-31 Wal-Mart Stores, Inc. +george + +// ggee : 2014-01-09 GMO Internet, Inc. +ggee + +// gift : 2013-10-17 Uniregistry, Corp. +gift + +// gifts : 2014-07-03 Goose Sky, LLC +gifts + +// gives : 2014-03-06 United TLD Holdco Ltd. +gives + +// giving : 2014-11-13 Giving Limited +giving + +// glade : 2015-07-23 Johnson Shareholdings, Inc. +glade + +// glass : 2013-11-07 Black Cover, LLC +glass + +// gle : 2014-07-24 Charleston Road Registry Inc. +gle + +// global : 2014-04-17 Dot GLOBAL AS +global + +// globo : 2013-12-19 Globo Comunicação e Participações S.A +globo + +// gmail : 2014-05-01 Charleston Road Registry Inc. +gmail + +// gmbh : 2016-01-29 Extra Dynamite, LLC +gmbh + +// gmo : 2014-01-09 GMO Internet, Inc. +gmo + +// gmx : 2014-04-24 1&1 Mail & Media GmbH +gmx + +// godaddy : 2015-07-23 Go Daddy East, LLC +godaddy + +// gold : 2015-01-22 June Edge, LLC +gold + +// goldpoint : 2014-11-20 YODOBASHI CAMERA CO.,LTD. +goldpoint + +// golf : 2014-12-18 Lone falls, LLC +golf + +// goo : 2014-12-18 NTT Resonant Inc. +goo + +// goodhands : 2015-07-31 Allstate Fire and Casualty Insurance Company +goodhands + +// goodyear : 2015-07-02 The Goodyear Tire & Rubber Company +goodyear + +// goog : 2014-11-20 Charleston Road Registry Inc. +goog + +// google : 2014-07-24 Charleston Road Registry Inc. +google + +// gop : 2014-01-16 Republican State Leadership Committee, Inc. +gop + +// got : 2014-12-18 Amazon EU S.à r.l. +got + +// grainger : 2015-05-07 Grainger Registry Services, LLC +grainger + +// graphics : 2013-09-13 Over Madison, LLC +graphics + +// gratis : 2014-03-20 Pioneer Tigers, LLC +gratis + +// green : 2014-05-08 Afilias Limited +green + +// gripe : 2014-03-06 Corn Sunset, LLC +gripe + +// grocery : 2016-06-16 Wal-Mart Stores, Inc. +grocery + +// group : 2014-08-15 Romeo Town, LLC +group + +// guardian : 2015-07-30 The Guardian Life Insurance Company of America +guardian + +// gucci : 2014-11-13 Guccio Gucci S.p.a. +gucci + +// guge : 2014-08-28 Charleston Road Registry Inc. +guge + +// guide : 2013-09-13 Snow Moon, LLC +guide + +// guitars : 2013-11-14 Uniregistry, Corp. +guitars + +// guru : 2013-08-27 Pioneer Cypress, LLC +guru + +// hair : 2015-12-03 L'Oréal +hair + +// hamburg : 2014-02-20 Hamburg Top-Level-Domain GmbH +hamburg + +// hangout : 2014-11-13 Charleston Road Registry Inc. +hangout + +// haus : 2013-12-05 +haus + +// hbo : 2015-07-30 HBO Registry Services, Inc. +hbo + +// hdfc : 2015-07-30 HOUSING DEVELOPMENT FINANCE CORPORATION LIMITED +hdfc + +// hdfcbank : 2015-02-12 HDFC Bank Limited +hdfcbank + +// health : 2015-02-11 DotHealth, LLC +health + +// healthcare : 2014-06-12 Silver Glen, LLC +healthcare + +// help : 2014-06-26 Uniregistry, Corp. +help + +// helsinki : 2015-02-05 City of Helsinki +helsinki + +// here : 2014-02-06 Charleston Road Registry Inc. +here + +// hermes : 2014-07-10 HERMES INTERNATIONAL +hermes + +// hgtv : 2015-07-02 Lifestyle Domain Holdings, Inc. +hgtv + +// hiphop : 2014-03-06 Uniregistry, Corp. +hiphop + +// hisamitsu : 2015-07-16 Hisamitsu Pharmaceutical Co.,Inc. +hisamitsu + +// hitachi : 2014-10-31 Hitachi, Ltd. +hitachi + +// hiv : 2014-03-13 +hiv + +// hkt : 2015-05-14 PCCW-HKT DataCom Services Limited +hkt + +// hockey : 2015-03-19 Half Willow, LLC +hockey + +// holdings : 2013-08-27 John Madison, LLC +holdings + +// holiday : 2013-11-07 Goose Woods, LLC +holiday + +// homedepot : 2015-04-02 Homer TLC, Inc. +homedepot + +// homegoods : 2015-07-16 The TJX Companies, Inc. +homegoods + +// homes : 2014-01-09 DERHomes, LLC +homes + +// homesense : 2015-07-16 The TJX Companies, Inc. +homesense + +// honda : 2014-12-18 Honda Motor Co., Ltd. +honda + +// honeywell : 2015-07-23 Honeywell GTLD LLC +honeywell + +// horse : 2013-11-21 Top Level Domain Holdings Limited +horse + +// hospital : 2016-10-20 Ruby Pike, LLC +hospital + +// host : 2014-04-17 DotHost Inc. +host + +// hosting : 2014-05-29 Uniregistry, Corp. +hosting + +// hot : 2015-08-27 Amazon EU S.à r.l. +hot + +// hoteles : 2015-03-05 Travel Reservations SRL +hoteles + +// hotels : 2016-04-07 Booking.com B.V. +hotels + +// hotmail : 2014-12-18 Microsoft Corporation +hotmail + +// house : 2013-11-07 Sugar Park, LLC +house + +// how : 2014-01-23 Charleston Road Registry Inc. +how + +// hsbc : 2014-10-24 HSBC Holdings PLC +hsbc + +// hughes : 2015-07-30 Hughes Satellite Systems Corporation +hughes + +// hyatt : 2015-07-30 Hyatt GTLD, L.L.C. +hyatt + +// hyundai : 2015-07-09 Hyundai Motor Company +hyundai + +// ibm : 2014-07-31 International Business Machines Corporation +ibm + +// icbc : 2015-02-19 Industrial and Commercial Bank of China Limited +icbc + +// ice : 2014-10-30 IntercontinentalExchange, Inc. +ice + +// icu : 2015-01-08 One.com A/S +icu + +// ieee : 2015-07-23 IEEE Global LLC +ieee + +// ifm : 2014-01-30 ifm electronic gmbh +ifm + +// ikano : 2015-07-09 Ikano S.A. +ikano + +// imamat : 2015-08-06 Fondation Aga Khan (Aga Khan Foundation) +imamat + +// imdb : 2015-06-25 Amazon EU S.à r.l. +imdb + +// immo : 2014-07-10 Auburn Bloom, LLC +immo + +// immobilien : 2013-11-07 United TLD Holdco Ltd. +immobilien + +// industries : 2013-12-05 Outer House, LLC +industries + +// infiniti : 2014-03-27 NISSAN MOTOR CO., LTD. +infiniti + +// ing : 2014-01-23 Charleston Road Registry Inc. +ing + +// ink : 2013-12-05 Top Level Design, LLC +ink + +// institute : 2013-11-07 Outer Maple, LLC +institute + +// insurance : 2015-02-19 fTLD Registry Services LLC +insurance + +// insure : 2014-03-20 Pioneer Willow, LLC +insure + +// intel : 2015-08-06 Intel Corporation +intel + +// international : 2013-11-07 Wild Way, LLC +international + +// intuit : 2015-07-30 Intuit Administrative Services, Inc. +intuit + +// investments : 2014-03-20 Holly Glen, LLC +investments + +// ipiranga : 2014-08-28 Ipiranga Produtos de Petroleo S.A. +ipiranga + +// irish : 2014-08-07 Dot-Irish LLC +irish + +// iselect : 2015-02-11 iSelect Ltd +iselect + +// ismaili : 2015-08-06 Fondation Aga Khan (Aga Khan Foundation) +ismaili + +// ist : 2014-08-28 Istanbul Metropolitan Municipality +ist + +// istanbul : 2014-08-28 Istanbul Metropolitan Municipality +istanbul + +// itau : 2014-10-02 Itau Unibanco Holding S.A. +itau + +// itv : 2015-07-09 ITV Services Limited +itv + +// iveco : 2015-09-03 CNH Industrial N.V. +iveco + +// iwc : 2014-06-23 Richemont DNS Inc. +iwc + +// jaguar : 2014-11-13 Jaguar Land Rover Ltd +jaguar + +// java : 2014-06-19 Oracle Corporation +java + +// jcb : 2014-11-20 JCB Co., Ltd. +jcb + +// jcp : 2015-04-23 JCP Media, Inc. +jcp + +// jeep : 2015-07-30 FCA US LLC. +jeep + +// jetzt : 2014-01-09 +jetzt + +// jewelry : 2015-03-05 Wild Bloom, LLC +jewelry + +// jio : 2015-04-02 Affinity Names, Inc. +jio + +// jlc : 2014-12-04 Richemont DNS Inc. +jlc + +// jll : 2015-04-02 Jones Lang LaSalle Incorporated +jll + +// jmp : 2015-03-26 Matrix IP LLC +jmp + +// jnj : 2015-06-18 Johnson & Johnson Services, Inc. +jnj + +// joburg : 2014-03-24 ZA Central Registry NPC trading as ZA Central Registry +joburg + +// jot : 2014-12-18 Amazon EU S.à r.l. +jot + +// joy : 2014-12-18 Amazon EU S.à r.l. +joy + +// jpmorgan : 2015-04-30 JPMorgan Chase & Co. +jpmorgan + +// jprs : 2014-09-18 Japan Registry Services Co., Ltd. +jprs + +// juegos : 2014-03-20 Uniregistry, Corp. +juegos + +// juniper : 2015-07-30 JUNIPER NETWORKS, INC. +juniper + +// kaufen : 2013-11-07 United TLD Holdco Ltd. +kaufen + +// kddi : 2014-09-12 KDDI CORPORATION +kddi + +// kerryhotels : 2015-04-30 Kerry Trading Co. Limited +kerryhotels + +// kerrylogistics : 2015-04-09 Kerry Trading Co. Limited +kerrylogistics + +// kerryproperties : 2015-04-09 Kerry Trading Co. Limited +kerryproperties + +// kfh : 2014-12-04 Kuwait Finance House +kfh + +// kia : 2015-07-09 KIA MOTORS CORPORATION +kia + +// kim : 2013-09-23 Afilias Limited +kim + +// kinder : 2014-11-07 Ferrero Trading Lux S.A. +kinder + +// kindle : 2015-06-25 Amazon EU S.à r.l. +kindle + +// kitchen : 2013-09-20 Just Goodbye, LLC +kitchen + +// kiwi : 2013-09-20 DOT KIWI LIMITED +kiwi + +// koeln : 2014-01-09 NetCologne Gesellschaft für Telekommunikation mbH +koeln + +// komatsu : 2015-01-08 Komatsu Ltd. +komatsu + +// kosher : 2015-08-20 Kosher Marketing Assets LLC +kosher + +// kpmg : 2015-04-23 KPMG International Cooperative (KPMG International Genossenschaft) +kpmg + +// kpn : 2015-01-08 Koninklijke KPN N.V. +kpn + +// krd : 2013-12-05 KRG Department of Information Technology +krd + +// kred : 2013-12-19 KredTLD Pty Ltd +kred + +// kuokgroup : 2015-04-09 Kerry Trading Co. Limited +kuokgroup + +// kyoto : 2014-11-07 Academic Institution: Kyoto Jyoho Gakuen +kyoto + +// lacaixa : 2014-01-09 CAIXA D'ESTALVIS I PENSIONS DE BARCELONA +lacaixa + +// ladbrokes : 2015-08-06 LADBROKES INTERNATIONAL PLC +ladbrokes + +// lamborghini : 2015-06-04 Automobili Lamborghini S.p.A. +lamborghini + +// lamer : 2015-10-01 The Estée Lauder Companies Inc. +lamer + +// lancaster : 2015-02-12 LANCASTER +lancaster + +// lancia : 2015-07-31 Fiat Chrysler Automobiles N.V. +lancia + +// lancome : 2015-07-23 L'Oréal +lancome + +// land : 2013-09-10 Pine Moon, LLC +land + +// landrover : 2014-11-13 Jaguar Land Rover Ltd +landrover + +// lanxess : 2015-07-30 LANXESS Corporation +lanxess + +// lasalle : 2015-04-02 Jones Lang LaSalle Incorporated +lasalle + +// lat : 2014-10-16 ECOM-LAC Federaciòn de Latinoamèrica y el Caribe para Internet y el Comercio Electrònico +lat + +// latino : 2015-07-30 Dish DBS Corporation +latino + +// latrobe : 2014-06-16 La Trobe University +latrobe + +// law : 2015-01-22 Minds + Machines Group Limited +law + +// lawyer : 2014-03-20 +lawyer + +// lds : 2014-03-20 IRI Domain Management, LLC ("Applicant") +lds + +// lease : 2014-03-06 Victor Trail, LLC +lease + +// leclerc : 2014-08-07 A.C.D. LEC Association des Centres Distributeurs Edouard Leclerc +leclerc + +// lefrak : 2015-07-16 LeFrak Organization, Inc. +lefrak + +// legal : 2014-10-16 Blue Falls, LLC +legal + +// lego : 2015-07-16 LEGO Juris A/S +lego + +// lexus : 2015-04-23 TOYOTA MOTOR CORPORATION +lexus + +// lgbt : 2014-05-08 Afilias Limited +lgbt + +// liaison : 2014-10-02 Liaison Technologies, Incorporated +liaison + +// lidl : 2014-09-18 Schwarz Domains und Services GmbH & Co. KG +lidl + +// life : 2014-02-06 Trixy Oaks, LLC +life + +// lifeinsurance : 2015-01-15 American Council of Life Insurers +lifeinsurance + +// lifestyle : 2014-12-11 Lifestyle Domain Holdings, Inc. +lifestyle + +// lighting : 2013-08-27 John McCook, LLC +lighting + +// like : 2014-12-18 Amazon EU S.à r.l. +like + +// lilly : 2015-07-31 Eli Lilly and Company +lilly + +// limited : 2014-03-06 Big Fest, LLC +limited + +// limo : 2013-10-17 Hidden Frostbite, LLC +limo + +// lincoln : 2014-11-13 Ford Motor Company +lincoln + +// linde : 2014-12-04 Linde Aktiengesellschaft +linde + +// link : 2013-11-14 Uniregistry, Corp. +link + +// lipsy : 2015-06-25 Lipsy Ltd +lipsy + +// live : 2014-12-04 +live + +// living : 2015-07-30 Lifestyle Domain Holdings, Inc. +living + +// lixil : 2015-03-19 LIXIL Group Corporation +lixil + +// loan : 2014-11-20 dot Loan Limited +loan + +// loans : 2014-03-20 June Woods, LLC +loans + +// locker : 2015-06-04 Dish DBS Corporation +locker + +// locus : 2015-06-25 Locus Analytics LLC +locus + +// loft : 2015-07-30 Annco, Inc. +loft + +// lol : 2015-01-30 Uniregistry, Corp. +lol + +// london : 2013-11-14 Dot London Domains Limited +london + +// lotte : 2014-11-07 Lotte Holdings Co., Ltd. +lotte + +// lotto : 2014-04-10 Afilias Limited +lotto + +// love : 2014-12-22 Merchant Law Group LLP +love + +// lpl : 2015-07-30 LPL Holdings, Inc. +lpl + +// lplfinancial : 2015-07-30 LPL Holdings, Inc. +lplfinancial + +// ltd : 2014-09-25 Over Corner, LLC +ltd + +// ltda : 2014-04-17 DOMAIN ROBOT SERVICOS DE HOSPEDAGEM NA INTERNET LTDA +ltda + +// lundbeck : 2015-08-06 H. Lundbeck A/S +lundbeck + +// lupin : 2014-11-07 LUPIN LIMITED +lupin + +// luxe : 2014-01-09 Top Level Domain Holdings Limited +luxe + +// luxury : 2013-10-17 Luxury Partners, LLC +luxury + +// macys : 2015-07-31 Macys, Inc. +macys + +// madrid : 2014-05-01 Comunidad de Madrid +madrid + +// maif : 2014-10-02 Mutuelle Assurance Instituteur France (MAIF) +maif + +// maison : 2013-12-05 Victor Frostbite, LLC +maison + +// makeup : 2015-01-15 L'Oréal +makeup + +// man : 2014-12-04 MAN SE +man + +// management : 2013-11-07 John Goodbye, LLC +management + +// mango : 2013-10-24 PUNTO FA S.L. +mango + +// map : 2016-06-09 Charleston Road Registry Inc. +map + +// market : 2014-03-06 +market + +// marketing : 2013-11-07 Fern Pass, LLC +marketing + +// markets : 2014-12-11 IG Group Holdings PLC +markets + +// marriott : 2014-10-09 Marriott Worldwide Corporation +marriott + +// marshalls : 2015-07-16 The TJX Companies, Inc. +marshalls + +// maserati : 2015-07-31 Fiat Chrysler Automobiles N.V. +maserati + +// mattel : 2015-08-06 Mattel Sites, Inc. +mattel + +// mba : 2015-04-02 Lone Hollow, LLC +mba + +// mckinsey : 2015-07-31 McKinsey Holdings, Inc. +mckinsey + +// med : 2015-08-06 Medistry LLC +med + +// media : 2014-03-06 Grand Glen, LLC +media + +// meet : 2014-01-16 +meet + +// melbourne : 2014-05-29 The Crown in right of the State of Victoria, represented by its Department of State Development, Business and Innovation +melbourne + +// meme : 2014-01-30 Charleston Road Registry Inc. +meme + +// memorial : 2014-10-16 Dog Beach, LLC +memorial + +// men : 2015-02-26 Exclusive Registry Limited +men + +// menu : 2013-09-11 Wedding TLD2, LLC +menu + +// meo : 2014-11-07 PT Comunicacoes S.A. +meo + +// merckmsd : 2016-07-14 MSD Registry Holdings, Inc. +merckmsd + +// metlife : 2015-05-07 MetLife Services and Solutions, LLC +metlife + +// miami : 2013-12-19 Top Level Domain Holdings Limited +miami + +// microsoft : 2014-12-18 Microsoft Corporation +microsoft + +// mini : 2014-01-09 Bayerische Motoren Werke Aktiengesellschaft +mini + +// mint : 2015-07-30 Intuit Administrative Services, Inc. +mint + +// mit : 2015-07-02 Massachusetts Institute of Technology +mit + +// mitsubishi : 2015-07-23 Mitsubishi Corporation +mitsubishi + +// mlb : 2015-05-21 MLB Advanced Media DH, LLC +mlb + +// mls : 2015-04-23 The Canadian Real Estate Association +mls + +// mma : 2014-11-07 MMA IARD +mma + +// mobile : 2016-06-02 Dish DBS Corporation +mobile + +// mobily : 2014-12-18 GreenTech Consultancy Company W.L.L. +mobily + +// moda : 2013-11-07 United TLD Holdco Ltd. +moda + +// moe : 2013-11-13 Interlink Co., Ltd. +moe + +// moi : 2014-12-18 Amazon EU S.à r.l. +moi + +// mom : 2015-04-16 Uniregistry, Corp. +mom + +// monash : 2013-09-30 Monash University +monash + +// money : 2014-10-16 Outer McCook, LLC +money + +// monster : 2015-09-11 Monster Worldwide, Inc. +monster + +// mopar : 2015-07-30 FCA US LLC. +mopar + +// mormon : 2013-12-05 IRI Domain Management, LLC ("Applicant") +mormon + +// mortgage : 2014-03-20 +mortgage + +// moscow : 2013-12-19 Foundation for Assistance for Internet Technologies and Infrastructure Development (FAITID) +moscow + +// moto : 2015-06-04 +moto + +// motorcycles : 2014-01-09 DERMotorcycles, LLC +motorcycles + +// mov : 2014-01-30 Charleston Road Registry Inc. +mov + +// movie : 2015-02-05 New Frostbite, LLC +movie + +// movistar : 2014-10-16 Telefónica S.A. +movistar + +// msd : 2015-07-23 MSD Registry Holdings, Inc. +msd + +// mtn : 2014-12-04 MTN Dubai Limited +mtn + +// mtpc : 2014-11-20 Mitsubishi Tanabe Pharma Corporation +mtpc + +// mtr : 2015-03-12 MTR Corporation Limited +mtr + +// mutual : 2015-04-02 Northwestern Mutual MU TLD Registry, LLC +mutual + +// nab : 2015-08-20 National Australia Bank Limited +nab + +// nadex : 2014-12-11 IG Group Holdings PLC +nadex + +// nagoya : 2013-10-24 GMO Registry, Inc. +nagoya + +// nationwide : 2015-07-23 Nationwide Mutual Insurance Company +nationwide + +// natura : 2015-03-12 NATURA COSMÉTICOS S.A. +natura + +// navy : 2014-03-06 United TLD Holdco Ltd. +navy + +// nba : 2015-07-31 NBA REGISTRY, LLC +nba + +// nec : 2015-01-08 NEC Corporation +nec + +// netbank : 2014-06-26 COMMONWEALTH BANK OF AUSTRALIA +netbank + +// netflix : 2015-06-18 Netflix, Inc. +netflix + +// network : 2013-11-14 Trixy Manor, LLC +network + +// neustar : 2013-12-05 NeuStar, Inc. +neustar + +// new : 2014-01-30 Charleston Road Registry Inc. +new + +// newholland : 2015-09-03 CNH Industrial N.V. +newholland + +// news : 2014-12-18 +news + +// next : 2015-06-18 Next plc +next + +// nextdirect : 2015-06-18 Next plc +nextdirect + +// nexus : 2014-07-24 Charleston Road Registry Inc. +nexus + +// nfl : 2015-07-23 NFL Reg Ops LLC +nfl + +// ngo : 2014-03-06 Public Interest Registry +ngo + +// nhk : 2014-02-13 Japan Broadcasting Corporation (NHK) +nhk + +// nico : 2014-12-04 DWANGO Co., Ltd. +nico + +// nike : 2015-07-23 NIKE, Inc. +nike + +// nikon : 2015-05-21 NIKON CORPORATION +nikon + +// ninja : 2013-11-07 United TLD Holdco Ltd. +ninja + +// nissan : 2014-03-27 NISSAN MOTOR CO., LTD. +nissan + +// nissay : 2015-10-29 Nippon Life Insurance Company +nissay + +// nokia : 2015-01-08 Nokia Corporation +nokia + +// northwesternmutual : 2015-06-18 Northwestern Mutual Registry, LLC +northwesternmutual + +// norton : 2014-12-04 Symantec Corporation +norton + +// now : 2015-06-25 Amazon EU S.à r.l. +now + +// nowruz : 2014-09-04 Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti. +nowruz + +// nowtv : 2015-05-14 Starbucks (HK) Limited +nowtv + +// nra : 2014-05-22 NRA Holdings Company, INC. +nra + +// nrw : 2013-11-21 Minds + Machines GmbH +nrw + +// ntt : 2014-10-31 NIPPON TELEGRAPH AND TELEPHONE CORPORATION +ntt + +// nyc : 2014-01-23 The City of New York by and through the New York City Department of Information Technology & Telecommunications +nyc + +// obi : 2014-09-25 OBI Group Holding SE & Co. KGaA +obi + +// observer : 2015-04-30 +observer + +// off : 2015-07-23 Johnson Shareholdings, Inc. +off + +// office : 2015-03-12 Microsoft Corporation +office + +// okinawa : 2013-12-05 BusinessRalliart Inc. +okinawa + +// olayan : 2015-05-14 Crescent Holding GmbH +olayan + +// olayangroup : 2015-05-14 Crescent Holding GmbH +olayangroup + +// oldnavy : 2015-07-31 The Gap, Inc. +oldnavy + +// ollo : 2015-06-04 Dish DBS Corporation +ollo + +// omega : 2015-01-08 The Swatch Group Ltd +omega + +// one : 2014-11-07 One.com A/S +one + +// ong : 2014-03-06 Public Interest Registry +ong + +// onl : 2013-09-16 I-Registry Ltd. +onl + +// online : 2015-01-15 DotOnline Inc. +online + +// onyourside : 2015-07-23 Nationwide Mutual Insurance Company +onyourside + +// ooo : 2014-01-09 INFIBEAM INCORPORATION LIMITED +ooo + +// open : 2015-07-31 American Express Travel Related Services Company, Inc. +open + +// oracle : 2014-06-19 Oracle Corporation +oracle + +// orange : 2015-03-12 Orange Brand Services Limited +orange + +// organic : 2014-03-27 Afilias Limited +organic + +// origins : 2015-10-01 The Estée Lauder Companies Inc. +origins + +// osaka : 2014-09-04 Interlink Co., Ltd. +osaka + +// otsuka : 2013-10-11 Otsuka Holdings Co., Ltd. +otsuka + +// ott : 2015-06-04 Dish DBS Corporation +ott + +// ovh : 2014-01-16 OVH SAS +ovh + +// page : 2014-12-04 Charleston Road Registry Inc. +page + +// panasonic : 2015-07-30 Panasonic Corporation +panasonic + +// panerai : 2014-11-07 Richemont DNS Inc. +panerai + +// paris : 2014-01-30 City of Paris +paris + +// pars : 2014-09-04 Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti. +pars + +// partners : 2013-12-05 Magic Glen, LLC +partners + +// parts : 2013-12-05 Sea Goodbye, LLC +parts + +// party : 2014-09-11 Blue Sky Registry Limited +party + +// passagens : 2015-03-05 Travel Reservations SRL +passagens + +// pay : 2015-08-27 Amazon EU S.à r.l. +pay + +// pccw : 2015-05-14 PCCW Enterprises Limited +pccw + +// pet : 2015-05-07 Afilias plc +pet + +// pfizer : 2015-09-11 Pfizer Inc. +pfizer + +// pharmacy : 2014-06-19 National Association of Boards of Pharmacy +pharmacy + +// phd : 2016-07-28 Charleston Road Registry Inc. +phd + +// philips : 2014-11-07 Koninklijke Philips N.V. +philips + +// phone : 2016-06-02 Dish DBS Corporation +phone + +// photo : 2013-11-14 Uniregistry, Corp. +photo + +// photography : 2013-09-20 Sugar Glen, LLC +photography + +// photos : 2013-10-17 Sea Corner, LLC +photos + +// physio : 2014-05-01 PhysBiz Pty Ltd +physio + +// piaget : 2014-10-16 Richemont DNS Inc. +piaget + +// pics : 2013-11-14 Uniregistry, Corp. +pics + +// pictet : 2014-06-26 Pictet Europe S.A. +pictet + +// pictures : 2014-03-06 Foggy Sky, LLC +pictures + +// pid : 2015-01-08 Top Level Spectrum, Inc. +pid + +// pin : 2014-12-18 Amazon EU S.à r.l. +pin + +// ping : 2015-06-11 Ping Registry Provider, Inc. +ping + +// pink : 2013-10-01 Afilias Limited +pink + +// pioneer : 2015-07-16 Pioneer Corporation +pioneer + +// pizza : 2014-06-26 Foggy Moon, LLC +pizza + +// place : 2014-04-24 Snow Galley, LLC +place + +// play : 2015-03-05 Charleston Road Registry Inc. +play + +// playstation : 2015-07-02 Sony Computer Entertainment Inc. +playstation + +// plumbing : 2013-09-10 Spring Tigers, LLC +plumbing + +// plus : 2015-02-05 Sugar Mill, LLC +plus + +// pnc : 2015-07-02 PNC Domain Co., LLC +pnc + +// pohl : 2014-06-23 Deutsche Vermögensberatung Aktiengesellschaft DVAG +pohl + +// poker : 2014-07-03 Afilias Domains No. 5 Limited +poker + +// politie : 2015-08-20 Politie Nederland +politie + +// porn : 2014-10-16 ICM Registry PN LLC +porn + +// pramerica : 2015-07-30 Prudential Financial, Inc. +pramerica + +// praxi : 2013-12-05 Praxi S.p.A. +praxi + +// press : 2014-04-03 DotPress Inc. +press + +// prime : 2015-06-25 Amazon EU S.à r.l. +prime + +// prod : 2014-01-23 Charleston Road Registry Inc. +prod + +// productions : 2013-12-05 Magic Birch, LLC +productions + +// prof : 2014-07-24 Charleston Road Registry Inc. +prof + +// progressive : 2015-07-23 Progressive Casualty Insurance Company +progressive + +// promo : 2014-12-18 +promo + +// properties : 2013-12-05 Big Pass, LLC +properties + +// property : 2014-05-22 Uniregistry, Corp. +property + +// protection : 2015-04-23 +protection + +// pru : 2015-07-30 Prudential Financial, Inc. +pru + +// prudential : 2015-07-30 Prudential Financial, Inc. +prudential + +// pub : 2013-12-12 United TLD Holdco Ltd. +pub + +// pwc : 2015-10-29 PricewaterhouseCoopers LLP +pwc + +// qpon : 2013-11-14 dotCOOL, Inc. +qpon + +// quebec : 2013-12-19 PointQuébec Inc +quebec + +// quest : 2015-03-26 Quest ION Limited +quest + +// qvc : 2015-07-30 QVC, Inc. +qvc + +// racing : 2014-12-04 Premier Registry Limited +racing + +// radio : 2016-07-21 European Broadcasting Union (EBU) +radio + +// raid : 2015-07-23 Johnson Shareholdings, Inc. +raid + +// read : 2014-12-18 Amazon EU S.à r.l. +read + +// realestate : 2015-09-11 dotRealEstate LLC +realestate + +// realtor : 2014-05-29 Real Estate Domains LLC +realtor + +// realty : 2015-03-19 Fegistry, LLC +realty + +// recipes : 2013-10-17 Grand Island, LLC +recipes + +// red : 2013-11-07 Afilias Limited +red + +// redstone : 2014-10-31 Redstone Haute Couture Co., Ltd. +redstone + +// redumbrella : 2015-03-26 Travelers TLD, LLC +redumbrella + +// rehab : 2014-03-06 United TLD Holdco Ltd. +rehab + +// reise : 2014-03-13 +reise + +// reisen : 2014-03-06 New Cypress, LLC +reisen + +// reit : 2014-09-04 National Association of Real Estate Investment Trusts, Inc. +reit + +// reliance : 2015-04-02 Reliance Industries Limited +reliance + +// ren : 2013-12-12 Beijing Qianxiang Wangjing Technology Development Co., Ltd. +ren + +// rent : 2014-12-04 DERRent, LLC +rent + +// rentals : 2013-12-05 Big Hollow,LLC +rentals + +// repair : 2013-11-07 Lone Sunset, LLC +repair + +// report : 2013-12-05 Binky Glen, LLC +report + +// republican : 2014-03-20 United TLD Holdco Ltd. +republican + +// rest : 2013-12-19 Punto 2012 Sociedad Anonima Promotora de Inversion de Capital Variable +rest + +// restaurant : 2014-07-03 Snow Avenue, LLC +restaurant + +// review : 2014-11-20 dot Review Limited +review + +// reviews : 2013-09-13 +reviews + +// rexroth : 2015-06-18 Robert Bosch GMBH +rexroth + +// rich : 2013-11-21 I-Registry Ltd. +rich + +// richardli : 2015-05-14 Pacific Century Asset Management (HK) Limited +richardli + +// ricoh : 2014-11-20 Ricoh Company, Ltd. +ricoh + +// rightathome : 2015-07-23 Johnson Shareholdings, Inc. +rightathome + +// ril : 2015-04-02 Reliance Industries Limited +ril + +// rio : 2014-02-27 Empresa Municipal de Informática SA - IPLANRIO +rio + +// rip : 2014-07-10 United TLD Holdco Ltd. +rip + +// rmit : 2015-11-19 Royal Melbourne Institute of Technology +rmit + +// rocher : 2014-12-18 Ferrero Trading Lux S.A. +rocher + +// rocks : 2013-11-14 +rocks + +// rodeo : 2013-12-19 Top Level Domain Holdings Limited +rodeo + +// rogers : 2015-08-06 Rogers Communications Partnership +rogers + +// room : 2014-12-18 Amazon EU S.à r.l. +room + +// rsvp : 2014-05-08 Charleston Road Registry Inc. +rsvp + +// rugby : 2016-12-15 World Rugby Strategic Developments Limited +rugby + +// ruhr : 2013-10-02 regiodot GmbH & Co. KG +ruhr + +// run : 2015-03-19 Snow Park, LLC +run + +// rwe : 2015-04-02 RWE AG +rwe + +// ryukyu : 2014-01-09 BusinessRalliart Inc. +ryukyu + +// saarland : 2013-12-12 dotSaarland GmbH +saarland + +// safe : 2014-12-18 Amazon EU S.à r.l. +safe + +// safety : 2015-01-08 Safety Registry Services, LLC. +safety + +// sakura : 2014-12-18 SAKURA Internet Inc. +sakura + +// sale : 2014-10-16 +sale + +// salon : 2014-12-11 Outer Orchard, LLC +salon + +// samsclub : 2015-07-31 Wal-Mart Stores, Inc. +samsclub + +// samsung : 2014-04-03 SAMSUNG SDS CO., LTD +samsung + +// sandvik : 2014-11-13 Sandvik AB +sandvik + +// sandvikcoromant : 2014-11-07 Sandvik AB +sandvikcoromant + +// sanofi : 2014-10-09 Sanofi +sanofi + +// sap : 2014-03-27 SAP AG +sap + +// sapo : 2014-11-07 PT Comunicacoes S.A. +sapo + +// sarl : 2014-07-03 Delta Orchard, LLC +sarl + +// sas : 2015-04-02 Research IP LLC +sas + +// save : 2015-06-25 Amazon EU S.à r.l. +save + +// saxo : 2014-10-31 Saxo Bank A/S +saxo + +// sbi : 2015-03-12 STATE BANK OF INDIA +sbi + +// sbs : 2014-11-07 SPECIAL BROADCASTING SERVICE CORPORATION +sbs + +// sca : 2014-03-13 SVENSKA CELLULOSA AKTIEBOLAGET SCA (publ) +sca + +// scb : 2014-02-20 The Siam Commercial Bank Public Company Limited ("SCB") +scb + +// schaeffler : 2015-08-06 Schaeffler Technologies AG & Co. KG +schaeffler + +// schmidt : 2014-04-03 SALM S.A.S. +schmidt + +// scholarships : 2014-04-24 Scholarships.com, LLC +scholarships + +// school : 2014-12-18 Little Galley, LLC +school + +// schule : 2014-03-06 Outer Moon, LLC +schule + +// schwarz : 2014-09-18 Schwarz Domains und Services GmbH & Co. KG +schwarz + +// science : 2014-09-11 dot Science Limited +science + +// scjohnson : 2015-07-23 Johnson Shareholdings, Inc. +scjohnson + +// scor : 2014-10-31 SCOR SE +scor + +// scot : 2014-01-23 Dot Scot Registry Limited +scot + +// search : 2016-06-09 Charleston Road Registry Inc. +search + +// seat : 2014-05-22 SEAT, S.A. (Sociedad Unipersonal) +seat + +// secure : 2015-08-27 Amazon EU S.à r.l. +secure + +// security : 2015-05-14 +security + +// seek : 2014-12-04 Seek Limited +seek + +// select : 2015-10-08 iSelect Ltd +select + +// sener : 2014-10-24 Sener Ingeniería y Sistemas, S.A. +sener + +// services : 2014-02-27 Fox Castle, LLC +services + +// ses : 2015-07-23 SES +ses + +// seven : 2015-08-06 Seven West Media Ltd +seven + +// sew : 2014-07-17 SEW-EURODRIVE GmbH & Co KG +sew + +// sex : 2014-11-13 ICM Registry SX LLC +sex + +// sexy : 2013-09-11 Uniregistry, Corp. +sexy + +// sfr : 2015-08-13 Societe Francaise du Radiotelephone - SFR +sfr + +// shangrila : 2015-09-03 Shangri‐La International Hotel Management Limited +shangrila + +// sharp : 2014-05-01 Sharp Corporation +sharp + +// shaw : 2015-04-23 Shaw Cablesystems G.P. +shaw + +// shell : 2015-07-30 Shell Information Technology International Inc +shell + +// shia : 2014-09-04 Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti. +shia + +// shiksha : 2013-11-14 Afilias Limited +shiksha + +// shoes : 2013-10-02 Binky Galley, LLC +shoes + +// shop : 2016-04-08 GMO Registry, Inc. +shop + +// shopping : 2016-03-31 +shopping + +// shouji : 2015-01-08 QIHOO 360 TECHNOLOGY CO. LTD. +shouji + +// show : 2015-03-05 Snow Beach, LLC +show + +// showtime : 2015-08-06 CBS Domains Inc. +showtime + +// shriram : 2014-01-23 Shriram Capital Ltd. +shriram + +// silk : 2015-06-25 Amazon EU S.à r.l. +silk + +// sina : 2015-03-12 Sina Corporation +sina + +// singles : 2013-08-27 Fern Madison, LLC +singles + +// site : 2015-01-15 DotSite Inc. +site + +// ski : 2015-04-09 STARTING DOT LIMITED +ski + +// skin : 2015-01-15 L'Oréal +skin + +// sky : 2014-06-19 Sky IP International Ltd, a company incorporated in England and Wales, operating via its registered Swiss branch +sky + +// skype : 2014-12-18 Microsoft Corporation +skype + +// sling : 2015-07-30 Hughes Satellite Systems Corporation +sling + +// smart : 2015-07-09 Smart Communications, Inc. (SMART) +smart + +// smile : 2014-12-18 Amazon EU S.à r.l. +smile + +// sncf : 2015-02-19 Société Nationale des Chemins de fer Francais S N C F +sncf + +// soccer : 2015-03-26 Foggy Shadow, LLC +soccer + +// social : 2013-11-07 United TLD Holdco Ltd. +social + +// softbank : 2015-07-02 SoftBank Corp. +softbank + +// software : 2014-03-20 +software + +// sohu : 2013-12-19 Sohu.com Limited +sohu + +// solar : 2013-11-07 Ruby Town, LLC +solar + +// solutions : 2013-11-07 Silver Cover, LLC +solutions + +// song : 2015-02-26 Amazon EU S.à r.l. +song + +// sony : 2015-01-08 Sony Corporation +sony + +// soy : 2014-01-23 Charleston Road Registry Inc. +soy + +// space : 2014-04-03 DotSpace Inc. +space + +// spiegel : 2014-02-05 SPIEGEL-Verlag Rudolf Augstein GmbH & Co. KG +spiegel + +// spot : 2015-02-26 Amazon EU S.à r.l. +spot + +// spreadbetting : 2014-12-11 IG Group Holdings PLC +spreadbetting + +// srl : 2015-05-07 mySRL GmbH +srl + +// srt : 2015-07-30 FCA US LLC. +srt + +// stada : 2014-11-13 STADA Arzneimittel AG +stada + +// staples : 2015-07-30 Staples, Inc. +staples + +// star : 2015-01-08 Star India Private Limited +star + +// starhub : 2015-02-05 StarHub Ltd +starhub + +// statebank : 2015-03-12 STATE BANK OF INDIA +statebank + +// statefarm : 2015-07-30 State Farm Mutual Automobile Insurance Company +statefarm + +// statoil : 2014-12-04 Statoil ASA +statoil + +// stc : 2014-10-09 Saudi Telecom Company +stc + +// stcgroup : 2014-10-09 Saudi Telecom Company +stcgroup + +// stockholm : 2014-12-18 Stockholms kommun +stockholm + +// storage : 2014-12-22 Self Storage Company LLC +storage + +// store : 2015-04-09 DotStore Inc. +store + +// stream : 2016-01-08 dot Stream Limited +stream + +// studio : 2015-02-11 +studio + +// study : 2014-12-11 OPEN UNIVERSITIES AUSTRALIA PTY LTD +study + +// style : 2014-12-04 Binky Moon, LLC +style + +// sucks : 2014-12-22 Vox Populi Registry Inc. +sucks + +// supplies : 2013-12-19 Atomic Fields, LLC +supplies + +// supply : 2013-12-19 Half Falls, LLC +supply + +// support : 2013-10-24 Grand Orchard, LLC +support + +// surf : 2014-01-09 Top Level Domain Holdings Limited +surf + +// surgery : 2014-03-20 Tin Avenue, LLC +surgery + +// suzuki : 2014-02-20 SUZUKI MOTOR CORPORATION +suzuki + +// swatch : 2015-01-08 The Swatch Group Ltd +swatch + +// swiftcover : 2015-07-23 Swiftcover Insurance Services Limited +swiftcover + +// swiss : 2014-10-16 Swiss Confederation +swiss + +// sydney : 2014-09-18 State of New South Wales, Department of Premier and Cabinet +sydney + +// symantec : 2014-12-04 Symantec Corporation +symantec + +// systems : 2013-11-07 Dash Cypress, LLC +systems + +// tab : 2014-12-04 Tabcorp Holdings Limited +tab + +// taipei : 2014-07-10 Taipei City Government +taipei + +// talk : 2015-04-09 Amazon EU S.à r.l. +talk + +// taobao : 2015-01-15 Alibaba Group Holding Limited +taobao + +// target : 2015-07-31 Target Domain Holdings, LLC +target + +// tatamotors : 2015-03-12 Tata Motors Ltd +tatamotors + +// tatar : 2014-04-24 Limited Liability Company "Coordination Center of Regional Domain of Tatarstan Republic" +tatar + +// tattoo : 2013-08-30 Uniregistry, Corp. +tattoo + +// tax : 2014-03-20 Storm Orchard, LLC +tax + +// taxi : 2015-03-19 Pine Falls, LLC +taxi + +// tci : 2014-09-12 Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti. +tci + +// tdk : 2015-06-11 TDK Corporation +tdk + +// team : 2015-03-05 Atomic Lake, LLC +team + +// tech : 2015-01-30 Dot Tech LLC +tech + +// technology : 2013-09-13 Auburn Falls +technology + +// telecity : 2015-02-19 TelecityGroup International Limited +telecity + +// telefonica : 2014-10-16 Telefónica S.A. +telefonica + +// temasek : 2014-08-07 Temasek Holdings (Private) Limited +temasek + +// tennis : 2014-12-04 Cotton Bloom, LLC +tennis + +// teva : 2015-07-02 Teva Pharmaceutical Industries Limited +teva + +// thd : 2015-04-02 Homer TLC, Inc. +thd + +// theater : 2015-03-19 Blue Tigers, LLC +theater + +// theatre : 2015-05-07 +theatre + +// tiaa : 2015-07-23 Teachers Insurance and Annuity Association of America +tiaa + +// tickets : 2015-02-05 Accent Media Limited +tickets + +// tienda : 2013-11-14 Victor Manor, LLC +tienda + +// tiffany : 2015-01-30 Tiffany and Company +tiffany + +// tips : 2013-09-20 Corn Willow, LLC +tips + +// tires : 2014-11-07 Dog Edge, LLC +tires + +// tirol : 2014-04-24 punkt Tirol GmbH +tirol + +// tjmaxx : 2015-07-16 The TJX Companies, Inc. +tjmaxx + +// tjx : 2015-07-16 The TJX Companies, Inc. +tjx + +// tkmaxx : 2015-07-16 The TJX Companies, Inc. +tkmaxx + +// tmall : 2015-01-15 Alibaba Group Holding Limited +tmall + +// today : 2013-09-20 Pearl Woods, LLC +today + +// tokyo : 2013-11-13 GMO Registry, Inc. +tokyo + +// tools : 2013-11-21 Pioneer North, LLC +tools + +// top : 2014-03-20 Jiangsu Bangning Science & Technology Co.,Ltd. +top + +// toray : 2014-12-18 Toray Industries, Inc. +toray + +// toshiba : 2014-04-10 TOSHIBA Corporation +toshiba + +// total : 2015-08-06 Total SA +total + +// tours : 2015-01-22 Sugar Station, LLC +tours + +// town : 2014-03-06 Koko Moon, LLC +town + +// toyota : 2015-04-23 TOYOTA MOTOR CORPORATION +toyota + +// toys : 2014-03-06 Pioneer Orchard, LLC +toys + +// trade : 2014-01-23 Elite Registry Limited +trade + +// trading : 2014-12-11 IG Group Holdings PLC +trading + +// training : 2013-11-07 Wild Willow, LLC +training + +// travelchannel : 2015-07-02 Lifestyle Domain Holdings, Inc. +travelchannel + +// travelers : 2015-03-26 Travelers TLD, LLC +travelers + +// travelersinsurance : 2015-03-26 Travelers TLD, LLC +travelersinsurance + +// trust : 2014-10-16 +trust + +// trv : 2015-03-26 Travelers TLD, LLC +trv + +// tube : 2015-06-11 Latin American Telecom LLC +tube + +// tui : 2014-07-03 TUI AG +tui + +// tunes : 2015-02-26 Amazon EU S.à r.l. +tunes + +// tushu : 2014-12-18 Amazon EU S.à r.l. +tushu + +// tvs : 2015-02-19 T V SUNDRAM IYENGAR & SONS LIMITED +tvs + +// ubank : 2015-08-20 National Australia Bank Limited +ubank + +// ubs : 2014-12-11 UBS AG +ubs + +// uconnect : 2015-07-30 FCA US LLC. +uconnect + +// unicom : 2015-10-15 China United Network Communications Corporation Limited +unicom + +// university : 2014-03-06 Little Station, LLC +university + +// uno : 2013-09-11 Dot Latin LLC +uno + +// uol : 2014-05-01 UBN INTERNET LTDA. +uol + +// ups : 2015-06-25 UPS Market Driver, Inc. +ups + +// vacations : 2013-12-05 Atomic Tigers, LLC +vacations + +// vana : 2014-12-11 Lifestyle Domain Holdings, Inc. +vana + +// vanguard : 2015-09-03 The Vanguard Group, Inc. +vanguard + +// vegas : 2014-01-16 Dot Vegas, Inc. +vegas + +// ventures : 2013-08-27 Binky Lake, LLC +ventures + +// verisign : 2015-08-13 VeriSign, Inc. +verisign + +// versicherung : 2014-03-20 +versicherung + +// vet : 2014-03-06 +vet + +// viajes : 2013-10-17 Black Madison, LLC +viajes + +// video : 2014-10-16 +video + +// vig : 2015-05-14 VIENNA INSURANCE GROUP AG Wiener Versicherung Gruppe +vig + +// viking : 2015-04-02 Viking River Cruises (Bermuda) Ltd. +viking + +// villas : 2013-12-05 New Sky, LLC +villas + +// vin : 2015-06-18 Holly Shadow, LLC +vin + +// vip : 2015-01-22 Minds + Machines Group Limited +vip + +// virgin : 2014-09-25 Virgin Enterprises Limited +virgin + +// visa : 2015-07-30 Visa Worldwide Pte. Limited +visa + +// vision : 2013-12-05 Koko Station, LLC +vision + +// vista : 2014-09-18 Vistaprint Limited +vista + +// vistaprint : 2014-09-18 Vistaprint Limited +vistaprint + +// viva : 2014-11-07 Saudi Telecom Company +viva + +// vivo : 2015-07-31 Telefonica Brasil S.A. +vivo + +// vlaanderen : 2014-02-06 DNS.be vzw +vlaanderen + +// vodka : 2013-12-19 Top Level Domain Holdings Limited +vodka + +// volkswagen : 2015-05-14 Volkswagen Group of America Inc. +volkswagen + +// volvo : 2015-11-12 Volvo Holding Sverige Aktiebolag +volvo + +// vote : 2013-11-21 Monolith Registry LLC +vote + +// voting : 2013-11-13 Valuetainment Corp. +voting + +// voto : 2013-11-21 Monolith Registry LLC +voto + +// voyage : 2013-08-27 Ruby House, LLC +voyage + +// vuelos : 2015-03-05 Travel Reservations SRL +vuelos + +// wales : 2014-05-08 Nominet UK +wales + +// walmart : 2015-07-31 Wal-Mart Stores, Inc. +walmart + +// walter : 2014-11-13 Sandvik AB +walter + +// wang : 2013-10-24 Zodiac Leo Limited +wang + +// wanggou : 2014-12-18 Amazon EU S.à r.l. +wanggou + +// warman : 2015-06-18 Weir Group IP Limited +warman + +// watch : 2013-11-14 Sand Shadow, LLC +watch + +// watches : 2014-12-22 Richemont DNS Inc. +watches + +// weather : 2015-01-08 The Weather Channel, LLC +weather + +// weatherchannel : 2015-03-12 The Weather Channel, LLC +weatherchannel + +// webcam : 2014-01-23 dot Webcam Limited +webcam + +// weber : 2015-06-04 Saint-Gobain Weber SA +weber + +// website : 2014-04-03 DotWebsite Inc. +website + +// wed : 2013-10-01 Atgron, Inc. +wed + +// wedding : 2014-04-24 Top Level Domain Holdings Limited +wedding + +// weibo : 2015-03-05 Sina Corporation +weibo + +// weir : 2015-01-29 Weir Group IP Limited +weir + +// whoswho : 2014-02-20 Who's Who Registry +whoswho + +// wien : 2013-10-28 punkt.wien GmbH +wien + +// wiki : 2013-11-07 Top Level Design, LLC +wiki + +// williamhill : 2014-03-13 William Hill Organization Limited +williamhill + +// win : 2014-11-20 First Registry Limited +win + +// windows : 2014-12-18 Microsoft Corporation +windows + +// wine : 2015-06-18 June Station, LLC +wine + +// winners : 2015-07-16 The TJX Companies, Inc. +winners + +// wme : 2014-02-13 William Morris Endeavor Entertainment, LLC +wme + +// wolterskluwer : 2015-08-06 Wolters Kluwer N.V. +wolterskluwer + +// woodside : 2015-07-09 Woodside Petroleum Limited +woodside + +// work : 2013-12-19 Top Level Domain Holdings Limited +work + +// works : 2013-11-14 Little Dynamite, LLC +works + +// world : 2014-06-12 Bitter Fields, LLC +world + +// wow : 2015-10-08 Amazon EU S.à r.l. +wow + +// wtc : 2013-12-19 World Trade Centers Association, Inc. +wtc + +// wtf : 2014-03-06 Hidden Way, LLC +wtf + +// xbox : 2014-12-18 Microsoft Corporation +xbox + +// xerox : 2014-10-24 Xerox DNHC LLC +xerox + +// xfinity : 2015-07-09 Comcast IP Holdings I, LLC +xfinity + +// xihuan : 2015-01-08 QIHOO 360 TECHNOLOGY CO. LTD. +xihuan + +// xin : 2014-12-11 Elegant Leader Limited +xin + +// xn--11b4c3d : 2015-01-15 VeriSign Sarl +कॉम + +// xn--1ck2e1b : 2015-02-26 Amazon EU S.à r.l. +セール + +// xn--1qqw23a : 2014-01-09 Guangzhou YU Wei Information Technology Co., Ltd. +佛山 + +// xn--30rr7y : 2014-06-12 Excellent First Limited +慈善 + +// xn--3bst00m : 2013-09-13 Eagle Horizon Limited +集团 + +// xn--3ds443g : 2013-09-08 TLD REGISTRY LIMITED +在线 + +// xn--3oq18vl8pn36a : 2015-07-02 Volkswagen (China) Investment Co., Ltd. +大众汽车 + +// xn--3pxu8k : 2015-01-15 VeriSign Sarl +点看 + +// xn--42c2d9a : 2015-01-15 VeriSign Sarl +คอม + +// xn--45q11c : 2013-11-21 Zodiac Scorpio Limited +八卦 + +// xn--4gbrim : 2013-10-04 Suhub Electronic Establishment +موقع + +// xn--55qw42g : 2013-11-08 China Organizational Name Administration Center +公益 + +// xn--55qx5d : 2013-11-14 Computer Network Information Center of Chinese Academy of Sciences (China Internet Network Information Center) +公司 + +// xn--5su34j936bgsg : 2015-09-03 Shangri‐La International Hotel Management Limited +香格里拉 + +// xn--5tzm5g : 2014-12-22 Global Website TLD Asia Limited +网站 + +// xn--6frz82g : 2013-09-23 Afilias Limited +移动 + +// xn--6qq986b3xl : 2013-09-13 Tycoon Treasure Limited +我爱你 + +// xn--80adxhks : 2013-12-19 Foundation for Assistance for Internet Technologies and Infrastructure Development (FAITID) +москва + +// xn--80aqecdr1a : 2015-10-21 Pontificium Consilium de Comunicationibus Socialibus (PCCS) (Pontifical Council for Social Communication) +католик + +// xn--80asehdb : 2013-07-14 CORE Association +онлайн + +// xn--80aswg : 2013-07-14 CORE Association +сайт + +// xn--8y0a063a : 2015-03-26 China United Network Communications Corporation Limited +联通 + +// xn--9dbq2a : 2015-01-15 VeriSign Sarl +קום + +// xn--9et52u : 2014-06-12 RISE VICTORY LIMITED +时尚 + +// xn--9krt00a : 2015-03-12 Sina Corporation +微博 + +// xn--b4w605ferd : 2014-08-07 Temasek Holdings (Private) Limited +淡马锡 + +// xn--bck1b9a5dre4c : 2015-02-26 Amazon EU S.à r.l. +ファッション + +// xn--c1avg : 2013-11-14 Public Interest Registry +орг + +// xn--c2br7g : 2015-01-15 VeriSign Sarl +नेट + +// xn--cck2b3b : 2015-02-26 Amazon EU S.à r.l. +ストア + +// xn--cg4bki : 2013-09-27 SAMSUNG SDS CO., LTD +삼성 + +// xn--czr694b : 2014-01-16 Dot Trademark TLD Holding Company Limited +商标 + +// xn--czrs0t : 2013-12-19 Wild Island, LLC +商店 + +// xn--czru2d : 2013-11-21 Zodiac Capricorn Limited +商城 + +// xn--d1acj3b : 2013-11-20 The Foundation for Network Initiatives “The Smart Internet” +дети + +// xn--eckvdtc9d : 2014-12-18 Amazon EU S.à r.l. +ポイント + +// xn--efvy88h : 2014-08-22 Xinhua News Agency Guangdong Branch 新华通讯社广东分社 +新闻 + +// xn--estv75g : 2015-02-19 Industrial and Commercial Bank of China Limited +工行 + +// xn--fct429k : 2015-04-09 Amazon EU S.à r.l. +家電 + +// xn--fhbei : 2015-01-15 VeriSign Sarl +كوم + +// xn--fiq228c5hs : 2013-09-08 TLD REGISTRY LIMITED +中文网 + +// xn--fiq64b : 2013-10-14 CITIC Group Corporation +中信 + +// xn--fjq720a : 2014-05-22 Will Bloom, LLC +娱乐 + +// xn--flw351e : 2014-07-31 Charleston Road Registry Inc. +谷歌 + +// xn--fzys8d69uvgm : 2015-05-14 PCCW Enterprises Limited +電訊盈科 + +// xn--g2xx48c : 2015-01-30 Minds + Machines Group Limited +购物 + +// xn--gckr3f0f : 2015-02-26 Amazon EU S.à r.l. +クラウド + +// xn--gk3at1e : 2015-10-08 Amazon EU S.à r.l. +通販 + +// xn--hxt814e : 2014-05-15 Zodiac Libra Limited +网店 + +// xn--i1b6b1a6a2e : 2013-11-14 Public Interest Registry +संगठन + +// xn--imr513n : 2014-12-11 Dot Trademark TLD Holding Company Limited +餐厅 + +// xn--io0a7i : 2013-11-14 Computer Network Information Center of Chinese Academy of Sciences (China Internet Network Information Center) +网络 + +// xn--j1aef : 2015-01-15 VeriSign Sarl +ком + +// xn--jlq61u9w7b : 2015-01-08 Nokia Corporation +诺基亚 + +// xn--jvr189m : 2015-02-26 Amazon EU S.à r.l. +食品 + +// xn--kcrx77d1x4a : 2014-11-07 Koninklijke Philips N.V. +飞利浦 + +// xn--kpu716f : 2014-12-22 Richemont DNS Inc. +手表 + +// xn--kput3i : 2014-02-13 Beijing RITT-Net Technology Development Co., Ltd +手机 + +// xn--mgba3a3ejt : 2014-11-20 Aramco Services Company +ارامكو + +// xn--mgba7c0bbn0a : 2015-05-14 Crescent Holding GmbH +العليان + +// xn--mgbaakc7dvf : 2015-09-03 Emirates Telecommunications Corporation (trading as Etisalat) +اتصالات + +// xn--mgbab2bd : 2013-10-31 CORE Association +بازار + +// xn--mgbb9fbpob : 2014-12-18 GreenTech Consultancy Company W.L.L. +موبايلي + +// xn--mgbca7dzdo : 2015-07-30 Abu Dhabi Systems and Information Centre +ابوظبي + +// xn--mgbi4ecexp : 2015-10-21 Pontificium Consilium de Comunicationibus Socialibus (PCCS) (Pontifical Council for Social Communication) +كاثوليك + +// xn--mgbt3dhd : 2014-09-04 Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti. +همراه + +// xn--mk1bu44c : 2015-01-15 VeriSign Sarl +닷컴 + +// xn--mxtq1m : 2014-03-06 Net-Chinese Co., Ltd. +政府 + +// xn--ngbc5azd : 2013-07-13 International Domain Registry Pty. Ltd. +شبكة + +// xn--ngbe9e0a : 2014-12-04 Kuwait Finance House +بيتك + +// xn--ngbrx : 2015-11-12 League of Arab States +عرب + +// xn--nqv7f : 2013-11-14 Public Interest Registry +机构 + +// xn--nqv7fs00ema : 2013-11-14 Public Interest Registry +组织机构 + +// xn--nyqy26a : 2014-11-07 Stable Tone Limited +健康 + +// xn--p1acf : 2013-12-12 Rusnames Limited +рус + +// xn--pbt977c : 2014-12-22 Richemont DNS Inc. +珠宝 + +// xn--pssy2u : 2015-01-15 VeriSign Sarl +大拿 + +// xn--q9jyb4c : 2013-09-17 Charleston Road Registry Inc. +みんな + +// xn--qcka1pmc : 2014-07-31 Charleston Road Registry Inc. +グーグル + +// xn--rhqv96g : 2013-09-11 Stable Tone Limited +世界 + +// xn--rovu88b : 2015-02-26 Amazon EU S.à r.l. +書籍 + +// xn--ses554g : 2014-01-16 +网址 + +// xn--t60b56a : 2015-01-15 VeriSign Sarl +닷넷 + +// xn--tckwe : 2015-01-15 VeriSign Sarl +コム + +// xn--tiq49xqyj : 2015-10-21 Pontificium Consilium de Comunicationibus Socialibus (PCCS) (Pontifical Council for Social Communication) +天主教 + +// xn--unup4y : 2013-07-14 Spring Fields, LLC +游戏 + +// xn--vermgensberater-ctb : 2014-06-23 Deutsche Vermögensberatung Aktiengesellschaft DVAG +vermögensberater + +// xn--vermgensberatung-pwb : 2014-06-23 Deutsche Vermögensberatung Aktiengesellschaft DVAG +vermögensberatung + +// xn--vhquv : 2013-08-27 Dash McCook, LLC +企业 + +// xn--vuq861b : 2014-10-16 Beijing Tele-info Network Technology Co., Ltd. +信息 + +// xn--w4r85el8fhu5dnra : 2015-04-30 Kerry Trading Co. Limited +嘉里大酒店 + +// xn--w4rs40l : 2015-07-30 Kerry Trading Co. Limited +嘉里 + +// xn--xhq521b : 2013-11-14 Guangzhou YU Wei Information Technology Co., Ltd. +广东 + +// xn--zfr164b : 2013-11-08 China Organizational Name Administration Center +政务 + +// xperia : 2015-05-14 Sony Mobile Communications AB +xperia + +// xyz : 2013-12-05 XYZ.COM LLC +xyz + +// yachts : 2014-01-09 DERYachts, LLC +yachts + +// yahoo : 2015-04-02 Yahoo! Domain Services Inc. +yahoo + +// yamaxun : 2014-12-18 Amazon EU S.à r.l. +yamaxun + +// yandex : 2014-04-10 YANDEX, LLC +yandex + +// yodobashi : 2014-11-20 YODOBASHI CAMERA CO.,LTD. +yodobashi + +// yoga : 2014-05-29 Top Level Domain Holdings Limited +yoga + +// yokohama : 2013-12-12 GMO Registry, Inc. +yokohama + +// you : 2015-04-09 Amazon EU S.à r.l. +you + +// youtube : 2014-05-01 Charleston Road Registry Inc. +youtube + +// yun : 2015-01-08 QIHOO 360 TECHNOLOGY CO. LTD. +yun + +// zappos : 2015-06-25 Amazon EU S.à r.l. +zappos + +// zara : 2014-11-07 Industria de Diseño Textil, S.A. (INDITEX, S.A.) +zara + +// zero : 2014-12-18 Amazon EU S.à r.l. +zero + +// zip : 2014-05-08 Charleston Road Registry Inc. +zip + +// zippo : 2015-07-02 Zadco Company +zippo + +// zone : 2013-11-14 Outer Falls, LLC +zone + +// zuerich : 2014-11-07 Kanton Zürich (Canton of Zurich) +zuerich + + +// ===END ICANN DOMAINS=== +// ===BEGIN PRIVATE DOMAINS=== +// (Note: these are in alphabetical order by company name) + +// 1GB LLC : https://www.1gb.ua/ +// Submitted by 1GB LLC +cc.ua +inf.ua +ltd.ua + +// AgileBits Inc : https://agilebits.com +// Submitted by Roustem Karimov +1password.ca +1password.com +1password.eu + +// Agnat sp. z o.o. : https://domena.pl +// Submitted by Przemyslaw Plewa +beep.pl + +// Alces Software Ltd : http://alces-software.com +// Submitted by Mark J. Titorenko +*.compute.estate +*.alces.network + +// alwaysdata : https://www.alwaysdata.com +// Submitted by Cyril +alwaysdata.net + +// Amazon CloudFront : https://aws.amazon.com/cloudfront/ +// Submitted by Donavan Miller +cloudfront.net + +// Amazon Elastic Compute Cloud : https://aws.amazon.com/ec2/ +// Submitted by Luke Wells +*.compute.amazonaws.com +*.compute-1.amazonaws.com +*.compute.amazonaws.com.cn +us-east-1.amazonaws.com + +// Amazon Elastic Beanstalk : https://aws.amazon.com/elasticbeanstalk/ +// Submitted by Luke Wells +cn-north-1.eb.amazonaws.com.cn +elasticbeanstalk.com +ap-northeast-1.elasticbeanstalk.com +ap-northeast-2.elasticbeanstalk.com +ap-south-1.elasticbeanstalk.com +ap-southeast-1.elasticbeanstalk.com +ap-southeast-2.elasticbeanstalk.com +ca-central-1.elasticbeanstalk.com +eu-central-1.elasticbeanstalk.com +eu-west-1.elasticbeanstalk.com +eu-west-2.elasticbeanstalk.com +eu-west-3.elasticbeanstalk.com +sa-east-1.elasticbeanstalk.com +us-east-1.elasticbeanstalk.com +us-east-2.elasticbeanstalk.com +us-gov-west-1.elasticbeanstalk.com +us-west-1.elasticbeanstalk.com +us-west-2.elasticbeanstalk.com + +// Amazon Elastic Load Balancing : https://aws.amazon.com/elasticloadbalancing/ +// Submitted by Luke Wells +*.elb.amazonaws.com +*.elb.amazonaws.com.cn + +// Amazon S3 : https://aws.amazon.com/s3/ +// Submitted by Luke Wells +s3.amazonaws.com +s3-ap-northeast-1.amazonaws.com +s3-ap-northeast-2.amazonaws.com +s3-ap-south-1.amazonaws.com +s3-ap-southeast-1.amazonaws.com +s3-ap-southeast-2.amazonaws.com +s3-ca-central-1.amazonaws.com +s3-eu-central-1.amazonaws.com +s3-eu-west-1.amazonaws.com +s3-eu-west-2.amazonaws.com +s3-eu-west-3.amazonaws.com +s3-external-1.amazonaws.com +s3-fips-us-gov-west-1.amazonaws.com +s3-sa-east-1.amazonaws.com +s3-us-gov-west-1.amazonaws.com +s3-us-east-2.amazonaws.com +s3-us-west-1.amazonaws.com +s3-us-west-2.amazonaws.com +s3.ap-northeast-2.amazonaws.com +s3.ap-south-1.amazonaws.com +s3.cn-north-1.amazonaws.com.cn +s3.ca-central-1.amazonaws.com +s3.eu-central-1.amazonaws.com +s3.eu-west-2.amazonaws.com +s3.eu-west-3.amazonaws.com +s3.us-east-2.amazonaws.com +s3.dualstack.ap-northeast-1.amazonaws.com +s3.dualstack.ap-northeast-2.amazonaws.com +s3.dualstack.ap-south-1.amazonaws.com +s3.dualstack.ap-southeast-1.amazonaws.com +s3.dualstack.ap-southeast-2.amazonaws.com +s3.dualstack.ca-central-1.amazonaws.com +s3.dualstack.eu-central-1.amazonaws.com +s3.dualstack.eu-west-1.amazonaws.com +s3.dualstack.eu-west-2.amazonaws.com +s3.dualstack.eu-west-3.amazonaws.com +s3.dualstack.sa-east-1.amazonaws.com +s3.dualstack.us-east-1.amazonaws.com +s3.dualstack.us-east-2.amazonaws.com +s3-website-us-east-1.amazonaws.com +s3-website-us-west-1.amazonaws.com +s3-website-us-west-2.amazonaws.com +s3-website-ap-northeast-1.amazonaws.com +s3-website-ap-southeast-1.amazonaws.com +s3-website-ap-southeast-2.amazonaws.com +s3-website-eu-west-1.amazonaws.com +s3-website-sa-east-1.amazonaws.com +s3-website.ap-northeast-2.amazonaws.com +s3-website.ap-south-1.amazonaws.com +s3-website.ca-central-1.amazonaws.com +s3-website.eu-central-1.amazonaws.com +s3-website.eu-west-2.amazonaws.com +s3-website.eu-west-3.amazonaws.com +s3-website.us-east-2.amazonaws.com + +// Amune : https://amune.org/ +// Submitted by Team Amune +t3l3p0rt.net +tele.amune.org + +// Aptible : https://www.aptible.com/ +// Submitted by Thomas Orozco +on-aptible.com + +// Asociación Amigos de la Informática "Euskalamiga" : http://encounter.eus/ +// Submitted by Hector Martin +user.party.eus + +// Association potager.org : https://potager.org/ +// Submitted by Lunar +pimienta.org +poivron.org +potager.org +sweetpepper.org + +// ASUSTOR Inc. : http://www.asustor.com +// Submitted by Vincent Tseng +myasustor.com + +// AVM : https://avm.de +// Submitted by Andreas Weise +myfritz.net + +// AW AdvisorWebsites.com Software Inc : https://advisorwebsites.com +// Submitted by James Kennedy +*.awdev.ca +*.advisor.ws + +// backplane : https://www.backplane.io +// Submitted by Anthony Voutas +backplaneapp.io + +// BetaInABox +// Submitted by Adrian +betainabox.com + +// BinaryLane : http://www.binarylane.com +// Submitted by Nathan O'Sullivan +bnr.la + +// Boomla : https://boomla.com +// Submitted by Tibor Halter +boomla.net + +// Boxfuse : https://boxfuse.com +// Submitted by Axel Fontaine +boxfuse.io + +// bplaced : https://www.bplaced.net/ +// Submitted by Miroslav Bozic +square7.ch +bplaced.com +bplaced.de +square7.de +bplaced.net +square7.net + +// BrowserSafetyMark +// Submitted by Dave Tharp +browsersafetymark.io + +// callidomus : https://www.callidomus.com/ +// Submitted by Marcus Popp +mycd.eu + +// CentralNic : http://www.centralnic.com/names/domains +// Submitted by registry +ae.org +ar.com +br.com +cn.com +com.de +com.se +de.com +eu.com +gb.com +gb.net +hu.com +hu.net +jp.net +jpn.com +kr.com +mex.com +no.com +qc.com +ru.com +sa.com +se.com +se.net +uk.com +uk.net +us.com +uy.com +za.bz +za.com + +// Africa.com Web Solutions Ltd : https://registry.africa.com +// Submitted by Gavin Brown +africa.com + +// iDOT Services Limited : http://www.domain.gr.com +// Submitted by Gavin Brown +gr.com + +// Radix FZC : http://domains.in.net +// Submitted by Gavin Brown +in.net + +// US REGISTRY LLC : http://us.org +// Submitted by Gavin Brown +us.org + +// co.com Registry, LLC : https://registry.co.com +// Submitted by Gavin Brown +co.com + +// c.la : http://www.c.la/ +c.la + +// certmgr.org : https://certmgr.org +// Submitted by B. Blechschmidt +certmgr.org + +// Citrix : https://citrix.com +// Submitted by Alex Stoddard +xenapponazure.com + +// ClearVox : http://www.clearvox.nl/ +// Submitted by Leon Rowland +virtueeldomein.nl + +// Cloud66 : https://www.cloud66.com/ +// Submitted by Khash Sajadi +c66.me + +// CloudAccess.net : https://www.cloudaccess.net/ +// Submitted by Pawel Panek +jdevcloud.com +wpdevcloud.com +cloudaccess.host +freesite.host +cloudaccess.net + +// cloudControl : https://www.cloudcontrol.com/ +// Submitted by Tobias Wilken +cloudcontrolled.com +cloudcontrolapp.com + +// co.ca : http://registry.co.ca/ +co.ca + +// i-registry s.r.o. : http://www.i-registry.cz/ +// Submitted by Martin Semrad +co.cz + +// CDN77.com : http://www.cdn77.com +// Submitted by Jan Krpes +c.cdn77.org +cdn77-ssl.net +r.cdn77.net +rsc.cdn77.org +ssl.origin.cdn77-secure.org + +// Cloud DNS Ltd : http://www.cloudns.net +// Submitted by Aleksander Hristov +cloudns.asia +cloudns.biz +cloudns.club +cloudns.cc +cloudns.eu +cloudns.in +cloudns.info +cloudns.org +cloudns.pro +cloudns.pw +cloudns.us + +// CoDNS B.V. +co.nl +co.no + +// Combell.com : https://www.combell.com +// Submitted by Thomas Wouters +webhosting.be +hosting-cluster.nl + +// COSIMO GmbH : http://www.cosimo.de +// Submitted by Rene Marticke +dyn.cosidns.de +dynamisches-dns.de +dnsupdater.de +internet-dns.de +l-o-g-i-n.de +dynamic-dns.info +feste-ip.net +knx-server.net +static-access.net + +// Craynic, s.r.o. : http://www.craynic.com/ +// Submitted by Ales Krajnik +realm.cz + +// Cryptonomic : https://cryptonomic.net/ +// Submitted by Andrew Cady +*.cryptonomic.net + +// Cupcake : https://cupcake.io/ +// Submitted by Jonathan Rudenberg +cupcake.is + +// cyon GmbH : https://www.cyon.ch/ +// Submitted by Dominic Luechinger +cyon.link +cyon.site + +// Daplie, Inc : https://daplie.com +// Submitted by AJ ONeal +daplie.me +localhost.daplie.me + +// Dansk.net : http://www.dansk.net/ +// Submitted by Anani Voule +biz.dk +co.dk +firm.dk +reg.dk +store.dk + +// Debian : https://www.debian.org/ +// Submitted by Peter Palfrader / Debian Sysadmin Team +debian.net + +// deSEC : https://desec.io/ +// Submitted by Peter Thomassen +dedyn.io + +// DNShome : https://www.dnshome.de/ +// Submitted by Norbert Auler +dnshome.de + +// DrayTek Corp. : https://www.draytek.com/ +// Submitted by Paul Fang +drayddns.com + +// DreamHost : http://www.dreamhost.com/ +// Submitted by Andrew Farmer +dreamhosters.com + +// Drobo : http://www.drobo.com/ +// Submitted by Ricardo Padilha +mydrobo.com + +// Drud Holdings, LLC. : https://www.drud.com/ +// Submitted by Kevin Bridges +drud.io +drud.us + +// DuckDNS : http://www.duckdns.org/ +// Submitted by Richard Harper +duckdns.org + +// dy.fi : http://dy.fi/ +// Submitted by Heikki Hannikainen +dy.fi +tunk.org + +// DynDNS.com : http://www.dyndns.com/services/dns/dyndns/ +dyndns-at-home.com +dyndns-at-work.com +dyndns-blog.com +dyndns-free.com +dyndns-home.com +dyndns-ip.com +dyndns-mail.com +dyndns-office.com +dyndns-pics.com +dyndns-remote.com +dyndns-server.com +dyndns-web.com +dyndns-wiki.com +dyndns-work.com +dyndns.biz +dyndns.info +dyndns.org +dyndns.tv +at-band-camp.net +ath.cx +barrel-of-knowledge.info +barrell-of-knowledge.info +better-than.tv +blogdns.com +blogdns.net +blogdns.org +blogsite.org +boldlygoingnowhere.org +broke-it.net +buyshouses.net +cechire.com +dnsalias.com +dnsalias.net +dnsalias.org +dnsdojo.com +dnsdojo.net +dnsdojo.org +does-it.net +doesntexist.com +doesntexist.org +dontexist.com +dontexist.net +dontexist.org +doomdns.com +doomdns.org +dvrdns.org +dyn-o-saur.com +dynalias.com +dynalias.net +dynalias.org +dynathome.net +dyndns.ws +endofinternet.net +endofinternet.org +endoftheinternet.org +est-a-la-maison.com +est-a-la-masion.com +est-le-patron.com +est-mon-blogueur.com +for-better.biz +for-more.biz +for-our.info +for-some.biz +for-the.biz +forgot.her.name +forgot.his.name +from-ak.com +from-al.com +from-ar.com +from-az.net +from-ca.com +from-co.net +from-ct.com +from-dc.com +from-de.com +from-fl.com +from-ga.com +from-hi.com +from-ia.com +from-id.com +from-il.com +from-in.com +from-ks.com +from-ky.com +from-la.net +from-ma.com +from-md.com +from-me.org +from-mi.com +from-mn.com +from-mo.com +from-ms.com +from-mt.com +from-nc.com +from-nd.com +from-ne.com +from-nh.com +from-nj.com +from-nm.com +from-nv.com +from-ny.net +from-oh.com +from-ok.com +from-or.com +from-pa.com +from-pr.com +from-ri.com +from-sc.com +from-sd.com +from-tn.com +from-tx.com +from-ut.com +from-va.com +from-vt.com +from-wa.com +from-wi.com +from-wv.com +from-wy.com +ftpaccess.cc +fuettertdasnetz.de +game-host.org +game-server.cc +getmyip.com +gets-it.net +go.dyndns.org +gotdns.com +gotdns.org +groks-the.info +groks-this.info +ham-radio-op.net +here-for-more.info +hobby-site.com +hobby-site.org +home.dyndns.org +homedns.org +homeftp.net +homeftp.org +homeip.net +homelinux.com +homelinux.net +homelinux.org +homeunix.com +homeunix.net +homeunix.org +iamallama.com +in-the-band.net +is-a-anarchist.com +is-a-blogger.com +is-a-bookkeeper.com +is-a-bruinsfan.org +is-a-bulls-fan.com +is-a-candidate.org +is-a-caterer.com +is-a-celticsfan.org +is-a-chef.com +is-a-chef.net +is-a-chef.org +is-a-conservative.com +is-a-cpa.com +is-a-cubicle-slave.com +is-a-democrat.com +is-a-designer.com +is-a-doctor.com +is-a-financialadvisor.com +is-a-geek.com +is-a-geek.net +is-a-geek.org +is-a-green.com +is-a-guru.com +is-a-hard-worker.com +is-a-hunter.com +is-a-knight.org +is-a-landscaper.com +is-a-lawyer.com +is-a-liberal.com +is-a-libertarian.com +is-a-linux-user.org +is-a-llama.com +is-a-musician.com +is-a-nascarfan.com +is-a-nurse.com +is-a-painter.com +is-a-patsfan.org +is-a-personaltrainer.com +is-a-photographer.com +is-a-player.com +is-a-republican.com +is-a-rockstar.com +is-a-socialist.com +is-a-soxfan.org +is-a-student.com +is-a-teacher.com +is-a-techie.com +is-a-therapist.com +is-an-accountant.com +is-an-actor.com +is-an-actress.com +is-an-anarchist.com +is-an-artist.com +is-an-engineer.com +is-an-entertainer.com +is-by.us +is-certified.com +is-found.org +is-gone.com +is-into-anime.com +is-into-cars.com +is-into-cartoons.com +is-into-games.com +is-leet.com +is-lost.org +is-not-certified.com +is-saved.org +is-slick.com +is-uberleet.com +is-very-bad.org +is-very-evil.org +is-very-good.org +is-very-nice.org +is-very-sweet.org +is-with-theband.com +isa-geek.com +isa-geek.net +isa-geek.org +isa-hockeynut.com +issmarterthanyou.com +isteingeek.de +istmein.de +kicks-ass.net +kicks-ass.org +knowsitall.info +land-4-sale.us +lebtimnetz.de +leitungsen.de +likes-pie.com +likescandy.com +merseine.nu +mine.nu +misconfused.org +mypets.ws +myphotos.cc +neat-url.com +office-on-the.net +on-the-web.tv +podzone.net +podzone.org +readmyblog.org +saves-the-whales.com +scrapper-site.net +scrapping.cc +selfip.biz +selfip.com +selfip.info +selfip.net +selfip.org +sells-for-less.com +sells-for-u.com +sells-it.net +sellsyourhome.org +servebbs.com +servebbs.net +servebbs.org +serveftp.net +serveftp.org +servegame.org +shacknet.nu +simple-url.com +space-to-rent.com +stuff-4-sale.org +stuff-4-sale.us +teaches-yoga.com +thruhere.net +traeumtgerade.de +webhop.biz +webhop.info +webhop.net +webhop.org +worse-than.tv +writesthisblog.com + +// ddnss.de : https://www.ddnss.de/ +// Submitted by Robert Niedziela +ddnss.de +dyn.ddnss.de +dyndns.ddnss.de +dyndns1.de +dyn-ip24.de +home-webserver.de +dyn.home-webserver.de +myhome-server.de +ddnss.org + +// Definima : http://www.definima.com/ +// Submitted by Maxence Bitterli +definima.net +definima.io + +// Dynu.com : https://www.dynu.com/ +// Submitted by Sue Ye +ddnsfree.com +ddnsgeek.com +giize.com +gleeze.com +kozow.com +loseyourip.com +ooguy.com +theworkpc.com +casacam.net +dynu.net +accesscam.org +camdvr.org +freeddns.org +mywire.org +webredirect.org +myddns.rocks +blogsite.xyz + +// dynv6 : https://dynv6.com +// Submitted by Dominik Menke +dynv6.net + +// E4YOU spol. s.r.o. : https://e4you.cz/ +// Submitted by Vladimir Dudr +e4.cz + +// Enalean SAS: https://www.enalean.com +// Submitted by Thomas Cottier +mytuleap.com + +// Enonic : http://enonic.com/ +// Submitted by Erik Kaareng-Sunde +enonic.io +customer.enonic.io + +// EU.org https://eu.org/ +// Submitted by Pierre Beyssac +eu.org +al.eu.org +asso.eu.org +at.eu.org +au.eu.org +be.eu.org +bg.eu.org +ca.eu.org +cd.eu.org +ch.eu.org +cn.eu.org +cy.eu.org +cz.eu.org +de.eu.org +dk.eu.org +edu.eu.org +ee.eu.org +es.eu.org +fi.eu.org +fr.eu.org +gr.eu.org +hr.eu.org +hu.eu.org +ie.eu.org +il.eu.org +in.eu.org +int.eu.org +is.eu.org +it.eu.org +jp.eu.org +kr.eu.org +lt.eu.org +lu.eu.org +lv.eu.org +mc.eu.org +me.eu.org +mk.eu.org +mt.eu.org +my.eu.org +net.eu.org +ng.eu.org +nl.eu.org +no.eu.org +nz.eu.org +paris.eu.org +pl.eu.org +pt.eu.org +q-a.eu.org +ro.eu.org +ru.eu.org +se.eu.org +si.eu.org +sk.eu.org +tr.eu.org +uk.eu.org +us.eu.org + +// Evennode : http://www.evennode.com/ +// Submitted by Michal Kralik +eu-1.evennode.com +eu-2.evennode.com +eu-3.evennode.com +eu-4.evennode.com +us-1.evennode.com +us-2.evennode.com +us-3.evennode.com +us-4.evennode.com + +// eDirect Corp. : https://hosting.url.com.tw/ +// Submitted by C.S. chang +twmail.cc +twmail.net +twmail.org +mymailer.com.tw +url.tw + +// Facebook, Inc. +// Submitted by Peter Ruibal +apps.fbsbx.com + +// FAITID : https://faitid.org/ +// Submitted by Maxim Alzoba +// https://www.flexireg.net/stat_info +ru.net +adygeya.ru +bashkiria.ru +bir.ru +cbg.ru +com.ru +dagestan.ru +grozny.ru +kalmykia.ru +kustanai.ru +marine.ru +mordovia.ru +msk.ru +mytis.ru +nalchik.ru +nov.ru +pyatigorsk.ru +spb.ru +vladikavkaz.ru +vladimir.ru +abkhazia.su +adygeya.su +aktyubinsk.su +arkhangelsk.su +armenia.su +ashgabad.su +azerbaijan.su +balashov.su +bashkiria.su +bryansk.su +bukhara.su +chimkent.su +dagestan.su +east-kazakhstan.su +exnet.su +georgia.su +grozny.su +ivanovo.su +jambyl.su +kalmykia.su +kaluga.su +karacol.su +karaganda.su +karelia.su +khakassia.su +krasnodar.su +kurgan.su +kustanai.su +lenug.su +mangyshlak.su +mordovia.su +msk.su +murmansk.su +nalchik.su +navoi.su +north-kazakhstan.su +nov.su +obninsk.su +penza.su +pokrovsk.su +sochi.su +spb.su +tashkent.su +termez.su +togliatti.su +troitsk.su +tselinograd.su +tula.su +tuva.su +vladikavkaz.su +vladimir.su +vologda.su + +// Fancy Bits, LLC : http://getchannels.com +// Submitted by Aman Gupta +channelsdvr.net + +// Fastly Inc. : http://www.fastly.com/ +// Submitted by Fastly Security +fastlylb.net +map.fastlylb.net +freetls.fastly.net +map.fastly.net +a.prod.fastly.net +global.prod.fastly.net +a.ssl.fastly.net +b.ssl.fastly.net +global.ssl.fastly.net + +// Featherhead : https://featherhead.xyz/ +// Submitted by Simon Menke +fhapp.xyz + +// Fedora : https://fedoraproject.org/ +// submitted by Patrick Uiterwijk +fedorainfracloud.org +fedorapeople.org +cloud.fedoraproject.org +app.os.fedoraproject.org +app.os.stg.fedoraproject.org + +// Filegear Inc. : https://www.filegear.com +// Submitted by Jason Zhu +filegear.me + +// Firebase, Inc. +// Submitted by Chris Raynor +firebaseapp.com + +// Flynn : https://flynn.io +// Submitted by Jonathan Rudenberg +flynnhub.com +flynnhosting.net + +// Freebox : http://www.freebox.fr +// Submitted by Romain Fliedel +freebox-os.com +freeboxos.com +fbx-os.fr +fbxos.fr +freebox-os.fr +freeboxos.fr + +// Futureweb OG : http://www.futureweb.at +// Submitted by Andreas Schnederle-Wagner +*.futurecms.at +futurehosting.at +futuremailing.at +*.ex.ortsinfo.at +*.kunden.ortsinfo.at +*.statics.cloud + +// GDS : https://www.gov.uk/service-manual/operations/operating-servicegovuk-subdomains +// Submitted by David Illsley +service.gov.uk + +// GitHub, Inc. +// Submitted by Patrick Toomey +github.io +githubusercontent.com + +// GitLab, Inc. +// Submitted by Alex Hanselka +gitlab.io + +// UKHomeOffice : https://www.gov.uk/government/organisations/home-office +// Submitted by Jon Shanks +homeoffice.gov.uk + +// GlobeHosting, Inc. +// Submitted by Zoltan Egresi +ro.im +shop.ro + +// GoIP DNS Services : http://www.goip.de +// Submitted by Christian Poulter +goip.de + +// Google, Inc. +// Submitted by Eduardo Vela +*.0emm.com +appspot.com +blogspot.ae +blogspot.al +blogspot.am +blogspot.ba +blogspot.be +blogspot.bg +blogspot.bj +blogspot.ca +blogspot.cf +blogspot.ch +blogspot.cl +blogspot.co.at +blogspot.co.id +blogspot.co.il +blogspot.co.ke +blogspot.co.nz +blogspot.co.uk +blogspot.co.za +blogspot.com +blogspot.com.ar +blogspot.com.au +blogspot.com.br +blogspot.com.by +blogspot.com.co +blogspot.com.cy +blogspot.com.ee +blogspot.com.eg +blogspot.com.es +blogspot.com.mt +blogspot.com.ng +blogspot.com.tr +blogspot.com.uy +blogspot.cv +blogspot.cz +blogspot.de +blogspot.dk +blogspot.fi +blogspot.fr +blogspot.gr +blogspot.hk +blogspot.hr +blogspot.hu +blogspot.ie +blogspot.in +blogspot.is +blogspot.it +blogspot.jp +blogspot.kr +blogspot.li +blogspot.lt +blogspot.lu +blogspot.md +blogspot.mk +blogspot.mr +blogspot.mx +blogspot.my +blogspot.nl +blogspot.no +blogspot.pe +blogspot.pt +blogspot.qa +blogspot.re +blogspot.ro +blogspot.rs +blogspot.ru +blogspot.se +blogspot.sg +blogspot.si +blogspot.sk +blogspot.sn +blogspot.td +blogspot.tw +blogspot.ug +blogspot.vn +cloudfunctions.net +cloud.goog +codespot.com +googleapis.com +googlecode.com +pagespeedmobilizer.com +publishproxy.com +withgoogle.com +withyoutube.com + +// Hashbang : https://hashbang.sh +hashbang.sh + +// Hasura : https://hasura.io +// Submitted by Shahidh K Muhammed +hasura-app.io + +// Hepforge : https://www.hepforge.org +// Submitted by David Grellscheid +hepforge.org + +// Heroku : https://www.heroku.com/ +// Submitted by Tom Maher +herokuapp.com +herokussl.com + +// Ici la Lune : http://www.icilalune.com/ +// Submitted by Simon Morvan +moonscale.net + +// iki.fi +// Submitted by Hannu Aronsson +iki.fi + +// info.at : http://www.info.at/ +biz.at +info.at + +// info.cx : http://info.cx +// Submitted by Jacob Slater +info.cx + +// Interlegis : http://www.interlegis.leg.br +// Submitted by Gabriel Ferreira +ac.leg.br +al.leg.br +am.leg.br +ap.leg.br +ba.leg.br +ce.leg.br +df.leg.br +es.leg.br +go.leg.br +ma.leg.br +mg.leg.br +ms.leg.br +mt.leg.br +pa.leg.br +pb.leg.br +pe.leg.br +pi.leg.br +pr.leg.br +rj.leg.br +rn.leg.br +ro.leg.br +rr.leg.br +rs.leg.br +sc.leg.br +se.leg.br +sp.leg.br +to.leg.br + +// intermetrics GmbH : https://pixolino.com/ +// Submitted by Wolfgang Schwarz +pixolino.com + +// IPiFony Systems, Inc. : https://www.ipifony.com/ +// Submitted by Matthew Hardeman +ipifony.net + +// Joyent : https://www.joyent.com/ +// Submitted by Brian Bennett +*.triton.zone +*.cns.joyent.com + +// JS.ORG : http://dns.js.org +// Submitted by Stefan Keim +js.org + +// Keyweb AG : https://www.keyweb.de +// Submitted by Martin Dannehl +keymachine.de + +// KnightPoint Systems, LLC : http://www.knightpoint.com/ +// Submitted by Roy Keene +knightpoint.systems + +// .KRD : http://nic.krd/data/krd/Registration%20Policy.pdf +co.krd +edu.krd + +// LCube - Professional hosting e.K. : https://www.lcube-webhosting.de +// Submitted by Lars Laehn +git-repos.de +lcube-server.de +svn-repos.de + +// LiquidNet Ltd : http://www.liquidnetlimited.com/ +// Submitted by Victor Velchev +we.bs + +// Lukanet Ltd : https://lukanet.com +// Submitted by Anton Avramov +barsy.bg +barsyonline.com +barsy.de +barsy.eu +barsy.in +barsy.net +barsy.online +barsy.support + +// Magento Commerce +// Submitted by Damien Tournoud +*.magentosite.cloud + +// Mail.Ru Group : https://hb.cldmail.ru +// Submitted by Ilya Zaretskiy +hb.cldmail.ru + +// MetaCentrum, CESNET z.s.p.o. : https://www.metacentrum.cz/en/ +// Submitted by Zdeněk Šustr +cloud.metacentrum.cz +custom.metacentrum.cz + +// Meteor Development Group : https://www.meteor.com/hosting +// Submitted by Pierre Carrier +meteorapp.com +eu.meteorapp.com + +// Michau Enterprises Limited : http://www.co.pl/ +co.pl + +// Microsoft : http://microsoft.com +// Submitted by Barry Dorrans +azurewebsites.net +azure-mobile.net +cloudapp.net + +// Mozilla Foundation : https://mozilla.org/ +// Submitted by glob +bmoattachments.org + +// MSK-IX : https://www.msk-ix.ru/ +// Submitted by Khannanov Roman +net.ru +org.ru +pp.ru + +// Netlify : https://www.netlify.com +// Submitted by Jessica Parsons +bitballoon.com +netlify.com + +// Neustar Inc. +// Submitted by Trung Tran +4u.com + +// ngrok : https://ngrok.com/ +// Submitted by Alan Shreve +ngrok.io + +// Nimbus Hosting Ltd. : https://www.nimbushosting.co.uk/ +// Submitted by Nicholas Ford +nh-serv.co.uk + +// NFSN, Inc. : https://www.NearlyFreeSpeech.NET/ +// Submitted by Jeff Wheelhouse +nfshost.com + +// nsupdate.info : https://www.nsupdate.info/ +// Submitted by Thomas Waldmann +nsupdate.info +nerdpol.ovh + +// No-IP.com : https://noip.com/ +// Submitted by Deven Reza +blogsyte.com +brasilia.me +cable-modem.org +ciscofreak.com +collegefan.org +couchpotatofries.org +damnserver.com +ddns.me +ditchyourip.com +dnsfor.me +dnsiskinky.com +dvrcam.info +dynns.com +eating-organic.net +fantasyleague.cc +geekgalaxy.com +golffan.us +health-carereform.com +homesecuritymac.com +homesecuritypc.com +hopto.me +ilovecollege.info +loginto.me +mlbfan.org +mmafan.biz +myactivedirectory.com +mydissent.net +myeffect.net +mymediapc.net +mypsx.net +mysecuritycamera.com +mysecuritycamera.net +mysecuritycamera.org +net-freaks.com +nflfan.org +nhlfan.net +no-ip.ca +no-ip.co.uk +no-ip.net +noip.us +onthewifi.com +pgafan.net +point2this.com +pointto.us +privatizehealthinsurance.net +quicksytes.com +read-books.org +securitytactics.com +serveexchange.com +servehumour.com +servep2p.com +servesarcasm.com +stufftoread.com +ufcfan.org +unusualperson.com +workisboring.com +3utilities.com +bounceme.net +ddns.net +ddnsking.com +gotdns.ch +hopto.org +myftp.biz +myftp.org +myvnc.com +no-ip.biz +no-ip.info +no-ip.org +noip.me +redirectme.net +servebeer.com +serveblog.net +servecounterstrike.com +serveftp.com +servegame.com +servehalflife.com +servehttp.com +serveirc.com +serveminecraft.net +servemp3.com +servepics.com +servequake.com +sytes.net +webhop.me +zapto.org + +// NodeArt : https://nodeart.io +// Submitted by Konstantin Nosov +stage.nodeart.io + +// Nodum B.V. : https://nodum.io/ +// Submitted by Wietse Wind +nodum.co +nodum.io + +// NYC.mn : http://www.information.nyc.mn +// Submitted by Matthew Brown +nyc.mn + +// NymNom : https://nymnom.com/ +// Submitted by Dave McCormack +nom.ae +nom.ai +nom.al +nym.by +nym.bz +nom.cl +nom.gd +nom.gl +nym.gr +nom.gt +nom.hn +nom.im +nym.kz +nym.la +nom.li +nym.li +nym.lt +nym.lu +nym.me +nom.mk +nym.mx +nom.nu +nym.nz +nym.pe +nym.pt +nom.pw +nom.qa +nom.rs +nom.si +nym.sk +nym.su +nym.sx +nym.tw +nom.ug +nom.uy +nom.vc +nom.vg + +// Octopodal Solutions, LLC. : https://ulterius.io/ +// Submitted by Andrew Sampson +cya.gg + +// One Fold Media : http://www.onefoldmedia.com/ +// Submitted by Eddie Jones +nid.io + +// OpenCraft GmbH : http://opencraft.com/ +// Submitted by Sven Marnach +opencraft.hosting + +// Opera Software, A.S.A. +// Submitted by Yngve Pettersen +operaunite.com + +// OutSystems +// Submitted by Duarte Santos +outsystemscloud.com + +// OwnProvider : http://www.ownprovider.com +// Submitted by Jan Moennich +ownprovider.com + +// oy.lc +// Submitted by Charly Coste +oy.lc + +// Pagefog : https://pagefog.com/ +// Submitted by Derek Myers +pgfog.com + +// Pagefront : https://www.pagefronthq.com/ +// Submitted by Jason Kriss +pagefrontapp.com + +// .pl domains (grandfathered) +art.pl +gliwice.pl +krakow.pl +poznan.pl +wroc.pl +zakopane.pl + +// Pantheon Systems, Inc. : https://pantheon.io/ +// Submitted by Gary Dylina +pantheonsite.io +gotpantheon.com + +// Peplink | Pepwave : http://peplink.com/ +// Submitted by Steve Leung +mypep.link + +// Planet-Work : https://www.planet-work.com/ +// Submitted by Frédéric VANNIÈRE +on-web.fr + +// Platform.sh : https://platform.sh +// Submitted by Nikola Kotur +*.platform.sh +*.platformsh.site + +// prgmr.com : https://prgmr.com/ +// Submitted by Sarah Newman +xen.prgmr.com + +// priv.at : http://www.nic.priv.at/ +// Submitted by registry +priv.at + +// Protonet GmbH : http://protonet.io +// Submitted by Martin Meier +protonet.io + +// Publication Presse Communication SARL : https://ppcom.fr +// Submitted by Yaacov Akiba Slama +chirurgiens-dentistes-en-france.fr +byen.site + +// QA2 +// Submitted by Daniel Dent (https://www.danieldent.com/) +qa2.com + +// QNAP System Inc : https://www.qnap.com +// Submitted by Nick Chang +dev-myqnapcloud.com +alpha-myqnapcloud.com +myqnapcloud.com + +// Quip : https://quip.com +// Submitted by Patrick Linehan +*.quipelements.com + +// Qutheory LLC : http://qutheory.io +// Submitted by Jonas Schwartz +vapor.cloud +vaporcloud.io + +// Rackmaze LLC : https://www.rackmaze.com +// Submitted by Kirill Pertsev +rackmaze.com +rackmaze.net + +// Red Hat, Inc. OpenShift : https://openshift.redhat.com/ +// Submitted by Tim Kramer +rhcloud.com + +// Resin.io : https://resin.io +// Submitted by Tim Perry +resindevice.io +devices.resinstaging.io + +// RethinkDB : https://www.rethinkdb.com/ +// Submitted by Chris Kastorff +hzc.io + +// Revitalised Limited : http://www.revitalised.co.uk +// Submitted by Jack Price +wellbeingzone.eu +ptplus.fit +wellbeingzone.co.uk + +// Sandstorm Development Group, Inc. : https://sandcats.io/ +// Submitted by Asheesh Laroia +sandcats.io + +// SBE network solutions GmbH : https://www.sbe.de/ +// Submitted by Norman Meilick +logoip.de +logoip.com + +// Scry Security : http://www.scrysec.com +// Submitted by Shante Adam +scrysec.com + +// Securepoint GmbH : https://www.securepoint.de +// Submitted by Erik Anders +firewall-gateway.com +firewall-gateway.de +my-gateway.de +my-router.de +spdns.de +spdns.eu +firewall-gateway.net +my-firewall.org +myfirewall.org +spdns.org + +// SensioLabs, SAS : https://sensiolabs.com/ +// Submitted by Fabien Potencier +*.s5y.io +*.sensiosite.cloud + +// Service Online LLC : http://drs.ua/ +// Submitted by Serhii Bulakh +biz.ua +co.ua +pp.ua + +// ShiftEdit : https://shiftedit.net/ +// Submitted by Adam Jimenez +shiftedit.io + +// Shopblocks : http://www.shopblocks.com/ +// Submitted by Alex Bowers +myshopblocks.com + +// SinaAppEngine : http://sae.sina.com.cn/ +// Submitted by SinaAppEngine +1kapp.com +appchizi.com +applinzi.com +sinaapp.com +vipsinaapp.com + +// Skyhat : http://www.skyhat.io +// Submitted by Shante Adam +bounty-full.com +alpha.bounty-full.com +beta.bounty-full.com + +// staticland : https://static.land +// Submitted by Seth Vincent +static.land +dev.static.land +sites.static.land + +// SourceLair PC : https://www.sourcelair.com +// Submitted by Antonis Kalipetis +apps.lair.io +*.stolos.io + +// SpaceKit : https://www.spacekit.io/ +// Submitted by Reza Akhavan +spacekit.io + +// Stackspace : https://www.stackspace.io/ +// Submitted by Lina He +stackspace.space + +// Storj Labs Inc. : https://storj.io/ +// Submitted by Philip Hutchins +storj.farm + +// Sub 6 Limited: http://www.sub6.com +// Submitted by Dan Miller +temp-dns.com + +// Synology, Inc. : https://www.synology.com/ +// Submitted by Rony Weng +diskstation.me +dscloud.biz +dscloud.me +dscloud.mobi +dsmynas.com +dsmynas.net +dsmynas.org +familyds.com +familyds.net +familyds.org +i234.me +myds.me +synology.me +vpnplus.to + +// TAIFUN Software AG : http://taifun-software.de +// Submitted by Bjoern Henke +taifun-dns.de + +// TASK geographical domains (www.task.gda.pl/uslugi/dns) +gda.pl +gdansk.pl +gdynia.pl +med.pl +sopot.pl + +// Thingdust AG : https://thingdust.com/ +// Submitted by Adrian Imboden +cust.dev.thingdust.io +cust.disrec.thingdust.io +cust.prod.thingdust.io +cust.testing.thingdust.io + +// TownNews.com : http://www.townnews.com +// Submitted by Dustin Ward +bloxcms.com +townnews-staging.com + +// TrafficPlex GmbH : https://www.trafficplex.de/ +// Submitted by Phillipp Röll +12hp.at +2ix.at +4lima.at +lima-city.at +12hp.ch +2ix.ch +4lima.ch +lima-city.ch +trafficplex.cloud +de.cool +12hp.de +2ix.de +4lima.de +lima-city.de +1337.pictures +clan.rip +lima-city.rocks +webspace.rocks +lima.zone + +// TransIP : htts://www.transip.nl +// Submitted by Rory Breuk +*.transurl.be +*.transurl.eu +*.transurl.nl + +// TuxFamily : http://tuxfamily.org +// Submitted by TuxFamily administrators +tuxfamily.org + +// TwoDNS : https://www.twodns.de/ +// Submitted by TwoDNS-Support +dd-dns.de +diskstation.eu +diskstation.org +dray-dns.de +draydns.de +dyn-vpn.de +dynvpn.de +mein-vigor.de +my-vigor.de +my-wan.de +syno-ds.de +synology-diskstation.de +synology-ds.de + +// Uberspace : https://uberspace.de +// Submitted by Moritz Werner +uber.space + +// UDR Limited : http://www.udr.hk.com +// Submitted by registry +hk.com +hk.org +ltd.hk +inc.hk + +// .US +// Submitted by Ed Moore +lib.de.us + +// Viprinet Europe GmbH : http://www.viprinet.com +// Submitted by Simon Kissel +router.management + +// Virtual-Info : https://www.virtual-info.info/ +// Submitted by Adnan RIHAN +v-info.info + +// WeDeploy by Liferay, Inc. : https://www.wedeploy.com +// Submitted by Henrique Vicente +wedeploy.io +wedeploy.me +wedeploy.sh + +// Western Digital Technologies, Inc : https://www.wdc.com +// Submitted by Jung Jin +remotewd.com + +// Wikimedia Labs : https://wikitech.wikimedia.org +// Submitted by Yuvi Panda +wmflabs.org + +// XS4ALL Internet bv : https://www.xs4all.nl/ +// Submitted by Daniel Mostertman +cistron.nl +demon.nl +xs4all.space + +// Yola : https://www.yola.com/ +// Submitted by Stefano Rivera +yolasite.com + +// Yombo : https://yombo.net +// Submitted by Mitch Schwenk +ybo.faith +yombo.me +homelink.one +ybo.party +ybo.review +ybo.science +ybo.trade + +// ZaNiC : http://www.za.net/ +// Submitted by registry +za.net +za.org + +// Zeit, Inc. : https://zeit.domains/ +// Submitted by Olli Vanhoja +now.sh + +// ===END PRIVATE DOMAINS=== diff --git a/depcomp b/depcomp new file mode 100755 index 0000000..b39f98f --- /dev/null +++ b/depcomp @@ -0,0 +1,791 @@ +#! /bin/sh +# depcomp - compile a program generating dependencies as side-effects + +scriptversion=2016-01-11.22; # UTC + +# Copyright (C) 1999-2017 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, 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. + +# Originally written by Alexandre Oliva . + +case $1 in + '') + echo "$0: No command. Try '$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: depcomp [--help] [--version] PROGRAM [ARGS] + +Run PROGRAMS ARGS to compile a file, generating dependencies +as side-effects. + +Environment variables: + depmode Dependency tracking mode. + source Source file read by 'PROGRAMS ARGS'. + object Object file output by 'PROGRAMS ARGS'. + DEPDIR directory where to store dependencies. + depfile Dependency file to output. + tmpdepfile Temporary file to use when outputting dependencies. + libtool Whether libtool is used (yes/no). + +Report bugs to . +EOF + exit $? + ;; + -v | --v*) + echo "depcomp $scriptversion" + exit $? + ;; +esac + +# Get the directory component of the given path, and save it in the +# global variables '$dir'. Note that this directory component will +# be either empty or ending with a '/' character. This is deliberate. +set_dir_from () +{ + case $1 in + */*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;; + *) dir=;; + esac +} + +# Get the suffix-stripped basename of the given path, and save it the +# global variable '$base'. +set_base_from () +{ + base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'` +} + +# If no dependency file was actually created by the compiler invocation, +# we still have to create a dummy depfile, to avoid errors with the +# Makefile "include basename.Plo" scheme. +make_dummy_depfile () +{ + echo "#dummy" > "$depfile" +} + +# Factor out some common post-processing of the generated depfile. +# Requires the auxiliary global variable '$tmpdepfile' to be set. +aix_post_process_depfile () +{ + # If the compiler actually managed to produce a dependency file, + # post-process it. + if test -f "$tmpdepfile"; then + # Each line is of the form 'foo.o: dependency.h'. + # Do two passes, one to just change these to + # $object: dependency.h + # and one to simply output + # dependency.h: + # which is needed to avoid the deleted-header problem. + { sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile" + sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile" + } > "$depfile" + rm -f "$tmpdepfile" + else + make_dummy_depfile + fi +} + +# A tabulation character. +tab=' ' +# A newline character. +nl=' +' +# Character ranges might be problematic outside the C locale. +# These definitions help. +upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ +lower=abcdefghijklmnopqrstuvwxyz +digits=0123456789 +alpha=${upper}${lower} + +if test -z "$depmode" || test -z "$source" || test -z "$object"; then + echo "depcomp: Variables source, object and depmode must be set" 1>&2 + exit 1 +fi + +# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. +depfile=${depfile-`echo "$object" | + sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} +tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} + +rm -f "$tmpdepfile" + +# Avoid interferences from the environment. +gccflag= dashmflag= + +# Some modes work just like other modes, but use different flags. We +# parameterize here, but still list the modes in the big case below, +# to make depend.m4 easier to write. Note that we *cannot* use a case +# here, because this file can only contain one case statement. +if test "$depmode" = hp; then + # HP compiler uses -M and no extra arg. + gccflag=-M + depmode=gcc +fi + +if test "$depmode" = dashXmstdout; then + # This is just like dashmstdout with a different argument. + dashmflag=-xM + depmode=dashmstdout +fi + +cygpath_u="cygpath -u -f -" +if test "$depmode" = msvcmsys; then + # This is just like msvisualcpp but w/o cygpath translation. + # Just convert the backslash-escaped backslashes to single forward + # slashes to satisfy depend.m4 + cygpath_u='sed s,\\\\,/,g' + depmode=msvisualcpp +fi + +if test "$depmode" = msvc7msys; then + # This is just like msvc7 but w/o cygpath translation. + # Just convert the backslash-escaped backslashes to single forward + # slashes to satisfy depend.m4 + cygpath_u='sed s,\\\\,/,g' + depmode=msvc7 +fi + +if test "$depmode" = xlc; then + # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information. + gccflag=-qmakedep=gcc,-MF + depmode=gcc +fi + +case "$depmode" in +gcc3) +## gcc 3 implements dependency tracking that does exactly what +## we want. Yay! Note: for some reason libtool 1.4 doesn't like +## it if -MD -MP comes after the -MF stuff. Hmm. +## Unfortunately, FreeBSD c89 acceptance of flags depends upon +## the command line argument order; so add the flags where they +## appear in depend2.am. Note that the slowdown incurred here +## affects only configure: in makefiles, %FASTDEP% shortcuts this. + for arg + do + case $arg in + -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; + *) set fnord "$@" "$arg" ;; + esac + shift # fnord + shift # $arg + done + "$@" + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + mv "$tmpdepfile" "$depfile" + ;; + +gcc) +## Note that this doesn't just cater to obsosete pre-3.x GCC compilers. +## but also to in-use compilers like IMB xlc/xlC and the HP C compiler. +## (see the conditional assignment to $gccflag above). +## There are various ways to get dependency output from gcc. Here's +## why we pick this rather obscure method: +## - Don't want to use -MD because we'd like the dependencies to end +## up in a subdir. Having to rename by hand is ugly. +## (We might end up doing this anyway to support other compilers.) +## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like +## -MM, not -M (despite what the docs say). Also, it might not be +## supported by the other compilers which use the 'gcc' depmode. +## - Using -M directly means running the compiler twice (even worse +## than renaming). + if test -z "$gccflag"; then + gccflag=-MD, + fi + "$@" -Wp,"$gccflag$tmpdepfile" + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + # The second -e expression handles DOS-style file names with drive + # letters. + sed -e 's/^[^:]*: / /' \ + -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" +## This next piece of magic avoids the "deleted header file" problem. +## The problem is that when a header file which appears in a .P file +## is deleted, the dependency causes make to die (because there is +## typically no way to rebuild the header). We avoid this by adding +## dummy dependencies for each header file. Too bad gcc doesn't do +## this for us directly. +## Some versions of gcc put a space before the ':'. On the theory +## that the space means something, we add a space to the output as +## well. hp depmode also adds that space, but also prefixes the VPATH +## to the object. Take care to not repeat it in the output. +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \ + | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +sgi) + if test "$libtool" = yes; then + "$@" "-Wp,-MDupdate,$tmpdepfile" + else + "$@" -MDupdate "$tmpdepfile" + fi + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + + if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files + echo "$object : \\" > "$depfile" + # Clip off the initial element (the dependent). Don't try to be + # clever and replace this with sed code, as IRIX sed won't handle + # lines with more than a fixed number of characters (4096 in + # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; + # the IRIX cc adds comments like '#:fec' to the end of the + # dependency line. + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \ + | tr "$nl" ' ' >> "$depfile" + echo >> "$depfile" + # The second pass generates a dummy entry for each header file. + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ + >> "$depfile" + else + make_dummy_depfile + fi + rm -f "$tmpdepfile" + ;; + +xlc) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +aix) + # The C for AIX Compiler uses -M and outputs the dependencies + # in a .u file. In older versions, this file always lives in the + # current directory. Also, the AIX compiler puts '$object:' at the + # start of each line; $object doesn't have directory information. + # Version 6 uses the directory in both cases. + set_dir_from "$object" + set_base_from "$object" + if test "$libtool" = yes; then + tmpdepfile1=$dir$base.u + tmpdepfile2=$base.u + tmpdepfile3=$dir.libs/$base.u + "$@" -Wc,-M + else + tmpdepfile1=$dir$base.u + tmpdepfile2=$dir$base.u + tmpdepfile3=$dir$base.u + "$@" -M + fi + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + do + test -f "$tmpdepfile" && break + done + aix_post_process_depfile + ;; + +tcc) + # tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26 + # FIXME: That version still under development at the moment of writing. + # Make that this statement remains true also for stable, released + # versions. + # It will wrap lines (doesn't matter whether long or short) with a + # trailing '\', as in: + # + # foo.o : \ + # foo.c \ + # foo.h \ + # + # It will put a trailing '\' even on the last line, and will use leading + # spaces rather than leading tabs (at least since its commit 0394caf7 + # "Emit spaces for -MD"). + "$@" -MD -MF "$tmpdepfile" + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + # Each non-empty line is of the form 'foo.o : \' or ' dep.h \'. + # We have to change lines of the first kind to '$object: \'. + sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile" + # And for each line of the second kind, we have to emit a 'dep.h:' + # dummy dependency, to avoid the deleted-header problem. + sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile" + rm -f "$tmpdepfile" + ;; + +## The order of this option in the case statement is important, since the +## shell code in configure will try each of these formats in the order +## listed in this file. A plain '-MD' option would be understood by many +## compilers, so we must ensure this comes after the gcc and icc options. +pgcc) + # Portland's C compiler understands '-MD'. + # Will always output deps to 'file.d' where file is the root name of the + # source file under compilation, even if file resides in a subdirectory. + # The object file name does not affect the name of the '.d' file. + # pgcc 10.2 will output + # foo.o: sub/foo.c sub/foo.h + # and will wrap long lines using '\' : + # foo.o: sub/foo.c ... \ + # sub/foo.h ... \ + # ... + set_dir_from "$object" + # Use the source, not the object, to determine the base name, since + # that's sadly what pgcc will do too. + set_base_from "$source" + tmpdepfile=$base.d + + # For projects that build the same source file twice into different object + # files, the pgcc approach of using the *source* file root name can cause + # problems in parallel builds. Use a locking strategy to avoid stomping on + # the same $tmpdepfile. + lockdir=$base.d-lock + trap " + echo '$0: caught signal, cleaning up...' >&2 + rmdir '$lockdir' + exit 1 + " 1 2 13 15 + numtries=100 + i=$numtries + while test $i -gt 0; do + # mkdir is a portable test-and-set. + if mkdir "$lockdir" 2>/dev/null; then + # This process acquired the lock. + "$@" -MD + stat=$? + # Release the lock. + rmdir "$lockdir" + break + else + # If the lock is being held by a different process, wait + # until the winning process is done or we timeout. + while test -d "$lockdir" && test $i -gt 0; do + sleep 1 + i=`expr $i - 1` + done + fi + i=`expr $i - 1` + done + trap - 1 2 13 15 + if test $i -le 0; then + echo "$0: failed to acquire lock after $numtries attempts" >&2 + echo "$0: check lockdir '$lockdir'" >&2 + exit 1 + fi + + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + # Each line is of the form `foo.o: dependent.h', + # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process this invocation + # correctly. Breaking it into two sed invocations is a workaround. + sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \ + | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp2) + # The "hp" stanza above does not work with aCC (C++) and HP's ia64 + # compilers, which have integrated preprocessors. The correct option + # to use with these is +Maked; it writes dependencies to a file named + # 'foo.d', which lands next to the object file, wherever that + # happens to be. + # Much of this is similar to the tru64 case; see comments there. + set_dir_from "$object" + set_base_from "$object" + if test "$libtool" = yes; then + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir.libs/$base.d + "$@" -Wc,+Maked + else + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir$base.d + "$@" +Maked + fi + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile1" "$tmpdepfile2" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" + do + test -f "$tmpdepfile" && break + done + if test -f "$tmpdepfile"; then + sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile" + # Add 'dependent.h:' lines. + sed -ne '2,${ + s/^ *// + s/ \\*$// + s/$/:/ + p + }' "$tmpdepfile" >> "$depfile" + else + make_dummy_depfile + fi + rm -f "$tmpdepfile" "$tmpdepfile2" + ;; + +tru64) + # The Tru64 compiler uses -MD to generate dependencies as a side + # effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'. + # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put + # dependencies in 'foo.d' instead, so we check for that too. + # Subdirectories are respected. + set_dir_from "$object" + set_base_from "$object" + + if test "$libtool" = yes; then + # Libtool generates 2 separate objects for the 2 libraries. These + # two compilations output dependencies in $dir.libs/$base.o.d and + # in $dir$base.o.d. We have to check for both files, because + # one of the two compilations can be disabled. We should prefer + # $dir$base.o.d over $dir.libs/$base.o.d because the latter is + # automatically cleaned when .libs/ is deleted, while ignoring + # the former would cause a distcleancheck panic. + tmpdepfile1=$dir$base.o.d # libtool 1.5 + tmpdepfile2=$dir.libs/$base.o.d # Likewise. + tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504 + "$@" -Wc,-MD + else + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir$base.d + tmpdepfile3=$dir$base.d + "$@" -MD + fi + + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + do + test -f "$tmpdepfile" && break + done + # Same post-processing that is required for AIX mode. + aix_post_process_depfile + ;; + +msvc7) + if test "$libtool" = yes; then + showIncludes=-Wc,-showIncludes + else + showIncludes=-showIncludes + fi + "$@" $showIncludes > "$tmpdepfile" + stat=$? + grep -v '^Note: including file: ' "$tmpdepfile" + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + # The first sed program below extracts the file names and escapes + # backslashes for cygpath. The second sed program outputs the file + # name when reading, but also accumulates all include files in the + # hold buffer in order to output them again at the end. This only + # works with sed implementations that can handle large buffers. + sed < "$tmpdepfile" -n ' +/^Note: including file: *\(.*\)/ { + s//\1/ + s/\\/\\\\/g + p +}' | $cygpath_u | sort -u | sed -n ' +s/ /\\ /g +s/\(.*\)/'"$tab"'\1 \\/p +s/.\(.*\) \\/\1:/ +H +$ { + s/.*/'"$tab"'/ + G + p +}' >> "$depfile" + echo >> "$depfile" # make sure the fragment doesn't end with a backslash + rm -f "$tmpdepfile" + ;; + +msvc7msys) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +#nosideeffect) + # This comment above is used by automake to tell side-effect + # dependency tracking mechanisms from slower ones. + +dashmstdout) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout, regardless of -o. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + # Remove '-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + test -z "$dashmflag" && dashmflag=-M + # Require at least two characters before searching for ':' + # in the target name. This is to cope with DOS-style filenames: + # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise. + "$@" $dashmflag | + sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile" + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process this sed invocation + # correctly. Breaking it into two sed invocations is a workaround. + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ + | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +dashXmstdout) + # This case only exists to satisfy depend.m4. It is never actually + # run, as this mode is specially recognized in the preamble. + exit 1 + ;; + +makedepend) + "$@" || exit $? + # Remove any Libtool call + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + # X makedepend + shift + cleared=no eat=no + for arg + do + case $cleared in + no) + set ""; shift + cleared=yes ;; + esac + if test $eat = yes; then + eat=no + continue + fi + case "$arg" in + -D*|-I*) + set fnord "$@" "$arg"; shift ;; + # Strip any option that makedepend may not understand. Remove + # the object too, otherwise makedepend will parse it as a source file. + -arch) + eat=yes ;; + -*|$object) + ;; + *) + set fnord "$@" "$arg"; shift ;; + esac + done + obj_suffix=`echo "$object" | sed 's/^.*\././'` + touch "$tmpdepfile" + ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" + rm -f "$depfile" + # makedepend may prepend the VPATH from the source file name to the object. + # No need to regex-escape $object, excess matching of '.' is harmless. + sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process the last invocation + # correctly. Breaking it into two sed invocations is a workaround. + sed '1,2d' "$tmpdepfile" \ + | tr ' ' "$nl" \ + | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ + | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" "$tmpdepfile".bak + ;; + +cpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + # Remove '-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + "$@" -E \ + | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ + -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ + | sed '$ s: \\$::' > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + cat < "$tmpdepfile" >> "$depfile" + sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvisualcpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + IFS=" " + for arg + do + case "$arg" in + -o) + shift + ;; + $object) + shift + ;; + "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") + set fnord "$@" + shift + shift + ;; + *) + set fnord "$@" "$arg" + shift + shift + ;; + esac + done + "$@" -E 2>/dev/null | + sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile" + echo "$tab" >> "$depfile" + sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvcmsys) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +none) + exec "$@" + ;; + +*) + echo "Unknown depmode $depmode" 1>&2 + exit 1 + ;; +esac + +exit 0 + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC0" +# time-stamp-end: "; # UTC" +# End: diff --git a/docs/Makefile.am b/docs/Makefile.am new file mode 100644 index 0000000..f3ddc22 --- /dev/null +++ b/docs/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = reference diff --git a/docs/Makefile.in b/docs/Makefile.in new file mode 100644 index 0000000..67e6a6c --- /dev/null +++ b/docs/Makefile.in @@ -0,0 +1,703 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = docs +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_code_coverage.m4 \ + $(top_srcdir)/m4/glibtests.m4 $(top_srcdir)/m4/gtk-doc.m4 \ + $(top_srcdir)/m4/intltool.m4 $(top_srcdir)/m4/introspection.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/vapigen.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + distdir +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +ALL_LINGUAS = @ALL_LINGUAS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +APACHE_HTTPD = @APACHE_HTTPD@ +APACHE_MODULE_DIR = @APACHE_MODULE_DIR@ +APACHE_PHP_MODULE_DIR = @APACHE_PHP_MODULE_DIR@ +APACHE_SSL_MODULE_DIR = @APACHE_SSL_MODULE_DIR@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CODE_COVERAGE_CFLAGS = @CODE_COVERAGE_CFLAGS@ +CODE_COVERAGE_CPPFLAGS = @CODE_COVERAGE_CPPFLAGS@ +CODE_COVERAGE_CXXFLAGS = @CODE_COVERAGE_CXXFLAGS@ +CODE_COVERAGE_ENABLED = @CODE_COVERAGE_ENABLED@ +CODE_COVERAGE_LDFLAGS = @CODE_COVERAGE_LDFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CURL = @CURL@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GCOV = @GCOV@ +GENHTML = @GENHTML@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_COMPILE_RESOURCES = @GLIB_COMPILE_RESOURCES@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MAKEFILE = @GLIB_MAKEFILE@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GMSGFMT = @GMSGFMT@ +GOBJECT_QUERY = @GOBJECT_QUERY@ +GREP = @GREP@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +HAVE_GNOME = @HAVE_GNOME@ +HTML_DIR = @HTML_DIR@ +IF_HAVE_MOD_UNIXD = @IF_HAVE_MOD_UNIXD@ +IF_HAVE_PHP = @IF_HAVE_PHP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ +INTLTOOL_MERGE = @INTLTOOL_MERGE@ +INTLTOOL_PERL = @INTLTOOL_PERL@ +INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ +INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@ +INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@ +INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@ +INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LCOV = @LCOV@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PHP = @PHP@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOUP_AGE = @SOUP_AGE@ +SOUP_API_VERSION = @SOUP_API_VERSION@ +SOUP_CURRENT = @SOUP_CURRENT@ +SOUP_DEBUG_FLAGS = @SOUP_DEBUG_FLAGS@ +SOUP_HIDDEN_VISIBILITY_CFLAGS = @SOUP_HIDDEN_VISIBILITY_CFLAGS@ +SOUP_MAJOR_VERSION = @SOUP_MAJOR_VERSION@ +SOUP_MICRO_VERSION = @SOUP_MICRO_VERSION@ +SOUP_MINOR_VERSION = @SOUP_MINOR_VERSION@ +SOUP_REVISION = @SOUP_REVISION@ +SQLITE_CFLAGS = @SQLITE_CFLAGS@ +SQLITE_LIBS = @SQLITE_LIBS@ +STRIP = @STRIP@ +USE_NLS = @USE_NLS@ +VALAC = @VALAC@ +VAPIDIR = @VAPIDIR@ +VAPIGEN = @VAPIGEN@ +VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@ +VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@ +VERSION = @VERSION@ +XGETTEXT = @XGETTEXT@ +XML_CFLAGS = @XML_CFLAGS@ +XML_LIBS = @XML_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +installed_test_metadir = @installed_test_metadir@ +installed_testdir = @installed_testdir@ +intltool__v_merge_options_ = @intltool__v_merge_options_@ +intltool__v_merge_options_0 = @intltool__v_merge_options_0@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +ntlm_auth = @ntlm_auth@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = reference +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign docs/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign docs/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(am__recursive_targets) install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ + check-am clean clean-generic clean-libtool cscopelist-am ctags \ + ctags-am distclean distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ + ps ps-am tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/docs/reference/Makefile.am b/docs/reference/Makefile.am new file mode 100644 index 0000000..425d42e --- /dev/null +++ b/docs/reference/Makefile.am @@ -0,0 +1,86 @@ +## Process this file with automake to produce Makefile.in +AUTOMAKE_OPTIONS = 1.6 + +# The name of the module +DOC_MODULE=libsoup-2.4 + +# The top-level SGML file. +DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml + +# The directory containing the source code. Relative to $(srcdir). +# gtk-doc will search all .c & .h files beneath here for inline comments +# documenting functions and macros. +DOC_SOURCE_DIR=../../libsoup + +# Extra options to supply to gtkdoc-scan. +SCAN_OPTIONS=--deprecated-guards=SOUP_DISABLE_DEPRECATED --rebuild-types --ignore-decorators='SOUP_DEPRECATED\w*\s*\([^)]*\)|SOUP_DEPRECATED\w*|SOUP_AVAILABLE\w*' + +# Extra options to supply to gtkdoc-scangobj. +SCANGOBJ_OPTIONS= + +# Extra options to supply to gtkdoc-mkdb. +MKDB_OPTIONS=--sgml-mode --output-format=xml + +# Extra options to supply to gtkdoc-fixref. +FIXXREF_OPTIONS= + +# Used for dependencies. +HFILE_GLOB= +CFILE_GLOB= + +# Header files to ignore when scanning. +IGNORE_HFILES= soup.h soup-autocleanups.h soup-enum-types.h \ + soup-message-private.h soup-session-private.h \ + soup-auth-basic.h soup-auth-digest.h soup-auth-ntlm.h soup-auth-negotiate.h \ + soup-connection.h soup-connection-auth.h \ + soup-message-queue.h soup-path-map.h soup-gnome-features.h \ + soup-proxy-resolver.h soup-proxy-resolver-gnome.h \ + soup-proxy-resolver-static.h soup-directory-input-stream.h \ + soup-http-input-stream.h soup-password-manager.h \ + soup-password-manager-gnome.h soup-converter-wrapper.h \ + soup-body-input-stream.h soup-body-output-stream.h \ + soup-client-input-stream.h soup-content-processor.h \ + soup-content-sniffer-stream.h soup-io-stream.h \ + soup-cache-input-stream.h soup-filter-input-stream.h \ + soup-cookie-jar-sqlite.h soup-requester.h soup-tld-private.h \ + soup-misc-private.h soup-proxy-uri-resolver.h \ + soup-proxy-resolver-wrapper.h soup-proxy-uri-resolver.h \ + soup-cache-private.h soup-cache-client-input-stream.h \ + soup-socket-private.h soup-value-utils.h soup-xmlrpc-old.h + +# Images to copy into HTML directory. +HTML_IMAGES = + +# Extra XML files that are included by $(DOC_MAIN_SGML_FILE). +content_files = \ + build-howto.xml \ + client-howto.xml \ + request-howto.xml \ + server-howto.xml \ + session-porting.xml + +# Other files to distribute. +extra_files = + + +# CFLAGS and LDFLAGS for compiling scan program. Only needed +# if $(DOC_MODULE).types is non-empty. +GTKDOC_CFLAGS = \ + -I$(top_srcdir) \ + -I$(top_builddir) \ + $(GLIB_CFLAGS) \ + $(XML_CFLAGS) \ + $(GNUTLS_CFLAGS) + +GTKDOC_LIBS = \ + $(top_builddir)/libsoup/libsoup-2.4.la \ + $(GLIB_LIBS) + +# include common portion ... +include $(top_srcdir)/gtk-doc.make + +# kludges +$(srcdir)/tmpl/*.sgml: + +clean: clean-am + rm -rf tmpl diff --git a/docs/reference/Makefile.in b/docs/reference/Makefile.in new file mode 100644 index 0000000..f272c08 --- /dev/null +++ b/docs/reference/Makefile.in @@ -0,0 +1,912 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# -*- mode: makefile -*- +# +# gtk-doc.make - make rules for gtk-doc +# Copyright (C) 2003 James Henstridge +# 2004-2007 Damon Chaplin +# 2007-2017 Stefan Sauer +# +# 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 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 . + +#################################### +# Everything below here is generic # +#################################### +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = docs/reference +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_code_coverage.m4 \ + $(top_srcdir)/m4/glibtests.m4 $(top_srcdir)/m4/gtk-doc.m4 \ + $(top_srcdir)/m4/intltool.m4 $(top_srcdir)/m4/introspection.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/vapigen.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/gtk-doc.make +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALL_LINGUAS = @ALL_LINGUAS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +APACHE_HTTPD = @APACHE_HTTPD@ +APACHE_MODULE_DIR = @APACHE_MODULE_DIR@ +APACHE_PHP_MODULE_DIR = @APACHE_PHP_MODULE_DIR@ +APACHE_SSL_MODULE_DIR = @APACHE_SSL_MODULE_DIR@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CODE_COVERAGE_CFLAGS = @CODE_COVERAGE_CFLAGS@ +CODE_COVERAGE_CPPFLAGS = @CODE_COVERAGE_CPPFLAGS@ +CODE_COVERAGE_CXXFLAGS = @CODE_COVERAGE_CXXFLAGS@ +CODE_COVERAGE_ENABLED = @CODE_COVERAGE_ENABLED@ +CODE_COVERAGE_LDFLAGS = @CODE_COVERAGE_LDFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CURL = @CURL@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GCOV = @GCOV@ +GENHTML = @GENHTML@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_COMPILE_RESOURCES = @GLIB_COMPILE_RESOURCES@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MAKEFILE = @GLIB_MAKEFILE@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GMSGFMT = @GMSGFMT@ +GOBJECT_QUERY = @GOBJECT_QUERY@ +GREP = @GREP@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +HAVE_GNOME = @HAVE_GNOME@ +HTML_DIR = @HTML_DIR@ +IF_HAVE_MOD_UNIXD = @IF_HAVE_MOD_UNIXD@ +IF_HAVE_PHP = @IF_HAVE_PHP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ +INTLTOOL_MERGE = @INTLTOOL_MERGE@ +INTLTOOL_PERL = @INTLTOOL_PERL@ +INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ +INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@ +INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@ +INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@ +INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LCOV = @LCOV@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PHP = @PHP@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOUP_AGE = @SOUP_AGE@ +SOUP_API_VERSION = @SOUP_API_VERSION@ +SOUP_CURRENT = @SOUP_CURRENT@ +SOUP_DEBUG_FLAGS = @SOUP_DEBUG_FLAGS@ +SOUP_HIDDEN_VISIBILITY_CFLAGS = @SOUP_HIDDEN_VISIBILITY_CFLAGS@ +SOUP_MAJOR_VERSION = @SOUP_MAJOR_VERSION@ +SOUP_MICRO_VERSION = @SOUP_MICRO_VERSION@ +SOUP_MINOR_VERSION = @SOUP_MINOR_VERSION@ +SOUP_REVISION = @SOUP_REVISION@ +SQLITE_CFLAGS = @SQLITE_CFLAGS@ +SQLITE_LIBS = @SQLITE_LIBS@ +STRIP = @STRIP@ +USE_NLS = @USE_NLS@ +VALAC = @VALAC@ +VAPIDIR = @VAPIDIR@ +VAPIGEN = @VAPIGEN@ +VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@ +VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@ +VERSION = @VERSION@ +XGETTEXT = @XGETTEXT@ +XML_CFLAGS = @XML_CFLAGS@ +XML_LIBS = @XML_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +installed_test_metadir = @installed_test_metadir@ +installed_testdir = @installed_testdir@ +intltool__v_merge_options_ = @intltool__v_merge_options_@ +intltool__v_merge_options_0 = @intltool__v_merge_options_0@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +ntlm_auth = @ntlm_auth@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AUTOMAKE_OPTIONS = 1.6 + +# The name of the module +DOC_MODULE = libsoup-2.4 + +# The top-level SGML file. +DOC_MAIN_SGML_FILE = $(DOC_MODULE)-docs.sgml + +# The directory containing the source code. Relative to $(srcdir). +# gtk-doc will search all .c & .h files beneath here for inline comments +# documenting functions and macros. +DOC_SOURCE_DIR = ../../libsoup + +# Extra options to supply to gtkdoc-scan. +SCAN_OPTIONS = --deprecated-guards=SOUP_DISABLE_DEPRECATED --rebuild-types --ignore-decorators='SOUP_DEPRECATED\w*\s*\([^)]*\)|SOUP_DEPRECATED\w*|SOUP_AVAILABLE\w*' + +# Extra options to supply to gtkdoc-scangobj. +SCANGOBJ_OPTIONS = + +# Extra options to supply to gtkdoc-mkdb. +MKDB_OPTIONS = --sgml-mode --output-format=xml + +# Extra options to supply to gtkdoc-fixref. +FIXXREF_OPTIONS = + +# Used for dependencies. +HFILE_GLOB = +CFILE_GLOB = + +# Header files to ignore when scanning. +IGNORE_HFILES = soup.h soup-autocleanups.h soup-enum-types.h \ + soup-message-private.h soup-session-private.h \ + soup-auth-basic.h soup-auth-digest.h soup-auth-ntlm.h soup-auth-negotiate.h \ + soup-connection.h soup-connection-auth.h \ + soup-message-queue.h soup-path-map.h soup-gnome-features.h \ + soup-proxy-resolver.h soup-proxy-resolver-gnome.h \ + soup-proxy-resolver-static.h soup-directory-input-stream.h \ + soup-http-input-stream.h soup-password-manager.h \ + soup-password-manager-gnome.h soup-converter-wrapper.h \ + soup-body-input-stream.h soup-body-output-stream.h \ + soup-client-input-stream.h soup-content-processor.h \ + soup-content-sniffer-stream.h soup-io-stream.h \ + soup-cache-input-stream.h soup-filter-input-stream.h \ + soup-cookie-jar-sqlite.h soup-requester.h soup-tld-private.h \ + soup-misc-private.h soup-proxy-uri-resolver.h \ + soup-proxy-resolver-wrapper.h soup-proxy-uri-resolver.h \ + soup-cache-private.h soup-cache-client-input-stream.h \ + soup-socket-private.h soup-value-utils.h soup-xmlrpc-old.h + + +# Images to copy into HTML directory. +HTML_IMAGES = + +# Extra XML files that are included by $(DOC_MAIN_SGML_FILE). +content_files = \ + build-howto.xml \ + client-howto.xml \ + request-howto.xml \ + server-howto.xml \ + session-porting.xml + + +# Other files to distribute. +extra_files = + +# CFLAGS and LDFLAGS for compiling scan program. Only needed +# if $(DOC_MODULE).types is non-empty. +GTKDOC_CFLAGS = \ + -I$(top_srcdir) \ + -I$(top_builddir) \ + $(GLIB_CFLAGS) \ + $(XML_CFLAGS) \ + $(GNUTLS_CFLAGS) + +GTKDOC_LIBS = \ + $(top_builddir)/libsoup/libsoup-2.4.la \ + $(GLIB_LIBS) + +@GTK_DOC_USE_LIBTOOL_FALSE@GTKDOC_CC = $(CC) $(INCLUDES) $(GTKDOC_DEPS_CFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +@GTK_DOC_USE_LIBTOOL_TRUE@GTKDOC_CC = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(INCLUDES) $(GTKDOC_DEPS_CFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +@GTK_DOC_USE_LIBTOOL_FALSE@GTKDOC_LD = $(CC) $(GTKDOC_DEPS_LIBS) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) +@GTK_DOC_USE_LIBTOOL_TRUE@GTKDOC_LD = $(LIBTOOL) --tag=CC --mode=link $(CC) $(GTKDOC_DEPS_LIBS) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) +@GTK_DOC_USE_LIBTOOL_FALSE@GTKDOC_RUN = +@GTK_DOC_USE_LIBTOOL_TRUE@GTKDOC_RUN = $(LIBTOOL) --mode=execute + +# We set GPATH here; this gives us semantics for GNU make +# which are more like other make's VPATH, when it comes to +# whether a source that is a target of one rule is then +# searched for in VPATH/GPATH. +# +GPATH = $(srcdir) +TARGET_DIR = $(HTML_DIR)/$(DOC_MODULE) +SETUP_FILES = \ + $(content_files) \ + $(expand_content_files) \ + $(DOC_MAIN_SGML_FILE) \ + $(DOC_MODULE)-sections.txt \ + $(DOC_MODULE)-overrides.txt + +EXTRA_DIST = \ + $(HTML_IMAGES) \ + $(SETUP_FILES) + +DOC_STAMPS = setup-build.stamp scan-build.stamp sgml-build.stamp \ + html-build.stamp pdf-build.stamp \ + sgml.stamp html.stamp pdf.stamp + +SCANOBJ_FILES = \ + $(DOC_MODULE).args \ + $(DOC_MODULE).hierarchy \ + $(DOC_MODULE).interfaces \ + $(DOC_MODULE).prerequisites \ + $(DOC_MODULE).signals + +REPORT_FILES = \ + $(DOC_MODULE)-undocumented.txt \ + $(DOC_MODULE)-undeclared.txt \ + $(DOC_MODULE)-unused.txt + +CLEANFILES = $(SCANOBJ_FILES) $(REPORT_FILES) $(DOC_STAMPS) gtkdoc-check.test +@GTK_DOC_BUILD_HTML_FALSE@HTML_BUILD_STAMP = +@GTK_DOC_BUILD_HTML_TRUE@HTML_BUILD_STAMP = html-build.stamp +@GTK_DOC_BUILD_PDF_FALSE@PDF_BUILD_STAMP = +@GTK_DOC_BUILD_PDF_TRUE@PDF_BUILD_STAMP = pdf-build.stamp + +#### setup #### +GTK_DOC_V_SETUP = $(GTK_DOC_V_SETUP_@AM_V@) +GTK_DOC_V_SETUP_ = $(GTK_DOC_V_SETUP_@AM_DEFAULT_V@) +GTK_DOC_V_SETUP_0 = @echo " DOC Preparing build"; + +#### scan #### +GTK_DOC_V_SCAN = $(GTK_DOC_V_SCAN_@AM_V@) +GTK_DOC_V_SCAN_ = $(GTK_DOC_V_SCAN_@AM_DEFAULT_V@) +GTK_DOC_V_SCAN_0 = @echo " DOC Scanning header files"; +GTK_DOC_V_INTROSPECT = $(GTK_DOC_V_INTROSPECT_@AM_V@) +GTK_DOC_V_INTROSPECT_ = $(GTK_DOC_V_INTROSPECT_@AM_DEFAULT_V@) +GTK_DOC_V_INTROSPECT_0 = @echo " DOC Introspecting gobjects"; + +#### xml #### +GTK_DOC_V_XML = $(GTK_DOC_V_XML_@AM_V@) +GTK_DOC_V_XML_ = $(GTK_DOC_V_XML_@AM_DEFAULT_V@) +GTK_DOC_V_XML_0 = @echo " DOC Building XML"; + +#### html #### +GTK_DOC_V_HTML = $(GTK_DOC_V_HTML_@AM_V@) +GTK_DOC_V_HTML_ = $(GTK_DOC_V_HTML_@AM_DEFAULT_V@) +GTK_DOC_V_HTML_0 = @echo " DOC Building HTML"; +GTK_DOC_V_XREF = $(GTK_DOC_V_XREF_@AM_V@) +GTK_DOC_V_XREF_ = $(GTK_DOC_V_XREF_@AM_DEFAULT_V@) +GTK_DOC_V_XREF_0 = @echo " DOC Fixing cross-references"; + +#### pdf #### +GTK_DOC_V_PDF = $(GTK_DOC_V_PDF_@AM_V@) +GTK_DOC_V_PDF_ = $(GTK_DOC_V_PDF_@AM_DEFAULT_V@) +GTK_DOC_V_PDF_0 = @echo " DOC Building PDF"; +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/gtk-doc.make $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign docs/reference/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign docs/reference/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; +$(top_srcdir)/gtk-doc.make $(am__empty): + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +tags TAGS: + +ctags CTAGS: + +cscope cscopelist: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$(top_distdir)" distdir="$(distdir)" \ + dist-hook +check-am: all-am +check: check-am +@ENABLE_GTK_DOC_FALSE@all-local: +all-am: Makefile all-local +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean-am: clean-generic clean-libtool clean-local mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-local + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-data-local + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic \ + maintainer-clean-local + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-local + +.MAKE: install-am install-strip + +.PHONY: all all-am all-local check check-am clean clean-generic \ + clean-libtool clean-local cscopelist-am ctags-am dist-hook \ + distclean distclean-generic distclean-libtool distclean-local \ + distdir dvi dvi-am html html-am info info-am install \ + install-am install-data install-data-am install-data-local \ + install-dvi install-dvi-am install-exec install-exec-am \ + install-html install-html-am install-info install-info-am \ + install-man install-pdf install-pdf-am install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + maintainer-clean-local mostlyclean mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags-am uninstall \ + uninstall-am uninstall-local + +.PRECIOUS: Makefile + + +gtkdoc-check.test: Makefile + $(AM_V_GEN)echo "#!/bin/sh -e" > $@; \ + echo "$(GTKDOC_CHECK_PATH) || exit 1" >> $@; \ + chmod +x $@ + +all-gtk-doc: $(HTML_BUILD_STAMP) $(PDF_BUILD_STAMP) +.PHONY: all-gtk-doc + +@ENABLE_GTK_DOC_TRUE@all-local: all-gtk-doc + +docs: $(HTML_BUILD_STAMP) $(PDF_BUILD_STAMP) + +$(REPORT_FILES): sgml-build.stamp + +setup-build.stamp: + -$(GTK_DOC_V_SETUP)if test "$(abs_srcdir)" != "$(abs_builddir)" ; then \ + files=`echo $(SETUP_FILES) $(DOC_MODULE).types`; \ + if test "x$$files" != "x" ; then \ + for file in $$files ; do \ + destdir=`dirname $(abs_builddir)/$$file`; \ + test -d "$$destdir" || mkdir -p "$$destdir"; \ + test -f $(abs_srcdir)/$$file && \ + cp -pf $(abs_srcdir)/$$file $(abs_builddir)/$$file || true; \ + done; \ + fi; \ + fi + $(AM_V_at)touch setup-build.stamp + +scan-build.stamp: setup-build.stamp $(HFILE_GLOB) $(CFILE_GLOB) + $(GTK_DOC_V_SCAN)_source_dir='' ; \ + for i in $(DOC_SOURCE_DIR) ; do \ + _source_dir="$${_source_dir} --source-dir=$$i" ; \ + done ; \ + gtkdoc-scan --module=$(DOC_MODULE) --ignore-headers="$(IGNORE_HFILES)" $${_source_dir} $(SCAN_OPTIONS) $(EXTRA_HFILES) + $(GTK_DOC_V_INTROSPECT)if grep -l '^..*$$' $(DOC_MODULE).types > /dev/null 2>&1 ; then \ + scanobj_options=""; \ + gtkdoc-scangobj 2>&1 --help | grep >/dev/null "\-\-verbose"; \ + if test "$$?" = "0"; then \ + if test "x$(V)" = "x1"; then \ + scanobj_options="--verbose"; \ + fi; \ + fi; \ + CC="$(GTKDOC_CC)" LD="$(GTKDOC_LD)" RUN="$(GTKDOC_RUN)" CFLAGS="$(GTKDOC_CFLAGS) $(CFLAGS)" LDFLAGS="$(GTKDOC_LIBS) $(LDFLAGS)" \ + gtkdoc-scangobj $(SCANGOBJ_OPTIONS) $$scanobj_options --module=$(DOC_MODULE); \ + else \ + for i in $(SCANOBJ_FILES) ; do \ + test -f $$i || touch $$i ; \ + done \ + fi + $(AM_V_at)touch scan-build.stamp + +$(DOC_MODULE)-decl.txt $(SCANOBJ_FILES) $(DOC_MODULE)-sections.txt $(DOC_MODULE)-overrides.txt: scan-build.stamp + @true + +sgml-build.stamp: setup-build.stamp $(DOC_MODULE)-decl.txt $(SCANOBJ_FILES) $(HFILE_GLOB) $(CFILE_GLOB) $(DOC_MODULE)-sections.txt $(DOC_MODULE)-overrides.txt $(expand_content_files) xml/gtkdocentities.ent + $(GTK_DOC_V_XML)_source_dir='' ; \ + for i in $(DOC_SOURCE_DIR) ; do \ + _source_dir="$${_source_dir} --source-dir=$$i" ; \ + done ; \ + gtkdoc-mkdb --module=$(DOC_MODULE) --output-format=xml --expand-content-files="$(expand_content_files)" --main-sgml-file=$(DOC_MAIN_SGML_FILE) $${_source_dir} $(MKDB_OPTIONS) + $(AM_V_at)touch sgml-build.stamp + +sgml.stamp: sgml-build.stamp + @true + +$(DOC_MAIN_SGML_FILE): sgml-build.stamp + @true + +xml/gtkdocentities.ent: Makefile + $(GTK_DOC_V_XML)$(MKDIR_P) $(@D) && ( \ + echo ""; \ + echo ""; \ + echo ""; \ + echo ""; \ + echo ""; \ + echo ""; \ + echo ""; \ + ) > $@ + +html-build.stamp: sgml.stamp $(DOC_MAIN_SGML_FILE) $(content_files) $(expand_content_files) + $(GTK_DOC_V_HTML)rm -rf html && mkdir html && \ + mkhtml_options=""; \ + gtkdoc-mkhtml 2>&1 --help | grep >/dev/null "\-\-verbose"; \ + if test "$$?" = "0"; then \ + if test "x$(V)" = "x1"; then \ + mkhtml_options="$$mkhtml_options --verbose"; \ + fi; \ + fi; \ + gtkdoc-mkhtml 2>&1 --help | grep >/dev/null "\-\-path"; \ + if test "$$?" = "0"; then \ + mkhtml_options="$$mkhtml_options --path=\"$(abs_srcdir)\""; \ + fi; \ + cd html && gtkdoc-mkhtml $$mkhtml_options $(MKHTML_OPTIONS) $(DOC_MODULE) ../$(DOC_MAIN_SGML_FILE) + -@test "x$(HTML_IMAGES)" = "x" || \ + for file in $(HTML_IMAGES) ; do \ + test -f $(abs_srcdir)/$$file && cp $(abs_srcdir)/$$file $(abs_builddir)/html; \ + test -f $(abs_builddir)/$$file && cp $(abs_builddir)/$$file $(abs_builddir)/html; \ + test -f $$file && cp $$file $(abs_builddir)/html; \ + done; + $(GTK_DOC_V_XREF)gtkdoc-fixxref --module=$(DOC_MODULE) --module-dir=html --html-dir=$(HTML_DIR) $(FIXXREF_OPTIONS) + $(AM_V_at)touch html-build.stamp + +pdf-build.stamp: sgml.stamp $(DOC_MAIN_SGML_FILE) $(content_files) $(expand_content_files) + $(GTK_DOC_V_PDF)rm -f $(DOC_MODULE).pdf && \ + mkpdf_options=""; \ + gtkdoc-mkpdf 2>&1 --help | grep >/dev/null "\-\-verbose"; \ + if test "$$?" = "0"; then \ + if test "x$(V)" = "x1"; then \ + mkpdf_options="$$mkpdf_options --verbose"; \ + fi; \ + fi; \ + if test "x$(HTML_IMAGES)" != "x"; then \ + for img in $(HTML_IMAGES); do \ + part=`dirname $$img`; \ + echo $$mkpdf_options | grep >/dev/null "\-\-imgdir=$$part "; \ + if test $$? != 0; then \ + mkpdf_options="$$mkpdf_options --imgdir=$$part"; \ + fi; \ + done; \ + fi; \ + gtkdoc-mkpdf --path="$(abs_srcdir)" $$mkpdf_options $(DOC_MODULE) $(DOC_MAIN_SGML_FILE) $(MKPDF_OPTIONS) + $(AM_V_at)touch pdf-build.stamp + +############## + +clean-local: + @rm -f *~ *.bak + @rm -rf .libs + @if echo $(SCAN_OPTIONS) | grep -q "\-\-rebuild-types" ; then \ + rm -f $(DOC_MODULE).types; \ + fi + @if echo $(SCAN_OPTIONS) | grep -q "\-\-rebuild-sections" ; then \ + rm -f $(DOC_MODULE)-sections.txt; \ + fi + +distclean-local: + @rm -rf xml html $(REPORT_FILES) $(DOC_MODULE).pdf \ + $(DOC_MODULE)-decl-list.txt $(DOC_MODULE)-decl.txt + @if test "$(abs_srcdir)" != "$(abs_builddir)" ; then \ + rm -f $(SETUP_FILES) $(DOC_MODULE).types; \ + fi + +maintainer-clean-local: + @rm -rf xml html + +install-data-local: + @installfiles=`echo $(builddir)/html/*`; \ + if test "$$installfiles" = '$(builddir)/html/*'; \ + then echo 1>&2 'Nothing to install' ; \ + else \ + if test -n "$(DOC_MODULE_VERSION)"; then \ + installdir="$(DESTDIR)$(TARGET_DIR)-$(DOC_MODULE_VERSION)"; \ + else \ + installdir="$(DESTDIR)$(TARGET_DIR)"; \ + fi; \ + $(mkinstalldirs) $${installdir} ; \ + for i in $$installfiles; do \ + echo ' $(INSTALL_DATA) '$$i ; \ + $(INSTALL_DATA) $$i $${installdir}; \ + done; \ + if test -n "$(DOC_MODULE_VERSION)"; then \ + mv -f $${installdir}/$(DOC_MODULE).devhelp2 \ + $${installdir}/$(DOC_MODULE)-$(DOC_MODULE_VERSION).devhelp2; \ + fi; \ + $(GTKDOC_REBASE) --relative --dest-dir=$(DESTDIR) --html-dir=$${installdir}; \ + fi + +uninstall-local: + @if test -n "$(DOC_MODULE_VERSION)"; then \ + installdir="$(DESTDIR)$(TARGET_DIR)-$(DOC_MODULE_VERSION)"; \ + else \ + installdir="$(DESTDIR)$(TARGET_DIR)"; \ + fi; \ + rm -rf $${installdir} + +# +# Require gtk-doc when making dist +# +@HAVE_GTK_DOC_TRUE@dist-check-gtkdoc: docs +@HAVE_GTK_DOC_FALSE@dist-check-gtkdoc: +@HAVE_GTK_DOC_FALSE@ @echo "*** gtk-doc is needed to run 'make dist'. ***" +@HAVE_GTK_DOC_FALSE@ @echo "*** gtk-doc was not found when 'configure' ran. ***" +@HAVE_GTK_DOC_FALSE@ @echo "*** please install gtk-doc and rerun 'configure'. ***" +@HAVE_GTK_DOC_FALSE@ @false + +dist-hook: dist-check-gtkdoc all-gtk-doc dist-hook-local + @mkdir $(distdir)/html + @cp ./html/* $(distdir)/html + @-cp ./$(DOC_MODULE).pdf $(distdir)/ + @-cp ./$(DOC_MODULE).types $(distdir)/ + @-cp ./$(DOC_MODULE)-sections.txt $(distdir)/ + @cd $(distdir) && rm -f $(DISTCLEANFILES) + @$(GTKDOC_REBASE) --online --relative --html-dir=$(distdir)/html + +.PHONY : dist-hook-local docs + +# include common portion ... + +# kludges +$(srcdir)/tmpl/*.sgml: + +clean: clean-am + rm -rf tmpl + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/docs/reference/build-howto.xml b/docs/reference/build-howto.xml new file mode 100644 index 0000000..bec9a45 --- /dev/null +++ b/docs/reference/build-howto.xml @@ -0,0 +1,106 @@ + + + + +Compiling with libsoup +3 +LIBSOUP Library + + + +Compiling with libsoupNotes on compiling + + + +Using pkg-config + + +Like other GNOME libraries, libsoup uses +pkg-config to provide compiler options. The +package name is "libsoup-2.4". So in your +configure script, you might specify something like: + + + +PKG_CHECK_MODULES(LIBSOUP, [libsoup-2.4 >= 2.26]) +AC_SUBST(LIBSOUP_CFLAGS) +AC_SUBST(LIBSOUP_LIBS) + + + +The "2.4" in the package name is the "API version" +(indicating "the version of the libsoup API +that first appeared in version 2.4") and is essentially just part of +the package name. + + + + + +API Availability and Deprecation Warnings + + +If you want to restrict your program to a particular +libsoup version or range of versions, you +can define SOUP_VERSION_MIN_REQUIRED +and/or SOUP_VERSION_MAX_ALLOWED. +Eg: + + + +LIBSOUP_CFLAGS="$LIBSOUP_CFLAGS -DSOUP_VERSION_MIN_REQUIRED=SOUP_VERSION_2_36" +LIBSOUP_CFLAGS="$LIBSOUP_CFLAGS -DSOUP_VERSION_MAX_ALLOWED=SOUP_VERSION_2_40" + + + +The SOUP_VERSION_MIN_REQUIRED declaration states +that the code is not expected to compile on versions of +libsoup older than the indicated version +(here, 2.36), and so the compiler should print warnings if the code +uses functions that were deprecated as of that release. + + + +The SOUP_VERSION_MAX_ALLOWED declaration states +that the code is expected to compile on versions +of libsoup up to the indicated version +(here, 2.40), and so, when compiling the program against a newer +version than that, the compiler should print warnings if the code uses +functions that did not yet exist in the max-allowed release. + + + +You can use SOUP_CHECK_VERSION +to check the version of libsoup at compile time, to compile different +code for different libsoup versions. (If +you are setting SOUP_VERSION_MIN_REQUIRED and +SOUP_VERSION_MAX_ALLOWED to different versions, as +in the example above, then you almost certainly need to be doing +this.) + + + + + +Headers + + +Code using libsoup should do: + + + +#include <libsoup/soup.h> + + + +Including individual headers rather than soup.h is not +recommended. + + + + + diff --git a/docs/reference/client-howto.xml b/docs/reference/client-howto.xml new file mode 100644 index 0000000..e694cb7 --- /dev/null +++ b/docs/reference/client-howto.xml @@ -0,0 +1,558 @@ + + + + +libsoup Client Basics +3 +LIBSOUP Library + + + +libsoup Client BasicsClient-side tutorial + + + + +This section explains how to use libsoup as +an HTTP client using several new APIs introduced in version 2.42. If +you want to be compatible with older versions of +libsoup, consult the documentation for that +version. + + + + +Creating a <type>SoupSession</type> + + +The first step in using the client API is to create a SoupSession. The session object +encapsulates all of the state that libsoup +is keeping on behalf of your program; cached HTTP connections, +authentication information, etc. + + + +When you create the session with soup_session_new_with_options, +you can specify various additional options: + + + + + SOUP_SESSION_MAX_CONNS + + Allows you to set the maximum total number of connections + the session will have open at one time. (Once it reaches + this limit, it will either close idle connections, or + wait for existing connections to free up before starting + new requests.) The default value is 10. + + + + SOUP_SESSION_MAX_CONNS_PER_HOST + + Allows you to set the maximum total number of connections + the session will have open to a single + host at one time. The default value is 2. + + + + SOUP_SESSION_USER_AGENT + + Allows you to set a User-Agent string that will be sent + on all outgoing requests. + + + + SOUP_SESSION_ACCEPT_LANGUAGE + and SOUP_SESSION_ACCEPT_LANGUAGE_AUTO + + Allow you to set an Accept-Language header on all outgoing + requests. SOUP_SESSION_ACCEPT_LANGUAGE + takes a list of language tags to use, while + SOUP_SESSION_ACCEPT_LANGUAGE_AUTO + automatically generates the list from the user's locale + settings. + + + + SOUP_SESSION_HTTP_ALIASES + and SOUP_SESSION_HTTPS_ALIASES + + Allow you to tell the session to recognize additional URI + schemes as aliases for "http" or + https. You can set this if you are + using URIs with schemes like "dav" or + "webcal" (and in particular, you need + to set this if the server you are talking to might return + redirects with such a scheme). + + + + SOUP_SESSION_PROXY_RESOLVER and SOUP_SESSION_PROXY_URI + + + SOUP_SESSION_PROXY_RESOLVER + specifies a GProxyResolver + to use to determine the HTTP proxies to use. By default, + this is set to the resolver returned by g_proxy_resolver_get_default, + so you do not need to set it yourself. + + + Alternatively, if you want all requests to go through a + single proxy, you can set SOUP_SESSION_PROXY_URI. + + + + + SOUP_SESSION_ADD_FEATURE and SOUP_SESSION_ADD_FEATURE_BY_TYPE + + These allow you to specify SoupSessionFeatures + (discussed below) + to add at construct-time. + + + + + +Other properties are also available; see the SoupSession documentation for +more details. + + + +If you don't need to specify any options, you can just use soup_session_new, +which takes no arguments. + + + + + +Session features + + +Additional session functionality is provided as SoupSessionFeatures, +which can be added to a session, via the SOUP_SESSION_ADD_FEATURE +and SOUP_SESSION_ADD_FEATURE_BY_TYPE +options at session-construction-time, or afterward via the soup_session_add_feature +and soup_session_add_feature_by_type +functions. + + + +A SoupContentDecoder is +added for you automatically. This advertises to servers that the +client supports compression, and automatically decompresses compressed +responses. + + + +Some other available features that you can add include: + + + + + SoupLogger + + A debugging aid, which logs all of libsoup's HTTP traffic + to stdout (or another place you specify). + + + + + SoupCookieJar, + SoupCookieJarText, + and SoupCookieJarDB + + + Support for HTTP cookies. SoupCookieJar + provides non-persistent cookie storage, while + SoupCookieJarText uses a text file to keep + track of cookies between sessions, and + SoupCookieJarDB uses a + SQLite database. + + + + SoupContentSniffer + + Uses the HTML5 sniffing rules to attempt to + determine the Content-Type of a response when the + server does not identify the Content-Type, or appears to + have provided an incorrect one. + + + + + +Use the "add_feature_by_type" property/function to add features that +don't require any configuration (such as SoupContentSniffer), +and the "add_feature" property/function to add features that must be +constructed first (such as SoupLogger). For example, an +application might do something like the following: + + + + session = soup_session_new_with_options ( + SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_CONTENT_SNIFFER, + NULL); + + if (debug_level) { + SoupLogger *logger; + + logger = soup_logger_new (debug_level, -1); + soup_session_add_feature (session, SOUP_SESSION_FEATURE (logger)); + g_object_unref (logger); + } + + + + + +Creating and Sending SoupMessages + + +Once you have a session, you send HTTP requests using SoupMessage. In the simplest +case, you only need to create the message and it's ready to send: + + + + SoupMessage *msg; + + msg = soup_message_new ("GET", "http://example.com/"); + + + +In more complicated cases, you can use various SoupMessage, SoupMessageHeaders, and SoupMessageBody methods to set the +request headers and body of the message: + + + + SoupMessage *msg; + + msg = soup_message_new ("POST", "http://example.com/form.cgi"); + soup_message_set_request (msg, "application/x-www-form-urlencoded", + SOUP_MEMORY_COPY, formdata, strlen (formdata)); + soup_message_headers_append (msg->request_headers, "Referer", referring_url); + + + +(Although this is a bad example, because +libsoup actually has convenience methods +for dealing with HTML +forms, as well as XML-RPC.) + + + +You can also use soup_message_set_flags +to change some default behaviors. For example, by default, +SoupSession automatically handles responses from the +server that redirect to another URL. If you would like to handle these +yourself, you can set the SOUP_MESSAGE_NO_REDIRECT +flag. + + + +Sending a Message Synchronously + + +To send a message and wait for the response, use soup_session_send: + + + + GInputStream *stream; + GError *error = NULL; + + stream = soup_session_send (session, msg, cancellable, &error); + + + +At the point when soup_session_send returns, the +request will have been sent, and the response headers read back in; +you can examine the message's status_code, +reason_phrase, and +response_headers fields to see the response +metadata. To get the response body, read from the returned GInputStream, and close it +when you are done. + + + +Note that soup_session_send only returns an error +if a transport-level problem occurs (eg, it could not connect to the +host, or the request was cancelled). Use the message's +status_code field to determine whether the +request was successful or not at the HTTP level (ie, "200 +OK" vs "401 Bad Request"). + + + +If you would prefer to have libsoup gather +the response body for you and then return it all at once, you can use +the older +soup_session_send_message +API: + + + + guint status; + + status = soup_session_send_message (session, msg); + + + +In this case, the response body will be available in the message's +response_body field, and transport-level +errors will be indicated in the status_code +field via special pseudo-HTTP-status codes like SOUP_STATUS_CANT_CONNECT. + + + + + +Sending a Message Asynchronously + + +To send a message asynchronously, use soup_session_send_async: + + + +{ + ... + soup_session_send_async (session, msg, cancellable, my_callback, my_callback_data); + ... +} + +static void +my_callback (GObject *object, GAsyncResult *result, gpointer user_data) +{ + GInputStream *stream; + GError *error = NULL; + + stream = soup_session_send_finish (SOUP_SESSION (object), result, &error); + ... +} + + + +The message will be added to the session's queue, and eventually (when +control is returned back to the main loop), it will be sent and the +response be will be read. When the message has been sent, and its +headers received, the callback will be invoked, in the standard +GAsyncReadyCallback +style. + + + +As with synchronous sending, there is also an alternate API, soup_session_queue_message, +in which your callback is not invoked until the response has been +completely read: + + + +{ + ... + soup_session_queue_message (session, msg, my_callback, my_callback_data); + ... +} + +static void +my_callback (SoupSession *session, SoupMessage *msg, gpointer user_data) +{ + /* msg->response_body contains the response */ +} + + + +soup_session_queue_message +is slightly unusual in that it steals a reference to the message +object, and unrefs it after the last callback is invoked on it. So +when using this API, you should not unref the message yourself. + + + + + + + +Processing the Response + + +Once you have received the initial response from the server, +synchronously or asynchronously, streaming or not, you can look at the +response fields in the SoupMessage to decide what +to do next. The status_code and +reason_phrase fields contain the numeric +status and textual status response from the server. +response_headers contains the response +headers, which you can investigate using soup_message_headers_get +and soup_message_headers_foreach. + + + +SoupMessageHeaders +automatically parses several important headers in +response_headers for you and provides +specialized accessors for them. Eg, soup_message_headers_get_content_type. +There are several generic methods such as soup_header_parse_param_list +(for parsing an attribute-list-type header) and soup_header_contains +(for quickly testing if a list-type header contains a particular +token). These handle the various syntactical oddities of parsing HTTP +headers much better than functions like +g_strsplit or strstr. + + + + + +Handling Authentication + + +SoupSession handles most of the details of HTTP +authentication for you. If it receives a 401 ("Unauthorized") or 407 +("Proxy Authentication Required") response, the session will emit the +authenticate signal, +providing you with a SoupAuth object indicating the +authentication type ("Basic", "Digest", or "NTLM") and the realm name +provided by the server. If you have a username and password available +(or can generate one), call soup_auth_authenticate +to give the information to libsoup. The session will automatically +requeue the message and try it again with that authentication +information. (If you don't call +soup_auth_authenticate, the session will just +return the message to the application with its 401 or 407 status.) + + + +If the server doesn't accept the username and password provided, the +session will emit authenticate again, with the +retrying parameter set to TRUE. This lets the +application know that the information it provided earlier was +incorrect, and gives it a chance to try again. If this +username/password pair also doesn't work, the session will contine to +emit authenticate again and again until the +provided username/password successfully authenticates, or until the +signal handler fails to call soup_auth_authenticate, +at which point libsoup will allow the +message to fail (with status 401 or 407). + + + +If you need to handle authentication asynchronously (eg, to pop up a +password dialog without recursively entering the main loop), you can +do that as well. Just call soup_session_pause_message +on the message before returning from the signal handler, and +g_object_ref the SoupAuth. Then, +later on, after calling soup_auth_authenticate +(or deciding not to), call soup_session_unpause_message +to resume the paused message. + + + +By default, NTLM authentication is not enabled. To add NTLM support to +a session, call: + + + + soup_session_add_feature_by_type (session, SOUP_TYPE_AUTH_NTLM); + + + +(You can also disable Basic or Digest authentication by calling soup_session_remove_feature_by_type +on SOUP_TYPE_AUTH_BASIC +or SOUP_TYPE_AUTH_DIGEST.) + + + + + +Multi-threaded usage + + +A SoupSession can be +used from multiple threads. However, if you are using the async APIs, +then each thread you use the session from must have its own +thread-default GMainContext. + + + +SoupMessage is +not thread-safe, so once you send a message on +the session, you must not interact with it from any thread other than +the one where it was sent. + + + + + +Sample Programs + + +A few sample programs are available in the +libsoup sources, in the +examples directory: + + + + + get is a simple command-line + HTTP GET utility using the asynchronous API. + + + + simple-proxy uses both the + client and server APIs to create a simple (and not very + RFC-compliant) proxy server. It shows how to use the SOUP_MESSAGE_OVERWRITE_CHUNKS + flag when reading a message to save memory by processing each + chunk of the message as it is read, rather than accumulating + them all into a single buffer to process all at the end. + + + + +More complicated examples are available in GNOME git. + + + + + diff --git a/docs/reference/html/SoupAddress.html b/docs/reference/html/SoupAddress.html new file mode 100644 index 0000000..1a8f8ae --- /dev/null +++ b/docs/reference/html/SoupAddress.html @@ -0,0 +1,1079 @@ + + + + +SoupAddress: libsoup Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

SoupAddress

+

SoupAddress — DNS support

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+SoupAddress * + +soup_address_new () +
+SoupAddress * + +soup_address_new_from_sockaddr () +
+SoupAddress * + +soup_address_new_any () +
+void + +(*SoupAddressCallback) () +
+void + +soup_address_resolve_async () +
+guint + +soup_address_resolve_sync () +
+gboolean + +soup_address_is_resolved () +
const char * + +soup_address_get_name () +
struct sockaddr * + +soup_address_get_sockaddr () +
+GSocketAddress * + +soup_address_get_gsockaddr () +
const char * + +soup_address_get_physical () +
+guint + +soup_address_get_port () +
+gboolean + +soup_address_equal_by_name () +
+guint + +soup_address_hash_by_name () +
+gboolean + +soup_address_equal_by_ip () +
+guint + +soup_address_hash_by_ip () +
+
+
+

Properties

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SoupAddressFamilyfamilyRead / Write / Construct Only
+gchar *nameRead / Write / Construct Only
+gchar *physicalRead
gintportRead / Write / Construct Only
+gchar *protocolRead / Write / Construct Only
gpointersockaddrRead / Write / Construct Only
+
+
+

Types and Values

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 SoupAddress
enumSoupAddressFamily
#defineSOUP_ADDRESS_ANY_PORT
#defineSOUP_ADDRESS_FAMILY
#defineSOUP_ADDRESS_NAME
#defineSOUP_ADDRESS_PHYSICAL
#defineSOUP_ADDRESS_PORT
#defineSOUP_ADDRESS_SOCKADDR
#defineSOUP_ADDRESS_PROTOCOL
+
+
+

Object Hierarchy

+
    GObject
+    ╰── SoupAddress
+
+
+
+

Implemented Interfaces

+

+SoupAddress implements + GSocketConnectable.

+
+
+

Includes

+
#include <libsoup/soup.h>
+
+
+
+

Description

+

SoupAddress represents the address of a TCP connection endpoint: +both the IP address and the port. (It is somewhat like an +object-oriented version of struct sockaddr.)

+

Although SoupAddress is still used in some libsoup API's, it +should not be used in new code; use GLib's GNetworkAddress or +GSocketAddress instead.

+
+
+

Functions

+
+

soup_address_new ()

+
SoupAddress *
+soup_address_new (const char *name,
+                  guint port);
+

Creates a SoupAddress from name + and port +. The SoupAddress's IP +address may not be available right away; the caller can call +soup_address_resolve_async() or soup_address_resolve_sync() to +force a DNS resolution.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

name

a hostname or physical address

 

port

a port number

 
+
+
+

Returns

+

a SoupAddress

+
+
+
+
+

soup_address_new_from_sockaddr ()

+
SoupAddress *
+soup_address_new_from_sockaddr (struct sockaddr *sa,
+                                int len);
+

Returns a SoupAddress equivalent to sa + (or NULL if sa +'s +address family isn't supported)

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

sa

a pointer to a sockaddr

 

len

size of sa +

 
+
+
+

Returns

+

the new SoupAddress.

+

[nullable]

+
+
+
+
+

soup_address_new_any ()

+
SoupAddress *
+soup_address_new_any (SoupAddressFamily family,
+                      guint port);
+

Returns a SoupAddress corresponding to the "any" address +for family + (or NULL if family + isn't supported), suitable for +using as a listening SoupSocket.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

family

the address family

 

port

the port number (usually SOUP_ADDRESS_ANY_PORT)

 
+
+
+

Returns

+

the new SoupAddress.

+

[nullable]

+
+
+
+
+

SoupAddressCallback ()

+
void
+(*SoupAddressCallback) (SoupAddress *addr,
+                        guint status,
+                        gpointer user_data);
+

The callback function passed to soup_address_resolve_async().

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

addr

the SoupAddress that was resolved

 

status

SOUP_STATUS_OK, SOUP_STATUS_CANT_RESOLVE, or +SOUP_STATUS_CANCELLED

 

user_data

the user data that was passed to +soup_address_resolve_async()

 
+
+
+
+
+

soup_address_resolve_async ()

+
void
+soup_address_resolve_async (SoupAddress *addr,
+                            GMainContext *async_context,
+                            GCancellable *cancellable,
+                            SoupAddressCallback callback,
+                            gpointer user_data);
+

Asynchronously resolves the missing half of addr + (its IP address +if it was created with soup_address_new(), or its hostname if it +was created with soup_address_new_from_sockaddr() or +soup_address_new_any().)

+

If cancellable + is non-NULL, it can be used to cancel the +resolution. callback + will still be invoked in this case, with a +status of SOUP_STATUS_CANCELLED.

+

It is safe to call this more than once on a given address, from the +same thread, with the same async_context + (and doing so will not +result in redundant DNS queries being made). But it is not safe to +call from multiple threads, or with different async_contexts +, or +mixed with calls to soup_address_resolve_sync().

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

addr

a SoupAddress

 

async_context

the GMainContext to call callback +from.

[allow-none]

cancellable

a GCancellable object, or NULL

 

callback

callback to call with the result.

[scope async]

user_data

data for callback +

 
+
+
+
+
+

soup_address_resolve_sync ()

+
guint
+soup_address_resolve_sync (SoupAddress *addr,
+                           GCancellable *cancellable);
+

Synchronously resolves the missing half of addr +, as with +soup_address_resolve_async().

+

If cancellable + is non-NULL, it can be used to cancel the +resolution. soup_address_resolve_sync() will then return a status +of SOUP_STATUS_CANCELLED.

+

It is safe to call this more than once, even from different +threads, but it is not safe to mix calls to +soup_address_resolve_sync() with calls to +soup_address_resolve_async() on the same address.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

addr

a SoupAddress

 

cancellable

a GCancellable object, or NULL

 
+
+ +
+
+
+

soup_address_is_resolved ()

+
gboolean
+soup_address_is_resolved (SoupAddress *addr);
+

Tests if addr + has already been resolved. Unlike the other +SoupAddress "get" methods, this is safe to call when addr + might +be being resolved in another thread.

+
+

Parameters

+
+++++ + + + + + +

addr

a SoupAddress

 
+
+
+

Returns

+

TRUE if addr +has been resolved.

+
+
+
+
+

soup_address_get_name ()

+
const char *
+soup_address_get_name (SoupAddress *addr);
+

Returns the hostname associated with addr +.

+

This method is not thread-safe; if you call it while addr + is being +resolved in another thread, it may return garbage. You can use +soup_address_is_resolved() to safely test whether or not an address +is resolved before fetching its name or address.

+
+

Parameters

+
+++++ + + + + + +

addr

a SoupAddress

 
+
+
+

Returns

+

the hostname, or NULL if it is not known.

+

[nullable]

+
+
+
+
+

soup_address_get_sockaddr ()

+
struct sockaddr *
+soup_address_get_sockaddr (SoupAddress *addr,
+                           int *len);
+

Returns the sockaddr associated with addr +, with its length in +*len +. If the sockaddr is not yet known, returns NULL.

+

This method is not thread-safe; if you call it while addr + is being +resolved in another thread, it may return garbage. You can use +soup_address_is_resolved() to safely test whether or not an address +is resolved before fetching its name or address.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

addr

a SoupAddress

 

len

return location for sockaddr length

 
+
+
+

Returns

+

the sockaddr, or NULL.

+

[nullable][transfer none]

+
+
+
+
+

soup_address_get_gsockaddr ()

+
GSocketAddress *
+soup_address_get_gsockaddr (SoupAddress *addr);
+

Creates a new GSocketAddress corresponding to addr + (which is assumed +to only have one socket address associated with it).

+
+

Parameters

+
+++++ + + + + + +

addr

a SoupAddress

 
+
+
+

Returns

+

a new GSocketAddress.

+

[transfer full]

+
+

Since: 2.32

+
+
+
+

soup_address_get_physical ()

+
const char *
+soup_address_get_physical (SoupAddress *addr);
+

Returns the physical address associated with addr + as a string. +(Eg, "127.0.0.1"). If the address is not yet known, returns NULL.

+

This method is not thread-safe; if you call it while addr + is being +resolved in another thread, it may return garbage. You can use +soup_address_is_resolved() to safely test whether or not an address +is resolved before fetching its name or address.

+
+

Parameters

+
+++++ + + + + + +

addr

a SoupAddress

 
+
+
+

Returns

+

the physical address, or NULL.

+

[nullable]

+
+
+
+
+

soup_address_get_port ()

+
guint
+soup_address_get_port (SoupAddress *addr);
+

Returns the port associated with addr +.

+
+

Parameters

+
+++++ + + + + + +

addr

a SoupAddress

 
+
+
+

Returns

+

the port

+
+
+
+
+

soup_address_equal_by_name ()

+
gboolean
+soup_address_equal_by_name (gconstpointer addr1,
+                            gconstpointer addr2);
+

Tests if addr1 + and addr2 + have the same "name". This method can be +used with soup_address_hash_by_name() to create a GHashTable that +hashes on address "names".

+

Comparing by name normally means comparing the addresses by their +hostnames. But if the address was originally created using an IP +address literal, then it will be compared by that instead.

+

In particular, if "www.example.com" has the IP address 10.0.0.1, +and addr1 + was created with the name "www.example.com" and addr2 + +was created with the name "10.0.0.1", then they will compare as +unequal for purposes of soup_address_equal_by_name().

+

This would be used to distinguish hosts in situations where +different virtual hosts on the same IP address should be considered +different. Eg, for purposes of HTTP authentication or cookies, two +hosts with the same IP address but different names are considered +to be different hosts.

+

See also soup_address_equal_by_ip(), which compares by IP address +rather than by name.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

addr1

a SoupAddress with a resolved name.

[type Soup.Address]

addr2

another SoupAddress with a resolved +name.

[type Soup.Address]
+
+
+

Returns

+

whether or not addr1 +and addr2 +have the same name

+
+

Since: 2.26

+
+
+
+

soup_address_hash_by_name ()

+
guint
+soup_address_hash_by_name (gconstpointer addr);
+

A hash function (for GHashTable) that corresponds to +soup_address_equal_by_name(), qv

+
+

Parameters

+
+++++ + + + + + +

addr

a SoupAddress.

[type Soup.Address]
+
+
+

Returns

+

the named-based hash value for addr +.

+
+

Since: 2.26

+
+
+
+

soup_address_equal_by_ip ()

+
gboolean
+soup_address_equal_by_ip (gconstpointer addr1,
+                          gconstpointer addr2);
+

Tests if addr1 + and addr2 + have the same IP address. This method +can be used with soup_address_hash_by_ip() to create a +GHashTable that hashes on IP address.

+

This would be used to distinguish hosts in situations where +different virtual hosts on the same IP address should be considered +the same. Eg, if "www.example.com" and "www.example.net" have the +same IP address, then a single connection can be used to talk +to either of them.

+

See also soup_address_equal_by_name(), which compares by name +rather than by IP address.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

addr1

a SoupAddress with a resolved IP +address.

[type Soup.Address]

addr2

another SoupAddress with a resolved +IP address.

[type Soup.Address]
+
+
+

Returns

+

whether or not addr1 +and addr2 +have the same IP +address.

+
+

Since: 2.26

+
+
+
+

soup_address_hash_by_ip ()

+
guint
+soup_address_hash_by_ip (gconstpointer addr);
+

A hash function (for GHashTable) that corresponds to +soup_address_equal_by_ip(), qv

+
+

Parameters

+
+++++ + + + + + +

addr

a SoupAddress.

[type Soup.Address]
+
+
+

Returns

+

the IP-based hash value for addr +.

+
+

Since: 2.26

+
+
+
+

Types and Values

+
+

SoupAddress

+
typedef struct _SoupAddress SoupAddress;
+
+
+
+

enum SoupAddressFamily

+

The supported address families.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + +

SOUP_ADDRESS_FAMILY_INVALID

+

an invalid SoupAddress

+
 

SOUP_ADDRESS_FAMILY_IPV4

+

an IPv4 address

+
 

SOUP_ADDRESS_FAMILY_IPV6

+

an IPv6 address

+
 
+
+
+
+
+

SOUP_ADDRESS_ANY_PORT

+
#define SOUP_ADDRESS_ANY_PORT 0
+
+

This can be passed to any SoupAddress method that expects a port, +to indicate that you don't care what port is used.

+
+
+
+

SOUP_ADDRESS_FAMILY

+
#define SOUP_ADDRESS_FAMILY   "family"
+
+

Alias for the “family” property. (The +SoupAddressFamily for this address.)

+
+
+
+

SOUP_ADDRESS_NAME

+
#define SOUP_ADDRESS_NAME     "name"
+
+

Alias for the “name” property. (The hostname for +this address.)

+
+
+
+

SOUP_ADDRESS_PHYSICAL

+
#define SOUP_ADDRESS_PHYSICAL "physical"
+
+

An alias for the “physical” property. (The +stringified IP address for this address.)

+
+
+
+

SOUP_ADDRESS_PORT

+
#define SOUP_ADDRESS_PORT     "port"
+
+

An alias for the “port” property. (The port for +this address.)

+
+
+
+

SOUP_ADDRESS_SOCKADDR

+
#define SOUP_ADDRESS_SOCKADDR "sockaddr"
+
+

An alias for the “sockaddr” property. (A pointer +to the struct sockaddr for this address.)

+
+
+
+

SOUP_ADDRESS_PROTOCOL

+
#define SOUP_ADDRESS_PROTOCOL "protocol"
+
+

Alias for the “protocol” property. (The URI scheme +used with this address.)

+
+
+
+

Property Details

+
+

The “family” property

+
  “family”                   SoupAddressFamily
+

Address family for this address.

+

Flags: Read / Write / Construct Only

+

Default value: SOUP_ADDRESS_FAMILY_INVALID

+
+
+
+

The “name” property

+
  “name”                     gchar *
+

Hostname for this address.

+

Flags: Read / Write / Construct Only

+

Default value: NULL

+
+
+
+

The “physical” property

+
  “physical”                 gchar *
+

IP address for this address.

+

Flags: Read

+

Default value: NULL

+
+
+
+

The “port” property

+
  “port”                     gint
+

Port for this address.

+

Flags: Read / Write / Construct Only

+

Allowed values: [-1,65535]

+

Default value: -1

+
+
+
+

The “protocol” property

+
  “protocol”                 gchar *
+

URI scheme for this address.

+

Flags: Read / Write / Construct Only

+

Default value: NULL

+
+
+
+

The “sockaddr” property

+
  “sockaddr”                 gpointer
+

struct sockaddr for this address.

+

Flags: Read / Write / Construct Only

+
+
+
+ + + \ No newline at end of file diff --git a/docs/reference/html/SoupAuth.html b/docs/reference/html/SoupAuth.html new file mode 100644 index 0000000..fb2a7a7 --- /dev/null +++ b/docs/reference/html/SoupAuth.html @@ -0,0 +1,921 @@ + + + + +SoupAuth: libsoup Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

SoupAuth

+

SoupAuth — HTTP client-side authentication support

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+SoupAuth * + +soup_auth_new () +
+gboolean + +soup_auth_update () +
+gboolean + +soup_auth_negotiate_supported () +
+gboolean + +soup_auth_is_for_proxy () +
const char * + +soup_auth_get_scheme_name () +
const char * + +soup_auth_get_host () +
const char * + +soup_auth_get_realm () +
+char * + +soup_auth_get_info () +
+void + +soup_auth_authenticate () +
+gboolean + +soup_auth_can_authenticate () +
+gboolean + +soup_auth_is_authenticated () +
+gboolean + +soup_auth_is_ready () +
+char * + +soup_auth_get_authorization () +
+GSList * + +soup_auth_get_protection_space () +
+void + +soup_auth_free_protection_space () +
+
+
+

Properties

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+gchar *hostRead / Write
gbooleanis-authenticatedRead
gbooleanis-for-proxyRead / Write
+gchar *realmRead / Write
+gchar *scheme-nameRead
+
+
+

Types and Values

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 SoupAuth
#defineSOUP_TYPE_AUTH_BASIC
#defineSOUP_TYPE_AUTH_DIGEST
#defineSOUP_TYPE_AUTH_NTLM
#defineSOUP_TYPE_AUTH_NEGOTIATE
#defineSOUP_AUTH_SCHEME_NAME
#defineSOUP_AUTH_REALM
#defineSOUP_AUTH_HOST
#defineSOUP_AUTH_IS_FOR_PROXY
#defineSOUP_AUTH_IS_AUTHENTICATED
+
+
+

Object Hierarchy

+
    GObject
+    ╰── SoupAuth
+
+
+
+

Includes

+
#include <libsoup/soup.h>
+
+
+
+

Description

+

SoupAuth objects store the authentication data associated with a +given bit of web space. They are created automatically by +SoupSession.

+
+
+

Functions

+
+

soup_auth_new ()

+
SoupAuth *
+soup_auth_new (GType type,
+               SoupMessage *msg,
+               const char *auth_header);
+

Creates a new SoupAuth of type type + with the information from +msg + and auth_header +.

+

This is called by SoupSession; you will normally not create auths +yourself.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

type

the type of auth to create (a subtype of SoupAuth)

 

msg

the SoupMessage the auth is being created for

 

auth_header

the WWW-Authenticate/Proxy-Authenticate header

 
+
+
+

Returns

+

the new SoupAuth, or NULL if it could +not be created.

+

[nullable]

+
+
+
+
+

soup_auth_update ()

+
gboolean
+soup_auth_update (SoupAuth *auth,
+                  SoupMessage *msg,
+                  const char *auth_header);
+

Updates auth + with the information from msg + and auth_header +, +possibly un-authenticating it. As with soup_auth_new(), this is +normally only used by SoupSession.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

auth

a SoupAuth

 

msg

the SoupMessage auth +is being updated for

 

auth_header

the WWW-Authenticate/Proxy-Authenticate header

 
+
+
+

Returns

+

TRUE if auth +is still a valid (but potentially +unauthenticated) SoupAuth. FALSE if something about auth_params +could not be parsed or incorporated into auth +at all.

+
+
+
+
+

soup_auth_negotiate_supported ()

+
gboolean
+soup_auth_negotiate_supported (void);
+

Indicates whether libsoup was built with GSSAPI support. If this is +FALSE, SOUP_TYPE_AUTH_NEGOTIATE will still be defined and can +still be added to a SoupSession, but libsoup will never attempt to +actually use this auth type.

+

Since: 2.54

+
+
+
+

soup_auth_is_for_proxy ()

+
gboolean
+soup_auth_is_for_proxy (SoupAuth *auth);
+

Tests whether or not auth + is associated with a proxy server rather +than an "origin" server.

+
+

Parameters

+
+++++ + + + + + +

auth

a SoupAuth

 
+
+
+

Returns

+

TRUE or FALSE

+
+
+
+
+

soup_auth_get_scheme_name ()

+
const char *
+soup_auth_get_scheme_name (SoupAuth *auth);
+

Returns auth +'s scheme name. (Eg, "Basic", "Digest", or "NTLM")

+
+

Parameters

+
+++++ + + + + + +

auth

a SoupAuth

 
+
+
+

Returns

+

the scheme name

+
+
+
+
+

soup_auth_get_host ()

+
const char *
+soup_auth_get_host (SoupAuth *auth);
+

Returns the host that auth + is associated with.

+
+

Parameters

+
+++++ + + + + + +

auth

a SoupAuth

 
+
+
+

Returns

+

the hostname

+
+
+
+
+

soup_auth_get_realm ()

+
const char *
+soup_auth_get_realm (SoupAuth *auth);
+

Returns auth +'s realm. This is an identifier that distinguishes +separate authentication spaces on a given server, and may be some +string that is meaningful to the user. (Although it is probably not +localized.)

+
+

Parameters

+
+++++ + + + + + +

auth

a SoupAuth

 
+
+
+

Returns

+

the realm name

+
+
+
+
+

soup_auth_get_info ()

+
char *
+soup_auth_get_info (SoupAuth *auth);
+

Gets an opaque identifier for auth +, for use as a hash key or the +like. SoupAuth objects from the same server with the same +identifier refer to the same authentication domain (eg, the URLs +associated with them take the same usernames and passwords).

+
+

Parameters

+
+++++ + + + + + +

auth

a SoupAuth

 
+
+
+

Returns

+

the identifier

+
+
+
+
+

soup_auth_authenticate ()

+
void
+soup_auth_authenticate (SoupAuth *auth,
+                        const char *username,
+                        const char *password);
+

Call this on an auth to authenticate it; normally this will cause +the auth's message to be requeued with the new authentication info.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

auth

a SoupAuth

 

username

the username provided by the user or client

 

password

the password provided by the user or client

 
+
+
+
+
+

soup_auth_can_authenticate ()

+
gboolean
+soup_auth_can_authenticate (SoupAuth *auth);
+

Tests if auth + is able to authenticate by providing credentials to the +soup_auth_authenticate().

+
+

Parameters

+
+++++ + + + + + +

auth

a SoupAuth

 
+
+
+

Returns

+

TRUE if auth +is able to accept credentials.

+
+

Since: 2.54

+
+
+
+

soup_auth_is_authenticated ()

+
gboolean
+soup_auth_is_authenticated (SoupAuth *auth);
+

Tests if auth + has been given a username and password

+
+

Parameters

+
+++++ + + + + + +

auth

a SoupAuth

 
+
+
+

Returns

+

TRUE if auth +has been given a username and password

+
+
+
+
+

soup_auth_is_ready ()

+
gboolean
+soup_auth_is_ready (SoupAuth *auth,
+                    SoupMessage *msg);
+

Tests if auth + is ready to make a request for msg + with. For most +auths, this is equivalent to soup_auth_is_authenticated(), but for +some auth types (eg, NTLM), the auth may be sendable (eg, as an +authentication request) even before it is authenticated.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

auth

a SoupAuth

 

msg

a SoupMessage

 
+
+
+

Returns

+

TRUE if auth +is ready to make a request with.

+
+

Since: 2.42

+
+
+
+

soup_auth_get_authorization ()

+
char *
+soup_auth_get_authorization (SoupAuth *auth,
+                             SoupMessage *msg);
+

Generates an appropriate "Authorization" header for msg +. (The +session will only call this if soup_auth_is_authenticated() +returned TRUE.)

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

auth

a SoupAuth

 

msg

the SoupMessage to be authorized

 
+
+
+

Returns

+

the "Authorization" header, which must be freed.

+
+
+
+
+

soup_auth_get_protection_space ()

+
GSList *
+soup_auth_get_protection_space (SoupAuth *auth,
+                                SoupURI *source_uri);
+

Returns a list of paths on the server which auth + extends over. +(All subdirectories of these paths are also assumed to be part +of auth +'s protection space, unless otherwise discovered not to +be.)

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

auth

a SoupAuth

 

source_uri

the URI of the request that auth +was generated in +response to.

 
+
+
+

Returns

+

the list of +paths, which can be freed with soup_auth_free_protection_space().

+

[element-type utf8][transfer full]

+
+
+
+
+

soup_auth_free_protection_space ()

+
void
+soup_auth_free_protection_space (SoupAuth *auth,
+                                 GSList *space);
+

Frees space +.

+

[skip]

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

auth

a SoupAuth

 

space

the return value from soup_auth_get_protection_space()

 
+
+
+
+
+

Types and Values

+
+

SoupAuth

+
typedef struct _SoupAuth SoupAuth;
+

The abstract base class for handling authentication. Specific HTTP +Authentication mechanisms are implemented by its subclasses, but +applications never need to be aware of the specific subclasses +being used.

+
+
+
+

SOUP_TYPE_AUTH_BASIC

+
#define SOUP_TYPE_AUTH_BASIC  (soup_auth_basic_get_type ())
+
+

A GType corresponding to HTTP "Basic" authentication. +SoupSessions support this by default; if you want to disable +support for it, call soup_session_remove_feature_by_type(), +passing SOUP_TYPE_AUTH_BASIC.

+

Since: 2.34

+
+
+
+

SOUP_TYPE_AUTH_DIGEST

+
#define SOUP_TYPE_AUTH_DIGEST (soup_auth_digest_get_type ())
+
+

A GType corresponding to HTTP "Digest" authentication. +SoupSessions support this by default; if you want to disable +support for it, call soup_session_remove_feature_by_type(), +passing SOUP_TYPE_AUTH_DIGEST.

+

Since: 2.34

+
+
+
+

SOUP_TYPE_AUTH_NTLM

+
#define SOUP_TYPE_AUTH_NTLM   (soup_auth_ntlm_get_type ())
+
+

A GType corresponding to HTTP-based NTLM authentication. +SoupSessions do not support this type by default; if you want to +enable support for it, call soup_session_add_feature_by_type(), +passing SOUP_TYPE_AUTH_NTLM.

+

Since: 2.34

+
+
+
+

SOUP_TYPE_AUTH_NEGOTIATE

+
#define SOUP_TYPE_AUTH_NEGOTIATE  (soup_auth_negotiate_get_type ())
+
+

A GType corresponding to HTTP-based GSS-Negotiate authentication. +SoupSessions do not support this type by default; if you want to +enable support for it, call soup_session_add_feature_by_type(), +passing SOUP_TYPE_AUTH_NEGOTIATE.

+

This auth type will only work if libsoup was compiled with GSSAPI +support; you can check soup_auth_negotiate_supported() to see if it +was.

+

Since: 2.54

+
+
+
+

SOUP_AUTH_SCHEME_NAME

+
#define SOUP_AUTH_SCHEME_NAME      "scheme-name"
+
+

An alias for the “scheme-name” property. (The +authentication scheme name.)

+
+
+
+

SOUP_AUTH_REALM

+
#define SOUP_AUTH_REALM            "realm"
+
+

An alias for the “realm” property. (The +authentication realm.)

+
+
+
+

SOUP_AUTH_HOST

+
#define SOUP_AUTH_HOST             "host"
+
+

An alias for the “host” property. (The +host being authenticated to.)

+
+
+
+

SOUP_AUTH_IS_FOR_PROXY

+
#define SOUP_AUTH_IS_FOR_PROXY     "is-for-proxy"
+
+

An alias for the “is-for-proxy” property. (Whether +or not the auth is for a proxy server.)

+
+
+
+

SOUP_AUTH_IS_AUTHENTICATED

+
#define SOUP_AUTH_IS_AUTHENTICATED "is-authenticated"
+
+

An alias for the “is-authenticated” property. +(Whether or not the auth has been authenticated.)

+
+
+
+

Property Details

+
+

The “host” property

+
  “host”                     gchar *
+

Authentication host.

+

Flags: Read / Write

+

Default value: NULL

+
+
+
+

The “is-authenticated” property

+
  “is-authenticated”         gboolean
+

Whether or not the auth is authenticated.

+

Flags: Read

+

Default value: FALSE

+
+
+
+

The “is-for-proxy” property

+
  “is-for-proxy”             gboolean
+

Whether or not the auth is for a proxy server.

+

Flags: Read / Write

+

Default value: FALSE

+
+
+
+

The “realm” property

+
  “realm”                    gchar *
+

Authentication realm.

+

Flags: Read / Write

+

Default value: NULL

+
+
+
+

The “scheme-name” property

+
  “scheme-name”              gchar *
+

Authentication scheme name.

+

Flags: Read

+

Default value: NULL

+
+
+
+

See Also

+

SoupSession

+
+
+ + + \ No newline at end of file diff --git a/docs/reference/html/SoupAuthDomain.html b/docs/reference/html/SoupAuthDomain.html new file mode 100644 index 0000000..dcc3d3d --- /dev/null +++ b/docs/reference/html/SoupAuthDomain.html @@ -0,0 +1,928 @@ + + + + +SoupAuthDomain: libsoup Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

SoupAuthDomain

+

SoupAuthDomain — Server-side authentication

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+void + +soup_auth_domain_add_path () +
+void + +soup_auth_domain_remove_path () +
+gboolean + +(*SoupAuthDomainFilter) () +
+void + +soup_auth_domain_set_filter () +
const char * + +soup_auth_domain_get_realm () +
+gboolean + +(*SoupAuthDomainGenericAuthCallback) () +
+void + +soup_auth_domain_set_generic_auth_callback () +
+gboolean + +soup_auth_domain_check_password () +
+gboolean + +soup_auth_domain_covers () +
+char * + +soup_auth_domain_accepts () +
+void + +soup_auth_domain_challenge () +
+
+
+

Properties

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+gchar *add-pathWrite
gpointerfilterRead / Write
gpointerfilter-dataRead / Write
gpointergeneric-auth-callbackRead / Write
gpointergeneric-auth-dataRead / Write
gbooleanproxyRead / Write / Construct Only
+gchar *realmRead / Write / Construct Only
+gchar *remove-pathWrite
+
+
+

Types and Values

+ +
+
+

Object Hierarchy

+
    GObject
+    ╰── SoupAuthDomain
+        ├── SoupAuthDomainBasic
+        ╰── SoupAuthDomainDigest
+
+
+
+

Includes

+
#include <libsoup/soup.h>
+
+
+
+

Description

+

A SoupAuthDomain manages authentication for all or part of a +SoupServer. To make a server require authentication, first create +an appropriate subclass of SoupAuthDomain, and then add it to the +server with soup_server_add_auth_domain().

+

In order for an auth domain to have any effect, you must add one or +more paths to it (via soup_auth_domain_add_path() or the +SOUP_AUTH_DOMAIN_ADD_PATH property). To require authentication for +all ordinary requests, add the path "/". (Note that this does not +include the special "*" URI (eg, "OPTIONS *"), which must be added +as a separate path if you want to cover it.)

+

If you need greater control over which requests should and +shouldn't be authenticated, add paths covering everything you +might want authenticated, and then use a +filter (soup_auth_domain_set_filter()) to bypass authentication for +those requests that don't need it.

+
+
+

Functions

+
+

soup_auth_domain_add_path ()

+
void
+soup_auth_domain_add_path (SoupAuthDomain *domain,
+                           const char *path);
+

Adds path + to domain +, such that requests under path + on domain +'s +server will require authentication (unless overridden by +soup_auth_domain_remove_path() or soup_auth_domain_set_filter()).

+

You can also add paths by setting the SOUP_AUTH_DOMAIN_ADD_PATH +property, which can also be used to add one or more paths at +construct time.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

domain

a SoupAuthDomain

 

path

the path to add to domain +

 
+
+
+
+
+

soup_auth_domain_remove_path ()

+
void
+soup_auth_domain_remove_path (SoupAuthDomain *domain,
+                              const char *path);
+

Removes path + from domain +, such that requests under path + on +domain +'s server will NOT require authentication.

+

This is not simply an undo-er for soup_auth_domain_add_path(); it +can be used to "carve out" a subtree that does not require +authentication inside a hierarchy that does. Note also that unlike +with soup_auth_domain_add_path(), this cannot be overridden by +adding a filter, as filters can only bypass authentication that +would otherwise be required, not require it where it would +otherwise be unnecessary.

+

You can also remove paths by setting the +SOUP_AUTH_DOMAIN_REMOVE_PATH property, which can also be used to +remove one or more paths at construct time.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

domain

a SoupAuthDomain

 

path

the path to remove from domain +

 
+
+
+
+
+

SoupAuthDomainFilter ()

+
gboolean
+(*SoupAuthDomainFilter) (SoupAuthDomain *domain,
+                         SoupMessage *msg,
+                         gpointer user_data);
+

The prototype for a SoupAuthDomain filter; see +soup_auth_domain_set_filter() for details.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

domain

a SoupAuthDomain

 

msg

a SoupMessage

 

user_data

the data passed to soup_auth_domain_set_filter()

 
+
+
+

Returns

+

TRUE if msg +requires authentication, FALSE if not.

+
+
+
+
+

soup_auth_domain_set_filter ()

+
void
+soup_auth_domain_set_filter (SoupAuthDomain *domain,
+                             SoupAuthDomainFilter filter,
+                             gpointer filter_data,
+                             GDestroyNotify dnotify);
+

Adds filter + as an authentication filter to domain +. The filter +gets a chance to bypass authentication for certain requests that +would otherwise require it. Eg, it might check the message's path +in some way that is too complicated to do via the other methods, or +it might check the message's method, and allow GETs but not PUTs.

+

The filter function returns TRUE if the request should still +require authentication, or FALSE if authentication is unnecessary +for this request.

+

To help prevent security holes, your filter should return TRUE by +default, and only return FALSE under specifically-tested +circumstances, rather than the other way around. Eg, in the example +above, where you want to authenticate PUTs but not GETs, you should +check if the method is GET and return FALSE in that case, and then +return TRUE for all other methods (rather than returning TRUE for +PUT and FALSE for all other methods). This way if it turned out +(now or later) that some paths supported additional methods besides +GET and PUT, those methods would default to being NOT allowed for +unauthenticated users.

+

You can also set the filter by setting the SOUP_AUTH_DOMAIN_FILTER +and SOUP_AUTH_DOMAIN_FILTER_DATA properties, which can also be +used to set the filter at construct time.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

domain

a SoupAuthDomain

 

filter

the auth filter for domain +

 

filter_data

data to pass to filter +

 

dnotify

destroy notifier to free filter_data +when domain +is destroyed

 
+
+
+
+
+

soup_auth_domain_get_realm ()

+
const char *
+soup_auth_domain_get_realm (SoupAuthDomain *domain);
+

Gets the realm name associated with domain +

+
+

Parameters

+
+++++ + + + + + +

domain

a SoupAuthDomain

 
+
+
+

Returns

+

domain +'s realm

+
+
+
+
+

SoupAuthDomainGenericAuthCallback ()

+
gboolean
+(*SoupAuthDomainGenericAuthCallback) (SoupAuthDomain *domain,
+                                      SoupMessage *msg,
+                                      const char *username,
+                                      gpointer user_data);
+

The prototype for a SoupAuthDomain generic authentication callback.

+

The callback should look up the user's password, call +soup_auth_domain_check_password(), and use the return value from +that method as its own return value.

+

In general, for security reasons, it is preferable to use the +auth-domain-specific auth callbacks (eg, +SoupAuthDomainBasicAuthCallback and +SoupAuthDomainDigestAuthCallback), because they don't require +keeping a cleartext password database. Most users will use the same +password for many different sites, meaning if any site with a +cleartext password database is compromised, accounts on other +servers might be compromised as well. For many of the cases where +SoupServer is used, this is not really relevant, but it may still +be worth considering.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

domain

a SoupAuthDomain

 

msg

the SoupMessage being authenticated

 

username

the username from msg +

 

user_data

the data passed to +soup_auth_domain_set_generic_auth_callback()

 
+
+
+

Returns

+

TRUE if msg +is authenticated, FALSE if not.

+
+
+
+
+

soup_auth_domain_set_generic_auth_callback ()

+
void
+soup_auth_domain_set_generic_auth_callback
+                               (SoupAuthDomain *domain,
+                                SoupAuthDomainGenericAuthCallback auth_callback,
+                                gpointer auth_data,
+                                GDestroyNotify dnotify);
+

Sets auth_callback + as an authentication-handling callback for +domain +. Whenever a request comes in to domain + which cannot be +authenticated via a domain-specific auth callback (eg, +SoupAuthDomainDigestAuthCallback), the generic auth callback +will be invoked. See SoupAuthDomainGenericAuthCallback for information +on what the callback should do.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

domain

a SoupAuthDomain

 

auth_callback

the auth callback

 

auth_data

data to pass to auth_callback +

 

dnotify

destroy notifier to free auth_data +when domain +is destroyed

 
+
+
+
+
+

soup_auth_domain_check_password ()

+
gboolean
+soup_auth_domain_check_password (SoupAuthDomain *domain,
+                                 SoupMessage *msg,
+                                 const char *username,
+                                 const char *password);
+

Checks if msg + authenticates to domain + via username + and +password +. This would normally be called from a +SoupAuthDomainGenericAuthCallback.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

domain

a SoupAuthDomain

 

msg

a SoupMessage

 

username

a username

 

password

a password

 
+
+
+

Returns

+

whether or not the message is authenticated

+
+
+
+
+

soup_auth_domain_covers ()

+
gboolean
+soup_auth_domain_covers (SoupAuthDomain *domain,
+                         SoupMessage *msg);
+

Checks if domain + requires msg + to be authenticated (according to +its paths and filter function). This does not actually look at +whether msg + is authenticated, merely whether +or not it needs to be.

+

This is used by SoupServer internally and is probably of no use to +anyone else.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

domain

a SoupAuthDomain

 

msg

a SoupMessage

 
+
+
+

Returns

+

TRUE if domain +requires msg +to be authenticated

+
+
+
+
+

soup_auth_domain_accepts ()

+
char *
+soup_auth_domain_accepts (SoupAuthDomain *domain,
+                          SoupMessage *msg);
+

Checks if msg + contains appropriate authorization for domain + to +accept it. Mirroring soup_auth_domain_covers(), this does not check +whether or not domain + cares if msg + is +authorized.

+

This is used by SoupServer internally and is probably of no use to +anyone else.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

domain

a SoupAuthDomain

 

msg

a SoupMessage

 
+
+
+

Returns

+

the username that msg +has authenticated +as, if in fact it has authenticated. NULL otherwise.

+

[nullable]

+
+
+
+
+

soup_auth_domain_challenge ()

+
void
+soup_auth_domain_challenge (SoupAuthDomain *domain,
+                            SoupMessage *msg);
+

Adds a "WWW-Authenticate" or "Proxy-Authenticate" header to msg +, +requesting that the client authenticate, and sets msg +'s status +accordingly.

+

This is used by SoupServer internally and is probably of no use to +anyone else.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

domain

a SoupAuthDomain

 

msg

a SoupMessage

 
+
+
+
+
+

Types and Values

+
+

SoupAuthDomain

+
typedef struct _SoupAuthDomain SoupAuthDomain;
+
+
+
+

SOUP_AUTH_DOMAIN_REALM

+
#define SOUP_AUTH_DOMAIN_REALM       "realm"
+
+

Alias for the “realm” property. (The realm of +this auth domain.)

+
+
+
+

SOUP_AUTH_DOMAIN_PROXY

+
#define SOUP_AUTH_DOMAIN_PROXY       "proxy"
+
+

Alias for the “proxy” property. (Whether or +not this is a proxy auth domain.)

+
+
+
+

SOUP_AUTH_DOMAIN_ADD_PATH

+
#define SOUP_AUTH_DOMAIN_ADD_PATH    "add-path"
+
+

Alias for the “add-path” property. (Shortcut +for calling soup_auth_domain_add_path().)

+
+
+
+

SOUP_AUTH_DOMAIN_REMOVE_PATH

+
#define SOUP_AUTH_DOMAIN_REMOVE_PATH "remove-path"
+
+

Alias for the “remove-path” property. +(Shortcut for calling soup_auth_domain_remove_path().)

+
+
+
+

SOUP_AUTH_DOMAIN_FILTER

+
#define SOUP_AUTH_DOMAIN_FILTER      "filter"
+
+

Alias for the “filter” property. (The +SoupAuthDomainFilter for the domain.)

+
+
+
+

SOUP_AUTH_DOMAIN_FILTER_DATA

+
#define SOUP_AUTH_DOMAIN_FILTER_DATA "filter-data"
+
+

Alias for the “filter-data” property. (Data +to pass to the SoupAuthDomainFilter.)

+
+
+
+

SOUP_AUTH_DOMAIN_GENERIC_AUTH_CALLBACK

+
#define SOUP_AUTH_DOMAIN_GENERIC_AUTH_CALLBACK "generic-auth-callback"
+
+

Alias for the “generic-auth-callback” property. +(The SoupAuthDomainGenericAuthCallback.)

+
+
+
+

SOUP_AUTH_DOMAIN_GENERIC_AUTH_DATA

+
#define SOUP_AUTH_DOMAIN_GENERIC_AUTH_DATA     "generic-auth-data"
+
+

Alias for the “generic-auth-data” property. +(The data to pass to the SoupAuthDomainGenericAuthCallback.)

+
+
+
+

Property Details

+
+

The “add-path” property

+
  “add-path”                 gchar *
+

Add a path covered by this auth domain.

+

Flags: Write

+

Default value: NULL

+
+
+
+

The “filter” property

+
  “filter”                   gpointer
+

A filter for deciding whether or not to require authentication.

+

Flags: Read / Write

+
+
+
+

The “filter-data” property

+
  “filter-data”              gpointer
+

Data to pass to filter.

+

Flags: Read / Write

+
+
+
+

The “generic-auth-callback” property

+
  “generic-auth-callback”    gpointer
+

An authentication callback that can be used with any SoupAuthDomain subclass.

+

Flags: Read / Write

+
+
+
+

The “generic-auth-data” property

+
  “generic-auth-data”        gpointer
+

Data to pass to auth callback.

+

Flags: Read / Write

+
+
+
+

The “proxy” property

+
  “proxy”                    gboolean
+

Whether or not this is a proxy auth domain.

+

Flags: Read / Write / Construct Only

+

Default value: FALSE

+
+
+
+

The “realm” property

+
  “realm”                    gchar *
+

The realm of this auth domain.

+

Flags: Read / Write / Construct Only

+

Default value: NULL

+
+
+
+

The “remove-path” property

+
  “remove-path”              gchar *
+

Remove a path covered by this auth domain.

+

Flags: Write

+

Default value: NULL

+
+
+
+

See Also

+

SoupServer

+
+
+ + + \ No newline at end of file diff --git a/docs/reference/html/SoupAuthDomainBasic.html b/docs/reference/html/SoupAuthDomainBasic.html new file mode 100644 index 0000000..cef727f --- /dev/null +++ b/docs/reference/html/SoupAuthDomainBasic.html @@ -0,0 +1,339 @@ + + + + +SoupAuthDomainBasic: libsoup Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

SoupAuthDomainBasic

+

SoupAuthDomainBasic — Server-side "Basic" authentication

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + +
+SoupAuthDomain * + +soup_auth_domain_basic_new () +
+gboolean + +(*SoupAuthDomainBasicAuthCallback) () +
+void + +soup_auth_domain_basic_set_auth_callback () +
+
+
+

Properties

+
+++++ + + + + + + + + + + + + +
gpointerauth-callbackRead / Write
gpointerauth-dataRead / Write
+
+
+

Types and Values

+ +
+
+

Object Hierarchy

+
    GObject
+    ╰── SoupAuthDomain
+        ╰── SoupAuthDomainBasic
+
+
+
+

Includes

+
#include <libsoup/soup.h>
+
+
+
+

Description

+

SoupAuthDomainBasic handles the server side of HTTP "Basic" (ie, +cleartext password) authentication.

+
+
+

Functions

+
+

soup_auth_domain_basic_new ()

+
SoupAuthDomain *
+soup_auth_domain_basic_new (const char *optname1,
+                            ...);
+

Creates a SoupAuthDomainBasic. You must set the +SOUP_AUTH_DOMAIN_REALM parameter, to indicate the realm name to be +returned with the authentication challenge to the client. Other +parameters are optional.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

optname1

name of first option, or NULL

 

...

option name/value pairs

 
+
+
+

Returns

+

the new SoupAuthDomain

+
+
+
+
+

SoupAuthDomainBasicAuthCallback ()

+
gboolean
+(*SoupAuthDomainBasicAuthCallback) (SoupAuthDomain *domain,
+                                    SoupMessage *msg,
+                                    const char *username,
+                                    const char *password,
+                                    gpointer user_data);
+

Callback used by SoupAuthDomainBasic for authentication purposes. +The application should verify that username + and password + and valid +and return TRUE or FALSE.

+

If you are maintaining your own password database (rather than +using the password to authenticate against some other system like +PAM or a remote server), you should make sure you know what you are +doing. In particular, don't store cleartext passwords, or +easily-computed hashes of cleartext passwords, even if you don't +care that much about the security of your server, because users +will frequently use the same password for multiple sites, and so +compromising any site with a cleartext (or easily-cracked) password +database may give attackers access to other more-interesting sites +as well.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

domain

the domain

 

msg

the message being authenticated

 

username

the username provided by the client

 

password

the password provided by the client

 

user_data

the data passed to soup_auth_domain_basic_set_auth_callback()

 
+
+
+

Returns

+

TRUE if username +and password +are valid

+
+
+
+
+

soup_auth_domain_basic_set_auth_callback ()

+
void
+soup_auth_domain_basic_set_auth_callback
+                               (SoupAuthDomain *domain,
+                                SoupAuthDomainBasicAuthCallback callback,
+                                gpointer user_data,
+                                GDestroyNotify dnotify);
+

Sets the callback that domain + will use to authenticate incoming +requests. For each request containing authorization, domain + will +invoke the callback, and then either accept or reject the request +based on callback +'s return value.

+

You can also set the auth callback by setting the +SOUP_AUTH_DOMAIN_BASIC_AUTH_CALLBACK and +SOUP_AUTH_DOMAIN_BASIC_AUTH_DATA properties, which can also be +used to set the callback at construct time.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

domain

the domain

 

callback

the callback

 

user_data

data to pass to auth_callback +

 

dnotify

destroy notifier to free user_data +when domain +is destroyed

 
+
+
+
+
+

Types and Values

+
+

SoupAuthDomainBasic

+
typedef struct _SoupAuthDomainBasic SoupAuthDomainBasic;
+
+
+
+

SOUP_AUTH_DOMAIN_BASIC_AUTH_CALLBACK

+
#define SOUP_AUTH_DOMAIN_BASIC_AUTH_CALLBACK "auth-callback"
+
+

Alias for the “auth-callback” property. +(The SoupAuthDomainBasicAuthCallback.)

+
+
+
+

SOUP_AUTH_DOMAIN_BASIC_AUTH_DATA

+
#define SOUP_AUTH_DOMAIN_BASIC_AUTH_DATA     "auth-data"
+
+

Alias for the “auth-data” property. +(The data to pass to the SoupAuthDomainBasicAuthCallback.)

+
+
+
+

Property Details

+
+

The “auth-callback” property

+
  “auth-callback”            gpointer
+

Password-checking callback.

+

Flags: Read / Write

+
+
+
+

The “auth-data” property

+
  “auth-data”                gpointer
+

Data to pass to authentication callback.

+

Flags: Read / Write

+
+
+
+ + + \ No newline at end of file diff --git a/docs/reference/html/SoupAuthDomainDigest.html b/docs/reference/html/SoupAuthDomainDigest.html new file mode 100644 index 0000000..3e6f780 --- /dev/null +++ b/docs/reference/html/SoupAuthDomainDigest.html @@ -0,0 +1,391 @@ + + + + +SoupAuthDomainDigest: libsoup Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

SoupAuthDomainDigest

+

SoupAuthDomainDigest — Server-side "Digest" authentication

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + +
+SoupAuthDomain * + +soup_auth_domain_digest_new () +
+char * + +(*SoupAuthDomainDigestAuthCallback) () +
+void + +soup_auth_domain_digest_set_auth_callback () +
+char * + +soup_auth_domain_digest_encode_password () +
+
+
+

Properties

+
+++++ + + + + + + + + + + + + +
gpointerauth-callbackRead / Write
gpointerauth-dataRead / Write
+
+
+

Types and Values

+ +
+
+

Object Hierarchy

+
    GObject
+    ╰── SoupAuthDomain
+        ╰── SoupAuthDomainDigest
+
+
+
+

Includes

+
#include <libsoup/soup.h>
+
+
+
+

Description

+

SoupAuthDomainDigest handles the server side of HTTP "Digest" +authentication.

+
+
+

Functions

+
+

soup_auth_domain_digest_new ()

+
SoupAuthDomain *
+soup_auth_domain_digest_new (const char *optname1,
+                             ...);
+

Creates a SoupAuthDomainDigest. You must set the +SOUP_AUTH_DOMAIN_REALM parameter, to indicate the realm name to be +returned with the authentication challenge to the client. Other +parameters are optional.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

optname1

name of first option, or NULL

 

...

option name/value pairs

 
+
+
+

Returns

+

the new SoupAuthDomain

+
+
+
+
+

SoupAuthDomainDigestAuthCallback ()

+
char *
+(*SoupAuthDomainDigestAuthCallback) (SoupAuthDomain *domain,
+                                     SoupMessage *msg,
+                                     const char *username,
+                                     gpointer user_data);
+

Callback used by SoupAuthDomainDigest for authentication purposes. +The application should look up username + in its password database, +and return the corresponding encoded password (see +soup_auth_domain_digest_encode_password()).

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

domain

the domain

 

msg

the message being authenticated

 

username

the username provided by the client

 

user_data

the data passed to soup_auth_domain_digest_set_auth_callback()

 
+
+
+

Returns

+

the encoded password, or NULL if +username +is not a valid user. domain +will free the password when +it is done with it.

+

[nullable]

+
+
+
+
+

soup_auth_domain_digest_set_auth_callback ()

+
void
+soup_auth_domain_digest_set_auth_callback
+                               (SoupAuthDomain *domain,
+                                SoupAuthDomainDigestAuthCallback callback,
+                                gpointer user_data,
+                                GDestroyNotify dnotify);
+

Sets the callback that domain + will use to authenticate incoming +requests. For each request containing authorization, domain + will +invoke the callback, and then either accept or reject the request +based on callback +'s return value.

+

You can also set the auth callback by setting the +SOUP_AUTH_DOMAIN_DIGEST_AUTH_CALLBACK and +SOUP_AUTH_DOMAIN_DIGEST_AUTH_DATA properties, which can also be +used to set the callback at construct time.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

domain

the domain

 

callback

the callback

 

user_data

data to pass to auth_callback +

 

dnotify

destroy notifier to free user_data +when domain +is destroyed

 
+
+
+
+
+

soup_auth_domain_digest_encode_password ()

+
char *
+soup_auth_domain_digest_encode_password
+                               (const char *username,
+                                const char *realm,
+                                const char *password);
+

Encodes the username/realm/password triplet for Digest +authentication. (That is, it returns a stringified MD5 hash of +username +, realm +, and password + concatenated together). This is +the form that is needed as the return value of +SoupAuthDomainDigest's auth handler.

+

For security reasons, you should store the encoded hash, rather +than storing the cleartext password itself and calling this method +only when you need to verify it. This way, if your server is +compromised, the attackers will not gain access to cleartext +passwords which might also be usable at other sites. (Note also +that the encoded password returned by this method is identical to +the encoded password stored in an Apache .htdigest file.)

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

username

a username

 

realm

an auth realm name

 

password

the password for username +in realm +

 
+
+
+

Returns

+

the encoded password

+
+
+
+
+

Types and Values

+
+

SoupAuthDomainDigest

+
typedef struct _SoupAuthDomainDigest SoupAuthDomainDigest;
+
+
+
+

SOUP_AUTH_DOMAIN_DIGEST_AUTH_CALLBACK

+
#define SOUP_AUTH_DOMAIN_DIGEST_AUTH_CALLBACK "auth-callback"
+
+

Alias for the “auth-callback” property. +(The SoupAuthDomainDigestAuthCallback.)

+
+
+
+

SOUP_AUTH_DOMAIN_DIGEST_AUTH_DATA

+
#define SOUP_AUTH_DOMAIN_DIGEST_AUTH_DATA     "auth-data"
+
+

Alias for the “auth-callback” property. +(The SoupAuthDomainDigestAuthCallback.)

+
+
+
+

Property Details

+
+

The “auth-callback” property

+
  “auth-callback”            gpointer
+

Password-finding callback.

+

Flags: Read / Write

+
+
+
+

The “auth-data” property

+
  “auth-data”                gpointer
+

Data to pass to authentication callback.

+

Flags: Read / Write

+
+
+
+ + + \ No newline at end of file diff --git a/docs/reference/html/SoupAuthManager.html b/docs/reference/html/SoupAuthManager.html new file mode 100644 index 0000000..6283963 --- /dev/null +++ b/docs/reference/html/SoupAuthManager.html @@ -0,0 +1,284 @@ + + + + +SoupAuthManager: libsoup Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

SoupAuthManager

+

SoupAuthManager — HTTP client-side authentication handler

+
+
+

Functions

+
++++ + + + + + + + + + + +
+void + +soup_auth_manager_use_auth () +
+void + +soup_auth_manager_clear_cached_credentials () +
+
+
+

Signals

+
+++++ + + + + + +
voidauthenticateRun First
+
+
+

Types and Values

+
++++ + + + + + + + + + + +
 SoupAuthManager
#defineSOUP_TYPE_AUTH_MANAGER
+
+
+

Object Hierarchy

+
    GObject
+    ╰── SoupAuthManager
+
+
+
+

Implemented Interfaces

+

+SoupAuthManager implements + SoupSessionFeature.

+
+
+

Includes

+
#include <libsoup/soup.h>
+
+
+
+

Description

+

SoupAuthManager is the SoupSessionFeature that handles HTTP +authentication for a SoupSession.

+

A SoupAuthManager is added to the session by default, and normally +you don't need to worry about it at all. However, if you want to +disable HTTP authentication, you can remove the feature from the +session with soup_session_remove_feature_by_type(), or disable it on +individual requests with soup_message_disable_feature().

+
+
+

Functions

+
+

soup_auth_manager_use_auth ()

+
void
+soup_auth_manager_use_auth (SoupAuthManager *manager,
+                            SoupURI *uri,
+                            SoupAuth *auth);
+

Records that auth + is to be used under uri +, as though a +WWW-Authenticate header had been received at that URI. This can be +used to "preload" manager +'s auth cache, to avoid an extra HTTP +round trip in the case where you know ahead of time that a 401 +response will be returned.

+

This is only useful for authentication types where the initial +Authorization header does not depend on any additional information +from the server. (Eg, Basic or NTLM, but not Digest.)

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

manager

a SoupAuthManager

 

uri

the SoupURI under which auth +is to be used

 

auth

the SoupAuth to use

 
+
+

Since: 2.42

+
+
+
+

soup_auth_manager_clear_cached_credentials ()

+
void
+soup_auth_manager_clear_cached_credentials
+                               (SoupAuthManager *manager);
+

Clear all credentials cached by manager +

+
+

Parameters

+
+++++ + + + + + +

manager

a SoupAuthManager

 
+
+

Since: 2.58

+
+
+
+

Types and Values

+
+

SoupAuthManager

+
typedef struct _SoupAuthManager SoupAuthManager;
+
+
+
+

SOUP_TYPE_AUTH_MANAGER

+
#define SOUP_TYPE_AUTH_MANAGER            (soup_auth_manager_get_type ())
+
+

The GType of SoupAuthManager; you can use this with +soup_session_remove_feature_by_type() or +soup_message_disable_feature().

+

(Although this type has only been publicly visible since libsoup +2.42, it has always existed in the background, and you can use +g_type_from_name ("SoupAuthManager") +to get its GType in earlier releases.)

+

Since: 2.42

+
+
+
+

Signal Details

+
+

The “authenticate” signal

+
void
+user_function (SoupAuthManager *manager,
+               SoupMessage     *msg,
+               SoupAuth        *auth,
+               gboolean         retrying,
+               gpointer         user_data)
+

Emitted when the manager requires the application to +provide authentication credentials.

+

SoupSession connects to this signal and emits its own +“authenticate” signal when it is emitted, so +you shouldn't need to use this signal directly.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

manager

the SoupAuthManager

 

msg

the SoupMessage being sent

 

auth

the SoupAuth to authenticate

 

retrying

TRUE if this is the second (or later) attempt

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+
+
+
+

See Also

+

SoupSession, SoupAuth

+
+
+ + + \ No newline at end of file diff --git a/docs/reference/html/SoupCache.html b/docs/reference/html/SoupCache.html new file mode 100644 index 0000000..e112201 --- /dev/null +++ b/docs/reference/html/SoupCache.html @@ -0,0 +1,431 @@ + + + + +SoupCache: libsoup Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

SoupCache

+

SoupCache — Caching support

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+SoupCache * + +soup_cache_new () +
+void + +soup_cache_flush () +
+void + +soup_cache_clear () +
+void + +soup_cache_dump () +
+void + +soup_cache_load () +
+guint + +soup_cache_get_max_size () +
+void + +soup_cache_set_max_size () +
+
+
+

Properties

+
+++++ + + + + + + + + + + + + +
+gchar *cache-dirRead / Write / Construct Only
SoupCacheTypecache-typeRead / Write / Construct Only
+
+
+

Types and Values

+
++++ + + + + + + + + + + +
structSoupCache
enumSoupCacheType
+
+
+

Object Hierarchy

+
    GObject
+    ╰── SoupCache
+
+
+
+

Implemented Interfaces

+

+SoupCache implements + SoupSessionFeature and SoupContentProcessor.

+
+
+

Includes

+
#include <libsoup/soup.h>
+
+
+
+

Description

+

SoupCache implements a file-based cache for HTTP resources.

+
+
+

Functions

+
+

soup_cache_new ()

+
SoupCache *
+soup_cache_new (const char *cache_dir,
+                SoupCacheType cache_type);
+

Creates a new SoupCache.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

cache_dir

the directory to store the cached data, or NULL +to use the default one. Note that since the cache isn't safe to access for +multiple processes at once, and the default directory isn't namespaced by +process, clients are strongly discouraged from passing NULL.

[allow-none]

cache_type

the SoupCacheType of the cache

 
+
+
+

Returns

+

a new SoupCache

+
+

Since: 2.34

+
+
+
+

soup_cache_flush ()

+
void
+soup_cache_flush (SoupCache *cache);
+

This function will force all pending writes in the cache + to be +committed to disk. For doing so it will iterate the GMainContext +associated with cache +'s session as long as needed.

+

Contrast with soup_cache_dump(), which writes out the cache index +file.

+
+

Parameters

+
+++++ + + + + + +

cache

a SoupCache

 
+
+

Since: 2.34

+
+
+
+

soup_cache_clear ()

+
void
+soup_cache_clear (SoupCache *cache);
+

Will remove all entries in the cache + plus all the cache files.

+
+

Parameters

+
+++++ + + + + + +

cache

a SoupCache

 
+
+

Since: 2.34

+
+
+
+

soup_cache_dump ()

+
void
+soup_cache_dump (SoupCache *cache);
+

Synchronously writes the cache index out to disk. Contrast with +soup_cache_flush(), which writes pending cache +entries to disk.

+

You must call this before exiting if you want your cache data to +persist between sessions.

+
+

Parameters

+
+++++ + + + + + +

cache

a SoupCache

 
+
+

Since: 2.34.

+
+
+
+

soup_cache_load ()

+
void
+soup_cache_load (SoupCache *cache);
+

Loads the contents of cache +'s index into memory.

+
+

Parameters

+
+++++ + + + + + +

cache

a SoupCache

 
+
+

Since: 2.34

+
+
+
+

soup_cache_get_max_size ()

+
guint
+soup_cache_get_max_size (SoupCache *cache);
+

Gets the maximum size of the cache.

+
+

Parameters

+
+++++ + + + + + +

cache

a SoupCache

 
+
+
+

Returns

+

the maximum size of the cache, in bytes.

+
+

Since: 2.34

+
+
+
+

soup_cache_set_max_size ()

+
void
+soup_cache_set_max_size (SoupCache *cache,
+                         guint max_size);
+

Sets the maximum size of the cache.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

cache

a SoupCache

 

max_size

the maximum size of the cache, in bytes

 
+
+

Since: 2.34

+
+
+
+

Types and Values

+
+

struct SoupCache

+
struct SoupCache;
+
+
+
+

enum SoupCacheType

+

The type of cache; this affects what kinds of responses will be +saved.

+
+

Members

+
+++++ + + + + + + + + + + + + +

SOUP_CACHE_SINGLE_USER

+

a single-user cache

+
 

SOUP_CACHE_SHARED

+

a shared cache

+
 
+
+

Since: 2.34

+
+
+
+

Property Details

+
+

The “cache-dir” property

+
  “cache-dir”                gchar *
+

The directory to store the cache files.

+

Flags: Read / Write / Construct Only

+

Default value: NULL

+
+
+
+

The “cache-type” property

+
  “cache-type”               SoupCacheType
+

Whether the cache is private or shared.

+

Flags: Read / Write / Construct Only

+

Default value: SOUP_CACHE_SINGLE_USER

+
+
+
+ + + \ No newline at end of file diff --git a/docs/reference/html/SoupContentDecoder.html b/docs/reference/html/SoupContentDecoder.html new file mode 100644 index 0000000..9082cb9 --- /dev/null +++ b/docs/reference/html/SoupContentDecoder.html @@ -0,0 +1,108 @@ + + + + +SoupContentDecoder: libsoup Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

SoupContentDecoder

+

SoupContentDecoder — Content-Encoding handler

+
+
+

Types and Values

+
++++ + + + + +
 SoupContentDecoder
+
+
+

Object Hierarchy

+
    GObject
+    ╰── SoupContentDecoder
+
+
+
+

Implemented Interfaces

+

+SoupContentDecoder implements + SoupSessionFeature and SoupContentProcessor.

+
+
+

Includes

+
#include <libsoup/soup.h>
+
+
+
+

Description

+

SoupContentDecoder handles adding the "Accept-Encoding" header on +outgoing messages, and processing the "Content-Encoding" header on +incoming ones. Currently it supports the "gzip" and "deflate" +content codings.

+

If you are using a plain SoupSession (ie, not SoupSessionAsync or +SoupSessionSync), then a SoupContentDecoder will automatically be +added to the session by default. (You can use +SOUP_SESSION_REMOVE_FEATURE_BY_TYPE at construct time if you don't +want this.) If you are using one of the deprecated SoupSession +subclasses, you can add a SoupContentDecoder to your session with +soup_session_add_feature() or soup_session_add_feature_by_type().

+

If SoupContentDecoder successfully decodes the Content-Encoding, +it will set the SOUP_MESSAGE_CONTENT_DECODED flag on the message, +and the message body and the chunks in the “got_chunk” +signals will contain the decoded data; however, the message headers +will be unchanged (and so "Content-Encoding" will still be present, +"Content-Length" will describe the original encoded length, etc).

+

If "Content-Encoding" contains any encoding types that +SoupContentDecoder doesn't recognize, then none of the encodings +will be decoded (and the SOUP_MESSAGE_CONTENT_DECODED flag will +not be set).

+

(Note that currently there is no way to (automatically) use +Content-Encoding when sending a request body, or to pick specific +encoding types to support.)

+
+
+

Functions

+

+
+
+

Types and Values

+
+

SoupContentDecoder

+
typedef struct _SoupContentDecoder SoupContentDecoder;
+
+
+
+ + + \ No newline at end of file diff --git a/docs/reference/html/SoupContentSniffer.html b/docs/reference/html/SoupContentSniffer.html new file mode 100644 index 0000000..7bfe8ab --- /dev/null +++ b/docs/reference/html/SoupContentSniffer.html @@ -0,0 +1,219 @@ + + + + +SoupContentSniffer: libsoup Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

SoupContentSniffer

+

SoupContentSniffer — Content sniffing for SoupSession

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + +
+SoupContentSniffer * + +soup_content_sniffer_new () +
+char * + +soup_content_sniffer_sniff () +
+gsize + +soup_content_sniffer_get_buffer_size () +
+
+
+

Types and Values

+
++++ + + + + +
 SoupContentSniffer
+
+
+

Object Hierarchy

+
    GObject
+    ╰── SoupContentSniffer
+
+
+
+

Implemented Interfaces

+

+SoupContentSniffer implements + SoupSessionFeature and SoupContentProcessor.

+
+
+

Includes

+
#include <libsoup/soup.h>
+
+
+
+

Description

+

A SoupContentSniffer tries to detect the actual content type of +the files that are being downloaded by looking at some of the data +before the SoupMessage emits its “got-headers” signal. +SoupContentSniffer implements SoupSessionFeature, so you can add +content sniffing to a session with soup_session_add_feature() or +soup_session_add_feature_by_type().

+
+
+

Functions

+
+

soup_content_sniffer_new ()

+
SoupContentSniffer *
+soup_content_sniffer_new (void);
+

Creates a new SoupContentSniffer.

+
+

Returns

+

a new SoupContentSniffer

+
+

Since: 2.28

+
+
+
+

soup_content_sniffer_sniff ()

+
char *
+soup_content_sniffer_sniff (SoupContentSniffer *sniffer,
+                            SoupMessage *msg,
+                            SoupBuffer *buffer,
+                            GHashTable **params);
+

Sniffs buffer + to determine its Content-Type. The result may also +be influenced by the Content-Type declared in msg +'s response +headers.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

sniffer

a SoupContentSniffer

 

msg

the message to sniff

 

buffer

a buffer containing the start of msg +'s response body

 

params

return +location for Content-Type parameters (eg, "charset"), or NULL.

[element-type utf8 utf8][out][transfer full][allow-none]
+
+
+

Returns

+

the sniffed Content-Type of buffer +; this will never be NULL, +but may be "application/octet-stream".

+
+

Since: 2.28

+
+
+
+

soup_content_sniffer_get_buffer_size ()

+
gsize
+soup_content_sniffer_get_buffer_size (SoupContentSniffer *sniffer);
+

Gets the number of bytes sniffer + needs in order to properly sniff +a buffer.

+
+

Parameters

+
+++++ + + + + + +

sniffer

a SoupContentSniffer

 
+
+
+

Returns

+

the number of bytes to sniff

+
+

Since: 2.28

+
+
+
+

Types and Values

+
+

SoupContentSniffer

+
typedef struct _SoupContentSniffer SoupContentSniffer;
+
+
+
+ + + \ No newline at end of file diff --git a/docs/reference/html/SoupCookie.html b/docs/reference/html/SoupCookie.html new file mode 100644 index 0000000..45f6443 --- /dev/null +++ b/docs/reference/html/SoupCookie.html @@ -0,0 +1,1468 @@ + + + + +SoupCookie: libsoup Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

SoupCookie

+

SoupCookie — HTTP Cookies

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+SoupCookie * + +soup_cookie_new () +
+SoupCookie * + +soup_cookie_parse () +
+SoupCookie * + +soup_cookie_copy () +
+void + +soup_cookie_free () +
+void + +soup_cookie_set_name () +
const char * + +soup_cookie_get_name () +
+void + +soup_cookie_set_value () +
const char * + +soup_cookie_get_value () +
+void + +soup_cookie_set_domain () +
const char * + +soup_cookie_get_domain () +
+void + +soup_cookie_set_path () +
const char * + +soup_cookie_get_path () +
+void + +soup_cookie_set_max_age () +
+void + +soup_cookie_set_expires () +
+SoupDate * + +soup_cookie_get_expires () +
+void + +soup_cookie_set_secure () +
+gboolean + +soup_cookie_get_secure () +
+void + +soup_cookie_set_http_only () +
+gboolean + +soup_cookie_get_http_only () +
+gboolean + +soup_cookie_applies_to_uri () +
+gboolean + +soup_cookie_domain_matches () +
+char * + +soup_cookie_to_cookie_header () +
+char * + +soup_cookie_to_set_cookie_header () +
+GSList * + +soup_cookies_from_request () +
+GSList * + +soup_cookies_from_response () +
+void + +soup_cookies_to_request () +
+void + +soup_cookies_to_response () +
+char * + +soup_cookies_to_cookie_header () +
+void + +soup_cookies_free () +
+
+
+

Types and Values

+
++++ + + + + + + + + + + + + + + + + + + + + + + +
 SoupCookie
#defineSOUP_COOKIE_MAX_AGE_ONE_HOUR
#defineSOUP_COOKIE_MAX_AGE_ONE_DAY
#defineSOUP_COOKIE_MAX_AGE_ONE_WEEK
#defineSOUP_COOKIE_MAX_AGE_ONE_YEAR
+
+
+

Object Hierarchy

+
    GBoxed
+    ╰── SoupCookie
+
+
+
+

Includes

+
#include <libsoup/soup.h>
+
+
+
+

Description

+

SoupCookie implements HTTP cookies, as described by RFC 6265.

+

To have a SoupSession handle cookies for your appliction +automatically, use a SoupCookieJar.

+
+
+

Functions

+
+

soup_cookie_new ()

+
SoupCookie *
+soup_cookie_new (const char *name,
+                 const char *value,
+                 const char *domain,
+                 const char *path,
+                 int max_age);
+

Creates a new SoupCookie with the given attributes. (Use +soup_cookie_set_secure() and soup_cookie_set_http_only() if you +need to set those attributes on the returned cookie.)

+

If domain + starts with ".", that indicates a domain (which matches +the string after the ".", or any hostname that has domain + as a +suffix). Otherwise, it is a hostname and must match exactly.

+

max_age + is used to set the "expires" attribute on the cookie; pass +-1 to not include the attribute (indicating that the cookie expires +with the current session), 0 for an already-expired cookie, or a +lifetime in seconds. You can use the constants +SOUP_COOKIE_MAX_AGE_ONE_HOUR, SOUP_COOKIE_MAX_AGE_ONE_DAY, +SOUP_COOKIE_MAX_AGE_ONE_WEEK and SOUP_COOKIE_MAX_AGE_ONE_YEAR (or +multiples thereof) to calculate this value. (If you really care +about setting the exact time that the cookie will expire, use +soup_cookie_set_expires().)

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

name

cookie name

 

value

cookie value

 

domain

cookie domain or hostname

 

path

cookie path, or NULL

 

max_age

max age of the cookie, or -1 for a session cookie

 
+
+
+

Returns

+

a new SoupCookie.

+
+

Since: 2.24

+
+
+
+

soup_cookie_parse ()

+
SoupCookie *
+soup_cookie_parse (const char *header,
+                   SoupURI *origin);
+

Parses header + and returns a SoupCookie. (If header + contains +multiple cookies, only the first one will be parsed.)

+

If header + does not have "path" or "domain" attributes, they will +be defaulted from origin +. If origin + is NULL, path will default +to "/", but domain will be left as NULL. Note that this is not a +valid state for a SoupCookie, and you will need to fill in some +appropriate string for the domain if you want to actually make use +of the cookie.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

header

a cookie string (eg, the value of a Set-Cookie header)

 

origin

origin of the cookie, or NULL

 
+
+
+

Returns

+

a new SoupCookie, or NULL if it could +not be parsed, or contained an illegal "domain" attribute for a +cookie originating from origin +.

+

[nullable]

+
+

Since: 2.24

+
+
+
+

soup_cookie_copy ()

+
SoupCookie *
+soup_cookie_copy (SoupCookie *cookie);
+

Copies cookie +.

+
+

Parameters

+
+++++ + + + + + +

cookie

a SoupCookie

 
+
+
+

Returns

+

a copy of cookie +

+
+

Since: 2.24

+
+
+
+

soup_cookie_free ()

+
void
+soup_cookie_free (SoupCookie *cookie);
+

Frees cookie +

+
+

Parameters

+
+++++ + + + + + +

cookie

a SoupCookie

 
+
+

Since: 2.24

+
+
+
+

soup_cookie_set_name ()

+
void
+soup_cookie_set_name (SoupCookie *cookie,
+                      const char *name);
+

Sets cookie +'s name to name +

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

cookie

a SoupCookie

 

name

the new name

 
+
+

Since: 2.24

+
+
+
+

soup_cookie_get_name ()

+
const char *
+soup_cookie_get_name (SoupCookie *cookie);
+

Gets cookie +'s name

+
+

Parameters

+
+++++ + + + + + +

cookie

a SoupCookie

 
+
+
+

Returns

+

cookie +'s name

+
+

Since: 2.32

+
+
+
+

soup_cookie_set_value ()

+
void
+soup_cookie_set_value (SoupCookie *cookie,
+                       const char *value);
+

Sets cookie +'s value to value +

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

cookie

a SoupCookie

 

value

the new value

 
+
+

Since: 2.24

+
+
+
+

soup_cookie_get_value ()

+
const char *
+soup_cookie_get_value (SoupCookie *cookie);
+

Gets cookie +'s value

+
+

Parameters

+
+++++ + + + + + +

cookie

a SoupCookie

 
+
+
+

Returns

+

cookie +'s value

+
+

Since: 2.32

+
+
+
+

soup_cookie_set_domain ()

+
void
+soup_cookie_set_domain (SoupCookie *cookie,
+                        const char *domain);
+

Sets cookie +'s domain to domain +

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

cookie

a SoupCookie

 

domain

the new domain

 
+
+

Since: 2.24

+
+
+
+

soup_cookie_get_domain ()

+
const char *
+soup_cookie_get_domain (SoupCookie *cookie);
+

Gets cookie +'s domain

+
+

Parameters

+
+++++ + + + + + +

cookie

a SoupCookie

 
+
+
+

Returns

+

cookie +'s domain

+
+

Since: 2.32

+
+
+
+

soup_cookie_set_path ()

+
void
+soup_cookie_set_path (SoupCookie *cookie,
+                      const char *path);
+

Sets cookie +'s path to path +

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

cookie

a SoupCookie

 

path

the new path

 
+
+

Since: 2.24

+
+
+
+

soup_cookie_get_path ()

+
const char *
+soup_cookie_get_path (SoupCookie *cookie);
+

Gets cookie +'s path

+
+

Parameters

+
+++++ + + + + + +

cookie

a SoupCookie

 
+
+
+

Returns

+

cookie +'s path

+
+

Since: 2.32

+
+
+
+

soup_cookie_set_max_age ()

+
void
+soup_cookie_set_max_age (SoupCookie *cookie,
+                         int max_age);
+

Sets cookie +'s max age to max_age +. If max_age + is -1, the cookie +is a session cookie, and will expire at the end of the client's +session. Otherwise, it is the number of seconds until the cookie +expires. You can use the constants SOUP_COOKIE_MAX_AGE_ONE_HOUR, +SOUP_COOKIE_MAX_AGE_ONE_DAY, SOUP_COOKIE_MAX_AGE_ONE_WEEK and +SOUP_COOKIE_MAX_AGE_ONE_YEAR (or multiples thereof) to calculate +this value. (A value of 0 indicates that the cookie should be +considered already-expired.)

+

(This sets the same property as soup_cookie_set_expires().)

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

cookie

a SoupCookie

 

max_age

the new max age

 
+
+

Since: 2.24

+
+
+
+

soup_cookie_set_expires ()

+
void
+soup_cookie_set_expires (SoupCookie *cookie,
+                         SoupDate *expires);
+

Sets cookie +'s expiration time to expires +. If expires + is NULL, +cookie + will be a session cookie and will expire at the end of the +client's session.

+

(This sets the same property as soup_cookie_set_max_age().)

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

cookie

a SoupCookie

 

expires

the new expiration time, or NULL

 
+
+

Since: 2.24

+
+
+
+

soup_cookie_get_expires ()

+
SoupDate *
+soup_cookie_get_expires (SoupCookie *cookie);
+

Gets cookie +'s expiration time.

+
+

Parameters

+
+++++ + + + + + +

cookie

a SoupCookie

 
+
+
+

Returns

+

cookie +'s expiration +time, which is owned by cookie +and should not be modified or +freed.

+

[nullable][transfer none]

+
+

Since: 2.32

+
+
+
+

soup_cookie_set_secure ()

+
void
+soup_cookie_set_secure (SoupCookie *cookie,
+                        gboolean secure);
+

Sets cookie +'s secure attribute to secure +. If TRUE, cookie + will +only be transmitted from the client to the server over secure +(https) connections.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

cookie

a SoupCookie

 

secure

the new value for the secure attribute

 
+
+

Since: 2.24

+
+
+
+

soup_cookie_get_secure ()

+
gboolean
+soup_cookie_get_secure (SoupCookie *cookie);
+

Gets cookie +'s secure attribute

+
+

Parameters

+
+++++ + + + + + +

cookie

a SoupCookie

 
+
+
+

Returns

+

cookie +'s secure attribute

+
+

Since: 2.32

+
+
+
+

soup_cookie_set_http_only ()

+
void
+soup_cookie_set_http_only (SoupCookie *cookie,
+                           gboolean http_only);
+

Sets cookie +'s HttpOnly attribute to http_only +. If TRUE, cookie + +will be marked as "http only", meaning it should not be exposed to +web page scripts or other untrusted code.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

cookie

a SoupCookie

 

http_only

the new value for the HttpOnly attribute

 
+
+

Since: 2.24

+
+
+
+

soup_cookie_get_http_only ()

+
gboolean
+soup_cookie_get_http_only (SoupCookie *cookie);
+

Gets cookie +'s HttpOnly attribute

+
+

Parameters

+
+++++ + + + + + +

cookie

a SoupCookie

 
+
+
+

Returns

+

cookie +'s HttpOnly attribute

+
+

Since: 2.32

+
+
+
+

soup_cookie_applies_to_uri ()

+
gboolean
+soup_cookie_applies_to_uri (SoupCookie *cookie,
+                            SoupURI *uri);
+

Tests if cookie + should be sent to uri +.

+

(At the moment, this does not check that cookie +'s domain matches +uri +, because it assumes that the caller has already done that. +But don't rely on that; it may change in the future.)

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

cookie

a SoupCookie

 

uri

a SoupURI

 
+
+
+

Returns

+

TRUE if cookie +should be sent to uri +, FALSE if +not

+
+

Since: 2.24

+
+
+
+

soup_cookie_domain_matches ()

+
gboolean
+soup_cookie_domain_matches (SoupCookie *cookie,
+                            const char *host);
+

Checks if the cookie +'s domain and host + match in the sense that +cookie + should be sent when making a request to host +, or that +cookie + should be accepted when receiving a response from host +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

cookie

a SoupCookie

 

host

a URI

 
+
+
+

Returns

+

TRUE if the domains match, FALSE otherwise

+
+

Since: 2.30

+
+
+
+

soup_cookie_to_cookie_header ()

+
char *
+soup_cookie_to_cookie_header (SoupCookie *cookie);
+

Serializes cookie + in the format used by the Cookie header (ie, for +returning a cookie from a SoupSession to a server).

+
+

Parameters

+
+++++ + + + + + +

cookie

a SoupCookie

 
+
+
+

Returns

+

the header

+
+

Since: 2.24

+
+
+
+

soup_cookie_to_set_cookie_header ()

+
char *
+soup_cookie_to_set_cookie_header (SoupCookie *cookie);
+

Serializes cookie + in the format used by the Set-Cookie header +(ie, for sending a cookie from a SoupServer to a client).

+
+

Parameters

+
+++++ + + + + + +

cookie

a SoupCookie

 
+
+
+

Returns

+

the header

+
+

Since: 2.24

+
+
+
+

soup_cookies_from_request ()

+
GSList *
+soup_cookies_from_request (SoupMessage *msg);
+

Parses msg +'s Cookie request header and returns a GSList of +SoupCookies. As the "Cookie" header, unlike "Set-Cookie", +only contains cookie names and values, none of the other +SoupCookie fields will be filled in. (Thus, you can't generally +pass a cookie returned from this method directly to +soup_cookies_to_response().)

+
+

Parameters

+
+++++ + + + + + +

msg

a SoupMessage containing a "Cookie" request header

 
+
+
+

Returns

+

a GSList +of SoupCookies, which can be freed with +soup_cookies_free().

+

[element-type SoupCookie][transfer full]

+
+

Since: 2.24

+
+
+
+

soup_cookies_from_response ()

+
GSList *
+soup_cookies_from_response (SoupMessage *msg);
+

Parses msg +'s Set-Cookie response headers and returns a GSList of +SoupCookies. Cookies that do not specify "path" or +"domain" attributes will have their values defaulted from msg +.

+
+

Parameters

+
+++++ + + + + + +

msg

a SoupMessage containing a "Set-Cookie" response header

 
+
+
+

Returns

+

a GSList +of SoupCookies, which can be freed with +soup_cookies_free().

+

[element-type SoupCookie][transfer full]

+
+

Since: 2.24

+
+
+
+

soup_cookies_to_request ()

+
void
+soup_cookies_to_request (GSList *cookies,
+                         SoupMessage *msg);
+

Adds the name and value of each cookie in cookies + to msg +'s +"Cookie" request. (If msg + already has a "Cookie" request header, +these cookies will be appended to the cookies already present. Be +careful that you do not append the same cookies twice, eg, when +requeuing a message.)

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

cookies

a GSList of SoupCookie.

[element-type SoupCookie]

msg

a SoupMessage

 
+
+

Since: 2.24

+
+
+
+

soup_cookies_to_response ()

+
void
+soup_cookies_to_response (GSList *cookies,
+                          SoupMessage *msg);
+

Appends a "Set-Cookie" response header to msg + for each cookie in +cookies +. (This is in addition to any other "Set-Cookie" headers +msg + may already have.)

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

cookies

a GSList of SoupCookie.

[element-type SoupCookie]

msg

a SoupMessage

 
+
+

Since: 2.24

+
+
+
+

soup_cookies_to_cookie_header ()

+
char *
+soup_cookies_to_cookie_header (GSList *cookies);
+

Serializes a GSList of SoupCookie into a string suitable for +setting as the value of the "Cookie" header.

+
+

Parameters

+
+++++ + + + + + +

cookies

a GSList of SoupCookie.

[element-type SoupCookie]
+
+
+

Returns

+

the serialization of cookies +

+
+

Since: 2.24

+
+
+
+

soup_cookies_free ()

+
void
+soup_cookies_free (GSList *cookies);
+

Frees cookies +.

+

[skip]

+
+

Parameters

+
+++++ + + + + + +

cookies

a GSList of SoupCookie.

[element-type SoupCookie]
+
+

Since: 2.24

+
+
+
+

Types and Values

+
+

SoupCookie

+
typedef struct {
+	char     *name;
+	char     *value;
+	char     *domain;
+	char     *path;
+	SoupDate *expires;
+	gboolean  secure;
+	gboolean  http_only;
+} SoupCookie;
+
+

An HTTP cookie.

+

name + and value + will be set for all cookies. If the cookie is +generated from a string that appears to have no name, then name + +will be the empty string.

+

domain + and path + give the host or domain, and path within that +host/domain, to restrict this cookie to. If domain + starts with +".", that indicates a domain (which matches the string after the +".", or any hostname that has domain + as a suffix). Otherwise, it +is a hostname and must match exactly.

+

expires + will be non-NULL if the cookie uses either the original +"expires" attribute, or the newer "max-age" attribute. If expires + +is NULL, it indicates that neither "expires" nor "max-age" was +specified, and the cookie expires at the end of the session.

+

If http_only + is set, the cookie should not be exposed to untrusted +code (eg, javascript), so as to minimize the danger posed by +cross-site scripting attacks.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

char *name;

the cookie name

 

char *value;

the cookie value

 

char *domain;

the "domain" attribute, or else the hostname that the +cookie came from.

 

char *path;

the "path" attribute, or NULL

 

SoupDate *expires;

the cookie expiration time, or NULL for a session cookie

 

gboolean secure;

TRUE if the cookie should only be tranferred over SSL

 

gboolean http_only;

TRUE if the cookie should not be exposed to scripts

 
+
+

Since: 2.24

+
+
+
+

SOUP_COOKIE_MAX_AGE_ONE_HOUR

+
#define SOUP_COOKIE_MAX_AGE_ONE_HOUR (60 * 60)
+
+

A constant corresponding to 1 hour, for use with soup_cookie_new() +and soup_cookie_set_max_age().

+

Since: 2.24

+
+
+
+

SOUP_COOKIE_MAX_AGE_ONE_DAY

+
#define SOUP_COOKIE_MAX_AGE_ONE_DAY  (SOUP_COOKIE_MAX_AGE_ONE_HOUR * 24)
+
+

A constant corresponding to 1 day, for use with soup_cookie_new() +and soup_cookie_set_max_age().

+

Since: 2.24

+
+
+
+

SOUP_COOKIE_MAX_AGE_ONE_WEEK

+
#define SOUP_COOKIE_MAX_AGE_ONE_WEEK (SOUP_COOKIE_MAX_AGE_ONE_DAY * 7)
+
+

A constant corresponding to 1 week, for use with soup_cookie_new() +and soup_cookie_set_max_age().

+

Since: 2.24

+
+
+
+

SOUP_COOKIE_MAX_AGE_ONE_YEAR

+
#define SOUP_COOKIE_MAX_AGE_ONE_YEAR (SOUP_COOKIE_MAX_AGE_ONE_DAY * 365.2422)
+
+

A constant corresponding to 1 year, for use with soup_cookie_new() +and soup_cookie_set_max_age().

+

Since: 2.24

+
+
+
+

See Also

+

SoupMessage, SoupCookieJar

+
+
+ + + \ No newline at end of file diff --git a/docs/reference/html/SoupCookieJar.html b/docs/reference/html/SoupCookieJar.html new file mode 100644 index 0000000..1b322e8 --- /dev/null +++ b/docs/reference/html/SoupCookieJar.html @@ -0,0 +1,860 @@ + + + + +SoupCookieJar: libsoup Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

SoupCookieJar

+

SoupCookieJar — Automatic cookie handling for SoupSession

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+SoupCookieJar * + +soup_cookie_jar_new () +
+char * + +soup_cookie_jar_get_cookies () +
+GSList * + +soup_cookie_jar_get_cookie_list () +
+void + +soup_cookie_jar_set_cookie () +
+void + +soup_cookie_jar_set_cookie_with_first_party () +
+void + +soup_cookie_jar_add_cookie () +
+void + +soup_cookie_jar_add_cookie_with_first_party () +
+void + +soup_cookie_jar_delete_cookie () +
+GSList * + +soup_cookie_jar_all_cookies () +
+SoupCookieJarAcceptPolicy + +soup_cookie_jar_get_accept_policy () +
+void + +soup_cookie_jar_set_accept_policy () +
+gboolean + +soup_cookie_jar_is_persistent () +
+
+
+

Properties

+
+++++ + + + + + + + + + + + + +
SoupCookieJarAcceptPolicyaccept-policyRead / Write
gbooleanread-onlyRead / Write / Construct Only
+
+
+

Signals

+
+++++ + + + + + +
voidchangedRun First
+
+
+

Types and Values

+
++++ + + + + + + + + + + + + + + + + + + +
 SoupCookieJar
enumSoupCookieJarAcceptPolicy
#defineSOUP_COOKIE_JAR_READ_ONLY
#defineSOUP_COOKIE_JAR_ACCEPT_POLICY
+
+
+

Object Hierarchy

+
    GObject
+    ╰── SoupCookieJar
+        ├── SoupCookieJarDB
+        ╰── SoupCookieJarText
+
+
+
+

Implemented Interfaces

+

+SoupCookieJar implements + SoupSessionFeature.

+
+
+

Includes

+
#include <libsoup/soup.h>
+
+
+
+

Description

+

A SoupCookieJar stores SoupCookies and arrange for them +to be sent with the appropriate SoupMessages. +SoupCookieJar implements SoupSessionFeature, so you can add a +cookie jar to a session with soup_session_add_feature() or +soup_session_add_feature_by_type().

+

Note that the base SoupCookieJar class does not support any form +of long-term cookie persistence.

+
+
+

Functions

+
+

soup_cookie_jar_new ()

+
SoupCookieJar *
+soup_cookie_jar_new (void);
+

Creates a new SoupCookieJar. The base SoupCookieJar class does +not support persistent storage of cookies; use a subclass for that.

+
+

Returns

+

a new SoupCookieJar

+
+

Since: 2.24

+
+
+
+

soup_cookie_jar_get_cookies ()

+
char *
+soup_cookie_jar_get_cookies (SoupCookieJar *jar,
+                             SoupURI *uri,
+                             gboolean for_http);
+

Retrieves (in Cookie-header form) the list of cookies that would +be sent with a request to uri +.

+

If for_http + is TRUE, the return value will include cookies marked +"HttpOnly" (that is, cookies that the server wishes to keep hidden +from client-side scripting operations such as the JavaScript +document.cookies property). Since SoupCookieJar sets the Cookie +header itself when making the actual HTTP request, you should +almost certainly be setting for_http + to FALSE if you are calling +this.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

jar

a SoupCookieJar

 

uri

a SoupURI

 

for_http

whether or not the return value is being passed directly +to an HTTP operation

 
+
+
+

Returns

+

the cookies, in string form, or NULL if +there are no cookies for uri +.

+

[nullable]

+
+

Since: 2.24

+
+
+
+

soup_cookie_jar_get_cookie_list ()

+
GSList *
+soup_cookie_jar_get_cookie_list (SoupCookieJar *jar,
+                                 SoupURI *uri,
+                                 gboolean for_http);
+

Retrieves the list of cookies that would be sent with a request to uri + +as a GSList of SoupCookie objects.

+

If for_http + is TRUE, the return value will include cookies marked +"HttpOnly" (that is, cookies that the server wishes to keep hidden +from client-side scripting operations such as the JavaScript +document.cookies property). Since SoupCookieJar sets the Cookie +header itself when making the actual HTTP request, you should +almost certainly be setting for_http + to FALSE if you are calling +this.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

jar

a SoupCookieJar

 

uri

a SoupURI

 

for_http

whether or not the return value is being passed directly +to an HTTP operation

 
+
+
+

Returns

+

a GSList +with the cookies in the jar +that would be sent with a request to uri +.

+

[transfer full][element-type Soup.Cookie]

+
+

Since: 2.40

+
+
+
+

soup_cookie_jar_set_cookie ()

+
void
+soup_cookie_jar_set_cookie (SoupCookieJar *jar,
+                            SoupURI *uri,
+                            const char *cookie);
+

Adds cookie + to jar +, exactly as though it had appeared in a +Set-Cookie header returned from a request to uri +.

+

Keep in mind that if the SoupCookieJarAcceptPolicy +SOUP_COOKIE_JAR_ACCEPT_NO_THIRD_PARTY is set you'll need to use +soup_cookie_jar_set_cookie_with_first_party(), otherwise the jar +will have no way of knowing if the cookie is being set by a third +party or not.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

jar

a SoupCookieJar

 

uri

the URI setting the cookie

 

cookie

the stringified cookie to set

 
+
+

Since: 2.24

+
+
+
+

soup_cookie_jar_set_cookie_with_first_party ()

+
void
+soup_cookie_jar_set_cookie_with_first_party
+                               (SoupCookieJar *jar,
+                                SoupURI *uri,
+                                SoupURI *first_party,
+                                const char *cookie);
+

Adds cookie + to jar +, exactly as though it had appeared in a +Set-Cookie header returned from a request to uri +. first_party + +will be used to reject cookies coming from third party resources in +case such a security policy is set in the jar +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

jar

a SoupCookieJar

 

uri

the URI setting the cookie

 

first_party

the URI for the main document

 

cookie

the stringified cookie to set

 
+
+

Since: 2.30

+
+
+
+

soup_cookie_jar_add_cookie ()

+
void
+soup_cookie_jar_add_cookie (SoupCookieJar *jar,
+                            SoupCookie *cookie);
+

Adds cookie + to jar +, emitting the 'changed' signal if we are modifying +an existing cookie or adding a valid new cookie ('valid' means +that the cookie's expire date is not in the past).

+

cookie + will be 'stolen' by the jar, so don't free it afterwards.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

jar

a SoupCookieJar

 

cookie

a SoupCookie.

[transfer full]
+
+

Since: 2.26

+
+
+
+

soup_cookie_jar_add_cookie_with_first_party ()

+
void
+soup_cookie_jar_add_cookie_with_first_party
+                               (SoupCookieJar *jar,
+                                SoupURI *first_party,
+                                SoupCookie *cookie);
+

Adds cookie + to jar +, emitting the 'changed' signal if we are modifying +an existing cookie or adding a valid new cookie ('valid' means +that the cookie's expire date is not in the past).

+

first_party + will be used to reject cookies coming from third party +resources in case such a security policy is set in the jar +.

+

cookie + will be 'stolen' by the jar, so don't free it afterwards.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

jar

a SoupCookieJar

 

first_party

the URI for the main document

 

cookie

a SoupCookie.

[transfer full]
+
+

Since: 2.40

+
+
+
+

soup_cookie_jar_delete_cookie ()

+
void
+soup_cookie_jar_delete_cookie (SoupCookieJar *jar,
+                               SoupCookie *cookie);
+

Deletes cookie + from jar +, emitting the 'changed' signal.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

jar

a SoupCookieJar

 

cookie

a SoupCookie

 
+
+

Since: 2.26

+
+
+
+

soup_cookie_jar_all_cookies ()

+
GSList *
+soup_cookie_jar_all_cookies (SoupCookieJar *jar);
+

Constructs a GSList with every cookie inside the jar +. +The cookies in the list are a copy of the original, so +you have to free them when you are done with them.

+
+

Parameters

+
+++++ + + + + + +

jar

a SoupCookieJar

 
+
+
+

Returns

+

a GSList +with all the cookies in the jar +.

+

[transfer full][element-type Soup.Cookie]

+
+

Since: 2.26

+
+
+
+

soup_cookie_jar_get_accept_policy ()

+
SoupCookieJarAcceptPolicy
+soup_cookie_jar_get_accept_policy (SoupCookieJar *jar);
+

Gets jar +'s SoupCookieJarAcceptPolicy

+
+

Parameters

+
+++++ + + + + + +

jar

a SoupCookieJar

 
+
+
+

Returns

+

the SoupCookieJarAcceptPolicy set in the jar +

+
+

Since: 2.30

+
+
+
+

soup_cookie_jar_set_accept_policy ()

+
void
+soup_cookie_jar_set_accept_policy (SoupCookieJar *jar,
+                                   SoupCookieJarAcceptPolicy policy);
+

Sets policy + as the cookie acceptance policy for jar +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

jar

a SoupCookieJar

 

policy

a SoupCookieJarAcceptPolicy

 
+
+

Since: 2.30

+
+
+
+

soup_cookie_jar_is_persistent ()

+
gboolean
+soup_cookie_jar_is_persistent (SoupCookieJar *jar);
+

Gets whether jar + stores cookies persistenly.

+
+

Parameters

+
+++++ + + + + + +

jar

a SoupCookieJar

 
+
+
+

Returns

+

TRUE if jar +storage is persistent or FALSE otherwise.

+
+

Since: 2.40

+
+
+
+

Types and Values

+
+

SoupCookieJar

+
typedef struct _SoupCookieJar SoupCookieJar;
+
+
+
+

enum SoupCookieJarAcceptPolicy

+

The policy for accepting or rejecting cookies returned in +responses.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + +

SOUP_COOKIE_JAR_ACCEPT_ALWAYS

+

accept all cookies unconditionally.

+
 

SOUP_COOKIE_JAR_ACCEPT_NEVER

+

reject all cookies unconditionally.

+
 

SOUP_COOKIE_JAR_ACCEPT_NO_THIRD_PARTY

+

accept all cookies set by +the main document loaded in the application using libsoup. An +example of the most common case, web browsers, would be: If +http://www.example.com is the page loaded, accept all cookies set +by example.com, but if a resource from http://www.third-party.com +is loaded from that page reject any cookie that it could try to +set. For libsoup to be able to tell apart first party cookies from +the rest, the application must call soup_message_set_first_party() +on each outgoing SoupMessage, setting the SoupURI of the main +document. If no first party is set in a message when this policy is +in effect, cookies will be assumed to be third party by default.

+
 
+
+

Since: 2.30

+
+
+
+

SOUP_COOKIE_JAR_READ_ONLY

+
#define SOUP_COOKIE_JAR_READ_ONLY "read-only"
+
+

Alias for the “read-only” property. (Whether +or not the cookie jar is read-only.)

+
+
+
+

SOUP_COOKIE_JAR_ACCEPT_POLICY

+
#define SOUP_COOKIE_JAR_ACCEPT_POLICY "accept-policy"
+
+

Alias for the “accept-policy” property.

+

Since: 2.30

+
+
+
+

Property Details

+
+

The “accept-policy” property

+
  “accept-policy”            SoupCookieJarAcceptPolicy
+

The policy the jar should follow to accept or reject cookies

+

Flags: Read / Write

+

Default value: SOUP_COOKIE_JAR_ACCEPT_ALWAYS

+

Since: 2.30

+
+
+
+

The “read-only” property

+
  “read-only”                gboolean
+

Whether or not the cookie jar is read-only.

+

Flags: Read / Write / Construct Only

+

Default value: FALSE

+
+
+
+

Signal Details

+
+

The “changed” signal

+
void
+user_function (SoupCookieJar *jar,
+               SoupCookie    *old_cookie,
+               SoupCookie    *new_cookie,
+               gpointer       user_data)
+

Emitted when jar + changes. If a cookie has been added, +new_cookie + will contain the newly-added cookie and +old_cookie + will be NULL. If a cookie has been deleted, +old_cookie + will contain the to-be-deleted cookie and +new_cookie + will be NULL. If a cookie has been changed, +old_cookie + will contain its old value, and new_cookie + its +new value.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

jar

the SoupCookieJar

 

old_cookie

the old SoupCookie value

 

new_cookie

the new SoupCookie value

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+
+
+
+ + + \ No newline at end of file diff --git a/docs/reference/html/SoupCookieJarDB.html b/docs/reference/html/SoupCookieJarDB.html new file mode 100644 index 0000000..1a77cbb --- /dev/null +++ b/docs/reference/html/SoupCookieJarDB.html @@ -0,0 +1,192 @@ + + + + +SoupCookieJarDB: libsoup Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

SoupCookieJarDB

+

SoupCookieJarDB — Database-based Cookie Jar

+
+
+

Functions

+
++++ + + + + +
+SoupCookieJar * + +soup_cookie_jar_db_new () +
+
+
+

Properties

+
+++++ + + + + + +
+gchar *filenameRead / Write / Construct Only
+
+
+

Types and Values

+
++++ + + + + + + + + + + +
 SoupCookieJarDB
#defineSOUP_COOKIE_JAR_DB_FILENAME
+
+
+

Object Hierarchy

+
    GObject
+    ╰── SoupCookieJar
+        ╰── SoupCookieJarDB
+
+
+
+

Implemented Interfaces

+

+SoupCookieJarDB implements + SoupSessionFeature.

+
+
+

Includes

+
#include <libsoup/soup.h>
+
+
+
+

Description

+

SoupCookieJarDB is a SoupCookieJar that reads cookies from and +writes them to a sqlite database in the new Mozilla format.

+

(This is identical to SoupCookieJarSqlite in +libsoup-gnome; it has just been moved into libsoup proper, and +renamed to avoid conflicting.)

+
+
+

Functions

+
+

soup_cookie_jar_db_new ()

+
SoupCookieJar *
+soup_cookie_jar_db_new (const char *filename,
+                        gboolean read_only);
+

Creates a SoupCookieJarDB.

+

filename + will be read in at startup to create an initial set of +cookies. If read_only + is FALSE, then the non-session cookies will +be written to filename + when the 'changed' signal is emitted from +the jar. (If read_only + is TRUE, then the cookie jar will only be +used for this session, and changes made to it will be lost when the +jar is destroyed.)

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

filename

the filename to read to/write from, or NULL

 

read_only

TRUE if filename +is read-only

 
+
+
+

Returns

+

the new SoupCookieJar

+
+

Since: 2.42

+
+
+
+

Types and Values

+
+

SoupCookieJarDB

+
typedef struct _SoupCookieJarDB SoupCookieJarDB;
+
+
+
+

SOUP_COOKIE_JAR_DB_FILENAME

+
#define SOUP_COOKIE_JAR_DB_FILENAME  "filename"
+
+

Alias for the “filename” property. (The +cookie-storage filename.)

+
+
+
+

Property Details

+
+

The “filename” property

+
  “filename”                 gchar *
+

Cookie-storage filename.

+

Flags: Read / Write / Construct Only

+

Default value: NULL

+
+
+
+ + + \ No newline at end of file diff --git a/docs/reference/html/SoupCookieJarText.html b/docs/reference/html/SoupCookieJarText.html new file mode 100644 index 0000000..72ae02d --- /dev/null +++ b/docs/reference/html/SoupCookieJarText.html @@ -0,0 +1,189 @@ + + + + +SoupCookieJarText: libsoup Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

SoupCookieJarText

+

SoupCookieJarText — Text-file-based ("cookies.txt") Cookie Jar

+
+
+

Functions

+
++++ + + + + +
+SoupCookieJar * + +soup_cookie_jar_text_new () +
+
+
+

Properties

+
+++++ + + + + + +
+gchar *filenameRead / Write / Construct Only
+
+
+

Types and Values

+
++++ + + + + + + + + + + +
 SoupCookieJarText
#defineSOUP_COOKIE_JAR_TEXT_FILENAME
+
+
+

Object Hierarchy

+
    GObject
+    ╰── SoupCookieJar
+        ╰── SoupCookieJarText
+
+
+
+

Implemented Interfaces

+

+SoupCookieJarText implements + SoupSessionFeature.

+
+
+

Includes

+
#include <libsoup/soup.h>
+
+
+
+

Description

+

SoupCookieJarText is a SoupCookieJar that reads cookies from and +writes them to a text file in the Mozilla "cookies.txt" format.

+
+
+

Functions

+
+

soup_cookie_jar_text_new ()

+
SoupCookieJar *
+soup_cookie_jar_text_new (const char *filename,
+                          gboolean read_only);
+

Creates a SoupCookieJarText.

+

filename + will be read in at startup to create an initial set of +cookies. If read_only + is FALSE, then the non-session cookies will +be written to filename + when the 'changed' signal is emitted from +the jar. (If read_only + is TRUE, then the cookie jar will only be +used for this session, and changes made to it will be lost when the +jar is destroyed.)

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

filename

the filename to read to/write from

 

read_only

TRUE if filename +is read-only

 
+
+
+

Returns

+

the new SoupCookieJar

+
+

Since: 2.26

+
+
+
+

Types and Values

+
+

SoupCookieJarText

+
typedef struct _SoupCookieJarText SoupCookieJarText;
+
+
+
+

SOUP_COOKIE_JAR_TEXT_FILENAME

+
#define SOUP_COOKIE_JAR_TEXT_FILENAME  "filename"
+
+

Alias for the “filename” property. (The +cookie-storage filename.)

+
+
+
+

Property Details

+
+

The “filename” property

+
  “filename”                 gchar *
+

Cookie-storage filename.

+

Flags: Read / Write / Construct Only

+

Default value: NULL

+
+
+
+ + + \ No newline at end of file diff --git a/docs/reference/html/SoupLogger.html b/docs/reference/html/SoupLogger.html new file mode 100644 index 0000000..7ed95d3 --- /dev/null +++ b/docs/reference/html/SoupLogger.html @@ -0,0 +1,595 @@ + + + + +SoupLogger: libsoup Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

SoupLogger

+

SoupLogger — Debug logging support

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+SoupLogger * + +soup_logger_new () +
+SoupLoggerLogLevel + +(*SoupLoggerFilter) () +
+void + +soup_logger_set_request_filter () +
+void + +soup_logger_set_response_filter () +
+void + +(*SoupLoggerPrinter) () +
+void + +soup_logger_set_printer () +
+
+
+

Properties

+
+++++ + + + + + + + + + + + + +
SoupLoggerLogLevellevelRead / Write
gintmax-body-sizeRead / Write
+
+
+

Types and Values

+
++++ + + + + + + + + + + +
 SoupLogger
enumSoupLoggerLogLevel
+
+
+

Object Hierarchy

+
    GObject
+    ╰── SoupLogger
+
+
+
+

Implemented Interfaces

+

+SoupLogger implements + SoupSessionFeature.

+
+
+

Includes

+
#include <libsoup/soup.h>
+
+
+
+

Description

+

SoupLogger watches a SoupSession and logs the HTTP traffic that +it generates, for debugging purposes. Many applications use an +environment variable to determine whether or not to use +SoupLogger, and to determine the amount of debugging output.

+

To use SoupLogger, first create a logger with soup_logger_new(), +optionally configure it with soup_logger_set_request_filter(), +soup_logger_set_response_filter(), and soup_logger_set_printer(), +and then attach it to a session (or multiple sessions) with +soup_session_add_feature().

+

By default, the debugging output is sent to +stdout, and looks something like:

+
+> POST /unauth HTTP/1.1
+> Soup-Debug-Timestamp: 1200171744
+> Soup-Debug: SoupSessionAsync 1 (0x612190), SoupMessage 1 (0x617000), SoupSocket 1 (0x612220)
+> Host: localhost
+> Content-Type: text/plain
+> Connection: close
+>
+> This is a test.
+
+< HTTP/1.1 201 Created
+< Soup-Debug-Timestamp: 1200171744
+< Soup-Debug: SoupMessage 1 (0x617000)
+< Date: Sun, 12 Jan 2008 21:02:24 GMT
+< Content-Length: 0
+
+

The Soup-Debug-Timestamp line gives the time (as +a time_t) when the request was sent, or the response fully +received.

+

The Soup-Debug line gives further debugging +information about the SoupSession, SoupMessage, and SoupSocket +involved; the hex numbers are the addresses of the objects in +question (which may be useful if you are running in a debugger). +The decimal IDs are simply counters that uniquely identify objects +across the lifetime of the SoupLogger. In particular, this can be +used to identify when multiple messages are sent across the same +connection.

+

Currently, the request half of the message is logged just before +the first byte of the request gets written to the network (from the +“starting” signal), which means that if you have +not made the complete request body available at that point, it will +not be logged.

+

The response is logged just after the last byte of the response +body is read from the network (from the “got_body” or +“got_informational” signal), which means that the +“got_headers” signal, and anything triggered off it +(such as “authenticate”) will be emitted +before the response headers are actually +logged.

+

If the response doesn't happen to trigger the +“got_body” nor “got_informational” signals +due to, for example, a cancellation before receiving the last byte +of the response body, the response will still be logged on the +event of the “finished” signal.

+
+
+

Functions

+
+

soup_logger_new ()

+
SoupLogger *
+soup_logger_new (SoupLoggerLogLevel level,
+                 int max_body_size);
+

Creates a new SoupLogger with the given debug level. If level + is +SOUP_LOGGER_LOG_BODY, max_body_size + gives the maximum number of +bytes of the body that will be logged. (-1 means "no limit".)

+

If you need finer control over what message parts are and aren't +logged, use soup_logger_set_request_filter() and +soup_logger_set_response_filter().

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

level

the debug level

 

max_body_size

the maximum body size to output, or -1

 
+
+
+

Returns

+

a new SoupLogger

+
+
+
+
+

SoupLoggerFilter ()

+
SoupLoggerLogLevel
+(*SoupLoggerFilter) (SoupLogger *logger,
+                     SoupMessage *msg,
+                     gpointer user_data);
+

The prototype for a logging filter. The filter callback will be +invoked for each request or response, and should analyze it and +return a SoupLoggerLogLevel value indicating how much of the +message to log. Eg, it might choose between SOUP_LOGGER_LOG_BODY +and SOUP_LOGGER_LOG_HEADERS depending on the Content-Type.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

logger

the SoupLogger

 

msg

the message being logged

 

user_data

the data passed to soup_logger_set_request_filter() +or soup_logger_set_response_filter()

 
+
+
+

Returns

+

a SoupLoggerLogLevel value indicating how much of +the message to log

+
+
+
+
+

soup_logger_set_request_filter ()

+
void
+soup_logger_set_request_filter (SoupLogger *logger,
+                                SoupLoggerFilter request_filter,
+                                gpointer filter_data,
+                                GDestroyNotify destroy);
+

Sets up a filter to determine the log level for a given request. +For each HTTP request logger + will invoke request_filter + to +determine how much (if any) of that request to log. (If you do not +set a request filter, logger + will just always log requests at the +level passed to soup_logger_new().)

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

logger

a SoupLogger

 

request_filter

the callback for request debugging

 

filter_data

data to pass to the callback

 

destroy

a GDestroyNotify to free filter_data +

 
+
+
+
+
+

soup_logger_set_response_filter ()

+
void
+soup_logger_set_response_filter (SoupLogger *logger,
+                                 SoupLoggerFilter response_filter,
+                                 gpointer filter_data,
+                                 GDestroyNotify destroy);
+

Sets up a filter to determine the log level for a given response. +For each HTTP response logger + will invoke response_filter + to +determine how much (if any) of that response to log. (If you do not +set a response filter, logger + will just always log responses at +the level passed to soup_logger_new().)

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

logger

a SoupLogger

 

response_filter

the callback for response debugging

 

filter_data

data to pass to the callback

 

destroy

a GDestroyNotify to free filter_data +

 
+
+
+
+
+

SoupLoggerPrinter ()

+
void
+(*SoupLoggerPrinter) (SoupLogger *logger,
+                      SoupLoggerLogLevel level,
+                      char direction,
+                      const char *data,
+                      gpointer user_data);
+

The prototype for a custom printing callback.

+

level + indicates what kind of information is being printed. Eg, it +will be SOUP_LOGGER_LOG_HEADERS if data + is header data.

+

direction + is either '<', '>', or ' ', and data + is the single line +to print; the printer is expected to add a terminating newline.

+

To get the effect of the default printer, you would do:

+
+ + + + + + + +
1
printf ("%c %s\n", direction, data);
+
+ +
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

logger

the SoupLogger

 

level

the level of the information being printed.

 

direction

a single-character prefix to data +

 

data

data to print

 

user_data

the data passed to soup_logger_set_printer()

 
+
+
+
+
+

soup_logger_set_printer ()

+
void
+soup_logger_set_printer (SoupLogger *logger,
+                         SoupLoggerPrinter printer,
+                         gpointer printer_data,
+                         GDestroyNotify destroy);
+

Sets up an alternate log printing routine, if you don't want +the log to go to stdout.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

logger

a SoupLogger

 

printer

the callback for printing logging output

 

printer_data

data to pass to the callback

 

destroy

a GDestroyNotify to free printer_data +

 
+
+
+
+
+

Types and Values

+
+

SoupLogger

+
typedef struct _SoupLogger SoupLogger;
+
+
+
+

enum SoupLoggerLogLevel

+

Describes the level of logging output to provide.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

SOUP_LOGGER_LOG_NONE

+

No logging

+
 

SOUP_LOGGER_LOG_MINIMAL

+

Log the Request-Line or Status-Line and +the Soup-Debug pseudo-headers

+
 

SOUP_LOGGER_LOG_HEADERS

+

Log the full request/response headers

+
 

SOUP_LOGGER_LOG_BODY

+

Log the full headers and request/response +bodies.

+
 
+
+
+
+
+

Property Details

+
+

The “level” property

+
  “level”                    SoupLoggerLogLevel
+

The level of logging output

+

Flags: Read / Write

+

Default value: SOUP_LOGGER_LOG_MINIMAL

+

Since: 2.56

+
+
+
+

The “max-body-size” property

+
  “max-body-size”            gint
+

If “level” is SOUP_LOGGER_LOG_BODY, this gives +the maximum number of bytes of the body that will be logged. +(-1 means "no limit".)

+

Flags: Read / Write

+

Allowed values: >= -1

+

Default value: -1

+

Since: 2.56

+
+
+
+ + + \ No newline at end of file diff --git a/docs/reference/html/SoupMessage.html b/docs/reference/html/SoupMessage.html new file mode 100644 index 0000000..5c59e8c --- /dev/null +++ b/docs/reference/html/SoupMessage.html @@ -0,0 +1,2737 @@ + + + + +SoupMessage: libsoup Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

SoupMessage

+

SoupMessage — An HTTP request and response.

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+SoupMessage * + +soup_message_new () +
+SoupMessage * + +soup_message_new_from_uri () +
+void + +soup_message_set_request () +
+void + +soup_message_set_response () +
+void + +soup_message_set_http_version () +
+SoupHTTPVersion + +soup_message_get_http_version () +
+SoupURI * + +soup_message_get_uri () +
+void + +soup_message_set_uri () +
+SoupAddress * + +soup_message_get_address () +
+void + +soup_message_set_status () +
+void + +soup_message_set_status_full () +
+void + +soup_message_set_redirect () +
+gboolean + +soup_message_is_keepalive () +
+gboolean + +soup_message_get_https_status () +
+void + +soup_message_set_first_party () +
+SoupURI * + +soup_message_get_first_party () +
+guint + +soup_message_add_header_handler () +
+guint + +soup_message_add_status_code_handler () +
+void + +soup_message_set_flags () +
+SoupMessageFlags + +soup_message_get_flags () +
+SoupBuffer * + +(*SoupChunkAllocator) () +
+void + +soup_message_disable_feature () +
+SoupRequest * + +soup_message_get_soup_request () +
+SoupMessagePriority + +soup_message_get_priority () +
+void + +soup_message_set_priority () +
+
+
+

Properties

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+SoupURI *first-partyRead / Write
SoupMessageFlagsflagsRead / Write
SoupHTTPVersionhttp-versionRead / Write
+gchar *methodRead / Write
SoupMessagePrioritypriorityRead / Write
+gchar *reason-phraseRead / Write
+SoupMessageBody *request-bodyRead
+GBytes *request-body-dataRead
+SoupMessageHeaders *request-headersRead
+SoupMessageBody *response-bodyRead
+GBytes *response-body-dataRead
+SoupMessageHeaders *response-headersRead
gbooleanserver-sideRead / Write / Construct Only
guintstatus-codeRead / Write
+GTlsCertificate *tls-certificateRead / Write
GTlsCertificateFlagstls-errorsRead / Write
+SoupURI *uriRead / Write
+
+
+

Signals

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
voidcontent-sniffedRun First
voidfinishedRun First
voidgot-bodyRun First
voidgot-chunkRun First
voidgot-headersRun First
voidgot-informationalRun First
voidnetwork-eventRun First
voidrestartedRun First
voidstartingRun First
voidwrote-bodyRun First
voidwrote-body-dataRun First
voidwrote-chunkRun First
voidwrote-headersRun First
voidwrote-informationalRun First
+
+
+

Types and Values

+ +
+
+

Object Hierarchy

+
    GObject
+    ╰── SoupMessage
+
+
+
+

Includes

+
#include <libsoup/soup.h>
+
+
+
+

Description

+

A SoupMessage represents an HTTP message that is being sent or +received.

+

For client-side usage, if you are using the traditional +SoupSession APIs (soup_session_queue_message() and +soup_session_send_message()), you would create a SoupMessage with +soup_message_new() or soup_message_new_from_uri(), set up its +fields appropriately, and send it. If you are using the newer +SoupRequest API, you would create a request with +soup_session_request_http() or soup_session_request_http_uri(), and +the returned SoupRequestHTTP will already have an associated +SoupMessage that you can retrieve via +soup_request_http_get_message().

+

For server-side usage, SoupServer will create SoupMessages automatically for incoming requests, which your application +will receive via handlers.

+

Note that libsoup's terminology here does not quite match the HTTP +specification: in RFC 2616, an "HTTP-message" is +either a Request, or a +Response. In libsoup, a SoupMessage combines both the request and +the response.

+
+
+

Functions

+
+

soup_message_new ()

+
SoupMessage *
+soup_message_new (const char *method,
+                  const char *uri_string);
+

Creates a new empty SoupMessage, which will connect to uri +

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

method

the HTTP method for the created request

 

uri_string

the destination endpoint (as a string)

 
+
+
+

Returns

+

the new SoupMessage (or NULL if uri +could not be parsed).

+

[nullable]

+
+
+
+
+

soup_message_new_from_uri ()

+
SoupMessage *
+soup_message_new_from_uri (const char *method,
+                           SoupURI *uri);
+

Creates a new empty SoupMessage, which will connect to uri +

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

method

the HTTP method for the created request

 

uri

the destination endpoint (as a SoupURI)

 
+
+
+

Returns

+

the new SoupMessage

+
+
+
+
+

soup_message_set_request ()

+
void
+soup_message_set_request (SoupMessage *msg,
+                          const char *content_type,
+                          SoupMemoryUse req_use,
+                          const char *req_body,
+                          gsize req_length);
+

Convenience function to set the request body of a SoupMessage. If +content_type + is NULL, the request body must be empty as well.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

msg

the message

 

content_type

MIME Content-Type of the body.

[allow-none]

req_use

a SoupMemoryUse describing how to handle req_body +

 

req_body

a data buffer containing the body of the message request.

[allow-none][array length=req_length][element-type guint8]

req_length

the byte length of req_body +.

 
+
+
+
+
+

soup_message_set_response ()

+
void
+soup_message_set_response (SoupMessage *msg,
+                           const char *content_type,
+                           SoupMemoryUse resp_use,
+                           const char *resp_body,
+                           gsize resp_length);
+

Convenience function to set the response body of a SoupMessage. If +content_type + is NULL, the response body must be empty as well.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

msg

the message

 

content_type

MIME Content-Type of the body.

[allow-none]

resp_use

a SoupMemoryUse describing how to handle resp_body +

 

resp_body

a data buffer containing the body of the message response.

[allow-none][array length=resp_length][element-type guint8]

resp_length

the byte length of resp_body +.

 
+
+
+
+
+

soup_message_set_http_version ()

+
void
+soup_message_set_http_version (SoupMessage *msg,
+                               SoupHTTPVersion version);
+

Sets the HTTP version on msg +. The default version is +SOUP_HTTP_1_1. Setting it to SOUP_HTTP_1_0 will prevent certain +functionality from being used.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

msg

a SoupMessage

 

version

the HTTP version

 
+
+
+
+
+

soup_message_get_http_version ()

+
SoupHTTPVersion
+soup_message_get_http_version (SoupMessage *msg);
+

Gets the HTTP version of msg +. This is the minimum of the +version from the request and the version from the response.

+
+

Parameters

+
+++++ + + + + + +

msg

a SoupMessage

 
+
+
+

Returns

+

the HTTP version

+
+
+
+
+

soup_message_get_uri ()

+
SoupURI *
+soup_message_get_uri (SoupMessage *msg);
+

Gets msg +'s URI

+
+

Parameters

+
+++++ + + + + + +

msg

a SoupMessage

 
+
+
+

Returns

+

the URI msg +is targeted for.

+

[transfer none]

+
+
+
+
+

soup_message_set_uri ()

+
void
+soup_message_set_uri (SoupMessage *msg,
+                      SoupURI *uri);
+

Sets msg +'s URI to uri +. If msg + has already been sent and you want +to re-send it with the new URI, you need to call +soup_session_requeue_message().

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

msg

a SoupMessage

 

uri

the new SoupURI

 
+
+
+
+
+

soup_message_get_address ()

+
SoupAddress *
+soup_message_get_address (SoupMessage *msg);
+

Gets the address msg +'s URI points to. After first setting the +URI on a message, this will be unresolved, although the message's +session will resolve it before sending the message.

+
+

Parameters

+
+++++ + + + + + +

msg

a SoupMessage

 
+
+
+

Returns

+

the address msg +'s URI points to.

+

[transfer none]

+
+

Since: 2.26

+
+
+
+

soup_message_set_status ()

+
void
+soup_message_set_status (SoupMessage *msg,
+                         guint status_code);
+

Sets msg +'s status code to status_code +. If status_code + is a +known value, it will also set msg +'s reason_phrase.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

msg

a SoupMessage

 

status_code

an HTTP status code

 
+
+
+
+
+

soup_message_set_status_full ()

+
void
+soup_message_set_status_full (SoupMessage *msg,
+                              guint status_code,
+                              const char *reason_phrase);
+

Sets msg +'s status code and reason phrase.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

msg

a SoupMessage

 

status_code

an HTTP status code

 

reason_phrase

a description of the status

 
+
+
+
+
+

soup_message_set_redirect ()

+
void
+soup_message_set_redirect (SoupMessage *msg,
+                           guint status_code,
+                           const char *redirect_uri);
+

Sets msg +'s status_code to status_code + and adds a Location header +pointing to redirect_uri +. Use this from a SoupServer when you +want to redirect the client to another URI.

+

redirect_uri + can be a relative URI, in which case it is +interpreted relative to msg +'s current URI. In particular, if +redirect_uri + is just a path, it will replace the path +and query of msg +'s URI.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

msg

a SoupMessage

 

status_code

a 3xx status code

 

redirect_uri

the URI to redirect msg +to

 
+
+

Since: 2.38

+
+
+
+

soup_message_is_keepalive ()

+
gboolean
+soup_message_is_keepalive (SoupMessage *msg);
+

Determines whether or not msg +'s connection can be kept alive for +further requests after processing msg +, based on the HTTP version, +Connection header, etc.

+
+

Parameters

+
+++++ + + + + + +

msg

a SoupMessage

 
+
+
+

Returns

+

TRUE or FALSE.

+
+
+
+
+

soup_message_get_https_status ()

+
gboolean
+soup_message_get_https_status (SoupMessage *msg,
+                               GTlsCertificate **certificate,
+                               GTlsCertificateFlags *errors);
+

If msg + is using https (or attempted to use https but got +SOUP_STATUS_SSL_FAILED), this retrieves the GTlsCertificate +associated with its connection, and the GTlsCertificateFlags +showing what problems, if any, have been found with that +certificate.

+

This is only meaningful with messages processed by a SoupSession and is +not useful for messages received by a SoupServer

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

msg

a SoupMessage

 

certificate

msg +'s TLS certificate.

[out][transfer none]

errors

the verification status of certificate +.

[out]
+
+
+

Returns

+

TRUE if msg +used/attempted https, FALSE if not

+
+

Since: 2.34

+
+
+
+

soup_message_set_first_party ()

+
void
+soup_message_set_first_party (SoupMessage *msg,
+                              SoupURI *first_party);
+

Sets first_party + as the main document SoupURI for msg +. For +details of when and how this is used refer to the documentation for +SoupCookieJarAcceptPolicy.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

msg

a SoupMessage

 

first_party

the SoupURI for the msg +'s first party

 
+
+

Since: 2.30

+
+
+
+

soup_message_get_first_party ()

+
SoupURI *
+soup_message_get_first_party (SoupMessage *msg);
+

Gets msg +'s first-party SoupURI

+
+

Parameters

+
+++++ + + + + + +

msg

a SoupMessage

 
+
+
+

Returns

+

the msg +'s first party SoupURI.

+

[transfer none]

+
+

Since: 2.30

+
+
+
+

soup_message_add_header_handler ()

+
guint
+soup_message_add_header_handler (SoupMessage *msg,
+                                 const char *signal,
+                                 const char *header,
+                                 GCallback callback,
+                                 gpointer user_data);
+

Adds a signal handler to msg + for signal +, as with +g_signal_connect(), but the callback + will only be run if msg +'s +incoming messages headers (that is, the +request_headers for a client SoupMessage, or +the response_headers for a server SoupMessage) +contain a header named header +.

+

[skip]

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

msg

a SoupMessage

 

signal

signal to connect the handler to.

 

header

HTTP response header to match against

 

callback

the header handler

 

user_data

data to pass to handler_cb +

 
+
+
+

Returns

+

the handler ID from g_signal_connect()

+
+
+
+
+

soup_message_add_status_code_handler ()

+
guint
+soup_message_add_status_code_handler (SoupMessage *msg,
+                                      const char *signal,
+                                      guint status_code,
+                                      GCallback callback,
+                                      gpointer user_data);
+

Adds a signal handler to msg + for signal +, as with +g_signal_connect(), but the callback + will only be run if msg + has +the status status_code +.

+

signal + must be a signal that will be emitted after msg +'s status +is set. For a client SoupMessage, this means it can't be a "wrote" +signal. For a server SoupMessage, this means it can't be a "got" +signal.

+

[skip]

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

msg

a SoupMessage

 

signal

signal to connect the handler to.

 

status_code

status code to match against

 

callback

the header handler

 

user_data

data to pass to handler_cb +

 
+
+
+

Returns

+

the handler ID from g_signal_connect()

+
+
+
+
+

soup_message_set_flags ()

+
void
+soup_message_set_flags (SoupMessage *msg,
+                        SoupMessageFlags flags);
+

Sets the specified flags on msg +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

msg

a SoupMessage

 

flags

a set of SoupMessageFlags values

 
+
+
+
+
+

soup_message_get_flags ()

+
SoupMessageFlags
+soup_message_get_flags (SoupMessage *msg);
+

Gets the flags on msg +

+
+

Parameters

+
+++++ + + + + + +

msg

a SoupMessage

 
+
+
+

Returns

+

the flags

+
+
+
+
+

SoupChunkAllocator ()

+
SoupBuffer *
+(*SoupChunkAllocator) (SoupMessage *msg,
+                       gsize max_len,
+                       gpointer user_data);
+
+

SoupChunkAllocator is deprecated and should not be used in newly-written code.

+

Use SoupRequest if you want to read into your +own buffers.

+
+

The prototype for a chunk allocation callback. This should allocate +a new SoupBuffer and return it for the I/O layer to read message +body data off the network into.

+

If max_len + is non-0, it indicates the maximum number of bytes that +could be read, based on what is known about the message size. Note +that this might be a very large number, and you should not simply +try to allocate that many bytes blindly. If max_len + is 0, that +means that libsoup does not know how many bytes remain to be read, +and the allocator should return a buffer of a size that it finds +convenient.

+

If the allocator returns NULL, the message will be paused. It is +up to the application to make sure that it gets unpaused when it +becomes possible to allocate a new buffer.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

msg

the SoupMessage the chunk is being allocated for

 

max_len

the maximum length that will be read, or 0.

 

user_data

the data passed to soup_message_set_chunk_allocator()

 
+
+
+

Returns

+

the new buffer (or NULL).

+

[nullable]

+
+
+
+
+

soup_message_disable_feature ()

+
void
+soup_message_disable_feature (SoupMessage *msg,
+                              GType feature_type);
+

This disables the actions of SoupSessionFeatures with the +given feature_type + (or a subclass of that type) on msg +, so that +msg + is processed as though the feature(s) hadn't been added to the +session. Eg, passing SOUP_TYPE_CONTENT_SNIFFER for feature_type + +will disable Content-Type sniffing on the message.

+

You must call this before queueing msg + on a session; calling it on +a message that has already been queued is undefined. In particular, +you cannot call this on a message that is being requeued after a +redirect or authentication.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

msg

a SoupMessage

 

feature_type

the GType of a SoupSessionFeature

 
+
+

Since: 2.28

+
+
+
+

soup_message_get_soup_request ()

+
SoupRequest *
+soup_message_get_soup_request (SoupMessage *msg);
+

If msg + is associated with a SoupRequest, this returns that +request. Otherwise it returns NULL.

+
+

Parameters

+
+++++ + + + + + +

msg

a SoupMessage

 
+
+
+

Returns

+

msg +'s associated SoupRequest.

+

[transfer none]

+
+

Since: 2.42

+
+
+
+

soup_message_get_priority ()

+
SoupMessagePriority
+soup_message_get_priority (SoupMessage *msg);
+

Retrieves the SoupMessagePriority. If not set this value defaults +to SOUP_MESSAGE_PRIORITY_NORMAL.

+
+

Parameters

+
+++++ + + + + + +

msg

a SoupMessage

 
+
+
+

Returns

+

the priority of the message.

+
+

Since: 2.44

+
+
+
+

soup_message_set_priority ()

+
void
+soup_message_set_priority (SoupMessage *msg,
+                           SoupMessagePriority priority);
+

Sets the priority of a message. Note that this won't have any +effect unless used before the message is added to the session's +message processing queue.

+

The message will be placed just before any other previously added +message with lower priority (messages with the same priority are +processed on a FIFO basis).

+

Setting priorities does not currently work with SoupSessionSync +(or with synchronous messages on a plain SoupSession) because in +the synchronous/blocking case, priority ends up being determined +semi-randomly by thread scheduling.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

msg

a SoupMessage

 

priority

the SoupMessagePriority

 
+
+

Since: 2.44

+
+
+
+

Types and Values

+
+

SoupMessage

+
typedef struct {
+	const char         *method;
+
+	guint               status_code;
+	char               *reason_phrase;
+
+	SoupMessageBody    *request_body;
+	SoupMessageHeaders *request_headers;
+
+	SoupMessageBody    *response_body;
+	SoupMessageHeaders *response_headers;
+} SoupMessage;
+
+

Represents an HTTP message being sent or received.

+

status_code + will normally be a SoupStatus value, eg, +SOUP_STATUS_OK, though of course it might actually be an unknown +status code. reason_phrase + is the actual text returned from the +server, which may or may not correspond to the "standard" +description of status_code +. At any rate, it is almost certainly +not localized, and not very descriptive even if it is in the user's +language; you should not use reason_phrase + in user-visible +messages. Rather, you should look at status_code +, and determine an +end-user-appropriate message based on that and on what you were +trying to do.

+

As described in the SoupMessageBody documentation, the +request_body + and response_body + data fields +will not necessarily be filled in at all times. When the body +fields are filled in, they will be terminated with a '\0' byte +(which is not included in the length), so you +can use them as ordinary C strings (assuming that you know that the +body doesn't have any other '\0' bytes).

+

For a client-side SoupMessage, request_body +'s +data is usually filled in right before libsoup +writes the request to the network, but you should not count on +this; use soup_message_body_flatten() if you want to ensure that +data is filled in. If you are not using +SoupRequest to read the response, then response_body +'s +data will be filled in before +“finished” is emitted. (If you are using SoupRequest, +then the message body is not accumulated by default, so +response_body +'s data will always be NULL.)

+

For a server-side SoupMessage, request_body +'s data will be +filled in before “got_body” is emitted.

+

To prevent the data field from being filled in at all (eg, if you +are handling the data from a “got_chunk”, and so don't +need to see it all at the end), call +soup_message_body_set_accumulate() on response_body + or +request_body + as appropriate, passing FALSE.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

const char *method;

the HTTP method

 

guint status_code;

the HTTP status code

 

char *reason_phrase;

the status phrase associated with status_code +

 

SoupMessageBody *request_body;

the request body

 

SoupMessageHeaders *request_headers;

the request headers

 

SoupMessageBody *response_body;

the response body

 

SoupMessageHeaders *response_headers;

the response headers

 
+
+
+
+
+

enum SoupHTTPVersion

+

Indicates the HTTP protocol version being used.

+
+

Members

+
+++++ + + + + + + + + + + + + +

SOUP_HTTP_1_0

+

HTTP 1.0 (RFC 1945)

+
 

SOUP_HTTP_1_1

+

HTTP 1.1 (RFC 2616)

+
 
+
+
+
+
+

enum SoupMessageFlags

+

Various flags that can be set on a SoupMessage to alter its +behavior.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

SOUP_MESSAGE_NO_REDIRECT

+

The session should not follow redirect + (3xx) responses received by this message.

+
 

SOUP_MESSAGE_CAN_REBUILD

+

The caller will rebuild the request + body if the message is restarted; see + soup_message_body_set_accumulate() for more details.

+
 

SOUP_MESSAGE_OVERWRITE_CHUNKS

+

Deprecated: equivalent to calling + soup_message_body_set_accumulate() on the incoming message body + (ie, “response_body” for a client-side request), + passing FALSE.

+
 

SOUP_MESSAGE_CONTENT_DECODED

+

Set by SoupContentDecoder to + indicate that it has removed the Content-Encoding on a message (and + so headers such as Content-Length may no longer accurately describe + the body).

+
 

SOUP_MESSAGE_CERTIFICATE_TRUSTED

+

if set after an https response + has been received, indicates that the server's SSL certificate is + trusted according to the session's CA.

+
 

SOUP_MESSAGE_NEW_CONNECTION

+

Requests that the message should be + sent on a newly-created connection, not reusing an existing + persistent connection. Note that messages with non-idempotent + “method”s behave this way by default, unless + SOUP_MESSAGE_IDEMPOTENT is set.

+
 

SOUP_MESSAGE_IDEMPOTENT

+

The message is considered idempotent, + regardless its “method”, and allows reuse of existing + idle connections, instead of always requiring a new one, unless + SOUP_MESSAGE_NEW_CONNECTION is set.

+
 

SOUP_MESSAGE_IGNORE_CONNECTION_LIMITS

+

Request that a new connection is + created for the message if there aren't idle connections available + and it's not possible to create new connections due to any of the + connection limits has been reached. If a dedicated connection is + eventually created for this message, it will be dropped when the + message finishes. Since 2.50

+
 

SOUP_MESSAGE_DO_NOT_USE_AUTH_CACHE

+

The SoupAuthManager should not use + the credentials cache for this message, neither to use cached credentials + to automatically authenticate this message nor to cache the credentials + after the message is successfully authenticated. This applies to both server + and proxy authentication. Note that “authenticate” signal will + be emitted, if you want to disable authentication for a message use + soup_message_disable_feature() passing SOUP_TYPE_AUTH_MANAGER instead. Since 2.58

+
 
+
+
+
+
+

enum SoupMessagePriority

+

Priorities that can be set on a SoupMessage to instruct the +message queue to process it before any other message with lower +priority.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

SOUP_MESSAGE_PRIORITY_VERY_LOW

+

The lowest priority, the messages + with this priority will be the last ones to be attended.

+
 

SOUP_MESSAGE_PRIORITY_LOW

+

Use this for low priority messages, a + SoupMessage with the default priority will be processed first.

+
 

SOUP_MESSAGE_PRIORITY_NORMAL

+

The default priotity, this is the + priority assigned to the SoupMessage by default.

+
 

SOUP_MESSAGE_PRIORITY_HIGH

+

High priority, a SoupMessage with + this priority will be processed before the ones with the default + priority.

+
 

SOUP_MESSAGE_PRIORITY_VERY_HIGH

+

The highest priority, use this + for very urgent SoupMessage as they will be the first ones to be + attended.

+
 
+
+
+
+
+

SOUP_MESSAGE_METHOD

+
#define SOUP_MESSAGE_METHOD             "method"
+
+

Alias for the “method” property. (The message's +HTTP method.)

+
+
+
+

SOUP_MESSAGE_URI

+
#define SOUP_MESSAGE_URI                "uri"
+
+

Alias for the “uri” property. (The message's +SoupURI.)

+
+
+
+

SOUP_MESSAGE_HTTP_VERSION

+
#define SOUP_MESSAGE_HTTP_VERSION       "http-version"
+
+

Alias for the “http-version” property. (The +message's SoupHTTPVersion.)

+
+
+
+

SOUP_MESSAGE_FLAGS

+
#define SOUP_MESSAGE_FLAGS              "flags"
+
+

Alias for the “flags” property. (The message's +SoupMessageFlags.)

+
+
+
+

SOUP_MESSAGE_STATUS_CODE

+
#define SOUP_MESSAGE_STATUS_CODE        "status-code"
+
+

Alias for the “status-code” property. (The +message's HTTP response status code.)

+
+
+
+

SOUP_MESSAGE_REASON_PHRASE

+
#define SOUP_MESSAGE_REASON_PHRASE      "reason-phrase"
+
+

Alias for the “reason-phrase” property. (The +message's HTTP response reason phrase.)

+
+
+
+

SOUP_MESSAGE_SERVER_SIDE

+
#define SOUP_MESSAGE_SERVER_SIDE        "server-side"
+
+

Alias for the “server-side” property. (TRUE if +the message was created by SoupServer.)

+
+
+
+

SOUP_MESSAGE_FIRST_PARTY

+
#define SOUP_MESSAGE_FIRST_PARTY        "first-party"
+
+

Alias for the “first-party” property. (The +SoupURI loaded in the application when the message was +queued.)

+

Since: 2.30

+
+
+
+

SOUP_MESSAGE_PRIORITY

+
#define SOUP_MESSAGE_PRIORITY           "priority"
+
+

Sets the priority of the SoupMessage. See +soup_message_set_priority() for further details.

+

Since: 2.44

+
+
+
+

SOUP_MESSAGE_REQUEST_BODY

+
#define SOUP_MESSAGE_REQUEST_BODY       "request-body"
+
+

Alias for the “request-body” property. (The +message's HTTP request body.)

+
+
+
+

SOUP_MESSAGE_REQUEST_BODY_DATA

+
#define SOUP_MESSAGE_REQUEST_BODY_DATA  "request-body-data"
+
+

Alias for the “request-body-data” property. (The +message's HTTP request body, as a GBytes.)

+

Since: 2.46

+
+
+
+

SOUP_MESSAGE_REQUEST_HEADERS

+
#define SOUP_MESSAGE_REQUEST_HEADERS    "request-headers"
+
+

Alias for the “request-headers” property. (The +message's HTTP request headers.)

+
+
+
+

SOUP_MESSAGE_RESPONSE_BODY

+
#define SOUP_MESSAGE_RESPONSE_BODY      "response-body"
+
+

Alias for the “response-body” property. (The +message's HTTP response body.)

+
+
+
+

SOUP_MESSAGE_RESPONSE_BODY_DATA

+
#define SOUP_MESSAGE_RESPONSE_BODY_DATA "response-body-data"
+
+

Alias for the “response-body-data” property. (The +message's HTTP response body, as a GBytes.)

+

Since: 2.46

+
+
+
+

SOUP_MESSAGE_RESPONSE_HEADERS

+
#define SOUP_MESSAGE_RESPONSE_HEADERS   "response-headers"
+
+

Alias for the “response-headers” property. (The +message's HTTP response headers.)

+
+
+
+

SOUP_MESSAGE_TLS_CERTIFICATE

+
#define SOUP_MESSAGE_TLS_CERTIFICATE    "tls-certificate"
+
+

Alias for the “tls-certificate” property. (The +TLS certificate associated with the message, if any.)

+

Since: 2.34

+
+
+
+

SOUP_MESSAGE_TLS_ERRORS

+
#define SOUP_MESSAGE_TLS_ERRORS         "tls-errors"
+
+

Alias for the “tls-errors” property. (The +verification errors on “tls-certificate”.)

+

Since: 2.34

+
+
+
+

Property Details

+
+

The “first-party” property

+
  “first-party”              SoupURI *
+

The SoupURI loaded in the application when the message was +queued.

+

Flags: Read / Write

+

Since: 2.30

+
+
+
+

The “flags” property

+
  “flags”                    SoupMessageFlags
+

Various message options.

+

Flags: Read / Write

+
+
+
+

The “http-version” property

+
  “http-version”             SoupHTTPVersion
+

The HTTP protocol version to use.

+

Flags: Read / Write

+

Default value: SOUP_HTTP_1_1

+
+
+
+

The “method” property

+
  “method”                   gchar *
+

The message's HTTP method.

+

Flags: Read / Write

+

Default value: "GET"

+
+
+
+

The “priority” property

+
  “priority”                 SoupMessagePriority
+

The priority of the message.

+

Flags: Read / Write

+

Default value: SOUP_MESSAGE_PRIORITY_NORMAL

+
+
+
+

The “reason-phrase” property

+
  “reason-phrase”            gchar *
+

The HTTP response reason phrase.

+

Flags: Read / Write

+

Default value: NULL

+
+
+
+

The “request-body” property

+
  “request-body”             SoupMessageBody *
+

The HTTP request content.

+

Flags: Read

+
+
+
+

The “request-body-data” property

+
  “request-body-data”        GBytes *
+

The message's HTTP request body, as a GBytes.

+

Flags: Read

+

Since: 2.46

+
+
+
+

The “request-headers” property

+
  “request-headers”          SoupMessageHeaders *
+

The HTTP request headers.

+

Flags: Read

+
+
+
+

The “response-body” property

+
  “response-body”            SoupMessageBody *
+

The HTTP response content.

+

Flags: Read

+
+
+
+

The “response-body-data” property

+
  “response-body-data”       GBytes *
+

The message's HTTP response body, as a GBytes.

+

Flags: Read

+

Since: 2.46

+
+
+
+

The “response-headers” property

+
  “response-headers”         SoupMessageHeaders *
+

The HTTP response headers.

+

Flags: Read

+
+
+
+

The “server-side” property

+
  “server-side”              gboolean
+

Whether or not the message is server-side rather than client-side.

+

Flags: Read / Write / Construct Only

+

Default value: FALSE

+
+
+
+

The “status-code” property

+
  “status-code”              guint
+

The HTTP response status code.

+

Flags: Read / Write

+

Allowed values: <= 999

+

Default value: 0

+
+
+
+

The “tls-certificate” property

+
  “tls-certificate”          GTlsCertificate *
+

The GTlsCertificate associated with the message

+

Flags: Read / Write

+

Since: 2.34

+
+
+
+

The “tls-errors” property

+
  “tls-errors”               GTlsCertificateFlags
+

The verification errors on “tls-certificate”

+

Flags: Read / Write

+

Since: 2.34

+
+
+
+

The “uri” property

+
  “uri”                      SoupURI *
+

The message's Request-URI.

+

Flags: Read / Write

+
+
+
+

Signal Details

+
+

The “content-sniffed” signal

+
void
+user_function (SoupMessage *msg,
+               gchar       *type,
+               GHashTable  *params,
+               gpointer     user_data)
+

This signal is emitted after “got-headers”, and +before the first “got-chunk”. If content +sniffing is disabled, or no content sniffing will be +performed, due to the sniffer deciding to trust the +Content-Type sent by the server, this signal is emitted +immediately after “got-headers”, and type + is +NULL.

+

If the SoupContentSniffer feature is enabled, and the +sniffer decided to perform sniffing, the first +“got-chunk” emission may be delayed, so that the +sniffer has enough data to correctly sniff the content. It +notified the library user that the content has been +sniffed, and allows it to change the header contents in the +message, if desired.

+

After this signal is emitted, the data that was spooled so +that sniffing could be done is delivered on the first +emission of “got-chunk”.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

msg

the message

 

type

the content type that we got from sniffing

 

params

a GHashTable with the parameters.

[element-type utf8 utf8]

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+

Since: 2.28

+
+
+
+

The “finished” signal

+
void
+user_function (SoupMessage *msg,
+               gpointer     user_data)
+

Emitted when all HTTP processing is finished for a message. +(After “got_body” for client-side messages, or +after “wrote_body” for server-side messages.)

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

msg

the message

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+
+
+
+

The “got-body” signal

+
void
+user_function (SoupMessage *msg,
+               gpointer     user_data)
+

Emitted after receiving the complete message body. (For a +server-side message, this means it has received the request +body. For a client-side message, this means it has received +the response body and is nearly done with the message.)

+

See also soup_message_add_header_handler() and +soup_message_add_status_code_handler(), which can be used +to connect to a subset of emissions of this signal.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

msg

the message

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+
+
+
+

The “got-chunk” signal

+
void
+user_function (SoupMessage *msg,
+               SoupBuffer  *chunk,
+               gpointer     user_data)
+

Emitted after receiving a chunk of a message body. Note +that "chunk" in this context means any subpiece of the +body, not necessarily the specific HTTP 1.1 chunks sent by +the other side.

+

If you cancel or requeue msg + while processing this signal, +then the current HTTP I/O will be stopped after this signal +emission finished, and msg +'s connection will be closed.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

msg

the message

 

chunk

the just-read chunk

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+
+
+
+

The “got-headers” signal

+
void
+user_function (SoupMessage *msg,
+               gpointer     user_data)
+

Emitted after receiving all message headers for a message. +(For a client-side message, this is after receiving the +Status-Line and response headers; for a server-side +message, it is after receiving the Request-Line and request +headers.)

+

See also soup_message_add_header_handler() and +soup_message_add_status_code_handler(), which can be used +to connect to a subset of emissions of this signal.

+

If you cancel or requeue msg + while processing this signal, +then the current HTTP I/O will be stopped after this signal +emission finished, and msg +'s connection will be closed. +(If you need to requeue a message--eg, after handling +authentication or redirection--it is usually better to +requeue it from a “got_body” handler rather +than a “got_headers” handler, so that the +existing HTTP connection can be reused.)

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

msg

the message

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+
+
+
+

The “got-informational” signal

+
void
+user_function (SoupMessage *msg,
+               gpointer     user_data)
+

Emitted after receiving a 1xx (Informational) response for +a (client-side) message. The response_headers will be +filled in with the headers associated with the +informational response; however, those header values will +be erased after this signal is done.

+

If you cancel or requeue msg + while processing this signal, +then the current HTTP I/O will be stopped after this signal +emission finished, and msg +'s connection will be closed.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

msg

the message

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+
+
+
+

The “network-event” signal

+
void
+user_function (SoupMessage       *msg,
+               GSocketClientEvent event,
+               GIOStream         *connection,
+               gpointer           user_data)
+

Emitted to indicate that some network-related event +related to msg + has occurred. This essentially proxies the +“event” signal, but only for events that +occur while msg + "owns" the connection; if msg + is sent on +an existing persistent connection, then this signal will +not be emitted. (If you want to force the message to be +sent on a new connection, set the +SOUP_MESSAGE_NEW_CONNECTION flag on it.)

+

See “event” for more information on what +the different values of event + correspond to, and what +connection + will be in each case.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

msg

the message

 

event

the network event

 

connection

the current state of the network connection

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+

Since: 2.38

+
+
+
+

The “restarted” signal

+
void
+user_function (SoupMessage *msg,
+               gpointer     user_data)
+

Emitted when a request that was already sent once is now +being sent again (eg, because the first attempt received a +redirection response, or because we needed to use +authentication).

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

msg

the message

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+
+
+
+

The “starting” signal

+
void
+user_function (SoupMessage *msg,
+               gpointer     user_data)
+

Emitted just before a message is sent.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

msg

the message

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+

Since: 2.50

+
+
+
+

The “wrote-body” signal

+
void
+user_function (SoupMessage *msg,
+               gpointer     user_data)
+

Emitted immediately after writing the complete body for a +message. (For a client-side message, this means that +libsoup is done writing and is now waiting for the response +from the server. For a server-side message, this means that +libsoup has finished writing the response and is nearly +done with the message.)

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

msg

the message

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+
+
+
+

The “wrote-body-data” signal

+
void
+user_function (SoupMessage *msg,
+               SoupBuffer  *chunk,
+               gpointer     user_data)
+

Emitted immediately after writing a portion of the message +body to the network.

+

Unlike “wrote_chunk”, this is emitted after +every successful write() call, not only after finishing a +complete "chunk".

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

msg

the message

 

chunk

the data written

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+

Since: 2.24

+
+
+
+

The “wrote-chunk” signal

+
void
+user_function (SoupMessage *msg,
+               gpointer     user_data)
+

Emitted immediately after writing a body chunk for a message.

+

Note that this signal is not parallel to +“got_chunk”; it is emitted only when a complete +chunk (added with soup_message_body_append() or +soup_message_body_append_buffer()) has been written. To get +more useful continuous progress information, use +“wrote_body_data”.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

msg

the message

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+
+
+
+

The “wrote-headers” signal

+
void
+user_function (SoupMessage *msg,
+               gpointer     user_data)
+

Emitted immediately after writing the headers for a +message. (For a client-side message, this is after writing +the request headers; for a server-side message, it is after +writing the response headers.)

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

msg

the message

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+
+
+
+

The “wrote-informational” signal

+
void
+user_function (SoupMessage *msg,
+               gpointer     user_data)
+

Emitted immediately after writing a 1xx (Informational) +response for a (server-side) message.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

msg

the message

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+
+
+ +
+ + + \ No newline at end of file diff --git a/docs/reference/html/SoupMessageBody.html b/docs/reference/html/SoupMessageBody.html new file mode 100644 index 0000000..ec02c57 --- /dev/null +++ b/docs/reference/html/SoupMessageBody.html @@ -0,0 +1,1269 @@ + + + + +SoupMessageBody: libsoup Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

SoupMessageBody

+

SoupMessageBody — HTTP message body

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+SoupBuffer * + +soup_buffer_new () +
+SoupBuffer * + +soup_buffer_new_subbuffer () +
+SoupBuffer * + +soup_buffer_new_with_owner () +
+SoupBuffer * + +soup_buffer_new_take () +
+gpointer + +soup_buffer_get_owner () +
+void + +soup_buffer_get_data () +
+SoupBuffer * + +soup_buffer_copy () +
+void + +soup_buffer_free () +
+GBytes * + +soup_buffer_get_as_bytes () +
+SoupMessageBody * + +soup_message_body_new () +
+void + +soup_message_body_free () +
+void + +soup_message_body_set_accumulate () +
+gboolean + +soup_message_body_get_accumulate () +
+void + +soup_message_body_append () +
+void + +soup_message_body_append_buffer () +
+void + +soup_message_body_append_take () +
+void + +soup_message_body_truncate () +
+void + +soup_message_body_complete () +
+SoupBuffer * + +soup_message_body_flatten () +
+SoupBuffer * + +soup_message_body_get_chunk () +
+void + +soup_message_body_got_chunk () +
+void + +soup_message_body_wrote_chunk () +
+
+
+

Types and Values

+
++++ + + + + + + + + + + + + + + +
 SoupBuffer
enumSoupMemoryUse
 SoupMessageBody
+
+
+

Object Hierarchy

+
    GBoxed
+    ├── SoupBuffer
+    ╰── SoupMessageBody
+
+
+
+

Includes

+
#include <libsoup/soup.h>
+
+
+
+

Description

+

SoupMessageBody represents the request or response body of a +SoupMessage.

+

In addition to SoupMessageBody, libsoup also defines a "smaller" +data buffer type, SoupBuffer, which is primarily used as a +component of SoupMessageBody. In particular, when using chunked +encoding to transmit or receive a message, each chunk is +represented as a SoupBuffer.

+
+
+

Functions

+
+

soup_buffer_new ()

+
SoupBuffer *
+soup_buffer_new (SoupMemoryUse use,
+                 gconstpointer data,
+                 gsize length);
+

Creates a new SoupBuffer containing length + bytes from data +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

use

how data +is to be used by the buffer

 

data

data.

[array length=length][element-type guint8]

length

length of data +

 
+
+
+

Returns

+

the new SoupBuffer.

+
+
+
+
+

soup_buffer_new_subbuffer ()

+
SoupBuffer *
+soup_buffer_new_subbuffer (SoupBuffer *parent,
+                           gsize offset,
+                           gsize length);
+

Creates a new SoupBuffer containing length + bytes "copied" from +parent + starting at offset +. (Normally this will not actually copy +any data, but will instead simply reference the same data as +parent + does.)

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

parent

the parent SoupBuffer

 

offset

offset within parent +to start at

 

length

number of bytes to copy from parent +

 
+
+
+

Returns

+

the new SoupBuffer.

+
+
+
+
+

soup_buffer_new_with_owner ()

+
SoupBuffer *
+soup_buffer_new_with_owner (gconstpointer data,
+                            gsize length,
+                            gpointer owner,
+                            GDestroyNotify owner_dnotify);
+

Creates a new SoupBuffer containing length + bytes from data +. When +the SoupBuffer is freed, it will call owner_dnotify +, passing +owner + to it. You must ensure that data + will remain valid until +owner_dnotify + is called.

+

For example, you could use this to create a buffer containing data +returned from libxml without needing to do an extra copy:

+
+ + + + + + + +
1
+2
+3
xmlDocDumpMemory (doc, &xmlbody, &len);
+return soup_buffer_new_with_owner (xmlbody, len, xmlbody,
+                                   (GDestroyNotify)xmlFree);
+
+ +

In this example, data + and owner + are the same, but in other cases +they would be different (eg, owner + would be a object, and data + +would be a pointer to one of the object's fields).

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

data

data.

[array length=length][element-type guint8]

length

length of data +

 

owner

pointer to an object that owns data +

 

owner_dnotify

a function to free/unref owner +when +the buffer is freed.

[allow-none]
+
+
+

Returns

+

the new SoupBuffer.

+
+
+
+
+

soup_buffer_new_take ()

+
SoupBuffer *
+soup_buffer_new_take (guchar *data,
+                      gsize length);
+

Creates a new SoupBuffer containing length + bytes from data +.

+

This function is exactly equivalent to soup_buffer_new() with +SOUP_MEMORY_TAKE as first argument; it exists mainly for +convenience and simplifying language bindings.

+

[rename-to soup_buffer_new]

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

data

data.

[array length=length][transfer full]

length

length of data +

 
+
+
+

Returns

+

the new SoupBuffer.

+
+

Since: 2.32

+
+
+
+

soup_buffer_get_owner ()

+
gpointer
+soup_buffer_get_owner (SoupBuffer *buffer);
+

Gets the "owner" object for a buffer created with +soup_buffer_new_with_owner().

+
+

Parameters

+
+++++ + + + + + +

buffer

a SoupBuffer created with soup_buffer_new_with_owner()

 
+
+
+

Returns

+

the owner pointer.

+

[transfer none]

+
+
+
+
+

soup_buffer_get_data ()

+
void
+soup_buffer_get_data (SoupBuffer *buffer,
+                      const guint8 **data,
+                      gsize *length);
+

This function exists for use by language bindings, because it's not +currently possible to get the right effect by annotating the fields +of SoupBuffer.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

buffer

a SoupBuffer

 

data

the pointer +to the buffer data is stored here.

[out][array length=length][transfer none]

length

the length of the buffer data is stored here.

[out]
+
+

Since: 2.32

+
+
+
+

soup_buffer_copy ()

+
SoupBuffer *
+soup_buffer_copy (SoupBuffer *buffer);
+

Makes a copy of buffer +. In reality, SoupBuffer is a refcounted +type, and calling soup_buffer_copy() will normally just increment +the refcount on buffer + and return it. However, if buffer + was +created with SOUP_MEMORY_TEMPORARY memory, then soup_buffer_copy() +will actually return a copy of it, so that the data in the copy +will remain valid after the temporary buffer is freed.

+
+

Parameters

+
+++++ + + + + + +

buffer

a SoupBuffer

 
+
+
+

Returns

+

the new (or newly-reffed) buffer

+
+
+
+
+

soup_buffer_free ()

+
void
+soup_buffer_free (SoupBuffer *buffer);
+

Frees buffer +. (In reality, as described in the documentation for +soup_buffer_copy(), this is actually an "unref" operation, and may +or may not actually free buffer +.)

+
+

Parameters

+
+++++ + + + + + +

buffer

a SoupBuffer

 
+
+
+
+
+

soup_buffer_get_as_bytes ()

+
GBytes *
+soup_buffer_get_as_bytes (SoupBuffer *buffer);
+

Creates a GBytes pointing to the same memory as buffer +. The +GBytes will hold a reference on buffer + to ensure that it is not +freed while the GBytes is still valid.

+
+

Parameters

+
+++++ + + + + + +

buffer

a SoupBuffer

 
+
+
+

Returns

+

a new GBytes which has the same content +as the SoupBuffer.

+

[transfer full]

+
+

Since: 2.40

+
+
+
+

soup_message_body_new ()

+
SoupMessageBody *
+soup_message_body_new (void);
+

Creates a new SoupMessageBody. SoupMessage uses this internally; you +will not normally need to call it yourself.

+
+

Returns

+

a new SoupMessageBody.

+
+
+
+
+

soup_message_body_free ()

+
void
+soup_message_body_free (SoupMessageBody *body);
+

Frees body +. You will not normally need to use this, as +SoupMessage frees its associated message bodies automatically.

+
+

Parameters

+
+++++ + + + + + +

body

a SoupMessageBody

 
+
+
+
+
+

soup_message_body_set_accumulate ()

+
void
+soup_message_body_set_accumulate (SoupMessageBody *body,
+                                  gboolean accumulate);
+

Sets or clears the accumulate flag on body +. (The default value is +TRUE.) If set to FALSE, body +'s data field will not be filled in +after the body is fully sent/received, and the chunks that make up +body + may be discarded when they are no longer needed.

+

In particular, if you set this flag to FALSE on an "incoming" +message body (that is, the “response_body” of a +client-side message, or “request_body” of a server-side +message), this will cause each chunk of the body to be discarded +after its corresponding “got_chunk” signal is emitted. +(This is equivalent to setting the deprecated +SOUP_MESSAGE_OVERWRITE_CHUNKS flag on the message.)

+

If you set this flag to FALSE on the “response_body” of +a server-side message, it will cause each chunk of the body to be +discarded after its corresponding “wrote_chunk” signal +is emitted.

+

If you set the flag to FALSE on the “request_body” of a +client-side message, it will block the accumulation of chunks into +body +'s data field, but it will not normally cause the chunks to +be discarded after being written like in the server-side +“response_body” case, because the request body needs to +be kept around in case the request needs to be sent a second time +due to redirection or authentication. However, if you set the +SOUP_MESSAGE_CAN_REBUILD flag on the message, then the chunks will +be discarded, and you will be responsible for recreating the +request body after the “restarted” signal is emitted.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

body

a SoupMessageBody

 

accumulate

whether or not to accumulate body chunks in body +

 
+
+

Since: 2.24

+
+
+
+

soup_message_body_get_accumulate ()

+
gboolean
+soup_message_body_get_accumulate (SoupMessageBody *body);
+

Gets the accumulate flag on body +; see +soup_message_body_set_accumulate() for details.

+
+

Parameters

+
+++++ + + + + + +

body

a SoupMessageBody

 
+
+
+

Returns

+

the accumulate flag for body +.

+
+

Since: 2.24

+
+
+
+

soup_message_body_append ()

+
void
+soup_message_body_append (SoupMessageBody *body,
+                          SoupMemoryUse use,
+                          gconstpointer data,
+                          gsize length);
+

Appends length + bytes from data + to body + according to use +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

body

a SoupMessageBody

 

use

how to use data +

 

data

data to append.

[array length=length][element-type guint8]

length

length of data +

 
+
+
+
+
+

soup_message_body_append_buffer ()

+
void
+soup_message_body_append_buffer (SoupMessageBody *body,
+                                 SoupBuffer *buffer);
+

Appends the data from buffer + to body +. (SoupMessageBody uses +SoupBuffers internally, so this is normally a constant-time +operation that doesn't actually require copying the data in +buffer +.)

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

body

a SoupMessageBody

 

buffer

a SoupBuffer

 
+
+
+
+
+

soup_message_body_append_take ()

+
void
+soup_message_body_append_take (SoupMessageBody *body,
+                               guchar *data,
+                               gsize length);
+

Appends length + bytes from data + to body +.

+

This function is exactly equivalent to soup_message_body_append() +with SOUP_MEMORY_TAKE as second argument; it exists mainly for +convenience and simplifying language bindings.

+

[rename-to soup_message_body_append]

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

body

a SoupMessageBody

 

data

data to append.

[array length=length][transfer full]

length

length of data +

 
+
+

Since: 2.32

+
+
+
+

soup_message_body_truncate ()

+
void
+soup_message_body_truncate (SoupMessageBody *body);
+

Deletes all of the data in body +.

+
+

Parameters

+
+++++ + + + + + +

body

a SoupMessageBody

 
+
+
+
+
+

soup_message_body_complete ()

+
void
+soup_message_body_complete (SoupMessageBody *body);
+

Tags body + as being complete; Call this when using chunked encoding +after you have appended the last chunk.

+
+

Parameters

+
+++++ + + + + + +

body

a SoupMessageBody

 
+
+
+
+
+

soup_message_body_flatten ()

+
SoupBuffer *
+soup_message_body_flatten (SoupMessageBody *body);
+

Fills in body +'s data field with a buffer containing all of the +data in body + (plus an additional '\0' byte not counted by body +'s +length field).

+
+

Parameters

+
+++++ + + + + + +

body

a SoupMessageBody

 
+
+
+

Returns

+

a SoupBuffer containing the same data as body +. +(You must free this buffer if you do not want it.)

+
+
+
+
+

soup_message_body_get_chunk ()

+
SoupBuffer *
+soup_message_body_get_chunk (SoupMessageBody *body,
+                             goffset offset);
+

Gets a SoupBuffer containing data from body + starting at offset +. +The size of the returned chunk is unspecified. You can iterate +through the entire body by first calling +soup_message_body_get_chunk() with an offset of 0, and then on each +successive call, increment the offset by the length of the +previously-returned chunk.

+

If offset + is greater than or equal to the total length of body +, +then the return value depends on whether or not +soup_message_body_complete() has been called or not; if it has, +then soup_message_body_get_chunk() will return a 0-length chunk +(indicating the end of body +). If it has not, then +soup_message_body_get_chunk() will return NULL (indicating that +body + may still potentially have more data, but that data is not +currently available).

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

body

a SoupMessageBody

 

offset

an offset

 
+
+
+

Returns

+

a SoupBuffer, or NULL.

+

[nullable]

+
+
+
+
+

soup_message_body_got_chunk ()

+
void
+soup_message_body_got_chunk (SoupMessageBody *body,
+                             SoupBuffer *chunk);
+

Handles the SoupMessageBody part of receiving a chunk of data from +the network. Normally this means appending chunk + to body +, exactly +as with soup_message_body_append_buffer(), but if you have set +body +'s accumulate flag to FALSE, then that will not happen.

+

This is a low-level method which you should not normally need to +use.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

body

a SoupMessageBody

 

chunk

a SoupBuffer received from the network

 
+
+

Since: 2.24

+
+
+
+

soup_message_body_wrote_chunk ()

+
void
+soup_message_body_wrote_chunk (SoupMessageBody *body,
+                               SoupBuffer *chunk);
+

Handles the SoupMessageBody part of writing a chunk of data to the +network. Normally this is a no-op, but if you have set body +'s +accumulate flag to FALSE, then this will cause chunk + to be +discarded to free up memory.

+

This is a low-level method which you should not need to use, and +there are further restrictions on its proper use which are not +documented here.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

body

a SoupMessageBody

 

chunk

a SoupBuffer returned from soup_message_body_get_chunk()

 
+
+

Since: 2.24

+
+
+
+

Types and Values

+
+

SoupBuffer

+
typedef struct {
+	const char *data;
+	gsize       length;
+} SoupBuffer;
+
+

A data buffer, generally used to represent a chunk of a +SoupMessageBody.

+

data + is a char because that's generally convenient; in some +situations you may need to cast it to guchar or another type.

+
+

Members

+
+++++ + + + + + + + + + + + + +

const char *data;

the data.

[type gpointer]

gsize length;

length of data +

 
+
+
+
+
+

enum SoupMemoryUse

+

Describes how SoupBuffer should use the data passed in by the +caller.

+

See also soup_buffer_new_with_owner(), which allows to you create a +buffer containing data which is owned by another object.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

SOUP_MEMORY_STATIC

+

The memory is statically allocated and +constant; libsoup can use the passed-in buffer directly and not +need to worry about it being modified or freed.

+
 

SOUP_MEMORY_TAKE

+

The caller has allocated the memory for the +SoupBuffer's use; libsoup will assume ownership of it and free it +(with g_free()) when it is done with it.

+
 

SOUP_MEMORY_COPY

+

The passed-in data belongs to the caller; the +SoupBuffer will copy it into new memory, leaving the caller free +to reuse the original memory.

+
 

SOUP_MEMORY_TEMPORARY

+

The passed-in data belongs to the caller, +but will remain valid for the lifetime of the SoupBuffer. The +difference between this and SOUP_MEMORY_STATIC + is that if you copy +a SOUP_MEMORY_TEMPORARY + buffer, it will make a copy of the memory +as well, rather than reusing the original memory.

+
 
+
+
+
+
+

SoupMessageBody

+
typedef struct {
+	const char *data;
+	goffset     length;
+} SoupMessageBody;
+
+

A SoupMessage request or response body.

+

Note that while length + always reflects the full length of the +message body, data + is normally NULL, and will only be filled in +after soup_message_body_flatten() is called. For client-side +messages, this automatically happens for the response body after it +has been fully read, unless you set the +SOUP_MESSAGE_OVERWRITE_CHUNKS flags. Likewise, for server-side +messages, the request body is automatically filled in after being +read.

+

As an added bonus, when data + is filled in, it is always terminated +with a '\0' byte (which is not reflected in length +).

+
+

Members

+
+++++ + + + + + + + + + + + + +

const char *data;

the data

 

goffset length;

length of data +

 
+
+
+
+
+

See Also

+

SoupMessage

+
+
+ + + \ No newline at end of file diff --git a/docs/reference/html/SoupMessageHeaders.html b/docs/reference/html/SoupMessageHeaders.html new file mode 100644 index 0000000..237e4fd --- /dev/null +++ b/docs/reference/html/SoupMessageHeaders.html @@ -0,0 +1,1904 @@ + + + + +SoupMessageHeaders: libsoup Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

SoupMessageHeaders

+

SoupMessageHeaders — HTTP message headers

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+SoupMessageHeaders * + +soup_message_headers_new () +
+void + +soup_message_headers_free () +
+void + +soup_message_headers_append () +
+void + +soup_message_headers_replace () +
+void + +soup_message_headers_remove () +
+void + +soup_message_headers_clear () +
+void + +soup_message_headers_clean_connection_headers () +
const char * + +soup_message_headers_get_one () +
const char * + +soup_message_headers_get_list () +
+SoupMessageHeadersType + +soup_message_headers_get_headers_type () +
+gboolean + +soup_message_headers_header_contains () +
+gboolean + +soup_message_headers_header_equals () +
+void + +(*SoupMessageHeadersForeachFunc) () +
+void + +soup_message_headers_foreach () +
+void + +soup_message_headers_iter_init () +
+gboolean + +soup_message_headers_iter_next () +
+SoupEncoding + +soup_message_headers_get_encoding () +
+void + +soup_message_headers_set_encoding () +
+goffset + +soup_message_headers_get_content_length () +
+void + +soup_message_headers_set_content_length () +
+SoupExpectation + +soup_message_headers_get_expectations () +
+void + +soup_message_headers_set_expectations () +
const char * + +soup_message_headers_get_content_type () +
+void + +soup_message_headers_set_content_type () +
+gboolean + +soup_message_headers_get_content_disposition () +
+void + +soup_message_headers_set_content_disposition () +
+gboolean + +soup_message_headers_get_ranges () +
+void + +soup_message_headers_set_ranges () +
+void + +soup_message_headers_set_range () +
+void + +soup_message_headers_free_ranges () +
+gboolean + +soup_message_headers_get_content_range () +
+void + +soup_message_headers_set_content_range () +
+
+
+

Types and Values

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + +
typedefSoupMessageHeaders
enumSoupMessageHeadersType
 SoupMessageHeadersIter
enumSoupEncoding
enumSoupExpectation
 SoupRange
+
+
+

Object Hierarchy

+
    GBoxed
+    ╰── SoupMessageHeaders
+
+
+
+

Includes

+
#include <libsoup/soup.h>
+
+
+
+

Description

+

SoupMessageHeaders represents the HTTP message headers associated +with a request or response.

+
+
+

Functions

+
+

soup_message_headers_new ()

+
SoupMessageHeaders *
+soup_message_headers_new (SoupMessageHeadersType type);
+

Creates a SoupMessageHeaders. (SoupMessage does this +automatically for its own headers. You would only need to use this +method if you are manually parsing or generating message headers.)

+
+

Parameters

+
+++++ + + + + + +

type

the type of headers

 
+
+
+

Returns

+

a new SoupMessageHeaders

+
+
+
+
+

soup_message_headers_free ()

+
void
+soup_message_headers_free (SoupMessageHeaders *hdrs);
+

Frees hdrs +.

+
+

Parameters

+
+++++ + + + + + +

hdrs

a SoupMessageHeaders

 
+
+
+
+
+

soup_message_headers_append ()

+
void
+soup_message_headers_append (SoupMessageHeaders *hdrs,
+                             const char *name,
+                             const char *value);
+

Appends a new header with name name + and value value + to hdrs +. (If +there is an existing header with name name +, then this creates a +second one, which is only allowed for list-valued headers; see also +soup_message_headers_replace().)

+

The caller is expected to make sure that name + and value + are +syntactically correct.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

hdrs

a SoupMessageHeaders

 

name

the header name to add

 

value

the new value of name +

 
+
+
+
+
+

soup_message_headers_replace ()

+
void
+soup_message_headers_replace (SoupMessageHeaders *hdrs,
+                              const char *name,
+                              const char *value);
+

Replaces the value of the header name + in hdrs + with value +. (See +also soup_message_headers_append().)

+

The caller is expected to make sure that name + and value + are +syntactically correct.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

hdrs

a SoupMessageHeaders

 

name

the header name to replace

 

value

the new value of name +

 
+
+
+
+
+

soup_message_headers_remove ()

+
void
+soup_message_headers_remove (SoupMessageHeaders *hdrs,
+                             const char *name);
+

Removes name + from hdrs +. If there are multiple values for name +, +they are all removed.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

hdrs

a SoupMessageHeaders

 

name

the header name to remove

 
+
+
+
+
+

soup_message_headers_clear ()

+
void
+soup_message_headers_clear (SoupMessageHeaders *hdrs);
+

Clears hdrs +.

+
+

Parameters

+
+++++ + + + + + +

hdrs

a SoupMessageHeaders

 
+
+
+
+
+

soup_message_headers_clean_connection_headers ()

+
void
+soup_message_headers_clean_connection_headers
+                               (SoupMessageHeaders *hdrs);
+

Removes all the headers listed in the Connection header.

+
+

Parameters

+
+++++ + + + + + +

hdrs

a SoupMessageHeaders

 
+
+

Since: 2.36

+
+
+
+

soup_message_headers_get_one ()

+
const char *
+soup_message_headers_get_one (SoupMessageHeaders *hdrs,
+                              const char *name);
+

Gets the value of header name + in hdrs +. Use this for headers whose +values are not comma-delimited lists, and +which therefore can only appear at most once in the headers. For +list-valued headers, use soup_message_headers_get_list().

+

If hdrs + does erroneously contain multiple copies of the header, it +is not defined which one will be returned. (Ideally, it will return +whichever one makes libsoup most compatible with other HTTP +implementations.)

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

hdrs

a SoupMessageHeaders

 

name

header name

 
+
+
+

Returns

+

the header's value or NULL if not found.

+

[nullable]

+
+

Since: 2.28

+
+
+
+

soup_message_headers_get_list ()

+
const char *
+soup_message_headers_get_list (SoupMessageHeaders *hdrs,
+                               const char *name);
+

Gets the value of header name + in hdrs +. Use this for headers whose +values are comma-delimited lists, and which are therefore allowed +to appear multiple times in the headers. For non-list-valued +headers, use soup_message_headers_get_one().

+

If name + appears multiple times in hdrs +, +soup_message_headers_get_list() will concatenate all of the values +together, separated by commas. This is sometimes awkward to parse +(eg, WWW-Authenticate, Set-Cookie), but you have to be able to deal +with it anyway, because the HTTP spec explicitly states that this +transformation is allowed, and so an upstream proxy could do the +same thing.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

hdrs

a SoupMessageHeaders

 

name

header name

 
+
+
+

Returns

+

the header's value or NULL if not found.

+

[nullable]

+
+

Since: 2.28

+
+
+
+

soup_message_headers_get_headers_type ()

+
SoupMessageHeadersType
+soup_message_headers_get_headers_type (SoupMessageHeaders *hdrs);
+

Gets the type of headers.

+
+

Parameters

+
+++++ + + + + + +

hdrs

a SoupMessageHeaders

 
+
+
+

Returns

+

the header's type.

+
+

Since: 2.50

+
+
+
+

soup_message_headers_header_contains ()

+
gboolean
+soup_message_headers_header_contains (SoupMessageHeaders *hdrs,
+                                      const char *name,
+                                      const char *token);
+

Checks whether the list-valued header name + is present in hdrs +, +and contains a case-insensitive match for token +.

+

(If name + is present in hdrs +, then this is equivalent to calling +soup_header_contains() on its value.)

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

hdrs

a SoupMessageHeaders

 

name

header name

 

token

token to look for

 
+
+
+

Returns

+

TRUE if the header is present and contains token +, +FALSE otherwise.

+
+

Since: 2.50

+
+
+
+

soup_message_headers_header_equals ()

+
gboolean
+soup_message_headers_header_equals (SoupMessageHeaders *hdrs,
+                                    const char *name,
+                                    const char *value);
+

Checks whether the header name + is present in hdrs + and is +(case-insensitively) equal to value +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

hdrs

a SoupMessageHeaders

 

name

header name

 

value

expected value

 
+
+
+

Returns

+

TRUE if the header is present and its value is +value +, FALSE otherwise.

+
+

Since: 2.50

+
+
+
+

SoupMessageHeadersForeachFunc ()

+
void
+(*SoupMessageHeadersForeachFunc) (const char *name,
+                                  const char *value,
+                                  gpointer user_data);
+

The callback passed to soup_message_headers_foreach().

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

name

the header name

 

value

the header value

 

user_data

the data passed to soup_message_headers_foreach()

 
+
+
+
+
+

soup_message_headers_foreach ()

+
void
+soup_message_headers_foreach (SoupMessageHeaders *hdrs,
+                              SoupMessageHeadersForeachFunc func,
+                              gpointer user_data);
+

Calls func + once for each header value in hdrs +.

+

Beware that unlike soup_message_headers_get(), this processes the +headers in exactly the way they were added, rather than +concatenating multiple same-named headers into a single value. +(This is intentional; it ensures that if you call +soup_message_headers_append() multiple times with the same name, +then the I/O code will output multiple copies of the header when +sending the message to the remote implementation, which may be +required for interoperability in some cases.)

+

You may not modify the headers from func +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

hdrs

a SoupMessageHeaders

 

func

callback function to run for each header.

[scope call]

user_data

data to pass to func +

 
+
+
+
+
+

soup_message_headers_iter_init ()

+
void
+soup_message_headers_iter_init (SoupMessageHeadersIter *iter,
+                                SoupMessageHeaders *hdrs);
+

Initializes iter + for iterating hdrs +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

iter

a pointer to a SoupMessageHeadersIter +structure.

[out][transfer none]

hdrs

a SoupMessageHeaders

 
+
+
+
+
+

soup_message_headers_iter_next ()

+
gboolean
+soup_message_headers_iter_next (SoupMessageHeadersIter *iter,
+                                const char **name,
+                                const char **value);
+

Yields the next name/value pair in the SoupMessageHeaders being +iterated by iter +. If iter + has already yielded the last header, +then soup_message_headers_iter_next() will return FALSE and name + +and value + will be unchanged.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

iter

a SoupMessageHeadersIter.

[inout][transfer none]

name

pointer to a variable to return +the header name in.

[out][transfer none]

value

pointer to a variable to return +the header value in.

[out][transfer none]
+
+
+

Returns

+

TRUE if another name and value were returned, FALSE +if the end of the headers has been reached.

+
+
+
+
+

soup_message_headers_get_encoding ()

+
SoupEncoding
+soup_message_headers_get_encoding (SoupMessageHeaders *hdrs);
+

Gets the message body encoding that hdrs + declare. This may not +always correspond to the encoding used on the wire; eg, a HEAD +response may declare a Content-Length or Transfer-Encoding, but +it will never actually include a body.

+
+

Parameters

+
+++++ + + + + + +

hdrs

a SoupMessageHeaders

 
+
+
+

Returns

+

the encoding declared by hdrs +.

+
+
+
+
+

soup_message_headers_set_encoding ()

+
void
+soup_message_headers_set_encoding (SoupMessageHeaders *hdrs,
+                                   SoupEncoding encoding);
+

Sets the message body encoding that hdrs + will declare. In particular, +you should use this if you are going to send a request or response in +chunked encoding.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

hdrs

a SoupMessageHeaders

 

encoding

a SoupEncoding

 
+
+
+
+
+

soup_message_headers_get_content_length ()

+
goffset
+soup_message_headers_get_content_length
+                               (SoupMessageHeaders *hdrs);
+

Gets the message body length that hdrs + declare. This will only +be non-0 if soup_message_headers_get_encoding() returns +SOUP_ENCODING_CONTENT_LENGTH.

+
+

Parameters

+
+++++ + + + + + +

hdrs

a SoupMessageHeaders

 
+
+
+

Returns

+

the message body length declared by hdrs +.

+
+
+
+
+

soup_message_headers_set_content_length ()

+
void
+soup_message_headers_set_content_length
+                               (SoupMessageHeaders *hdrs,
+                                goffset content_length);
+

Sets the message body length that hdrs + will declare, and sets +hdrs +'s encoding to SOUP_ENCODING_CONTENT_LENGTH.

+

You do not normally need to call this; if hdrs + is set to use +Content-Length encoding, libsoup will automatically set its +Content-Length header for you immediately before sending the +headers. One situation in which this method is useful is when +generating the response to a HEAD request; Calling +soup_message_headers_set_content_length() allows you to put the +correct content length into the response without needing to waste +memory by filling in a response body which won't actually be sent.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

hdrs

a SoupMessageHeaders

 

content_length

the message body length

 
+
+
+
+
+

soup_message_headers_get_expectations ()

+
SoupExpectation
+soup_message_headers_get_expectations (SoupMessageHeaders *hdrs);
+

Gets the expectations declared by hdrs +'s "Expect" header. +Currently this will either be SOUP_EXPECTATION_CONTINUE or +SOUP_EXPECTATION_UNRECOGNIZED.

+
+

Parameters

+
+++++ + + + + + +

hdrs

a SoupMessageHeaders

 
+
+
+

Returns

+

the contents of hdrs +'s "Expect" header

+
+
+
+
+

soup_message_headers_set_expectations ()

+
void
+soup_message_headers_set_expectations (SoupMessageHeaders *hdrs,
+                                       SoupExpectation expectations);
+

Sets hdrs +'s "Expect" header according to expectations +.

+

Currently SOUP_EXPECTATION_CONTINUE is the only known expectation +value. You should set this value on a request if you are sending a +large message body (eg, via POST or PUT), and want to give the +server a chance to reject the request after seeing just the headers +(eg, because it will require authentication before allowing you to +post, or because you're POSTing to a URL that doesn't exist). This +saves you from having to transmit the large request body when the +server is just going to ignore it anyway.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

hdrs

a SoupMessageHeaders

 

expectations

the expectations to set

 
+
+
+
+
+

soup_message_headers_get_content_type ()

+
const char *
+soup_message_headers_get_content_type (SoupMessageHeaders *hdrs,
+                                       GHashTable **params);
+

Looks up the "Content-Type" header in hdrs +, parses it, and returns +its value in *content_type + and *params +. params + can be NULL if you +are only interested in the content type itself.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

hdrs

a SoupMessageHeaders

 

params

return location for the Content-Type parameters (eg, "charset"), or +NULL.

[out][element-type utf8 utf8][allow-none][transfer full]
+
+
+

Returns

+

a string with the value of the +"Content-Type" header or NULL if hdrs +does not contain that +header or it cannot be parsed (in which case *params +will be +unchanged).

+

[nullable]

+
+

Since: 2.26

+
+
+
+

soup_message_headers_set_content_type ()

+
void
+soup_message_headers_set_content_type (SoupMessageHeaders *hdrs,
+                                       const char *content_type,
+                                       GHashTable *params);
+

Sets the "Content-Type" header in hdrs + to content_type +, +optionally with additional parameters specified in params +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

hdrs

a SoupMessageHeaders

 

content_type

the MIME type

 

params

additional +parameters, or NULL.

[allow-none][element-type utf8 utf8]
+
+

Since: 2.26

+
+
+
+

soup_message_headers_get_content_disposition ()

+
gboolean
+soup_message_headers_get_content_disposition
+                               (SoupMessageHeaders *hdrs,
+                                char **disposition,
+                                GHashTable **params);
+

Looks up the "Content-Disposition" header in hdrs +, parses it, and +returns its value in *disposition + and *params +. params + can be +NULL if you are only interested in the disposition-type.

+

In HTTP, the most common use of this header is to set a +disposition-type of "attachment", to suggest to the browser that a +response should be saved to disk rather than displayed in the +browser. If params + contains a "filename" parameter, this is a +suggestion of a filename to use. (If the parameter value in the +header contains an absolute or relative path, libsoup will truncate +it down to just the final path component, so you do not need to +test this yourself.)

+

Content-Disposition is also used in "multipart/form-data", however +this is handled automatically by SoupMultipart and the associated +form methods.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

hdrs

a SoupMessageHeaders

 

disposition

return location for the +disposition-type, or NULL.

[out][transfer full]

params

return +location for the Content-Disposition parameters, or NULL.

[out][transfer full][element-type utf8 utf8]
+
+
+

Returns

+

TRUE if hdrs +contains a "Content-Disposition" +header, FALSE if not (in which case *disposition +and *params +will be unchanged).

+
+

Since: 2.26

+
+
+
+

soup_message_headers_set_content_disposition ()

+
void
+soup_message_headers_set_content_disposition
+                               (SoupMessageHeaders *hdrs,
+                                const char *disposition,
+                                GHashTable *params);
+

Sets the "Content-Disposition" header in hdrs + to disposition +, +optionally with additional parameters specified in params +.

+

See soup_message_headers_get_content_disposition() for a discussion +of how Content-Disposition is used in HTTP.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

hdrs

a SoupMessageHeaders

 

disposition

the disposition-type

 

params

additional +parameters, or NULL.

[allow-none][element-type utf8 utf8]
+
+

Since: 2.26

+
+
+
+

soup_message_headers_get_ranges ()

+
gboolean
+soup_message_headers_get_ranges (SoupMessageHeaders *hdrs,
+                                 goffset total_length,
+                                 SoupRange **ranges,
+                                 int *length);
+

Parses hdrs +'s Range header and returns an array of the requested +byte ranges. The returned array must be freed with +soup_message_headers_free_ranges().

+

If total_length + is non-0, its value will be used to adjust the +returned ranges to have explicit start and end values, and the +returned ranges will be sorted and non-overlapping. If +total_length + is 0, then some ranges may have an end value of -1, +as described under SoupRange, and some of the ranges may be +redundant.

+

Beware that even if given a total_length +, this function does not +check that the ranges are satisfiable.

+

+SoupServer has built-in handling for range requests. If your +server handler returns a SOUP_STATUS_OK response containing the +complete response body (rather than pausing the message and +returning some of the response body later), and there is a Range +header in the request, then libsoup will automatically convert the +response to a SOUP_STATUS_PARTIAL_CONTENT response containing only +the range(s) requested by the client. + +The only time you need to process the Range header yourself is if +either you need to stream the response body rather than returning +it all at once, or you do not already have the complete response +body available, and only want to generate the parts that were +actually requested by the client. +

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

hdrs

a SoupMessageHeaders

 

total_length

the total_length of the response body

 

ranges

return location for an array +of SoupRange.

[out][array length=length]

length

the length of the returned array

 
+
+
+

Returns

+

TRUE if hdrs +contained a syntactically-valid +"Range" header, FALSE otherwise (in which case range +and length +will not be set).

+
+

Since: 2.26

+
+
+
+

soup_message_headers_set_ranges ()

+
void
+soup_message_headers_set_ranges (SoupMessageHeaders *hdrs,
+                                 SoupRange *ranges,
+                                 int length);
+

Sets hdrs +'s Range header to request the indicated ranges. (If you +only want to request a single range, you can use +soup_message_headers_set_range().)

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

hdrs

a SoupMessageHeaders

 

ranges

an array of SoupRange

 

length

the length of range +

 
+
+

Since: 2.26

+
+
+
+

soup_message_headers_set_range ()

+
void
+soup_message_headers_set_range (SoupMessageHeaders *hdrs,
+                                goffset start,
+                                goffset end);
+

Sets hdrs +'s Range header to request the indicated range. +start + and end + are interpreted as in a SoupRange.

+

If you need to request multiple ranges, use +soup_message_headers_set_ranges().

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

hdrs

a SoupMessageHeaders

 

start

the start of the range to request

 

end

the end of the range to request

 
+
+

Since: 2.26

+
+
+
+

soup_message_headers_free_ranges ()

+
void
+soup_message_headers_free_ranges (SoupMessageHeaders *hdrs,
+                                  SoupRange *ranges);
+

Frees the array of ranges returned from soup_message_headers_get_ranges().

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

hdrs

a SoupMessageHeaders

 

ranges

an array of SoupRange

 
+
+

Since: 2.26

+
+
+
+

soup_message_headers_get_content_range ()

+
gboolean
+soup_message_headers_get_content_range
+                               (SoupMessageHeaders *hdrs,
+                                goffset *start,
+                                goffset *end,
+                                goffset *total_length);
+

Parses hdrs +'s Content-Range header and returns it in start +, +end +, and total_length +. If the total length field in the header +was specified as "*", then total_length + will be set to -1.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

hdrs

a SoupMessageHeaders

 

start

return value for the start of the range.

[out]

end

return value for the end of the range.

[out]

total_length

return value for the total length of the +resource, or NULL if you don't care.

[out][optional]
+
+
+

Returns

+

TRUE if hdrs +contained a "Content-Range" header +containing a byte range which could be parsed, FALSE otherwise.

+
+

Since: 2.26

+
+
+
+

soup_message_headers_set_content_range ()

+
void
+soup_message_headers_set_content_range
+                               (SoupMessageHeaders *hdrs,
+                                goffset start,
+                                goffset end,
+                                goffset total_length);
+

Sets hdrs +'s Content-Range header according to the given values. +(Note that total_length + is the total length of the entire resource +that this is a range of, not simply end + - start + + 1.)

+

+SoupServer has built-in handling for range requests, and you do +not normally need to call this function youself. See +soup_message_headers_get_ranges() for more details. +

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

hdrs

a SoupMessageHeaders

 

start

the start of the range

 

end

the end of the range

 

total_length

the total length of the resource, or -1 if unknown

 
+
+

Since: 2.26

+
+
+
+

Types and Values

+
+

SoupMessageHeaders

+
typedef struct SoupMessageHeaders SoupMessageHeaders;
+
+

The HTTP message headers associated with a request or response.

+
+
+
+

enum SoupMessageHeadersType

+

Value passed to soup_message_headers_new() to set certain default +behaviors.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + +

SOUP_MESSAGE_HEADERS_REQUEST

+

request headers

+
 

SOUP_MESSAGE_HEADERS_RESPONSE

+

response headers

+
 

SOUP_MESSAGE_HEADERS_MULTIPART

+

multipart body part headers

+
 
+
+
+
+
+

SoupMessageHeadersIter

+
typedef struct {
+} SoupMessageHeadersIter;
+
+

An opaque type used to iterate over a SoupMessageHeaders +structure.

+

After intializing the iterator with +soup_message_headers_iter_init(), call +soup_message_headers_iter_next() to fetch data from it.

+

You may not modify the headers while iterating over them.

+
+
+
+

enum SoupEncoding

+

How a message body is encoded for transport

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

SOUP_ENCODING_UNRECOGNIZED

+

unknown / error

+
 

SOUP_ENCODING_NONE

+

no body is present (which is not the same as a +0-length body, and only occurs in certain places)

+
 

SOUP_ENCODING_CONTENT_LENGTH

+

Content-Length encoding

+
 

SOUP_ENCODING_EOF

+

Response body ends when the connection is closed

+
 

SOUP_ENCODING_CHUNKED

+

chunked encoding (currently only supported +for response)

+
 

SOUP_ENCODING_BYTERANGES

+

multipart/byteranges (Reserved for future +use: NOT CURRENTLY IMPLEMENTED)

+
 
+
+
+
+
+

enum SoupExpectation

+

Represents the parsed value of the "Expect" header.

+
+

Members

+
+++++ + + + + + + + + + + + + +

SOUP_EXPECTATION_UNRECOGNIZED

+

any unrecognized expectation

+
 

SOUP_EXPECTATION_CONTINUE

+

"100-continue"

+
 
+
+
+
+
+

SoupRange

+
typedef struct {
+	goffset start;
+	goffset end;
+} SoupRange;
+
+

Represents a byte range as used in the Range header.

+

If end + is non-negative, then start + and end + represent the bounds +of of the range, counting from 0. (Eg, the first 500 bytes would be +represented as start + = 0 and end + = 499.)

+

If end + is -1 and start + is non-negative, then this represents a +range starting at start + and ending with the last byte of the +requested resource body. (Eg, all but the first 500 bytes would be +start + = 500, and end + = -1.)

+

If end + is -1 and start + is negative, then it represents a "suffix +range", referring to the last -start + bytes of the resource body. +(Eg, the last 500 bytes would be start + = -500 and end + = -1.)

+
+

Members

+
+++++ + + + + + + + + + + + + +

goffset start;

the start of the range

 

goffset end;

the end of the range

 
+
+

Since: 2.26

+
+
+
+

See Also

+

SoupMessage

+
+
+ + + \ No newline at end of file diff --git a/docs/reference/html/SoupMultipart.html b/docs/reference/html/SoupMultipart.html new file mode 100644 index 0000000..b5bc3c7 --- /dev/null +++ b/docs/reference/html/SoupMultipart.html @@ -0,0 +1,533 @@ + + + + +SoupMultipart: libsoup Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

SoupMultipart

+

SoupMultipart — multipart HTTP message bodies

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+SoupMultipart * + +soup_multipart_new () +
+SoupMultipart * + +soup_multipart_new_from_message () +
+void + +soup_multipart_free () +
+int + +soup_multipart_get_length () +
+gboolean + +soup_multipart_get_part () +
+void + +soup_multipart_append_part () +
+void + +soup_multipart_append_form_string () +
+void + +soup_multipart_append_form_file () +
+void + +soup_multipart_to_message () +
+
+
+

Types and Values

+
++++ + + + + +
typedefSoupMultipart
+
+
+

Object Hierarchy

+
    GBoxed
+    ╰── SoupMultipart
+
+
+
+

Includes

+
#include <libsoup/soup.h>
+
+
+
+

Description

+
+
+

Functions

+
+

soup_multipart_new ()

+
SoupMultipart *
+soup_multipart_new (const char *mime_type);
+

Creates a new empty SoupMultipart with a randomly-generated +boundary string. Note that mime_type + must be the full MIME type, +including "multipart/".

+
+

Parameters

+
+++++ + + + + + +

mime_type

the MIME type of the multipart to create.

 
+
+
+

Returns

+

a new empty SoupMultipart of the given mime_type +

+
+

Since: 2.26

+
+
+
+

soup_multipart_new_from_message ()

+
SoupMultipart *
+soup_multipart_new_from_message (SoupMessageHeaders *headers,
+                                 SoupMessageBody *body);
+

Parses headers + and body + to form a new SoupMultipart

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

headers

the headers of the HTTP message to parse

 

body

the body of the HTTP message to parse

 
+
+
+

Returns

+

a new SoupMultipart (or NULL if the +message couldn't be parsed or wasn't multipart).

+

[nullable]

+
+

Since: 2.26

+
+
+
+

soup_multipart_free ()

+
void
+soup_multipart_free (SoupMultipart *multipart);
+

Frees multipart +

+
+

Parameters

+
+++++ + + + + + +

multipart

a SoupMultipart

 
+
+

Since: 2.26

+
+
+
+

soup_multipart_get_length ()

+
int
+soup_multipart_get_length (SoupMultipart *multipart);
+

Gets the number of body parts in multipart +

+
+

Parameters

+
+++++ + + + + + +

multipart

a SoupMultipart

 
+
+
+

Returns

+

the number of body parts in multipart +

+
+

Since: 2.26

+
+
+
+

soup_multipart_get_part ()

+
gboolean
+soup_multipart_get_part (SoupMultipart *multipart,
+                         int part,
+                         SoupMessageHeaders **headers,
+                         SoupBuffer **body);
+

Gets the indicated body part from multipart +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

multipart

a SoupMultipart

 

part

the part number to get (counting from 0)

 

headers

return location for the MIME part +headers.

[out][transfer none]

body

return location for the MIME part +body.

[out][transfer none]
+
+
+

Returns

+

TRUE on success, FALSE if part +is out of range (in +which case headers +and body +won't be set)

+
+

Since: 2.26

+
+
+
+

soup_multipart_append_part ()

+
void
+soup_multipart_append_part (SoupMultipart *multipart,
+                            SoupMessageHeaders *headers,
+                            SoupBuffer *body);
+

Adds a new MIME part to multipart + with the given headers and body. +(The multipart will make its own copies of headers + and body +, so +you should free your copies if you are not using them for anything +else.)

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

multipart

a SoupMultipart

 

headers

the MIME part headers

 

body

the MIME part body

 
+
+

Since: 2.26

+
+
+
+

soup_multipart_append_form_string ()

+
void
+soup_multipart_append_form_string (SoupMultipart *multipart,
+                                   const char *control_name,
+                                   const char *data);
+

Adds a new MIME part containing data + to multipart +, using +"Content-Disposition: form-data", as per the HTML forms +specification. See soup_form_request_new_from_multipart() for more +details.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

multipart

a multipart (presumably of type "multipart/form-data")

 

control_name

the name of the control associated with data +

 

data

the body data

 
+
+

Since: 2.26

+
+
+
+

soup_multipart_append_form_file ()

+
void
+soup_multipart_append_form_file (SoupMultipart *multipart,
+                                 const char *control_name,
+                                 const char *filename,
+                                 const char *content_type,
+                                 SoupBuffer *body);
+

Adds a new MIME part containing body + to multipart +, using +"Content-Disposition: form-data", as per the HTML forms +specification. See soup_form_request_new_from_multipart() for more +details.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

multipart

a multipart (presumably of type "multipart/form-data")

 

control_name

the name of the control associated with this file

 

filename

the name of the file, or NULL if not known

 

content_type

the MIME type of the file, or NULL if not known

 

body

the file data

 
+
+

Since: 2.26

+
+
+
+

soup_multipart_to_message ()

+
void
+soup_multipart_to_message (SoupMultipart *multipart,
+                           SoupMessageHeaders *dest_headers,
+                           SoupMessageBody *dest_body);
+

Serializes multipart + to dest_headers + and dest_body +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

multipart

a SoupMultipart

 

dest_headers

the headers of the HTTP message to serialize multipart +to

 

dest_body

the body of the HTTP message to serialize multipart +to

 
+
+

Since: 2.26

+
+
+
+

Types and Values

+
+

SoupMultipart

+
typedef struct SoupMultipart SoupMultipart;
+
+

Represents a multipart HTTP message body, parsed according to the +syntax of RFC 2046. Of particular interest to HTTP are +multipart/byte-ranges and +multipart/form-data.

+

Although the headers of a SoupMultipart body part will contain the +full headers from that body part, libsoup does not interpret them +according to MIME rules. For example, each body part is assumed to +have "binary" Content-Transfer-Encoding, even if its headers +explicitly state otherwise. In other words, don't try to use +SoupMultipart for handling real MIME multiparts.

+

Since: 2.26

+
+
+ +
+ + + \ No newline at end of file diff --git a/docs/reference/html/SoupMultipartInputStream.html b/docs/reference/html/SoupMultipartInputStream.html new file mode 100644 index 0000000..1c08830 --- /dev/null +++ b/docs/reference/html/SoupMultipartInputStream.html @@ -0,0 +1,396 @@ + + + + +SoupMultipartInputStream: libsoup Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

SoupMultipartInputStream

+

SoupMultipartInputStream — Multipart input handling stream

+
+
+

Functions

+ +
+
+

Properties

+
+++++ + + + + + +
+SoupMessage *messageRead / Write / Construct Only
+
+
+

Types and Values

+
++++ + + + + +
structSoupMultipartInputStream
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GInputStream
+        ╰── GFilterInputStream
+            ╰── SoupMultipartInputStream
+
+
+
+

Implemented Interfaces

+

+SoupMultipartInputStream implements + GPollableInputStream.

+
+
+

Includes

+
#include <libsoup/soup.h>
+
+
+
+

Description

+

This adds support for the multipart responses. For handling the +multiple parts the user needs to wrap the GInputStream obtained by +sending the request with a SoupMultipartInputStream and use +soup_multipart_input_stream_next_part() before reading. Responses +which are not wrapped will be treated like non-multipart responses.

+

Note that although SoupMultipartInputStream is a GInputStream, +you should not read directly from it, and the results are undefined +if you do.

+
+
+

Functions

+
+

soup_multipart_input_stream_new ()

+
SoupMultipartInputStream *
+soup_multipart_input_stream_new (SoupMessage *msg,
+                                 GInputStream *base_stream);
+

Creates a new SoupMultipartInputStream that wraps the +GInputStream obtained by sending the SoupRequest. Reads should +not be done directly through this object, use the input streams +returned by soup_multipart_input_stream_next_part() or its async +counterpart instead.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

msg

the SoupMessage the response is related to.

 

base_stream

the GInputStream returned by sending the request.

 
+
+
+

Returns

+

a new SoupMultipartInputStream

+
+

Since: 2.40

+
+
+
+

soup_multipart_input_stream_get_headers ()

+
SoupMessageHeaders *
+soup_multipart_input_stream_get_headers
+                               (SoupMultipartInputStream *multipart);
+

Obtains the headers for the part currently being processed. Note +that the SoupMessageHeaders that are returned are owned by the +SoupMultipartInputStream and will be replaced when a call is made +to soup_multipart_input_stream_next_part() or its async +counterpart, so if keeping the headers is required, a copy must be +made.

+

Note that if a part had no headers at all an empty SoupMessageHeaders +will be returned.

+
+

Parameters

+
+++++ + + + + + +

multipart

a SoupMultipartInputStream.

 
+
+
+

Returns

+

a SoupMessageHeaders +containing the headers for the part currently being processed or +NULL if the headers failed to parse.

+

[nullable][transfer none]

+
+

Since: 2.40

+
+
+
+

soup_multipart_input_stream_next_part ()

+
GInputStream *
+soup_multipart_input_stream_next_part (SoupMultipartInputStream *multipart,
+                                       GCancellable *cancellable,
+                                       GError **error);
+

Obtains an input stream for the next part. When dealing with a +multipart response the input stream needs to be wrapped in a +SoupMultipartInputStream and this function or its async +counterpart need to be called to obtain the first part for +reading.

+

After calling this function, +soup_multipart_input_stream_get_headers() can be used to obtain the +headers for the first part. A read of 0 bytes indicates the end of +the part; a new call to this function should be done at that point, +to obtain the next part.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

multipart

the SoupMultipartInputStream

 

cancellable

a GCancellable

 

error

a GError

 
+
+
+

Returns

+

a new GInputStream, or +NULL if there are no more parts.

+

[nullable][transfer full]

+
+

Since: 2.40

+
+
+
+

soup_multipart_input_stream_next_part_async ()

+
void
+soup_multipart_input_stream_next_part_async
+                               (SoupMultipartInputStream *multipart,
+                                int io_priority,
+                                GCancellable *cancellable,
+                                GAsyncReadyCallback callback,
+                                gpointer data);
+

Obtains a GInputStream for the next request. See +soup_multipart_input_stream_next_part() for details on the +workflow.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

multipart

the SoupMultipartInputStream.

 

io_priority

the I/O priority for the request.

 

cancellable

a GCancellable.

 

callback

callback to call when request is satisfied.

 

data

data for callback +

 
+
+

Since: 2.40

+
+
+
+

soup_multipart_input_stream_next_part_finish ()

+
GInputStream *
+soup_multipart_input_stream_next_part_finish
+                               (SoupMultipartInputStream *multipart,
+                                GAsyncResult *result,
+                                GError **error);
+

Finishes an asynchronous request for the next part.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

multipart

a SoupMultipartInputStream.

 

result

a GAsyncResult.

 

error

a GError location to store any error, or NULL to ignore.

 
+
+
+

Returns

+

a newly created +GInputStream for reading the next part or NULL if there are no +more parts.

+

[nullable][transfer full]

+
+

Since: 2.40

+
+
+
+

Types and Values

+
+

struct SoupMultipartInputStream

+
struct SoupMultipartInputStream;
+
+
+
+

Property Details

+
+

The “message” property

+
  “message”                  SoupMessage *
+

The SoupMessage.

+

Flags: Read / Write / Construct Only

+
+
+
+ + + \ No newline at end of file diff --git a/docs/reference/html/SoupProxyResolverDefault.html b/docs/reference/html/SoupProxyResolverDefault.html new file mode 100644 index 0000000..c52fa23 --- /dev/null +++ b/docs/reference/html/SoupProxyResolverDefault.html @@ -0,0 +1,118 @@ + + + + +SoupProxyResolverDefault: libsoup Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

SoupProxyResolverDefault

+

SoupProxyResolverDefault — System proxy configuration integration

+
+
+

Properties

+
+++++ + + + + + +
+GProxyResolver *gproxy-resolverWrite
+
+
+

Types and Values

+
++++ + + + + +
 SoupProxyResolverDefault
+
+
+

Object Hierarchy

+
    GObject
+    ╰── SoupProxyResolverDefault
+
+
+
+

Implemented Interfaces

+

+SoupProxyResolverDefault implements + SoupSessionFeature and SoupProxyURIResolver.

+
+
+

Includes

+
#include <libsoup/soup.h>
+
+
+
+

Description

+

SoupProxyResolverDefault is a SoupProxyURIResolver +implementation that uses the default gio GProxyResolver to resolve +proxies.

+

In libsoup 2.44 and later, you can set the session's +“proxy-resolver” property to the resolver returned by +g_proxy_resolver_get_default() to get the same effect. Note that +for "plain" SoupSessions (ie, not SoupSessionAsync or +SoupSessionSync), this is done for you automatically.

+
+
+

Functions

+

+
+
+

Types and Values

+
+

SoupProxyResolverDefault

+
typedef struct _SoupProxyResolverDefault SoupProxyResolverDefault;
+
+
+
+

Property Details

+
+

The “gproxy-resolver” property

+
  “gproxy-resolver”          GProxyResolver *
+

The underlying GProxyResolver.

+

Flags: Write

+
+
+
+ + + \ No newline at end of file diff --git a/docs/reference/html/SoupRequest.html b/docs/reference/html/SoupRequest.html new file mode 100644 index 0000000..de7e8ba --- /dev/null +++ b/docs/reference/html/SoupRequest.html @@ -0,0 +1,491 @@ + + + + +SoupRequest: libsoup Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

SoupRequest

+

SoupRequest — Protocol-independent streaming request interface

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+GInputStream * + +soup_request_send () +
+void + +soup_request_send_async () +
+GInputStream * + +soup_request_send_finish () +
+goffset + +soup_request_get_content_length () +
const char * + +soup_request_get_content_type () +
+SoupSession * + +soup_request_get_session () +
+SoupURI * + +soup_request_get_uri () +
+
+
+

Properties

+
+++++ + + + + + + + + + + + + +
+SoupSession *sessionRead / Write / Construct Only
+SoupURI *uriRead / Write / Construct Only
+
+
+

Types and Values

+
++++ + + + + + + + + + + + + + + +
 SoupRequest
#defineSOUP_REQUEST_SESSION
#defineSOUP_REQUEST_URI
+
+
+

Object Hierarchy

+
    GObject
+    ╰── SoupRequest
+        ├── SoupRequestData
+        ├── SoupRequestFile
+        ╰── SoupRequestHTTP
+
+
+
+

Implemented Interfaces

+

+SoupRequest implements + GInitable.

+
+
+

Includes

+
#include <libsoup/soup.h>
+
+
+
+

Description

+

A SoupRequest is created by SoupSession, and represents a request +to retrieve a particular URI.

+
+
+

Functions

+
+

soup_request_send ()

+
GInputStream *
+soup_request_send (SoupRequest *request,
+                   GCancellable *cancellable,
+                   GError **error);
+

Synchronously requests the URI pointed to by request +, and returns +a GInputStream that can be used to read its contents.

+

Note that you cannot use this method with SoupRequests attached to +a SoupSessionAsync.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

request

a SoupRequest

 

cancellable

a GCancellable or NULL

 

error

return location for a GError, or NULL

 
+
+
+

Returns

+

a GInputStream that can be used to +read from the URI pointed to by request +.

+

[transfer full]

+
+

Since: 2.42

+
+
+
+

soup_request_send_async ()

+
void
+soup_request_send_async (SoupRequest *request,
+                         GCancellable *cancellable,
+                         GAsyncReadyCallback callback,
+                         gpointer user_data);
+

Begins an asynchronously request for the URI pointed to by +request +.

+

Note that you cannot use this method with SoupRequests attached to +a SoupSessionSync.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

request

a SoupRequest

 

cancellable

a GCancellable or NULL

 

callback

a GAsyncReadyCallback

 

user_data

user data passed to callback +

 
+
+

Since: 2.42

+
+
+
+

soup_request_send_finish ()

+
GInputStream *
+soup_request_send_finish (SoupRequest *request,
+                          GAsyncResult *result,
+                          GError **error);
+

Gets the result of a soup_request_send_async().

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

request

a SoupRequest

 

result

the GAsyncResult

 

error

return location for a GError, or NULL

 
+
+
+

Returns

+

a GInputStream that can be used to +read from the URI pointed to by request +.

+

[transfer full]

+
+

Since: 2.42

+
+
+
+

soup_request_get_content_length ()

+
goffset
+soup_request_get_content_length (SoupRequest *request);
+

Gets the length of the data represented by request +. For most +request types, this will not be known until after you call +soup_request_send() or soup_request_send_finish().

+
+

Parameters

+
+++++ + + + + + +

request

a SoupRequest

 
+
+
+

Returns

+

the length of the data represented by request +, +or -1 if not known.

+
+

Since: 2.42

+
+
+
+

soup_request_get_content_type ()

+
const char *
+soup_request_get_content_type (SoupRequest *request);
+

Gets the type of the data represented by request +. For most request +types, this will not be known until after you call +soup_request_send() or soup_request_send_finish().

+

As in the HTTP Content-Type header, this may include parameters +after the MIME type.

+
+

Parameters

+
+++++ + + + + + +

request

a SoupRequest

 
+
+
+

Returns

+

the type of the data represented by +request +, or NULL if not known.

+

[nullable]

+
+

Since: 2.42

+
+
+
+

soup_request_get_session ()

+
SoupSession *
+soup_request_get_session (SoupRequest *request);
+

Gets request +'s SoupSession

+
+

Parameters

+
+++++ + + + + + +

request

a SoupRequest

 
+
+
+

Returns

+

request +'s SoupSession.

+

[transfer none]

+
+

Since: 2.42

+
+
+
+

soup_request_get_uri ()

+
SoupURI *
+soup_request_get_uri (SoupRequest *request);
+

Gets request +'s URI

+
+

Parameters

+
+++++ + + + + + +

request

a SoupRequest

 
+
+
+

Returns

+

request +'s URI.

+

[transfer none]

+
+

Since: 2.42

+
+
+
+

Types and Values

+
+

SoupRequest

+
typedef struct _SoupRequest SoupRequest;
+

A request to retrieve a particular URI.

+

Since: 2.42

+
+
+
+

SOUP_REQUEST_SESSION

+
#define SOUP_REQUEST_SESSION "session"
+
+

Alias for the “session” property, qv.

+

Since: 2.42

+
+
+
+

SOUP_REQUEST_URI

+
#define SOUP_REQUEST_URI     "uri"
+
+

Alias for the “uri” property, qv.

+

Since: 2.42

+
+
+
+

Property Details

+
+

The “session” property

+
  “session”                  SoupSession *
+

The request's SoupSession.

+

Flags: Read / Write / Construct Only

+

Since: 2.42

+
+
+
+

The “uri” property

+
  “uri”                      SoupURI *
+

The request URI.

+

Flags: Read / Write / Construct Only

+

Since: 2.42

+
+
+
+ + + \ No newline at end of file diff --git a/docs/reference/html/SoupRequestData.html b/docs/reference/html/SoupRequestData.html new file mode 100644 index 0000000..0c7251d --- /dev/null +++ b/docs/reference/html/SoupRequestData.html @@ -0,0 +1,86 @@ + + + + +SoupRequestData: libsoup Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

SoupRequestData

+

SoupRequestData — SoupRequest support for "data" URIs

+
+
+

Types and Values

+
++++ + + + + +
 SoupRequestData
+
+
+

Object Hierarchy

+
    GObject
+    ╰── SoupRequest
+        ╰── SoupRequestData
+
+
+
+

Implemented Interfaces

+

+SoupRequestData implements + GInitable.

+
+
+

Includes

+
#include <libsoup/soup.h>
+
+
+
+

Description

+

SoupRequestData implements SoupRequest for "data" URIs.

+
+
+

Functions

+

+
+
+

Types and Values

+
+

SoupRequestData

+
typedef struct _SoupRequestData SoupRequestData;
+
+
+
+ + + \ No newline at end of file diff --git a/docs/reference/html/SoupRequestFile.html b/docs/reference/html/SoupRequestFile.html new file mode 100644 index 0000000..ffe9d07 --- /dev/null +++ b/docs/reference/html/SoupRequestFile.html @@ -0,0 +1,132 @@ + + + + +SoupRequestFile: libsoup Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

SoupRequestFile

+

SoupRequestFile — SoupRequest support for "file" and "resource" URIs

+
+
+

Functions

+
++++ + + + + +
+GFile * + +soup_request_file_get_file () +
+
+
+

Types and Values

+
++++ + + + + +
 SoupRequestFile
+
+
+

Object Hierarchy

+
    GObject
+    ╰── SoupRequest
+        ╰── SoupRequestFile
+
+
+
+

Implemented Interfaces

+

+SoupRequestFile implements + GInitable.

+
+
+

Includes

+
#include <libsoup/soup.h>
+
+
+
+

Description

+

SoupRequestFile implements SoupRequest for "file" and "resource" +URIs.

+
+
+

Functions

+
+

soup_request_file_get_file ()

+
GFile *
+soup_request_file_get_file (SoupRequestFile *file);
+

Gets a GFile corresponding to file +'s URI

+
+

Parameters

+
+++++ + + + + + +

file

a SoupRequestFile

 
+
+
+

Returns

+

a GFile corresponding to file +.

+

[transfer full]

+
+

Since: 2.40

+
+
+
+

Types and Values

+
+

SoupRequestFile

+
typedef struct _SoupRequestFile SoupRequestFile;
+
+
+
+ + + \ No newline at end of file diff --git a/docs/reference/html/SoupRequestHTTP.html b/docs/reference/html/SoupRequestHTTP.html new file mode 100644 index 0000000..b30d126 --- /dev/null +++ b/docs/reference/html/SoupRequestHTTP.html @@ -0,0 +1,133 @@ + + + + +SoupRequestHTTP: libsoup Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

SoupRequestHTTP

+

SoupRequestHTTP — SoupRequest support for "http" and "https" URIs

+
+
+

Functions

+
++++ + + + + +
+SoupMessage * + +soup_request_http_get_message () +
+
+
+

Types and Values

+
++++ + + + + +
 SoupRequestHTTP
+
+
+

Object Hierarchy

+
    GObject
+    ╰── SoupRequest
+        ╰── SoupRequestHTTP
+
+
+
+

Implemented Interfaces

+

+SoupRequestHTTP implements + GInitable.

+
+
+

Includes

+
#include <libsoup/soup.h>
+
+
+
+

Description

+

SoupRequestHTTP implements SoupRequest for "http" and "https" +URIs.

+

To do more complicated HTTP operations using the SoupRequest APIs, +call soup_request_http_get_message() to get the request's +SoupMessage.

+
+
+

Functions

+
+

soup_request_http_get_message ()

+
SoupMessage *
+soup_request_http_get_message (SoupRequestHTTP *http);
+

Gets a new reference to the SoupMessage associated to this SoupRequest

+
+

Parameters

+
+++++ + + + + + +

http

a SoupRequestHTTP object

 
+
+
+

Returns

+

a new reference to the SoupMessage.

+

[transfer full]

+
+

Since: 2.40

+
+
+
+

Types and Values

+
+

SoupRequestHTTP

+
typedef struct _SoupRequestHTTP SoupRequestHTTP;
+
+
+
+ + + \ No newline at end of file diff --git a/docs/reference/html/SoupServer.html b/docs/reference/html/SoupServer.html new file mode 100644 index 0000000..fcfbca2 --- /dev/null +++ b/docs/reference/html/SoupServer.html @@ -0,0 +1,2407 @@ + + + + +SoupServer: libsoup Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

SoupServer

+

SoupServer — HTTP server

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+SoupServer * + +soup_server_new () +
+gboolean + +soup_server_set_ssl_cert_file () +
+gboolean + +soup_server_listen () +
+gboolean + +soup_server_listen_all () +
+gboolean + +soup_server_listen_local () +
+gboolean + +soup_server_listen_socket () +
+gboolean + +soup_server_listen_fd () +
+GSList * + +soup_server_get_listeners () +
+GSList * + +soup_server_get_uris () +
+void + +soup_server_disconnect () +
+gboolean + +soup_server_is_https () +
+gboolean + +soup_server_accept_iostream () +
+void + +(*SoupServerCallback) () +
+void + +soup_server_add_handler () +
+void + +soup_server_add_early_handler () +
+void + +soup_server_remove_handler () +
+void + +(*SoupServerWebsocketCallback) () +
+void + +soup_server_add_websocket_handler () +
+GSocketAddress * + +soup_client_context_get_local_address () +
+GSocketAddress * + +soup_client_context_get_remote_address () +
const char * + +soup_client_context_get_host () +
+SoupAuthDomain * + +soup_client_context_get_auth_domain () +
const char * + +soup_client_context_get_auth_user () +
+GSocket * + +soup_client_context_get_gsocket () +
+GIOStream * + +soup_client_context_steal_connection () +
+void + +soup_server_add_auth_domain () +
+void + +soup_server_remove_auth_domain () +
+void + +soup_server_pause_message () +
+void + +soup_server_unpause_message () +
+
+
+

Properties

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
gpointerasync-contextRead / Write / Construct Only
GStrvhttp-aliasesRead / Write
GStrvhttps-aliasesRead / Write
+SoupAddress *interfaceRead / Write / Construct Only
guintportRead / Write / Construct Only
gbooleanraw-pathsRead / Write / Construct Only
+gchar *server-headerRead / Write / Construct
+gchar *ssl-cert-fileRead / Write / Construct Only
+gchar *ssl-key-fileRead / Write / Construct Only
+GTlsCertificate *tls-certificateRead / Write / Construct Only
+
+
+

Signals

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +
voidrequest-abortedRun First
voidrequest-finishedRun First
voidrequest-readRun First
voidrequest-startedRun First
+
+
+

Types and Values

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 SoupServer
enumSoupServerListenOptions
typedefSoupClientContext
#defineSOUP_SERVER_TLS_CERTIFICATE
#defineSOUP_SERVER_RAW_PATHS
#defineSOUP_SERVER_SERVER_HEADER
#defineSOUP_SERVER_HTTP_ALIASES
#defineSOUP_SERVER_HTTPS_ALIASES
+
+
+

Object Hierarchy

+
    GBoxed
+    ╰── SoupClientContext
+    GObject
+    ╰── SoupServer
+
+
+
+

Includes

+
#include <libsoup/soup.h>
+
+
+
+

Description

+

SoupServer implements a simple HTTP server.

+

(The following documentation describes the current SoupServer API, +available in libsoup 2.48 and later. See +the section "The Old SoupServer +Listening API" in the server how-to documentation for +details on the older SoupServer API.)

+

To begin, create a server using soup_server_new(). Add at least one +handler by calling soup_server_add_handler() or +soup_server_add_early_handler(); the handler will be called to +process any requests underneath the path you pass. (If you want all +requests to go to the same handler, just pass "/" (or NULL) for +the path.)

+

When a new connection is accepted (or a new request is started on +an existing persistent connection), the SoupServer will emit +“request-started” and then begin processing the request +as described below, but note that once the message is assigned a +“status-code”, then callbacks after that point will be +skipped. Note also that it is not defined when the callbacks happen +relative to various SoupMessage signals.

+

Once the headers have been read, SoupServer will check if there is +a SoupAuthDomain (qv) covering the Request-URI; if so, and if the +message does not contain suitable authorization, then the +SoupAuthDomain will set a status of SOUP_STATUS_UNAUTHORIZED on +the message.

+

After checking for authorization, SoupServer will look for "early" +handlers (added with soup_server_add_early_handler()) matching the +Request-URI. If one is found, it will be run; in particular, this +can be used to connect to signals to do a streaming read of the +request body.

+

(At this point, if the request headers contain "Expect: +100-continue", and a status code has been set, then +SoupServer will skip the remaining steps and return the response. +If the request headers contain "Expect: +100-continue" and no status code has been set, +SoupServer will return a SOUP_STATUS_CONTINUE status before +continuing.)

+

The server will then read in the response body (if present). At +this point, if there are no handlers at all defined for the +Request-URI, then the server will return SOUP_STATUS_NOT_FOUND to +the client.

+

Otherwise (assuming no previous step assigned a status to the +message) any "normal" handlers (added with +soup_server_add_handler()) for the message's Request-URI will be +run.

+

Then, if the path has a WebSocket handler registered (and has +not yet been assigned a status), SoupServer will attempt to +validate the WebSocket handshake, filling in the response and +setting a status of SOUP_STATUS_SWITCHING_PROTOCOLS or +SOUP_STATUS_BAD_REQUEST accordingly.

+

If the message still has no status code at this point (and has not +been paused with soup_server_pause_message()), then it will be +given a status of SOUP_STATUS_INTERNAL_SERVER_ERROR (because at +least one handler ran, but returned without assigning a status).

+

Finally, the server will emit “request-finished” (or +“request-aborted” if an I/O error occurred before +handling was completed).

+

If you want to handle the special "*" URI (eg, "OPTIONS *"), you +must explicitly register a handler for "*"; the default handler +will not be used for that case.

+

If you want to process https connections in addition to (or instead +of) http connections, you can either set the +SOUP_SERVER_TLS_CERTIFICATE property when creating the server, or +else call soup_server_set_ssl_certificate() after creating it.

+

Once the server is set up, make one or more calls to +soup_server_listen(), soup_server_listen_local(), or +soup_server_listen_all() to tell it where to listen for +connections. (All ports on a SoupServer use the same handlers; if +you need to handle some ports differently, such as returning +different data for http and https, you'll need to create multiple +SoupServers, or else check the passed-in URI in the handler +function.).

+

SoupServer will begin processing connections as soon as you return +to (or start) the main loop for the current thread-default +GMainContext.

+
+
+

Functions

+
+

soup_server_new ()

+
SoupServer *
+soup_server_new (const char *optname1,
+                 ...);
+

Creates a new SoupServer. This is exactly equivalent to calling +g_object_new() and specifying SOUP_TYPE_SERVER as the type.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

optname1

name of first property to set

 

...

value of optname1 +, followed by additional property/value pairs

 
+
+
+

Returns

+

a new SoupServer. If you are using +certain legacy properties, this may also return NULL if an error +occurs.

+

[nullable]

+
+
+
+
+

soup_server_set_ssl_cert_file ()

+
gboolean
+soup_server_set_ssl_cert_file (SoupServer *server,
+                               const char *ssl_cert_file,
+                               const char *ssl_key_file,
+                               GError **error);
+

Sets server + up to do https, using the SSL/TLS certificate +specified by ssl_cert_file + and ssl_key_file + (which may point to +the same file).

+

Alternatively, you can set the “tls-certificate” property +at construction time, if you already have a GTlsCertificate.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

server

a SoupServer

 

ssl_cert_file

path to a file containing a PEM-encoded SSL/TLS +certificate.

 

ssl_key_file

path to a file containing a PEM-encoded private key.

 

error

return location for a GError

 
+
+
+

Returns

+

success or failure.

+
+

Since: 2.48

+
+
+
+

soup_server_listen ()

+
gboolean
+soup_server_listen (SoupServer *server,
+                    GSocketAddress *address,
+                    SoupServerListenOptions options,
+                    GError **error);
+

This attempts to set up server + to listen for connections on +address +.

+

If options + includes SOUP_SERVER_LISTEN_HTTPS, and server + has +been configured for TLS, then server + will listen for https +connections on this port. Otherwise it will listen for plain http.

+

You may call this method (along with the other "listen" methods) +any number of times on a server, if you want to listen on multiple +ports, or set up both http and https service.

+

After calling this method, server + will begin accepting and +processing connections as soon as the appropriate GMainContext is +run.

+

Note that SoupServer never makes use of dual IPv4/IPv6 sockets; if +address + is an IPv6 address, it will only accept IPv6 connections. +You must configure IPv4 listening separately.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

server

a SoupServer

 

address

the address of the interface to listen on

 

options

listening options for this server

 

error

return location for a GError

 
+
+
+

Returns

+

TRUE on success, FALSE if address +could not be +bound or any other error occurred (in which case error +will be +set).

+
+

Since: 2.48

+
+
+
+

soup_server_listen_all ()

+
gboolean
+soup_server_listen_all (SoupServer *server,
+                        guint port,
+                        SoupServerListenOptions options,
+                        GError **error);
+

This attempts to set up server + to listen for connections on all +interfaces on the system. (That is, it listens on the addresses +0.0.0.0 and/or ::, depending +on whether options + includes SOUP_SERVER_LISTEN_IPV4_ONLY, +SOUP_SERVER_LISTEN_IPV6_ONLY, or neither.) If port + is specified, +server + will listen on that port. If it is 0, server + will find an +unused port to listen on. (In that case, you can use +soup_server_get_uris() to find out what port it ended up choosing.)

+

See soup_server_listen() for more details.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

server

a SoupServer

 

port

the port to listen on, or 0

 

options

listening options for this server

 

error

return location for a GError

 
+
+
+

Returns

+

TRUE on success, FALSE if port +could not be bound +or any other error occurred (in which case error +will be set).

+
+

Since: 2.48

+
+
+
+

soup_server_listen_local ()

+
gboolean
+soup_server_listen_local (SoupServer *server,
+                          guint port,
+                          SoupServerListenOptions options,
+                          GError **error);
+

This attempts to set up server + to listen for connections on +"localhost" (that is, 127.0.0.1 and/or +::1, depending on whether options + includes +SOUP_SERVER_LISTEN_IPV4_ONLY, SOUP_SERVER_LISTEN_IPV6_ONLY, or +neither). If port + is specified, server + will listen on that port. +If it is 0, server + will find an unused port to listen on. (In that +case, you can use soup_server_get_uris() to find out what port it +ended up choosing.)

+

See soup_server_listen() for more details.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

server

a SoupServer

 

port

the port to listen on, or 0

 

options

listening options for this server

 

error

return location for a GError

 
+
+
+

Returns

+

TRUE on success, FALSE if port +could not be bound +or any other error occurred (in which case error +will be set).

+
+

Since: 2.48

+
+
+
+

soup_server_listen_socket ()

+
gboolean
+soup_server_listen_socket (SoupServer *server,
+                           GSocket *socket,
+                           SoupServerListenOptions options,
+                           GError **error);
+

This attempts to set up server + to listen for connections on +socket +.

+

See soup_server_listen() for more details.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

server

a SoupServer

 

socket

a listening GSocket

 

options

listening options for this server

 

error

return location for a GError

 
+
+
+

Returns

+

TRUE on success, FALSE if an error occurred (in +which case error +will be set).

+
+

Since: 2.48

+
+
+
+

soup_server_listen_fd ()

+
gboolean
+soup_server_listen_fd (SoupServer *server,
+                       int fd,
+                       SoupServerListenOptions options,
+                       GError **error);
+

This attempts to set up server + to listen for connections on +fd +.

+

See soup_server_listen() for more details.

+

Note that server + will close fd + when you free it or call +soup_server_disconnect().

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

server

a SoupServer

 

fd

the file descriptor of a listening socket

 

options

listening options for this server

 

error

return location for a GError

 
+
+
+

Returns

+

TRUE on success, FALSE if an error occurred (in +which case error +will be set).

+
+

Since: 2.48

+
+
+
+

soup_server_get_listeners ()

+
GSList *
+soup_server_get_listeners (SoupServer *server);
+

Gets server +'s list of listening sockets.

+

You should treat these sockets as read-only; writing to or +modifiying any of these sockets may cause server + to malfunction.

+

(Beware that in contrast to the old soup_server_get_listener(), this +function returns GSockets, not SoupSockets.)

+
+

Parameters

+
+++++ + + + + + +

server

a SoupServer

 
+
+
+

Returns

+

a +list of listening sockets.

+

[transfer container][element-type Gio.Socket]

+
+
+
+
+

soup_server_get_uris ()

+
GSList *
+soup_server_get_uris (SoupServer *server);
+

Gets a list of URIs corresponding to the interfaces server + is +listening on. These will contain IP addresses, not hostnames, and +will also indicate whether the given listener is http or https.

+

Note that if you used soup_server_listen_all(), the returned URIs +will use the addresses 0.0.0.0 and +::, rather than actually returning separate URIs +for each interface on the system.

+
+

Parameters

+
+++++ + + + + + +

server

a SoupServer

 
+
+
+

Returns

+

a list of +SoupURIs, which you must free when you are done with it.

+

[transfer full][element-type Soup.URI]

+
+

Since: 2.48

+
+
+
+

soup_server_disconnect ()

+
void
+soup_server_disconnect (SoupServer *server);
+

Closes and frees server +'s listening sockets. If you are using the +old SoupServer APIs, this also includes the effect of +soup_server_quit().

+

Note that if there are currently requests in progress on server +, +that they will continue to be processed if server +'s GMainContext +is still running.

+

You can call soup_server_listen(), etc, after calling this function +if you want to start listening again.

+
+

Parameters

+
+++++ + + + + + +

server

a SoupServer

 
+
+
+
+
+

soup_server_is_https ()

+
gboolean
+soup_server_is_https (SoupServer *server);
+

Checks whether server + is capable of https.

+

In order for a server to run https, you must call +soup_server_set_ssl_cert_file(), or set the +“tls-certificate” property, to provide it with a +certificate to use.

+

If you are using the deprecated single-listener APIs, then a return +value of TRUE indicates that the SoupServer serves https +exclusively. If you are using soup_server_listen(), etc, then a +TRUE return value merely indicates that the server is +able to do https, regardless of whether it +actually currently is or not. Use soup_server_get_uris() to see if +it currently has any https listeners.

+
+

Parameters

+
+++++ + + + + + +

server

a SoupServer

 
+
+
+

Returns

+

TRUE if server +is configured to serve https.

+
+
+
+
+

soup_server_accept_iostream ()

+
gboolean
+soup_server_accept_iostream (SoupServer *server,
+                             GIOStream *stream,
+                             GSocketAddress *local_addr,
+                             GSocketAddress *remote_addr,
+                             GError **error);
+

Add a new client stream to the server +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

server

a SoupServer

 

stream

a GIOStream

 

local_addr

the local GSocketAddress associated with the stream +.

[allow-none]

remote_addr

the remote GSocketAddress associated with the stream +.

[allow-none]

error

return location for a GError

 
+
+
+

Returns

+

TRUE on success, FALSE if the stream could not be +accepted or any other error occurred (in which case error +will be +set).

+
+

Since: 2.50

+
+
+
+

SoupServerCallback ()

+
void
+(*SoupServerCallback) (SoupServer *server,
+                       SoupMessage *msg,
+                       const char *path,
+                       GHashTable *query,
+                       SoupClientContext *client,
+                       gpointer user_data);
+

A callback used to handle requests to a SoupServer.

+

path + and query + contain the likewise-named components of the +Request-URI, subject to certain assumptions. By default, +SoupServer decodes all percent-encoding in the URI path, such that +"/foo%2Fbar" is treated the same as "/foo/bar". If your +server is serving resources in some non-POSIX-filesystem namespace, +you may want to distinguish those as two distinct paths. In that +case, you can set the SOUP_SERVER_RAW_PATHS property when creating +the SoupServer, and it will leave those characters undecoded. (You +may want to call soup_uri_normalize() to decode any percent-encoded +characters that you aren't handling specially.)

+

query + contains the query component of the Request-URI parsed +according to the rules for HTML form handling. Although this is the +only commonly-used query string format in HTTP, there is nothing +that actually requires that HTTP URIs use that format; if your +server needs to use some other format, you can just ignore query +, +and call soup_message_get_uri() and parse the URI's query field +yourself.

+

See soup_server_add_handler() and soup_server_add_early_handler() +for details of what handlers can/should do.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

server

the SoupServer

 

msg

the message being processed

 

path

the path component of msg +'s Request-URI

 

query

the parsed query +component of msg +'s Request-URI.

[element-type utf8 utf8][allow-none]

client

additional contextual information about the client

 

user_data

the data passed to soup_server_add_handler() or +soup_server_add_early_handler().

 
+
+
+
+
+

soup_server_add_handler ()

+
void
+soup_server_add_handler (SoupServer *server,
+                         const char *path,
+                         SoupServerCallback callback,
+                         gpointer user_data,
+                         GDestroyNotify destroy);
+

Adds a handler to server + for requests under path +. If path + is +NULL or "/", then this will be the default handler for all +requests that don't have a more specific handler. (Note though that +if you want to handle requests to the special "*" URI, you must +explicitly register a handler for "*"; the default handler will not +be used for that case.)

+

For requests under path + (that have not already been assigned a +status code by a SoupAuthDomain, an early SoupServerHandler, or a +signal handler), callback + will be invoked after receiving the +request body; the message's “method”, +“request-headers”, and “request-body” fields +will be filled in.

+

After determining what to do with the request, the callback must at +a minimum call soup_message_set_status() (or +soup_message_set_status_full()) on the message to set the response +status code. Additionally, it may set response headers and/or fill +in the response body.

+

If the callback cannot fully fill in the response before returning +(eg, if it needs to wait for information from a database, or +another network server), it should call soup_server_pause_message() +to tell server + to not send the response right away. When the +response is ready, call soup_server_unpause_message() to cause it +to be sent.

+

To send the response body a bit at a time using "chunked" encoding, +first call soup_message_headers_set_encoding() to set +SOUP_ENCODING_CHUNKED on the “response-headers”. Then call +soup_message_body_append() (or soup_message_body_append_buffer()) +to append each chunk as it becomes ready, and +soup_server_unpause_message() to make sure it's running. (The +server will automatically pause the message if it is using chunked +encoding but no more chunks are available.) When you are done, call +soup_message_body_complete() to indicate that no more chunks are +coming.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

server

a SoupServer

 

path

the toplevel path for the handler.

[allow-none]

callback

callback to invoke for requests under path +

 

user_data

data for callback +

 

destroy

destroy notifier to free user_data +

 
+
+
+
+
+

soup_server_add_early_handler ()

+
void
+soup_server_add_early_handler (SoupServer *server,
+                               const char *path,
+                               SoupServerCallback callback,
+                               gpointer user_data,
+                               GDestroyNotify destroy);
+

Adds an "early" handler to server + for requests under path +. Note +that "normal" and "early" handlers are matched up together, so if +you add a normal handler for "/foo" and an early handler for +"/foo/bar", then a request to "/foo/bar" (or any path below it) +will run only the early handler. (But if you add both handlers at +the same path, then both will get run.)

+

For requests under path + (that have not already been assigned a +status code by a SoupAuthDomain or a signal handler), callback + +will be invoked after receiving the request headers, but before +receiving the request body; the message's “method” and +“request-headers” fields will be filled in.

+

Early handlers are generally used for processing requests with +request bodies in a streaming fashion. If you determine that the +request will contain a message body, normally you would call +soup_message_body_set_accumulate() on the message's +“request-body” to turn off request-body accumulation, +and connect to the message's “got-chunk” signal to +process each chunk as it comes in.

+

To complete the message processing after the full message body has +been read, you can either also connect to “got-body”, +or else you can register a non-early handler for path + as well. As +long as you have not set the “status-code” by the time +“got-body” is emitted, the non-early handler will be +run as well.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

server

a SoupServer

 

path

the toplevel path for the handler.

[allow-none]

callback

callback to invoke for requests under path +

 

user_data

data for callback +

 

destroy

destroy notifier to free user_data +

 
+
+

Since: 2.50

+
+
+
+

soup_server_remove_handler ()

+
void
+soup_server_remove_handler (SoupServer *server,
+                            const char *path);
+

Removes all handlers (early and normal) registered at path +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

server

a SoupServer

 

path

the toplevel path for the handler

 
+
+
+
+
+

SoupServerWebsocketCallback ()

+
void
+(*SoupServerWebsocketCallback) (SoupServer *server,
+                                SoupWebsocketConnection *connection,
+                                const char *path,
+                                SoupClientContext *client,
+                                gpointer user_data);
+

A callback used to handle WebSocket requests to a SoupServer. The +callback will be invoked after sending the handshake response back +to the client (and is only invoked if the handshake was +successful).

+

path + contains the path of the Request-URI, subject to the same +rules as SoupServerCallback (qv).

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

server

the SoupServer

 

path

the path component of msg +'s Request-URI

 

connection

the newly created WebSocket connection

 

client

additional contextual information about the client

 

user_data

the data passed to soup_server_add_handler +

 
+
+
+
+
+

soup_server_add_websocket_handler ()

+
void
+soup_server_add_websocket_handler (SoupServer *server,
+                                   const char *path,
+                                   const char *origin,
+                                   char **protocols,
+                                   SoupServerWebsocketCallback callback,
+                                   gpointer user_data,
+                                   GDestroyNotify destroy);
+

Adds a WebSocket handler to server + for requests under path +. (If +path + is NULL or "/", then this will be the default handler for +all requests that don't have a more specific handler.)

+

When a path has a WebSocket handler registered, server + will check +incoming requests for WebSocket handshakes after all other handlers +have run (unless some earlier handler has already set a status code +on the message), and update the request's status, response headers, +and response body accordingly.

+

If origin + is non-NULL, then only requests containing a matching +"Origin" header will be accepted. If protocols + is non-NULL, then +only requests containing a compatible "Sec-WebSocket-Protocols" +header will be accepted. More complicated requirements can be +handled by adding a normal handler to path +, and having it perform +whatever checks are needed (possibly calling +soup_server_check_websocket_handshake() one or more times), and +setting a failure status code if the handshake should be rejected.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

server

a SoupServer

 

path

the toplevel path for the handler.

[allow-none]

origin

the origin of the connection.

[allow-none]

protocols

the protocols +supported by this handler.

[allow-none][array zero-terminated=1]

callback

callback to invoke for successful WebSocket requests under path +

 

user_data

data for callback +

 

destroy

destroy notifier to free user_data +

 
+
+
+
+
+

soup_client_context_get_local_address ()

+
GSocketAddress *
+soup_client_context_get_local_address (SoupClientContext *client);
+

Retrieves the GSocketAddress associated with the local end +of a connection.

+
+

Parameters

+
+++++ + + + + + +

client

a SoupClientContext

 
+
+
+

Returns

+

the GSocketAddress +associated with the local end of a connection, it may be +NULL if you used soup_server_accept_iostream().

+

[nullable][transfer none]

+
+

Since: 2.48

+
+
+
+

soup_client_context_get_remote_address ()

+
GSocketAddress *
+soup_client_context_get_remote_address
+                               (SoupClientContext *client);
+

Retrieves the GSocketAddress associated with the remote end +of a connection.

+
+

Parameters

+
+++++ + + + + + +

client

a SoupClientContext

 
+
+
+

Returns

+

the GSocketAddress +associated with the remote end of a connection, it may be +NULL if you used soup_server_accept_iostream().

+

[nullable][transfer none]

+
+

Since: 2.48

+
+
+
+

soup_client_context_get_host ()

+
const char *
+soup_client_context_get_host (SoupClientContext *client);
+

Retrieves the IP address associated with the remote end of a +connection.

+
+

Parameters

+
+++++ + + + + + +

client

a SoupClientContext

 
+
+
+

Returns

+

the IP address associated with the remote +end of a connection, it may be NULL if you used +soup_server_accept_iostream().

+

[nullable]

+
+
+
+
+

soup_client_context_get_auth_domain ()

+
SoupAuthDomain *
+soup_client_context_get_auth_domain (SoupClientContext *client);
+

Checks whether the request associated with client + has been +authenticated, and if so returns the SoupAuthDomain that +authenticated it.

+
+

Parameters

+
+++++ + + + + + +

client

a SoupClientContext

 
+
+
+

Returns

+

a SoupAuthDomain, or +NULL if the request was not authenticated.

+

[transfer none][nullable]

+
+
+
+
+

soup_client_context_get_auth_user ()

+
const char *
+soup_client_context_get_auth_user (SoupClientContext *client);
+

Checks whether the request associated with client + has been +authenticated, and if so returns the username that the client +authenticated as.

+
+

Parameters

+
+++++ + + + + + +

client

a SoupClientContext

 
+
+
+

Returns

+

the authenticated-as user, or NULL if +the request was not authenticated.

+

[nullable]

+
+
+
+
+

soup_client_context_get_gsocket ()

+
GSocket *
+soup_client_context_get_gsocket (SoupClientContext *client);
+

Retrieves the GSocket that client + is associated with.

+

If you are using this method to observe when multiple requests are +made on the same persistent HTTP connection (eg, as the ntlm-test +test program does), you will need to pay attention to socket +destruction as well (eg, by using weak references), so that you do +not get fooled when the allocator reuses the memory address of a +previously-destroyed socket to represent a new socket.

+
+

Parameters

+
+++++ + + + + + +

client

a SoupClientContext

 
+
+
+

Returns

+

the GSocket that client +is +associated with, NULL if you used soup_server_accept_iostream().

+

[nullable][transfer none]

+
+

Since: 2.48

+
+
+
+

soup_client_context_steal_connection ()

+
GIOStream *
+soup_client_context_steal_connection (SoupClientContext *client);
+

"Steals" the HTTP connection associated with client + from its +SoupServer. This happens immediately, regardless of the current +state of the connection; if the response to the current +SoupMessage has not yet finished being sent, then it will be +discarded; you can steal the connection from a +“wrote-informational” or “wrote-body” signal +handler if you need to wait for part or all of the response to be +sent.

+

Note that when calling this function from C, client + will most +likely be freed as a side effect.

+
+

Parameters

+
+++++ + + + + + +

client

a SoupClientContext

 
+
+
+

Returns

+

the GIOStream formerly associated +with client +(or NULL if client +was no longer associated with a +connection). No guarantees are made about what kind of GIOStream +is returned.

+

[transfer full]

+
+

Since: 2.50

+
+
+
+

soup_server_add_auth_domain ()

+
void
+soup_server_add_auth_domain (SoupServer *server,
+                             SoupAuthDomain *auth_domain);
+

Adds an authentication domain to server +. Each auth domain will +have the chance to require authentication for each request that +comes in; normally auth domains will require authentication for +requests on certain paths that they have been set up to watch, or +that meet other criteria set by the caller. If an auth domain +determines that a request requires authentication (and the request +doesn't contain authentication), server + will automatically reject +the request with an appropriate status (401 Unauthorized or 407 +Proxy Authentication Required). If the request used the +"100-continue" Expectation, server + will reject it before the +request body is sent.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

server

a SoupServer

 

auth_domain

a SoupAuthDomain

 
+
+
+
+
+

soup_server_remove_auth_domain ()

+
void
+soup_server_remove_auth_domain (SoupServer *server,
+                                SoupAuthDomain *auth_domain);
+

Removes auth_domain + from server +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

server

a SoupServer

 

auth_domain

a SoupAuthDomain

 
+
+
+
+
+

soup_server_pause_message ()

+
void
+soup_server_pause_message (SoupServer *server,
+                           SoupMessage *msg);
+

Pauses I/O on msg +. This can be used when you need to return from +the server handler without having the full response ready yet. Use +soup_server_unpause_message() to resume I/O.

+

This must only be called on SoupMessages which were created by the +SoupServer and are currently doing I/O, such as those passed into a +SoupServerCallback or emitted in a “request-read” signal.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

server

a SoupServer

 

msg

a SoupMessage associated with server +.

 
+
+
+
+
+

soup_server_unpause_message ()

+
void
+soup_server_unpause_message (SoupServer *server,
+                             SoupMessage *msg);
+

Resumes I/O on msg +. Use this to resume after calling +soup_server_pause_message(), or after adding a new chunk to a +chunked response.

+

I/O won't actually resume until you return to the main loop.

+

This must only be called on SoupMessages which were created by the +SoupServer and are currently doing I/O, such as those passed into a +SoupServerCallback or emitted in a “request-read” signal.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

server

a SoupServer

 

msg

a SoupMessage associated with server +.

 
+
+
+
+
+

Types and Values

+
+

SoupServer

+
typedef struct _SoupServer SoupServer;
+
+
+
+

enum SoupServerListenOptions

+

Options to pass to soup_server_listen(), etc.

+

SOUP_SERVER_LISTEN_IPV4_ONLY and SOUP_SERVER_LISTEN_IPV6_ONLY +only make sense with soup_server_listen_all() and +soup_server_listen_local(), not plain soup_server_listen() (which +simply listens on whatever kind of socket you give it). And you +cannot specify both of them in a single call.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + +

SOUP_SERVER_LISTEN_HTTPS

+

Listen for https connections rather + than plain http.

+
 

SOUP_SERVER_LISTEN_IPV4_ONLY

+

Only listen on IPv4 interfaces.

+
 

SOUP_SERVER_LISTEN_IPV6_ONLY

+

Only listen on IPv6 interfaces.

+
 
+
+

Since: 2.48

+
+
+
+

SoupClientContext

+
typedef struct SoupClientContext SoupClientContext;
+
+

A SoupClientContext provides additional information about the +client making a particular request. In particular, you can use +soup_client_context_get_auth_domain() and +soup_client_context_get_auth_user() to determine if HTTP +authentication was used successfully.

+

soup_client_context_get_remote_address() and/or +soup_client_context_get_host() can be used to get information for +logging or debugging purposes. soup_client_context_get_gsocket() may +also be of use in some situations (eg, tracking when multiple +requests are made on the same connection).

+
+
+
+

SOUP_SERVER_TLS_CERTIFICATE

+
#define SOUP_SERVER_TLS_CERTIFICATE "tls-certificate"
+
+

Alias for the “tls-certificate” property, qv.

+

Since: 2.38

+
+
+
+

SOUP_SERVER_RAW_PATHS

+
#define SOUP_SERVER_RAW_PATHS       "raw-paths"
+
+

Alias for the “raw-paths” property. (If TRUE, +percent-encoding in the Request-URI path will not be +automatically decoded.)

+
+
+
+

SOUP_SERVER_SERVER_HEADER

+
#define SOUP_SERVER_SERVER_HEADER   "server-header"
+
+

Alias for the “server-header” property, qv.

+
+
+
+

SOUP_SERVER_HTTP_ALIASES

+
#define SOUP_SERVER_HTTP_ALIASES    "http-aliases"
+
+

Alias for the “http-aliases” property, qv.

+

Since: 2.44

+
+
+
+

SOUP_SERVER_HTTPS_ALIASES

+
#define SOUP_SERVER_HTTPS_ALIASES   "https-aliases"
+
+

Alias for the “https-aliases” property, qv.

+

Since: 2.44

+
+
+
+

Property Details

+
+

The “async-context” property

+
  “async-context”            gpointer
+

The server's GMainContext, if you are using the old API. +Servers created using soup_server_listen() will listen on +the GMainContext that was the thread-default context at +the time soup_server_listen() was called.

+
+

SoupServer:async-context is deprecated and should not be used in newly-written code.

+

The new API uses the thread-default GMainContext +rather than having an explicitly-specified one.

+
+

Flags: Read / Write / Construct Only

+
+
+
+

The “http-aliases” property

+
  “http-aliases”             GStrv
+

A NULL-terminated array of URI schemes that should be +considered to be aliases for "http". Eg, if this included +"dav", than a URI of +dav://example.com/path would be treated +identically to http://example.com/path. +In particular, this is needed in cases where a client +sends requests with absolute URIs, where those URIs do +not use "http:".

+

The default value is an array containing the single element +"*", a special value which means that +any scheme except "https" is considered to be an alias for +"http".

+

See also “https-aliases”.

+

Flags: Read / Write

+

Since: 2.44

+
+
+
+

The “https-aliases” property

+
  “https-aliases”            GStrv
+

A comma-delimited list of URI schemes that should be +considered to be aliases for "https". See +“http-aliases” for more information.

+

The default value is NULL, meaning that no URI schemes +are considered aliases for "https".

+

Flags: Read / Write

+

Since: 2.44

+
+
+
+

The “interface” property

+
  “interface”                SoupAddress *
+

The address of the network interface the server is +listening on, if you are using the old SoupServer API. +(This will not be set if you use soup_server_listen(), +etc.)

+
+

SoupServer:interface is deprecated and should not be used in newly-written code.

+

SoupServers can listen on multiple interfaces +at once now. Use soup_server_listen(), etc, to listen on an +interface, and soup_server_get_uris() to see what addresses +are being listened on.

+
+

Flags: Read / Write / Construct Only

+
+
+
+

The “port” property

+
  “port”                     guint
+

The port the server is listening on, if you are using the +old SoupServer API. (This will not be set if you use +soup_server_listen(), etc.)

+
+

SoupServer:port is deprecated and should not be used in newly-written code.

+

SoupServers can listen on multiple interfaces +at once now. Use soup_server_listen(), etc, to listen on a +port, and soup_server_get_uris() to see what ports are +being listened on.

+
+

Flags: Read / Write / Construct Only

+

Allowed values: <= 65536

+

Default value: 0

+
+
+
+

The “raw-paths” property

+
  “raw-paths”                gboolean
+

If %TRUE, percent-encoding in the Request-URI path will not be automatically decoded.

+

Flags: Read / Write / Construct Only

+

Default value: FALSE

+
+
+
+

The “server-header” property

+
  “server-header”            gchar *
+

If non-NULL, the value to use for the "Server" header on +SoupMessages processed by this server.

+

The Server header is the server equivalent of the +User-Agent header, and provides information about the +server and its components. It contains a list of one or +more product tokens, separated by whitespace, with the most +significant product token coming first. The tokens must be +brief, ASCII, and mostly alphanumeric (although "-", "_", +and "." are also allowed), and may optionally include a "/" +followed by a version string. You may also put comments, +enclosed in parentheses, between or after the tokens.

+

Some HTTP server implementations intentionally do not use +version numbers in their Server header, so that +installations running older versions of the server don't +end up advertising their vulnerability to specific security +holes.

+

As with “user_agent”, if you set a +“server_header” property that has trailing whitespace, +SoupServer will append its own product token (eg, +"libsoup/2.3.2") to the end of the +header for you.

+

Flags: Read / Write / Construct

+

Default value: NULL

+
+
+
+

The “ssl-cert-file” property

+
  “ssl-cert-file”            gchar *
+

Path to a file containing a PEM-encoded certificate.

+

If you set this property and “ssl-key-file” at +construct time, then soup_server_new() will try to read the +files; if it cannot, it will return NULL, with no explicit +indication of what went wrong (and logging a warning with +newer versions of glib, since returning NULL from a +constructor is illegal).

+
+

SoupServer:ssl-cert-file is deprecated and should not be used in newly-written code.

+

use “tls-certificate” or +soup_server_set_ssl_certificate().

+
+

Flags: Read / Write / Construct Only

+

Default value: NULL

+
+
+
+

The “ssl-key-file” property

+
  “ssl-key-file”             gchar *
+

Path to a file containing a PEM-encoded private key. See +“ssl-cert-file” for more information about how this +is used.

+
+

SoupServer:ssl-key-file is deprecated and should not be used in newly-written code.

+

use “tls-certificate” or +soup_server_set_ssl_certificate().

+
+

Flags: Read / Write / Construct Only

+

Default value: NULL

+
+
+
+

The “tls-certificate” property

+
  “tls-certificate”          GTlsCertificate *
+

A GTlsCertificate that has a “private-key” +set. If this is set, then the server will be able to speak +https in addition to (or instead of) plain http.

+

Alternatively, you can call soup_server_set_ssl_cert_file() +to have SoupServer read in a a certificate from a file.

+

Flags: Read / Write / Construct Only

+

Since: 2.38

+
+
+
+

Signal Details

+
+

The “request-aborted” signal

+
void
+user_function (SoupServer        *server,
+               SoupMessage       *message,
+               SoupClientContext *client,
+               gpointer           user_data)
+

Emitted when processing has failed for a message; this +could mean either that it could not be read (if +“request_read” has not been emitted for it yet), +or that the response could not be written back (if +“request_read” has been emitted but +“request_finished” has not been).

+

message + is in an undefined state when this signal is +emitted; the signal exists primarily to allow the server to +free any state that it may have allocated in +“request_started”.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

server

the server

 

message

the message

 

client

the client context

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+
+
+
+

The “request-finished” signal

+
void
+user_function (SoupServer        *server,
+               SoupMessage       *message,
+               SoupClientContext *client,
+               gpointer           user_data)
+

Emitted when the server has finished writing a response to +a request.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

server

the server

 

message

the message

 

client

the client context

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+
+
+
+

The “request-read” signal

+
void
+user_function (SoupServer        *server,
+               SoupMessage       *message,
+               SoupClientContext *client,
+               gpointer           user_data)
+

Emitted when the server has successfully read a request. +message + will have all of its request-side information +filled in, and if the message was authenticated, client + +will have information about that. This signal is emitted +before any (non-early) handlers are called for the message, +and if it sets the message's status_code, then normal +handler processing will be skipped.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

server

the server

 

message

the message

 

client

the client context

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+
+
+
+

The “request-started” signal

+
void
+user_function (SoupServer        *server,
+               SoupMessage       *message,
+               SoupClientContext *client,
+               gpointer           user_data)
+

Emitted when the server has started reading a new request. +message + will be completely blank; not even the +Request-Line will have been read yet. About the only thing +you can usefully do with it is connect to its signals.

+

If the request is read successfully, this will eventually +be followed by a “request_read” signal. If a +response is then sent, the request processing will end with +a “request_finished” signal. If a network error +occurs, the processing will instead end with +“request_aborted”.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

server

the server

 

message

the new message

 

client

the client context

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+
+
+
+

See Also

+

SoupAuthDomain

+
+
+ + + \ No newline at end of file diff --git a/docs/reference/html/SoupSession.html b/docs/reference/html/SoupSession.html new file mode 100644 index 0000000..29bb00a --- /dev/null +++ b/docs/reference/html/SoupSession.html @@ -0,0 +1,3208 @@ + + + + +SoupSession: libsoup Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

SoupSession

+

SoupSession — Soup session state object

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+SoupSession * + +soup_session_new () +
+SoupSession * + +soup_session_new_with_options () +
+SoupRequest * + +soup_session_request () +
+SoupRequest * + +soup_session_request_uri () +
+SoupRequestHTTP * + +soup_session_request_http () +
+SoupRequestHTTP * + +soup_session_request_http_uri () +
+void + +(*SoupSessionCallback) () +
+void + +soup_session_queue_message () +
+void + +soup_session_requeue_message () +
+guint + +soup_session_send_message () +
+void + +soup_session_cancel_message () +
+GInputStream * + +soup_session_send () +
+void + +soup_session_send_async () +
+GInputStream * + +soup_session_send_finish () +
+void + +soup_session_websocket_connect_async () +
+SoupWebsocketConnection * + +soup_session_websocket_connect_finish () +
+void + +soup_session_prefetch_dns () +
+void + +soup_session_abort () +
+gboolean + +soup_session_would_redirect () +
+gboolean + +soup_session_redirect_message () +
+void + +soup_session_pause_message () +
+void + +soup_session_unpause_message () +
+GMainContext * + +soup_session_get_async_context () +
+void + +soup_session_add_feature () +
+void + +soup_session_add_feature_by_type () +
+void + +soup_session_remove_feature () +
+void + +soup_session_remove_feature_by_type () +
+GSList * + +soup_session_get_features () +
+SoupSessionFeature * + +soup_session_get_feature () +
+SoupSessionFeature * + +soup_session_get_feature_for_message () +
+gboolean + +soup_session_has_feature () +
+GIOStream * + +soup_session_steal_connection () +
+void + +(*SoupSessionConnectProgressCallback) () +
+void + +soup_session_connect_async () +
+GIOStream * + +soup_session_connect_finish () +
+
+
+

Properties

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+gchar *accept-languageRead / Write
gbooleanaccept-language-autoRead / Write
+SoupSessionFeature *add-featureRead / Write
+GType *add-feature-by-typeRead / Write
gpointerasync-contextRead / Write / Construct Only
GStrvhttp-aliasesRead / Write
GStrvhttps-aliasesRead / Write
guintidle-timeoutRead / Write
+SoupAddress *local-addressRead / Write / Construct Only
gintmax-connsRead / Write
gintmax-conns-per-hostRead / Write
+GProxyResolver *proxy-resolverRead / Write
+SoupURI *proxy-uriRead / Write
+GType *remove-feature-by-typeRead / Write
+gchar *ssl-ca-fileRead / Write
gbooleanssl-strictRead / Write
gbooleanssl-use-system-ca-fileRead / Write
guinttimeoutRead / Write
+GTlsDatabase *tls-databaseRead / Write
+GTlsInteraction *tls-interactionRead / Write
gbooleanuse-ntlmRead / Write
gbooleanuse-thread-contextRead / Write
+gchar *user-agentRead / Write
+
+
+

Signals

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
voidauthenticateRun First
voidconnection-createdRun First
voidrequest-queuedRun First
voidrequest-startedRun First
voidrequest-unqueuedRun First
voidtunnelingRun First
+
+ +
+

Object Hierarchy

+
    GObject
+    ╰── SoupSession
+        ├── SoupSessionAsync
+        ╰── SoupSessionSync
+
+
+
+

Includes

+
#include <libsoup/soup.h>
+
+
+
+

Description

+

SoupSession is the object that controls client-side HTTP. A +SoupSession encapsulates all of the state that libsoup is keeping +on behalf of your program; cached HTTP connections, authentication +information, etc. It also keeps track of various global options +and features that you are using.

+

Most applications will only need a single SoupSession; the primary +reason you might need multiple sessions is if you need to have +multiple independent authentication contexts. (Eg, you are +connecting to a server and authenticating as two different users at +different times; the easiest way to ensure that each SoupMessage +is sent with the authentication information you intended is to use +one session for the first user, and a second session for the other +user.)

+

In the past, SoupSession was an abstract class, and users needed +to choose between SoupSessionAsync (which always uses +GMainLoop-based I/O), or SoupSessionSync (which always uses +blocking I/O and can be used from multiple threads simultaneously). +This is no longer necessary; you can (and should) use a plain +SoupSession, which supports both synchronous and asynchronous use. +(When using a plain SoupSession, soup_session_queue_message() +behaves like it traditionally did on a SoupSessionAsync, and +soup_session_send_message() behaves like it traditionally did on a +SoupSessionSync.)

+

Additional SoupSession functionality is provided by +SoupSessionFeature objects, which can be added to a session with +soup_session_add_feature() or soup_session_add_feature_by_type() +(or at construct time with the SOUP_SESSION_ADD_FEATURE_BY_TYPE +pseudo-property). For example, SoupLogger provides support for +logging HTTP traffic, SoupContentDecoder provides support for +compressed response handling, and SoupContentSniffer provides +support for HTML5-style response body content sniffing. +Additionally, subtypes of SoupAuth and SoupRequest can be added +as features, to add support for additional authentication and URI +types.

+

All SoupSessions are created with a SoupAuthManager, and support +for SOUP_TYPE_AUTH_BASIC and SOUP_TYPE_AUTH_DIGEST. For +SoupRequest types, SoupRequestHTTP, SoupRequestFile, and +SoupRequestData are supported. Additionally, sessions using the +plain SoupSession class (rather than one of its deprecated +subtypes) have a SoupContentDecoder by default.

+
+
+

Functions

+
+

soup_session_new ()

+
SoupSession *
+soup_session_new (void);
+

Creates a SoupSession with the default options.

+
+

Returns

+

the new session.

+
+

Since: 2.42

+
+
+
+

soup_session_new_with_options ()

+
SoupSession *
+soup_session_new_with_options (const char *optname1,
+                               ...);
+

Creates a SoupSession with the specified options.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

optname1

name of first property to set

 

...

value of optname1 +, followed by additional property/value pairs

 
+
+
+

Returns

+

the new session.

+
+

Since: 2.42

+
+
+
+

soup_session_request ()

+
SoupRequest *
+soup_session_request (SoupSession *session,
+                      const char *uri_string,
+                      GError **error);
+

Creates a SoupRequest for retrieving uri_string +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

session

a SoupSession

 

uri_string

a URI, in string form

 

error

return location for a GError, or NULL

 
+
+
+

Returns

+

a new SoupRequest, or +NULL on error.

+

[transfer full]

+
+

Since: 2.42

+
+
+
+

soup_session_request_uri ()

+
SoupRequest *
+soup_session_request_uri (SoupSession *session,
+                          SoupURI *uri,
+                          GError **error);
+

Creates a SoupRequest for retrieving uri +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

session

a SoupSession

 

uri

a SoupURI representing the URI to retrieve

 

error

return location for a GError, or NULL

 
+
+
+

Returns

+

a new SoupRequest, or +NULL on error.

+

[transfer full]

+
+

Since: 2.42

+
+
+
+

soup_session_request_http ()

+
SoupRequestHTTP *
+soup_session_request_http (SoupSession *session,
+                           const char *method,
+                           const char *uri_string,
+                           GError **error);
+

Creates a SoupRequest for retrieving uri_string +, which must be an +"http" or "https" URI (or another protocol listed in session +'s +“http-aliases” or “https-aliases”).

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

session

a SoupSession

 

method

an HTTP method

 

uri_string

a URI, in string form

 

error

return location for a GError, or NULL

 
+
+
+

Returns

+

a new SoupRequestHTTP, or +NULL on error.

+

[transfer full]

+
+

Since: 2.42

+
+
+
+

soup_session_request_http_uri ()

+
SoupRequestHTTP *
+soup_session_request_http_uri (SoupSession *session,
+                               const char *method,
+                               SoupURI *uri,
+                               GError **error);
+

Creates a SoupRequest for retrieving uri +, which must be an +"http" or "https" URI (or another protocol listed in session +'s +“http-aliases” or “https-aliases”).

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

session

a SoupSession

 

method

an HTTP method

 

uri

a SoupURI representing the URI to retrieve

 

error

return location for a GError, or NULL

 
+
+
+

Returns

+

a new SoupRequestHTTP, or +NULL on error.

+

[transfer full]

+
+

Since: 2.42

+
+
+
+

SoupSessionCallback ()

+
void
+(*SoupSessionCallback) (SoupSession *session,
+                        SoupMessage *msg,
+                        gpointer user_data);
+

Prototype for the callback passed to soup_session_queue_message(), +qv.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

session

the session

 

msg

the message that has finished

 

user_data

the data passed to soup_session_queue_message

 
+
+
+
+
+

soup_session_queue_message ()

+
void
+soup_session_queue_message (SoupSession *session,
+                            SoupMessage *msg,
+                            SoupSessionCallback callback,
+                            gpointer user_data);
+

Queues the message msg + for asynchronously sending the request and +receiving a response in the current thread-default GMainContext. +If msg + has been processed before, any resources related to the +time it was last sent are freed.

+

Upon message completion, the callback specified in callback + will +be invoked. If after returning from this callback the message has not +been requeued, msg + will be unreffed.

+

(The behavior above applies to a plain SoupSession; if you are +using SoupSessionAsync or SoupSessionSync, then the GMainContext +that is used depends on the settings of “async-context” +and “use-thread-context”, and for SoupSessionSync, the +message will actually be sent and processed in another thread, with +only the final callback occurring in the indicated GMainContext.)

+

Contrast this method with soup_session_send_async(), which also +asynchronously sends a message, but returns before reading the +response body, and allows you to read the response via a +GInputStream.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

session

a SoupSession

 

msg

the message to queue.

[transfer full]

callback

a SoupSessionCallback which will +be called after the message completes or when an unrecoverable error occurs.

[allow-none][scope async]

user_data

a pointer passed to callback +.

[allow-none]
+
+
+
+
+

soup_session_requeue_message ()

+
void
+soup_session_requeue_message (SoupSession *session,
+                              SoupMessage *msg);
+

This causes msg + to be placed back on the queue to be attempted +again.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

session

a SoupSession

 

msg

the message to requeue

 
+
+
+
+
+

soup_session_send_message ()

+
guint
+soup_session_send_message (SoupSession *session,
+                           SoupMessage *msg);
+

Synchronously send msg +. This call will not return until the +transfer is finished successfully or there is an unrecoverable +error.

+

Unlike with soup_session_queue_message(), msg + is not freed upon +return.

+

(Note that if you call this method on a SoupSessionAsync, it will +still use asynchronous I/O internally, running the glib main loop +to process the message, which may also cause other events to be +processed.)

+

Contrast this method with soup_session_send(), which also +synchronously sends a message, but returns before reading the +response body, and allows you to read the response via a +GInputStream.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

session

a SoupSession

 

msg

the message to send

 
+
+
+

Returns

+

the HTTP status code of the response

+
+
+
+
+

soup_session_cancel_message ()

+
void
+soup_session_cancel_message (SoupSession *session,
+                             SoupMessage *msg,
+                             guint status_code);
+

Causes session + to immediately finish processing msg + (regardless +of its current state) with a final status_code of status_code +. You +may call this at any time after handing msg + off to session +; if +session + has started sending the request but has not yet received +the complete response, then it will close the request's connection. +Note that with requests that have side effects (eg, +POST, PUT, +DELETE) it is possible that you might cancel the +request after the server acts on it, but before it returns a +response, leaving the remote resource in an unknown state.

+

If the message is cancelled while its response body is being read, +then the response body in msg + will be left partially-filled-in. +The response headers, on the other hand, will always be either +empty or complete.

+

Beware that with the deprecated SoupSessionAsync, messages queued +with soup_session_queue_message() will have their callbacks invoked +before soup_session_cancel_message() returns. The plain +SoupSession does not have this behavior; cancelling an +asynchronous message will merely queue its callback to be run after +returning to the main loop.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

session

a SoupSession

 

msg

the message to cancel

 

status_code

status code to set on msg +(generally +SOUP_STATUS_CANCELLED)

 
+
+
+
+
+

soup_session_send ()

+
GInputStream *
+soup_session_send (SoupSession *session,
+                   SoupMessage *msg,
+                   GCancellable *cancellable,
+                   GError **error);
+

Synchronously sends msg + and waits for the beginning of a response. +On success, a GInputStream will be returned which you can use to +read the response body. ("Success" here means only that an HTTP +response was received and understood; it does not necessarily mean +that a 2xx class status code was received.)

+

If non-NULL, cancellable + can be used to cancel the request; +soup_session_send() will return a G_IO_ERROR_CANCELLED error. Note +that with requests that have side effects (eg, +POST, PUT, +DELETE) it is possible that you might cancel the +request after the server acts on it, but before it returns a +response, leaving the remote resource in an unknown state.

+

If msg + is requeued due to a redirect or authentication, the +initial (3xx/401/407) response body will be suppressed, and +soup_session_send() will only return once a final response has been +received.

+

Contrast this method with soup_session_send_message(), which also +synchronously sends a SoupMessage, but doesn't return until the +response has been completely read.

+

(Note that this method cannot be called on the deprecated +SoupSessionAsync subclass.)

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

session

a SoupSession

 

msg

a SoupMessage

 

cancellable

a GCancellable

 

error

return location for a GError, or NULL

 
+
+
+

Returns

+

a GInputStream for reading the +response body, or NULL on error.

+

[transfer full]

+
+

Since: 2.42

+
+
+
+

soup_session_send_async ()

+
void
+soup_session_send_async (SoupSession *session,
+                         SoupMessage *msg,
+                         GCancellable *cancellable,
+                         GAsyncReadyCallback callback,
+                         gpointer user_data);
+

Asynchronously sends msg + and waits for the beginning of a +response. When callback + is called, then either msg + has been sent, +and its response headers received, or else an error has occurred. +Call soup_session_send_finish() to get a GInputStream for reading +the response body.

+

See soup_session_send() for more details on the general semantics.

+

Contrast this method with soup_session_queue_message(), which also +asynchronously sends a SoupMessage, but doesn't invoke its +callback until the response has been completely read.

+

(Note that this method cannot be called on the deprecated +SoupSessionSync subclass, and can only be called on +SoupSessionAsync if you have set the +“use-thread-context” property.)

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

session

a SoupSession

 

msg

a SoupMessage

 

cancellable

a GCancellable

 

callback

the callback to invoke

 

user_data

data for callback +

 
+
+

Since: 2.42

+
+
+
+

soup_session_send_finish ()

+
GInputStream *
+soup_session_send_finish (SoupSession *session,
+                          GAsyncResult *result,
+                          GError **error);
+

Gets the response to a soup_session_send_async() call and (if +successful), returns a GInputStream that can be used to read the +response body.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

session

a SoupSession

 

result

the GAsyncResult passed to your callback

 

error

return location for a GError, or NULL

 
+
+
+

Returns

+

a GInputStream for reading the +response body, or NULL on error.

+

[transfer full]

+
+

Since: 2.42

+
+
+
+

soup_session_websocket_connect_async ()

+
void
+soup_session_websocket_connect_async (SoupSession *session,
+                                      SoupMessage *msg,
+                                      const char *origin,
+                                      char **protocols,
+                                      GCancellable *cancellable,
+                                      GAsyncReadyCallback callback,
+                                      gpointer user_data);
+

Asynchronously creates a SoupWebsocketConnection to communicate +with a remote server.

+

All necessary WebSocket-related headers will be added to msg +, and +it will then be sent and asynchronously processed normally +(including handling of redirection and HTTP authentication).

+

If the server returns "101 Switching Protocols", then msg +'s status +code and response headers will be updated, and then the WebSocket +handshake will be completed. On success, +soup_session_websocket_connect_finish() will return a new +SoupWebsocketConnection. On failure it will return a GError.

+

If the server returns a status other than "101 Switching +Protocols", then msg + will contain the complete response headers +and body from the server's response, and +soup_session_websocket_connect_finish() will return +SOUP_WEBSOCKET_ERROR_NOT_WEBSOCKET.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

session

a SoupSession

 

msg

SoupMessage indicating the WebSocket server to connect to

 

origin

origin of the connection.

[allow-none]

protocols

a +NULL-terminated array of protocols supported.

[allow-none][array zero-terminated=1]

cancellable

a GCancellable

 

callback

the callback to invoke

 

user_data

data for callback +

 
+
+

Since: 2.50

+
+
+
+

soup_session_websocket_connect_finish ()

+
SoupWebsocketConnection *
+soup_session_websocket_connect_finish (SoupSession *session,
+                                       GAsyncResult *result,
+                                       GError **error);
+

Gets the SoupWebsocketConnection response to a +soup_session_websocket_connect_async() call and (if successful), +returns a SoupWebsocketConnection that can be used to communicate +with the server.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

session

a SoupSession

 

result

the GAsyncResult passed to your callback

 

error

return location for a GError, or NULL

 
+
+
+

Returns

+

a new SoupWebsocketConnection, or +NULL on error.

+

[transfer full]

+
+

Since: 2.50

+
+
+
+

soup_session_prefetch_dns ()

+
void
+soup_session_prefetch_dns (SoupSession *session,
+                           const char *hostname,
+                           GCancellable *cancellable,
+                           SoupAddressCallback callback,
+                           gpointer user_data);
+

Tells session + that an URI from the given hostname + may be requested +shortly, and so the session can try to prepare by resolving the +domain name in advance, in order to work more quickly once the URI +is actually requested.

+

If cancellable + is non-NULL, it can be used to cancel the +resolution. callback + will still be invoked in this case, with a +status of SOUP_STATUS_CANCELLED.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

session

a SoupSession

 

hostname

a hostname to be resolved

 

cancellable

a GCancellable object, or NULL.

[allow-none]

callback

callback to call with the +result, or NULL.

[scope async][allow-none]

user_data

data for callback +

 
+
+

Since: 2.38

+
+
+
+

soup_session_abort ()

+
void
+soup_session_abort (SoupSession *session);
+

Cancels all pending requests in session + and closes all idle +persistent connections.

+

The message cancellation has the same semantics as with +soup_session_cancel_message(); asynchronous requests on a +SoupSessionAsync will have their callback called before +soup_session_abort() returns. Requests on a plain SoupSession will +not.

+
+

Parameters

+
+++++ + + + + + +

session

the session

 
+
+
+
+
+

soup_session_would_redirect ()

+
gboolean
+soup_session_would_redirect (SoupSession *session,
+                             SoupMessage *msg);
+

Checks if msg + contains a response that would cause session + to +redirect it to a new URL (ignoring msg +'s SOUP_MESSAGE_NO_REDIRECT +flag, and the number of times it has already been redirected).

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

session

a SoupSession

 

msg

a SoupMessage that has response headers

 
+
+
+

Returns

+

whether msg +would be redirected

+
+

Since: 2.38

+
+
+
+

soup_session_redirect_message ()

+
gboolean
+soup_session_redirect_message (SoupSession *session,
+                               SoupMessage *msg);
+

Updates msg +'s URI according to its status code and "Location" +header, and requeues it on session +. Use this when you have set +SOUP_MESSAGE_NO_REDIRECT on a message, but have decided to allow a +particular redirection to occur, or if you want to allow a +redirection that SoupSession will not perform automatically (eg, +redirecting a non-safe method such as DELETE).

+

If msg +'s status code indicates that it should be retried as a GET +request, then msg + will be modified accordingly.

+

If msg + has already been redirected too many times, this will +cause it to fail with SOUP_STATUS_TOO_MANY_REDIRECTS.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

session

the session

 

msg

a SoupMessage that has received a 3xx response

 
+
+
+

Returns

+

TRUE if a redirection was applied, FALSE if not +(eg, because there was no Location header, or it could not be +parsed).

+
+

Since: 2.38

+
+
+
+

soup_session_pause_message ()

+
void
+soup_session_pause_message (SoupSession *session,
+                            SoupMessage *msg);
+

Pauses HTTP I/O on msg +. Call soup_session_unpause_message() to +resume I/O.

+

This may only be called for asynchronous messages (those sent on a +SoupSessionAsync or using soup_session_queue_message()).

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

session

a SoupSession

 

msg

a SoupMessage currently running on session +

 
+
+
+
+
+

soup_session_unpause_message ()

+
void
+soup_session_unpause_message (SoupSession *session,
+                              SoupMessage *msg);
+

Resumes HTTP I/O on msg +. Use this to resume after calling +soup_session_pause_message().

+

If msg + is being sent via blocking I/O, this will resume reading or +writing immediately. If msg + is using non-blocking I/O, then +reading or writing won't resume until you return to the main loop.

+

This may only be called for asynchronous messages (those sent on a +SoupSessionAsync or using soup_session_queue_message()).

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

session

a SoupSession

 

msg

a SoupMessage currently running on session +

 
+
+
+
+
+

soup_session_get_async_context ()

+
GMainContext *
+soup_session_get_async_context (SoupSession *session);
+

Gets session +'s “async-context”. This does not add a ref +to the context, so you will need to ref it yourself if you want it +to outlive its session.

+

For a modern SoupSession, this will always just return the +thread-default GMainContext, and so is not especially useful.

+
+

Parameters

+
+++++ + + + + + +

session

a SoupSession

 
+
+
+

Returns

+

session +'s GMainContext, +which may be NULL.

+

[nullable][transfer none]

+
+
+
+
+

soup_session_add_feature ()

+
void
+soup_session_add_feature (SoupSession *session,
+                          SoupSessionFeature *feature);
+

Adds feature +'s functionality to session +. You can also add a +feature to the session at construct time by using the +SOUP_SESSION_ADD_FEATURE property.

+

See the main SoupSession documentation for information on what +features are present in sessions by default.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

session

a SoupSession

 

feature

an object that implements SoupSessionFeature

 
+
+

Since: 2.24

+
+
+
+

soup_session_add_feature_by_type ()

+
void
+soup_session_add_feature_by_type (SoupSession *session,
+                                  GType feature_type);
+

If feature_type + is the type of a class that implements +SoupSessionFeature, this creates a new feature of that type and +adds it to session + as with soup_session_add_feature(). You can use +this when you don't need to customize the new feature in any way.

+

If feature_type + is not a SoupSessionFeature type, this gives each +existing feature on session + the chance to accept feature_type + as +a "subfeature". This can be used to add new SoupAuth or +SoupRequest types, for instance.

+

You can also add a feature to the session at construct time by +using the SOUP_SESSION_ADD_FEATURE_BY_TYPE property.

+

See the main SoupSession documentation for information on what +features are present in sessions by default.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

session

a SoupSession

 

feature_type

a GType

 
+
+

Since: 2.24

+
+
+
+

soup_session_remove_feature ()

+
void
+soup_session_remove_feature (SoupSession *session,
+                             SoupSessionFeature *feature);
+

Removes feature +'s functionality from session +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

session

a SoupSession

 

feature

a feature that has previously been added to session +

 
+
+

Since: 2.24

+
+
+
+

soup_session_remove_feature_by_type ()

+
void
+soup_session_remove_feature_by_type (SoupSession *session,
+                                     GType feature_type);
+

Removes all features of type feature_type + (or any subclass of +feature_type +) from session +. You can also remove standard features +from the session at construct time by using the +SOUP_SESSION_REMOVE_FEATURE_BY_TYPE property.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

session

a SoupSession

 

feature_type

a GType

 
+
+

Since: 2.24

+
+
+
+

soup_session_get_features ()

+
GSList *
+soup_session_get_features (SoupSession *session,
+                           GType feature_type);
+

Generates a list of session +'s features of type feature_type +. (If +you want to see all features, you can pass SOUP_TYPE_SESSION_FEATURE +for feature_type +.)

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

session

a SoupSession

 

feature_type

the GType of the class of features to get

 
+
+
+

Returns

+

a list of features. You must free the list, but not its contents.

+

[transfer container][element-type Soup.SessionFeature]

+
+

Since: 2.26

+
+
+
+

soup_session_get_feature ()

+
SoupSessionFeature *
+soup_session_get_feature (SoupSession *session,
+                          GType feature_type);
+

Gets the first feature in session + of type feature_type +. For +features where there may be more than one feature of a given type, +use soup_session_get_features().

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

session

a SoupSession

 

feature_type

the GType of the feature to get

 
+
+
+

Returns

+

a SoupSessionFeature, or +NULL. The feature is owned by session +.

+

[nullable][transfer none]

+
+

Since: 2.26

+
+
+
+

soup_session_get_feature_for_message ()

+
SoupSessionFeature *
+soup_session_get_feature_for_message (SoupSession *session,
+                                      GType feature_type,
+                                      SoupMessage *msg);
+

Gets the first feature in session + of type feature_type +, provided +that it is not disabled for msg +. As with +soup_session_get_feature(), this should only be used for features +where feature_type + is only expected to match a single feature. In +particular, if there are two matching features, and the first is +disabled on msg +, and the second is not, then this will return +NULL, not the second feature.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

session

a SoupSession

 

feature_type

the GType of the feature to get

 

msg

a SoupMessage

 
+
+
+

Returns

+

a SoupSessionFeature, or NULL. The +feature is owned by session +.

+

[nullable][transfer none]

+
+

Since: 2.28

+
+
+
+

soup_session_has_feature ()

+
gboolean
+soup_session_has_feature (SoupSession *session,
+                          GType feature_type);
+

Tests if session + has at a feature of type feature_type + (which can +be the type of either a SoupSessionFeature, or else a subtype of +some class managed by another feature, such as SoupAuth or +SoupRequest).

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

session

a SoupSession

 

feature_type

the GType of the class of features to check for

 
+
+
+

Returns

+

TRUE or FALSE

+
+

Since: 2.42

+
+
+
+

soup_session_steal_connection ()

+
GIOStream *
+soup_session_steal_connection (SoupSession *session,
+                               SoupMessage *msg);
+

"Steals" the HTTP connection associated with msg + from session +. +This happens immediately, regardless of the current state of the +connection, and msg +'s callback will not be called. You can steal +the connection from a SoupMessage signal handler if you need to +wait for part or all of the response to be received first.

+

Calling this function may cause msg + to be freed if you are not +holding any other reference to it.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

session

a SoupSession

 

msg

the message whose connection is to be stolen

 
+
+
+

Returns

+

the GIOStream formerly associated +with msg +(or NULL if msg +was no longer associated with a +connection). No guarantees are made about what kind of GIOStream +is returned.

+

[transfer full]

+
+

Since: 2.50

+
+
+
+

SoupSessionConnectProgressCallback ()

+
void
+(*SoupSessionConnectProgressCallback) (SoupSession *session,
+                                       GSocketClientEvent event,
+                                       GIOStream *connection,
+                                       gpointer user_data);
+

Prototype for the progress callback passed to soup_session_connect_async().

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

session

the SoupSession

 

event

a GSocketClientEvent

 

connection

the current state of the network connection

 

user_data

the data passed to soup_session_connect_async().

 
+
+

Since: 2.62

+
+
+
+

soup_session_connect_async ()

+
void
+soup_session_connect_async (SoupSession *session,
+                            SoupURI *uri,
+                            GCancellable *cancellable,
+                            SoupSessionConnectProgressCallback progress_callback,
+                            GAsyncReadyCallback callback,
+                            gpointer user_data);
+

Start a connection to uri +. The operation can be monitored by providing a progress_callback + +and finishes when the connection is done or an error ocurred.

+

Call soup_session_connect_finish() to get the GIOStream to communicate with the server.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

session

a SoupSession

 

uri

a SoupURI to connect to

 

cancellable

a GCancellable

 

progress_callback

a SoupSessionConnectProgressCallback which +will be called for every network event that occurs during the connection.

[allow-none][scope async]

callback

the callback to invoke when the operation finishes.

[allow-none][scope async]

user_data

data for progress_callback +and callback +

 
+
+

Since: 2.62

+
+
+
+

soup_session_connect_finish ()

+
GIOStream *
+soup_session_connect_finish (SoupSession *session,
+                             GAsyncResult *result,
+                             GError **error);
+

Gets the GIOStream created for the connection to communicate with the server.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

session

a SoupSession

 

result

the GAsyncResult passed to your callback

 

error

return location for a GError, or NULL

 
+
+
+

Returns

+

a new GIOStream, or NULL on error.

+

[transfer full]

+
+

Since: 2.62

+
+
+
+

Types and Values

+
+

SoupSession

+
typedef struct _SoupSession SoupSession;
+
+
+
+

enum SoupRequestError

+

A SoupRequest error.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

SOUP_REQUEST_ERROR_BAD_URI

+

the URI could not be parsed

+
 

SOUP_REQUEST_ERROR_UNSUPPORTED_URI_SCHEME

+

the URI scheme is not + supported by this SoupSession

+
 

SOUP_REQUEST_ERROR_PARSING

+

the server's response could not + be parsed

+
 

SOUP_REQUEST_ERROR_ENCODING

+

the server's response was in an + unsupported format

+
 
+
+

Since: 2.42

+
+
+
+

SOUP_REQUEST_ERROR

+
#define SOUP_REQUEST_ERROR soup_request_error_quark ()
+
+

A GError domain for SoupRequest-related errors. Used with +SoupRequestError.

+

Since: 2.42

+
+
+
+

SOUP_SESSION_PROXY_URI

+
#define SOUP_SESSION_PROXY_URI              "proxy-uri"
+
+

Alias for the “proxy-uri” property, qv.

+
+
+
+

SOUP_SESSION_PROXY_RESOLVER

+
#define SOUP_SESSION_PROXY_RESOLVER         "proxy-resolver"
+
+

Alias for the “proxy-resolver” property, qv.

+
+
+
+

SOUP_SESSION_MAX_CONNS

+
#define SOUP_SESSION_MAX_CONNS              "max-conns"
+
+

Alias for the “max-conns” property, qv.

+
+
+
+

SOUP_SESSION_MAX_CONNS_PER_HOST

+
#define SOUP_SESSION_MAX_CONNS_PER_HOST     "max-conns-per-host"
+
+

Alias for the “max-conns-per-host” property, qv.

+
+
+
+

SOUP_SESSION_TLS_DATABASE

+
#define SOUP_SESSION_TLS_DATABASE           "tls-database"
+
+

Alias for the “tls-database” property, qv.

+

Since: 2.38

+
+
+
+

SOUP_SESSION_SSL_USE_SYSTEM_CA_FILE

+
#define SOUP_SESSION_SSL_USE_SYSTEM_CA_FILE "ssl-use-system-ca-file"
+
+

Alias for the “ssl-use-system-ca-file” property, +qv.

+

Since: 2.38

+
+
+
+

SOUP_SESSION_SSL_CA_FILE

+
#define SOUP_SESSION_SSL_CA_FILE            "ssl-ca-file"
+
+

Alias for the “ssl-ca-file” property, qv.

+
+
+
+

SOUP_SESSION_SSL_STRICT

+
#define SOUP_SESSION_SSL_STRICT             "ssl-strict"
+
+

Alias for the “ssl-strict” property, qv.

+

Since: 2.30

+
+
+
+

SOUP_SESSION_TLS_INTERACTION

+
#define SOUP_SESSION_TLS_INTERACTION        "tls-interaction"
+
+

Alias for the “tls-interaction” property, qv.

+

Since: 2.48

+
+
+
+

SOUP_SESSION_ASYNC_CONTEXT

+
#define SOUP_SESSION_ASYNC_CONTEXT          "async-context"
+
+

Alias for the “async-context” property, qv.

+
+
+
+

SOUP_SESSION_USE_THREAD_CONTEXT

+
#define SOUP_SESSION_USE_THREAD_CONTEXT     "use-thread-context"
+
+

Alias for the “use-thread-context” property, qv.

+

Since: 2.38

+
+
+
+

SOUP_SESSION_TIMEOUT

+
#define SOUP_SESSION_TIMEOUT                "timeout"
+
+

Alias for the “timeout” property, qv.

+
+
+
+

SOUP_SESSION_IDLE_TIMEOUT

+
#define SOUP_SESSION_IDLE_TIMEOUT           "idle-timeout"
+
+

Alias for the “idle-timeout” property, qv.

+

Since: 2.24

+
+
+
+

SOUP_SESSION_USER_AGENT

+
#define SOUP_SESSION_USER_AGENT             "user-agent"
+
+

Alias for the “user-agent” property, qv.

+
+
+
+

SOUP_SESSION_ADD_FEATURE

+
#define SOUP_SESSION_ADD_FEATURE            "add-feature"
+
+

Alias for the “add-feature” property, qv.

+

Since: 2.24

+
+
+
+

SOUP_SESSION_ADD_FEATURE_BY_TYPE

+
#define SOUP_SESSION_ADD_FEATURE_BY_TYPE    "add-feature-by-type"
+
+

Alias for the “add-feature-by-type” property, qv.

+

Since: 2.24

+
+
+
+

SOUP_SESSION_REMOVE_FEATURE_BY_TYPE

+
#define SOUP_SESSION_REMOVE_FEATURE_BY_TYPE "remove-feature-by-type"
+
+

Alias for the “remove-feature-by-type” property, +qv.

+

Since: 2.24

+
+
+
+

SOUP_SESSION_ACCEPT_LANGUAGE

+
#define SOUP_SESSION_ACCEPT_LANGUAGE        "accept-language"
+
+

Alias for the “accept-language” property, qv.

+

Since: 2.30

+
+
+
+

SOUP_SESSION_ACCEPT_LANGUAGE_AUTO

+
#define SOUP_SESSION_ACCEPT_LANGUAGE_AUTO   "accept-language-auto"
+
+

Alias for the “accept-language-auto” property, qv.

+

Since: 2.30

+
+
+
+

SOUP_SESSION_HTTP_ALIASES

+
#define SOUP_SESSION_HTTP_ALIASES       "http-aliases"
+
+

Alias for the “http-aliases” property, qv.

+

Since: 2.38

+
+
+
+

SOUP_SESSION_HTTPS_ALIASES

+
#define SOUP_SESSION_HTTPS_ALIASES      "https-aliases"
+
+

Alias for the “https-aliases” property, qv.

+

Since: 2.38

+
+
+
+

SOUP_SESSION_LOCAL_ADDRESS

+
#define SOUP_SESSION_LOCAL_ADDRESS          "local-address"
+
+

Alias for the “local-address” property, qv.

+

Since: 2.42

+
+
+
+

Property Details

+
+

The “accept-language” property

+
  “accept-language”          gchar *
+

If non-NULL, the value to use for the "Accept-Language" header +on SoupMessages sent from this session.

+

Setting this will disable +“accept-language-auto”.

+

Flags: Read / Write

+

Default value: NULL

+

Since: 2.30

+
+
+
+

The “accept-language-auto” property

+
  “accept-language-auto”     gboolean
+

If TRUE, SoupSession will automatically set the string +for the "Accept-Language" header on every SoupMessage +sent, based on the return value of g_get_language_names().

+

Setting this will override any previous value of +“accept-language”.

+

Flags: Read / Write

+

Default value: FALSE

+

Since: 2.30

+
+
+
+

The “add-feature” property

+
  “add-feature”              SoupSessionFeature *
+

Add a feature object to the session. (Shortcut for calling +soup_session_add_feature().)

+

[skip]

+

Flags: Read / Write

+

Since: 2.24

+
+
+
+

The “add-feature-by-type” property

+
  “add-feature-by-type”      GType *
+

Add a feature object of the given type to the session. +(Shortcut for calling soup_session_add_feature_by_type().)

+

[skip]

+

Flags: Read / Write

+

Allowed values: GObject

+

Since: 2.24

+
+
+
+

The “async-context” property

+
  “async-context”            gpointer
+

The GMainContext that miscellaneous session-related +asynchronous callbacks are invoked on. (Eg, setting +“idle-timeout” will add a timeout source on this +context.)

+

For a plain SoupSession, this property is always set to +the GMainContext that is the thread-default at the time +the session was created, and cannot be overridden. For the +deprecated SoupSession subclasses, the default value is +NULL, meaning to use the global default GMainContext.

+

If “use-thread-context” is FALSE, this context +will also be used for asynchronous HTTP I/O.

+

Flags: Read / Write / Construct Only

+
+
+
+

The “http-aliases” property

+
  “http-aliases”             GStrv
+

A NULL-terminated array of URI schemes that should be +considered to be aliases for "http". Eg, if this included +"dav", than a URI of +dav://example.com/path would be treated +identically to http://example.com/path.

+

In a plain SoupSession, the default value is NULL, +meaning that only "http" is recognized as meaning "http". +In SoupSessionAsync and SoupSessionSync, for backward +compatibility, the default value is an array containing the +single element "*", a special value +which means that any scheme except "https" is considered to +be an alias for "http".

+

See also “https-aliases”.

+

Flags: Read / Write

+

Since: 2.38

+
+
+
+

The “https-aliases” property

+
  “https-aliases”            GStrv
+

A comma-delimited list of URI schemes that should be +considered to be aliases for "https". See +“http-aliases” for more information.

+

The default value is NULL, meaning that no URI schemes +are considered aliases for "https".

+

Flags: Read / Write

+

Since: 2.38

+
+
+
+

The “idle-timeout” property

+
  “idle-timeout”             guint
+

Connection lifetime (in seconds) when idle. Any connection +left idle longer than this will be closed.

+

Although you can change this property at any time, it will +only affect newly-created connections, not currently-open +ones. You can call soup_session_abort() after setting this +if you want to ensure that all future connections will have +this timeout value.

+

Note that the default value of 60 seconds only applies to +plain SoupSessions. If you are using SoupSessionAsync or +SoupSessionSync, the default value is 0 (meaning idle +connections will never time out).

+

Flags: Read / Write

+

Default value: 60

+

Since: 2.24

+
+
+
+

The “local-address” property

+
  “local-address”            SoupAddress *
+

Sets the SoupAddress to use for the client side of +the connection.

+

Use this property if you want for instance to bind the +local socket to a specific IP address.

+

Flags: Read / Write / Construct Only

+

Since: 2.42

+
+
+
+

The “max-conns” property

+
  “max-conns”                gint
+

The maximum number of connections that the session can open at once.

+

Flags: Read / Write

+

Allowed values: >= 1

+

Default value: 10

+
+
+
+

The “max-conns-per-host” property

+
  “max-conns-per-host”       gint
+

The maximum number of connections that the session can open at once to a given host.

+

Flags: Read / Write

+

Allowed values: >= 1

+

Default value: 2

+
+
+
+

The “proxy-resolver” property

+
  “proxy-resolver”           GProxyResolver *
+

A GProxyResolver to use with this session. Setting this +will clear the “proxy-uri” property, and remove +any SoupProxyURIResolver features that have +been added to the session.

+

By default, in a plain SoupSession, this is set to the +default GProxyResolver, but you can set it to NULL if you +don't want to use proxies, or set it to your own +GProxyResolver if you want to control what proxies get +used.

+

Flags: Read / Write

+

Since: 2.42

+
+
+
+

The “proxy-uri” property

+
  “proxy-uri”                SoupURI *
+

A proxy to use for all http and https requests in this +session. Setting this will clear the +“proxy-resolver” property, and remove any

+SoupProxyURIResolver features that have been +

added to the session. Setting this property will also +cancel all currently pending messages.

+

Note that SoupSession will normally handle looking up the +user's proxy settings for you; you should only use +“proxy-uri” if you need to override the user's +normal proxy settings.

+

Also note that this proxy will be used for +all requests; even requests to +localhost. If you need more control over +proxies, you can create a GSimpleProxyResolver and set the +“proxy-resolver” property.

+

Flags: Read / Write

+
+
+
+

The “remove-feature-by-type” property

+
  “remove-feature-by-type”   GType *
+

Remove feature objects from the session. (Shortcut for +calling soup_session_remove_feature_by_type().)

+

[skip]

+

Flags: Read / Write

+

Allowed values: GObject

+

Since: 2.24

+
+
+
+

The “ssl-ca-file” property

+
  “ssl-ca-file”              gchar *
+

File containing SSL CA certificates.

+

If the specified file does not exist or cannot be read, +then libsoup will print a warning, and then behave as +though it had read in a empty CA file, meaning that all SSL +certificates will be considered invalid.

+
+

SoupSession:ssl-ca-file is deprecated and should not be used in newly-written code.

+

use “ssl-use-system-ca-file”, or +else “tls-database” with a GTlsFileDatabase +(which allows you to do explicit error handling).

+
+

Flags: Read / Write

+

Default value: NULL

+
+
+
+

The “ssl-strict” property

+
  “ssl-strict”               gboolean
+

Normally, if “tls-database” is set (including if +it was set via “ssl-use-system-ca-file” or +“ssl-ca-file”), then libsoup will reject any +certificate that is invalid (ie, expired) or that is not +signed by one of the given CA certificates, and the +SoupMessage will fail with the status +SOUP_STATUS_SSL_FAILED.

+

If you set “ssl-strict” to FALSE, then all +certificates will be accepted, and you will need to call +soup_message_get_https_status() to distinguish valid from +invalid certificates. (This can be used, eg, if you want to +accept invalid certificates after giving some sort of +warning.)

+

For a plain SoupSession, if the session has no CA file or +TLS database, and this property is TRUE, then all +certificates will be rejected. However, beware that the +deprecated SoupSession subclasses (SoupSessionAsync and +SoupSessionSync) have the opposite behavior: if there is +no CA file or TLS database, then all certificates are always +accepted, and this property has no effect.

+

Flags: Read / Write

+

Default value: TRUE

+

Since: 2.30

+
+
+
+

The “ssl-use-system-ca-file” property

+
  “ssl-use-system-ca-file”   gboolean
+

Setting this to TRUE is equivalent to setting +“tls-database” to the default system CA database. +(and likewise, setting “tls-database” to the +default database by hand will cause this property to +become TRUE).

+

Setting this to FALSE (when it was previously TRUE) will +clear the “tls-database” field.

+

See “ssl-strict” for more information on how +https certificate validation is handled.

+

Note that the default value of TRUE only applies to plain +SoupSessions. If you are using SoupSessionAsync or +SoupSessionSync, the default value is FALSE, for backward +compatibility.

+

Flags: Read / Write

+

Default value: TRUE

+

Since: 2.38

+
+
+
+

The “timeout” property

+
  “timeout”                  guint
+

The timeout (in seconds) for socket I/O operations +(including connecting to a server, and waiting for a reply +to an HTTP request).

+

Although you can change this property at any time, it will +only affect newly-created connections, not currently-open +ones. You can call soup_session_abort() after setting this +if you want to ensure that all future connections will have +this timeout value.

+

Note that the default value of 60 seconds only applies to +plain SoupSessions. If you are using SoupSessionAsync or +SoupSessionSync, the default value is 0 (meaning socket I/O +will not time out).

+

Not to be confused with “idle-timeout” (which is +the length of time that idle persistent connections will be +kept open).

+

Flags: Read / Write

+

Default value: 0

+
+
+
+

The “tls-database” property

+
  “tls-database”             GTlsDatabase *
+

Sets the GTlsDatabase to use for validating SSL/TLS +certificates.

+

Note that setting the “ssl-ca-file” or +“ssl-use-system-ca-file” property will cause +this property to be set to a GTlsDatabase corresponding to +the indicated file or system default.

+

See “ssl-strict” for more information on how +https certificate validation is handled.

+

If you are using a plain SoupSession then +“ssl-use-system-ca-file” will be TRUE by +default, and so this property will be a copy of the system +CA database. If you are using SoupSessionAsync or +SoupSessionSync, this property will be NULL by default.

+

Flags: Read / Write

+

Since: 2.38

+
+
+
+

The “tls-interaction” property

+
  “tls-interaction”          GTlsInteraction *
+

A GTlsInteraction object that will be passed on to any +GTlsConnections created by the session. (This can be used to +provide client-side certificates, for example.)

+

Flags: Read / Write

+

Since: 2.48

+
+
+
+

The “use-ntlm” property

+
  “use-ntlm”                 gboolean
+

Whether or not to use NTLM authentication.

+
+

SoupSession:use-ntlm is deprecated and should not be used in newly-written code.

+

use soup_session_add_feature_by_type() with +SOUP_TYPE_AUTH_NTLM.

+
+

Flags: Read / Write

+

Default value: FALSE

+
+
+
+

The “use-thread-context” property

+
  “use-thread-context”       gboolean
+

If TRUE (which it always is on a plain SoupSession), +asynchronous HTTP requests in this session will run in +whatever the thread-default GMainContext is at the time +they are started, rather than always occurring in +“async-context”.

+

Flags: Read / Write

+

Default value: FALSE

+

Since: 2.38

+
+
+
+

The “user-agent” property

+
  “user-agent”               gchar *
+

If non-NULL, the value to use for the "User-Agent" header +on SoupMessages sent from this session.

+

RFC 2616 says: "The User-Agent request-header field +contains information about the user agent originating the +request. This is for statistical purposes, the tracing of +protocol violations, and automated recognition of user +agents for the sake of tailoring responses to avoid +particular user agent limitations. User agents SHOULD +include this field with requests."

+

The User-Agent header contains a list of one or more +product tokens, separated by whitespace, with the most +significant product token coming first. The tokens must be +brief, ASCII, and mostly alphanumeric (although "-", "_", +and "." are also allowed), and may optionally include a "/" +followed by a version string. You may also put comments, +enclosed in parentheses, between or after the tokens.

+

If you set a “user_agent” property that has trailing +whitespace, SoupSession will append its own product token +(eg, "libsoup/2.3.2") to the end of the +header for you.

+

Flags: Read / Write

+

Default value: NULL

+
+
+
+

Signal Details

+
+

The “authenticate” signal

+
void
+user_function (SoupSession *session,
+               SoupMessage *msg,
+               SoupAuth    *auth,
+               gboolean     retrying,
+               gpointer     user_data)
+

Emitted when the session requires authentication. If +credentials are available call soup_auth_authenticate() on +auth +. If these credentials fail, the signal will be +emitted again, with retrying + set to TRUE, which will +continue until you return without calling +soup_auth_authenticate() on auth +.

+

Note that this may be emitted before msg +'s body has been +fully read.

+

If you call soup_session_pause_message() on msg + before +returning, then you can authenticate auth + asynchronously +(as long as you g_object_ref() it to make sure it doesn't +get destroyed), and then unpause msg + when you are ready +for it to continue.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

session

the session

 

msg

the SoupMessage being sent

 

auth

the SoupAuth to authenticate

 

retrying

TRUE if this is the second (or later) attempt

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+
+
+
+

The “connection-created” signal

+
void
+user_function (SoupSession *session,
+               GObject     *connection,
+               gpointer     user_data)
+

Emitted when a new connection is created. This is an +internal signal intended only to be used for debugging +purposes, and may go away in the future.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

session

the SoupSession

 

connection

the connection

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+

Since: 2.30

+
+
+
+

The “request-queued” signal

+
void
+user_function (SoupSession *session,
+               SoupMessage *msg,
+               gpointer     user_data)
+

Emitted when a request is queued on session +. (Note that +"queued" doesn't just mean soup_session_queue_message(); +soup_session_send_message() implicitly queues the message +as well.)

+

When sending a request, first “request_queued” +is emitted, indicating that the session has become aware of +the request.

+

Once a connection is available to send the request on, the +session emits “request_started”. Then, various +SoupMessage signals are emitted as the message is +processed. If the message is requeued, it will emit +“restarted”, which will then be followed by +another “request_started” and another set of +SoupMessage signals when the message is re-sent.

+

Eventually, the message will emit “finished”. +Normally, this signals the completion of message +processing. However, it is possible that the application +will requeue the message from the "finished" handler (or +equivalently, from the soup_session_queue_message() +callback). In that case, the process will loop back to +“request_started”.

+

Eventually, a message will reach "finished" and not be +requeued. At that point, the session will emit +“request_unqueued” to indicate that it is done +with the message.

+

To sum up: “request_queued” and +“request_unqueued” are guaranteed to be emitted +exactly once, but “request_started” and +“finished” (and all of the other SoupMessage +signals) may be invoked multiple times for a given message.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

session

the session

 

msg

the request that was queued

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+

Since: 2.24

+
+
+
+

The “request-started” signal

+
void
+user_function (SoupSession *session,
+               SoupMessage *msg,
+               SoupSocket  *socket,
+               gpointer     user_data)
+

Emitted just before a request is sent. See +“request_queued” for a detailed description of +the message lifecycle within a session.

+
+

SoupSession::request-started has been deprecated since version 2.50. and should not be used in newly-written code.

+

Use “starting” instead.

+
+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

session

the session

 

msg

the request being sent

 

socket

the socket the request is being sent on

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+
+
+
+

The “request-unqueued” signal

+
void
+user_function (SoupSession *session,
+               SoupMessage *msg,
+               gpointer     user_data)
+

Emitted when a request is removed from session +'s queue, +indicating that session + is done with it. See +“request_queued” for a detailed description of the +message lifecycle within a session.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

session

the session

 

msg

the request that was unqueued

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+

Since: 2.24

+
+
+
+

The “tunneling” signal

+
void
+user_function (SoupSession *session,
+               GObject     *connection,
+               gpointer     user_data)
+

Emitted when an SSL tunnel is being created on a proxy +connection. This is an internal signal intended only to be +used for debugging purposes, and may go away in the future.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

session

the SoupSession

 

connection

the connection

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+

Since: 2.30

+
+
+
+ + + \ No newline at end of file diff --git a/docs/reference/html/SoupSessionAsync.html b/docs/reference/html/SoupSessionAsync.html new file mode 100644 index 0000000..bf1ce9f --- /dev/null +++ b/docs/reference/html/SoupSessionAsync.html @@ -0,0 +1,81 @@ + + + + +SoupSessionAsync: libsoup Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

SoupSessionAsync

+

SoupSessionAsync — SoupSession for asynchronous (main-loop-based) I/O +(deprecated).

+
+
+

Types and Values

+
++++ + + + + +
 SoupSessionAsync
+
+
+

Object Hierarchy

+
    GObject
+    ╰── SoupSession
+        ╰── SoupSessionAsync
+
+
+
+

Includes

+
#include <libsoup/soup.h>
+
+
+
+

Description

+

SoupSessionAsync is an implementation of SoupSession that uses +non-blocking I/O via the glib main loop for all I/O.

+
+
+

Functions

+

+
+
+

Types and Values

+
+

SoupSessionAsync

+
typedef struct _SoupSessionAsync SoupSessionAsync;
+
+
+
+ + + \ No newline at end of file diff --git a/docs/reference/html/SoupSessionFeature.html b/docs/reference/html/SoupSessionFeature.html new file mode 100644 index 0000000..01bd008 --- /dev/null +++ b/docs/reference/html/SoupSessionFeature.html @@ -0,0 +1,197 @@ + + + + +SoupSessionFeature: libsoup Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

SoupSessionFeature

+

SoupSessionFeature — Interface for miscellaneous session features

+
+
+

Types and Values

+
++++ + + + + + + + + + + +
 SoupSessionFeature
 SoupSessionFeatureInterface
+
+
+

Object Hierarchy

+
    GInterface
+    ╰── SoupSessionFeature
+
+
+
+

Prerequisites

+

+SoupSessionFeature requires + GObject.

+
+ +
+

Includes

+
#include <libsoup/soup.h>
+
+
+
+

Description

+

SoupSessionFeature is the interface used by classes that extend +the functionality of a SoupSession. Some features like HTTP +authentication handling are implemented internally via +SoupSessionFeatures. Other features can be added to the session +by the application. (Eg, SoupLogger, SoupCookieJar.)

+

See soup_session_add_feature(), etc, to add a feature to a session.

+
+
+

Functions

+

+
+
+

Types and Values

+
+

SoupSessionFeature

+
typedef struct _SoupSessionFeature SoupSessionFeature;
+

An object that implement some sort of optional feature for +SoupSession.

+

Since: 2.24

+
+
+
+

SoupSessionFeatureInterface

+
typedef struct {
+	GTypeInterface parent;
+
+	/* methods */
+	void     (*attach)           (SoupSessionFeature *feature,
+				      SoupSession        *session);
+	void     (*detach)           (SoupSessionFeature *feature,
+				      SoupSession        *session);
+
+	void     (*request_queued)   (SoupSessionFeature *feature,
+				      SoupSession        *session,
+				      SoupMessage        *msg);
+	void     (*request_started)  (SoupSessionFeature *feature,
+				      SoupSession        *session,
+				      SoupMessage        *msg,
+				      SoupSocket         *socket);
+	void     (*request_unqueued) (SoupSessionFeature *feature,
+				      SoupSession        *session,
+				      SoupMessage        *msg);
+
+	gboolean (*add_feature)      (SoupSessionFeature *feature,
+				      GType               type);
+	gboolean (*remove_feature)   (SoupSessionFeature *feature,
+				      GType               type);
+	gboolean (*has_feature)      (SoupSessionFeature *feature,
+				      GType               type);
+} SoupSessionFeatureInterface;
+
+

The interface implemented by SoupSessionFeatures.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GTypeInterface parent;

The parent interface.

 

attach ()

Perform setup when a feature is added to a session

 

detach ()

Perform cleanup when a feature is removed from a session

 

request_queued ()

Proxies the session's “request_queued” signal

 

request_started ()

Proxies the session's “request_started” signal. Deprecated 2.50. Use “starting” instead.

 

request_unqueued ()

Proxies the session's “request_unqueued” signal

 

add_feature ()

adds a sub-feature to the main feature

 

remove_feature ()

removes a sub-feature from the main feature

 

has_feature ()

tests if the feature includes a sub-feature

 
+
+

Since: 2.24

+
+
+
+ + + \ No newline at end of file diff --git a/docs/reference/html/SoupSessionSync.html b/docs/reference/html/SoupSessionSync.html new file mode 100644 index 0000000..b9d6f14 --- /dev/null +++ b/docs/reference/html/SoupSessionSync.html @@ -0,0 +1,81 @@ + + + + +SoupSessionSync: libsoup Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

SoupSessionSync

+

SoupSessionSync — SoupSession for blocking I/O in multithreaded programs +(deprecated).

+
+
+

Types and Values

+
++++ + + + + +
 SoupSessionSync
+
+
+

Object Hierarchy

+
    GObject
+    ╰── SoupSession
+        ╰── SoupSessionSync
+
+
+
+

Includes

+
#include <libsoup/soup.h>
+
+
+
+

Description

+

SoupSessionSync is an implementation of SoupSession that uses +synchronous I/O, intended for use in multi-threaded programs.

+
+
+

Functions

+

+
+
+

Types and Values

+
+

SoupSessionSync

+
typedef struct _SoupSessionSync SoupSessionSync;
+
+
+
+ + + \ No newline at end of file diff --git a/docs/reference/html/SoupSocket.html b/docs/reference/html/SoupSocket.html new file mode 100644 index 0000000..59807f3 --- /dev/null +++ b/docs/reference/html/SoupSocket.html @@ -0,0 +1,1624 @@ + + + + +SoupSocket: libsoup Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

SoupSocket

+

SoupSocket — A network socket

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+SoupSocket * + +soup_socket_new () +
+void + +(*SoupSocketCallback) () +
+void + +soup_socket_connect_async () +
+guint + +soup_socket_connect_sync () +
+gboolean + +soup_socket_listen () +
+gboolean + +soup_socket_start_ssl () +
+gboolean + +soup_socket_start_proxy_ssl () +
+gboolean + +soup_socket_is_ssl () +
+void + +soup_socket_disconnect () +
+gboolean + +soup_socket_is_connected () +
+SoupAddress * + +soup_socket_get_local_address () +
+SoupAddress * + +soup_socket_get_remote_address () +
+int + +soup_socket_get_fd () +
+SoupSocketIOStatus + +soup_socket_read () +
+SoupSocketIOStatus + +soup_socket_read_until () +
+SoupSocketIOStatus + +soup_socket_write () +
+
+
+

Properties

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
gpointerasync-contextRead / Write / Construct Only
gintfdRead / Write / Construct Only
+GSocket *gsocketWrite / Construct Only
+GIOStream *iostreamWrite / Construct Only
gbooleanipv6-onlyRead / Write
gbooleanis-serverRead
+SoupAddress *local-addressRead / Write / Construct Only
gbooleannon-blockingRead / Write
+SoupAddress *remote-addressRead / Write / Construct Only
+SoupSocketProperties *socket-propertiesWrite
gpointerssl-credsRead / Write
gbooleanssl-fallbackRead / Write / Construct Only
gbooleanssl-strictRead / Write / Construct Only
guinttimeoutRead / Write
+GTlsCertificate *tls-certificateRead
GTlsCertificateFlagstls-errorsRead
gbooleantrusted-certificateRead
gbooleanuse-thread-contextRead / Write / Construct Only
+
+
+

Signals

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
voiddisconnectedRun Last
voideventRun Last
voidnew-connectionRun First
voidreadableRun Last
voidwritableRun Last
+
+
+

Types and Values

+ +
+
+

Object Hierarchy

+
    GObject
+    ╰── SoupSocket
+
+
+
+

Implemented Interfaces

+

+SoupSocket implements + GInitable.

+
+
+

Includes

+
#include <libsoup/soup.h>
+
+
+
+

Description

+

SoupSocket is libsoup's TCP socket type. While it is primarily +intended for internal use, SoupSockets are exposed in the +API in various places, and some of their methods (eg, +soup_socket_get_remote_address()) may be useful to applications.

+
+
+

Functions

+
+

soup_socket_new ()

+
SoupSocket *
+soup_socket_new (const char *optname1,
+                 ...);
+

Creates a new (disconnected) socket

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

optname1

name of first property to set (or NULL)

 

...

value of optname1 +, followed by additional property/value pairs

 
+
+
+

Returns

+

the new socket

+
+
+
+
+

SoupSocketCallback ()

+
void
+(*SoupSocketCallback) (SoupSocket *sock,
+                       guint status,
+                       gpointer user_data);
+

The callback function passed to soup_socket_connect_async().

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

sock

the SoupSocket

 

status

an HTTP status code indicating success or failure

 

user_data

the data passed to soup_socket_connect_async()

 
+
+
+
+
+

soup_socket_connect_async ()

+
void
+soup_socket_connect_async (SoupSocket *sock,
+                           GCancellable *cancellable,
+                           SoupSocketCallback callback,
+                           gpointer user_data);
+

Begins asynchronously connecting to sock +'s remote address. The +socket will call callback + when it succeeds or fails (but not +before returning from this function).

+

If cancellable + is non-NULL, it can be used to cancel the +connection. callback + will still be invoked in this case, with a +status of SOUP_STATUS_CANCELLED.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

sock

a client SoupSocket (which must not already be connected)

 

cancellable

a GCancellable, or NULL

 

callback

callback to call after connecting.

[scope async]

user_data

data to pass to callback +

 
+
+
+
+
+

soup_socket_connect_sync ()

+
guint
+soup_socket_connect_sync (SoupSocket *sock,
+                          GCancellable *cancellable);
+

Attempt to synchronously connect sock + to its remote address.

+

If cancellable + is non-NULL, it can be used to cancel the +connection, in which case soup_socket_connect_sync() will return +SOUP_STATUS_CANCELLED.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

sock

a client SoupSocket (which must not already be connected)

 

cancellable

a GCancellable, or NULL

 
+
+
+

Returns

+

a success or failure code.

+
+
+
+
+

soup_socket_listen ()

+
gboolean
+soup_socket_listen (SoupSocket *sock);
+

Makes sock + start listening on its local address. When connections +come in, sock + will emit “new_connection”.

+
+

Parameters

+
+++++ + + + + + +

sock

a server SoupSocket (which must not already be connected or +listening)

 
+
+
+

Returns

+

whether or not sock +is now listening.

+
+
+
+
+

soup_socket_start_ssl ()

+
gboolean
+soup_socket_start_ssl (SoupSocket *sock,
+                       GCancellable *cancellable);
+

Starts using SSL on socket +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

sock

the socket

 

cancellable

a GCancellable

 
+
+
+

Returns

+

success or failure

+
+
+
+
+

soup_socket_start_proxy_ssl ()

+
gboolean
+soup_socket_start_proxy_ssl (SoupSocket *sock,
+                             const char *ssl_host,
+                             GCancellable *cancellable);
+

Starts using SSL on socket +, expecting to find a host named +ssl_host +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

sock

the socket

 

ssl_host

hostname of the SSL server

 

cancellable

a GCancellable

 
+
+
+

Returns

+

success or failure

+
+
+
+
+

soup_socket_is_ssl ()

+
gboolean
+soup_socket_is_ssl (SoupSocket *sock);
+

Tests if sock + is doing (or has attempted to do) SSL.

+
+

Parameters

+
+++++ + + + + + +

sock

a SoupSocket

 
+
+
+

Returns

+

TRUE if sock +has SSL credentials set

+
+
+
+
+

soup_socket_disconnect ()

+
void
+soup_socket_disconnect (SoupSocket *sock);
+

Disconnects sock +. Any further read or write attempts on it will +fail.

+
+

Parameters

+
+++++ + + + + + +

sock

a SoupSocket

 
+
+
+
+
+

soup_socket_is_connected ()

+
gboolean
+soup_socket_is_connected (SoupSocket *sock);
+

Tests if sock + is connected to another host

+
+

Parameters

+
+++++ + + + + + +

sock

a SoupSocket

 
+
+
+

Returns

+

TRUE or FALSE.

+
+
+
+
+

soup_socket_get_local_address ()

+
SoupAddress *
+soup_socket_get_local_address (SoupSocket *sock);
+

Returns the SoupAddress corresponding to the local end of sock +.

+

Calling this method on an unconnected socket is considered to be +an error, and produces undefined results.

+
+

Parameters

+
+++++ + + + + + +

sock

a SoupSocket

 
+
+
+

Returns

+

the SoupAddress.

+

[transfer none]

+
+
+
+
+

soup_socket_get_remote_address ()

+
SoupAddress *
+soup_socket_get_remote_address (SoupSocket *sock);
+

Returns the SoupAddress corresponding to the remote end of sock +.

+

Calling this method on an unconnected socket is considered to be +an error, and produces undefined results.

+
+

Parameters

+
+++++ + + + + + +

sock

a SoupSocket

 
+
+
+

Returns

+

the SoupAddress.

+

[transfer none]

+
+
+
+
+

soup_socket_get_fd ()

+
int
+soup_socket_get_fd (SoupSocket *sock);
+

Gets sock +'s underlying file descriptor.

+

Note that fiddling with the file descriptor may break the +SoupSocket.

+
+

Parameters

+
+++++ + + + + + +

sock

a SoupSocket

 
+
+
+

Returns

+

sock +'s file descriptor.

+
+
+
+
+

soup_socket_read ()

+
SoupSocketIOStatus
+soup_socket_read (SoupSocket *sock,
+                  gpointer buffer,
+                  gsize len,
+                  gsize *nread,
+                  GCancellable *cancellable,
+                  GError **error);
+

Attempts to read up to len + bytes from sock + into buffer +. If some +data is successfully read, soup_socket_read() will return +SOUP_SOCKET_OK, and *nread + will contain the number of bytes +actually read (which may be less than len +).

+

If sock + is non-blocking, and no data is available, the return +value will be SOUP_SOCKET_WOULD_BLOCK. In this case, the caller +can connect to the “readable” signal to know when there +is more data to read. (NB: You MUST read all available data off the +socket first. “readable” is only emitted after +soup_socket_read() returns SOUP_SOCKET_WOULD_BLOCK, and it is only +emitted once. See the documentation for “non-blocking”.)

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

sock

the socket

 

buffer

buffer to read +into.

[array length=len][element-type guint8]

len

size of buffer +in bytes

 

nread

on return, the number of bytes read into buffer +.

[out]

cancellable

a GCancellable, or NULL

 

error

error pointer

 
+
+
+

Returns

+

a SoupSocketIOStatus, as described above (or +SOUP_SOCKET_EOF if the socket is no longer connected, or +SOUP_SOCKET_ERROR on any other error, in which case error +will +also be set).

+
+
+
+
+

soup_socket_read_until ()

+
SoupSocketIOStatus
+soup_socket_read_until (SoupSocket *sock,
+                        gpointer buffer,
+                        gsize len,
+                        gconstpointer boundary,
+                        gsize boundary_len,
+                        gsize *nread,
+                        gboolean *got_boundary,
+                        GCancellable *cancellable,
+                        GError **error);
+

Like soup_socket_read(), but reads no further than the first +occurrence of boundary +. (If the boundary is found, it will be +included in the returned data, and *got_boundary + will be set to +TRUE.) Any data after the boundary will returned in future reads.

+

soup_socket_read_until() will almost always return fewer than len + +bytes: if the boundary is found, then it will only return the bytes +up until the end of the boundary, and if the boundary is not found, +then it will leave the last (boundary_len - 1) +bytes in its internal buffer, in case they form the start of the +boundary string. Thus, len + normally needs to be at least 1 byte +longer than boundary_len + if you want to make any progress at all.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

sock

the socket

 

buffer

buffer to read +into.

[array length=len][element-type guint8]

len

size of buffer +in bytes

 

boundary

boundary to read until

 

boundary_len

length of boundary +in bytes

 

nread

on return, the number of bytes read into buffer +.

[out]

got_boundary

on return, whether or not the data in buffer +ends with the boundary string

 

cancellable

a GCancellable, or NULL

 

error

error pointer

 
+
+
+

Returns

+

as for soup_socket_read()

+
+
+
+
+

soup_socket_write ()

+
SoupSocketIOStatus
+soup_socket_write (SoupSocket *sock,
+                   gconstpointer buffer,
+                   gsize len,
+                   gsize *nwrote,
+                   GCancellable *cancellable,
+                   GError **error);
+

Attempts to write len + bytes from buffer + to sock +. If some data is +successfully written, the return status will be SOUP_SOCKET_OK, +and *nwrote + will contain the number of bytes actually written +(which may be less than len +).

+

If sock + is non-blocking, and no data could be written right away, +the return value will be SOUP_SOCKET_WOULD_BLOCK. In this case, +the caller can connect to the “writable” signal to know +when more data can be written. (NB: “writable” is only +emitted after soup_socket_write() returns SOUP_SOCKET_WOULD_BLOCK, +and it is only emitted once. See the documentation for +“non-blocking”.)

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

sock

the socket

 

buffer

data to write.

[array length=len][element-type guint8]

len

size of buffer +, in bytes

 

nwrote

on return, number of bytes written.

[out]

cancellable

a GCancellable, or NULL

 

error

error pointer

 
+
+
+

Returns

+

a SoupSocketIOStatus, as described above (or +SOUP_SOCKET_EOF or SOUP_SOCKET_ERROR. error +will be set if the +return value is SOUP_SOCKET_ERROR.)

+
+
+
+
+

Types and Values

+
+

SoupSocket

+
typedef struct _SoupSocket SoupSocket;
+
+
+
+

enum SoupSocketIOStatus

+

Return value from the SoupSocket IO methods.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

SOUP_SOCKET_OK

+

Success

+
 

SOUP_SOCKET_WOULD_BLOCK

+

Cannot read/write any more at this time

+
 

SOUP_SOCKET_EOF

+

End of file

+
 

SOUP_SOCKET_ERROR

+

Other error

+
 
+
+
+
+
+

SOUP_SOCKET_LOCAL_ADDRESS

+
#define SOUP_SOCKET_LOCAL_ADDRESS       "local-address"
+
+

Alias for the “local-address” property. (Address +of local end of socket.)

+
+
+
+

SOUP_SOCKET_REMOTE_ADDRESS

+
#define SOUP_SOCKET_REMOTE_ADDRESS      "remote-address"
+
+

Alias for the “remote-address” property. (Address +of remote end of socket.)

+
+
+
+

SOUP_SOCKET_FLAG_NONBLOCKING

+
#define SOUP_SOCKET_FLAG_NONBLOCKING    "non-blocking"
+
+

Alias for the “non-blocking” property. (Whether +or not the socket uses non-blocking I/O.)

+
+
+
+

SOUP_SOCKET_IS_SERVER

+
#define SOUP_SOCKET_IS_SERVER           "is-server"
+
+

Alias for the “is-server” property, qv.

+
+
+
+

SOUP_SOCKET_SSL_CREDENTIALS

+
#define SOUP_SOCKET_SSL_CREDENTIALS     "ssl-creds"
+
+

Alias for the “ssl-creds” property. +(SSL credential information.)

+
+
+
+

SOUP_SOCKET_ASYNC_CONTEXT

+
#define SOUP_SOCKET_ASYNC_CONTEXT       "async-context"
+
+

Alias for the “async-context” property. (The +socket's GMainContext.)

+
+
+
+

SOUP_SOCKET_TIMEOUT

+
#define SOUP_SOCKET_TIMEOUT             "timeout"
+
+

Alias for the “timeout” property. (The timeout +in seconds for blocking socket I/O operations.)

+
+
+
+

SOUP_SOCKET_SSL_FALLBACK

+
#define SOUP_SOCKET_SSL_FALLBACK        "ssl-fallback"
+
+

Alias for the “ssl-fallback” property.

+
+
+
+

SOUP_SOCKET_SSL_STRICT

+
#define SOUP_SOCKET_SSL_STRICT          "ssl-strict"
+
+

Alias for the “ssl-strict” property.

+
+
+
+

SOUP_SOCKET_TLS_CERTIFICATE

+
#define SOUP_SOCKET_TLS_CERTIFICATE     "tls-certificate"
+
+

Alias for the “tls-certificate” +property. Note that this property's value is only useful +if the socket is for a TLS connection, and only reliable +after some data has been transferred to or from it.

+

Since: 2.34

+
+
+
+

SOUP_SOCKET_TLS_ERRORS

+
#define SOUP_SOCKET_TLS_ERRORS          "tls-errors"
+
+

Alias for the “tls-errors” +property. Note that this property's value is only useful +if the socket is for a TLS connection, and only reliable +after some data has been transferred to or from it.

+

Since: 2.34

+
+
+
+

SOUP_SOCKET_TRUSTED_CERTIFICATE

+
#define SOUP_SOCKET_TRUSTED_CERTIFICATE "trusted-certificate"
+
+

Alias for the “trusted-certificate” +property.

+
+
+
+

SOUP_SOCKET_USE_THREAD_CONTEXT

+
#define SOUP_SOCKET_USE_THREAD_CONTEXT  "use-thread-context"
+
+

Alias for the “use-thread-context” property. (Use +g_main_context_get_thread_default())

+

Since: 2.38

+
+
+
+

Property Details

+
+

The “async-context” property

+
  “async-context”            gpointer
+

The GMainContext to dispatch this socket's async I/O in.

+

Flags: Read / Write / Construct Only

+
+
+
+

The “fd” property

+
  “fd”                       gint
+

The socket's file descriptor.

+

Flags: Read / Write / Construct Only

+

Allowed values: >= -1

+

Default value: -1

+
+
+
+

The “gsocket” property

+
  “gsocket”                  GSocket *
+

The socket's underlying GSocket.

+

Flags: Write / Construct Only

+
+
+
+

The “iostream” property

+
  “iostream”                 GIOStream *
+

The socket's underlying GIOStream.

+

Flags: Write / Construct Only

+
+
+
+

The “ipv6-only” property

+
  “ipv6-only”                gboolean
+

IPv6 only.

+

Flags: Read / Write

+

Default value: FALSE

+
+
+
+

The “is-server” property

+
  “is-server”                gboolean
+

Whether or not the socket is a server socket.

+

Note that for "ordinary" SoupSockets this will be set for +both listening sockets and the sockets emitted by +“new-connection”, but for sockets created by +setting “fd”, it will only be set for listening +sockets.

+

Flags: Read

+

Default value: FALSE

+
+
+
+

The “local-address” property

+
  “local-address”            SoupAddress *
+

Address of local end of socket.

+

Flags: Read / Write / Construct Only

+
+
+
+

The “non-blocking” property

+
  “non-blocking”             gboolean
+

Whether or not the socket uses non-blocking I/O.

+

SoupSocket's I/O methods are designed around the idea of +using a single codepath for both synchronous and +asynchronous I/O. If you want to read off a SoupSocket, +the "correct" way to do it is to call soup_socket_read() or +soup_socket_read_until() repeatedly until you have read +everything you want. If it returns SOUP_SOCKET_WOULD_BLOCK +at any point, stop reading and wait for it to emit the +“readable” signal. Then go back to the +reading-as-much-as-you-can loop. Likewise, for writing to a +SoupSocket, you should call soup_socket_write() either +until you have written everything, or it returns +SOUP_SOCKET_WOULD_BLOCK (in which case you wait for +“writable” and then go back into the loop).

+

Code written this way will work correctly with both +blocking and non-blocking sockets; blocking sockets will +simply never return SOUP_SOCKET_WOULD_BLOCK, and so the +code that handles that case just won't get used for them.

+

Flags: Read / Write

+

Default value: TRUE

+
+
+
+

The “remote-address” property

+
  “remote-address”           SoupAddress *
+

Address of remote end of socket.

+

Flags: Read / Write / Construct Only

+
+
+
+

The “socket-properties” property

+
  “socket-properties”        SoupSocketProperties *
+

Socket properties.

+

Flags: Write

+
+
+
+

The “ssl-creds” property

+
  “ssl-creds”                gpointer
+

SSL credential information, passed from the session to the SSL implementation.

+

Flags: Read / Write

+
+
+
+

The “ssl-fallback” property

+
  “ssl-fallback”             gboolean
+

Use SSLv3 instead of TLS (client-side only).

+

Flags: Read / Write / Construct Only

+

Default value: FALSE

+
+
+
+

The “ssl-strict” property

+
  “ssl-strict”               gboolean
+

Whether certificate errors should be considered a connection error.

+

Flags: Read / Write / Construct Only

+

Default value: TRUE

+
+
+
+

The “timeout” property

+
  “timeout”                  guint
+

Value in seconds to timeout a blocking I/O.

+

Flags: Read / Write

+

Default value: 0

+
+
+
+

The “tls-certificate” property

+
  “tls-certificate”          GTlsCertificate *
+

The peer's TLS certificate.

+

Flags: Read

+
+
+
+

The “tls-errors” property

+
  “tls-errors”               GTlsCertificateFlags
+

Errors with the peer's TLS certificate.

+

Flags: Read

+
+
+
+

The “trusted-certificate” property

+
  “trusted-certificate”      gboolean
+

Whether the server certificate is trusted, if this is an SSL socket.

+

Flags: Read

+

Default value: FALSE

+
+
+
+

The “use-thread-context” property

+
  “use-thread-context”       gboolean
+

Use g_main_context_get_thread_default().

+

Flags: Read / Write / Construct Only

+

Default value: FALSE

+

Since: 2.38

+
+
+
+

Signal Details

+
+

The “disconnected” signal

+
void
+user_function (SoupSocket *sock,
+               gpointer    user_data)
+

Emitted when the socket is disconnected, for whatever +reason.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

sock

the socket

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run Last

+
+
+
+

The “event” signal

+
void
+user_function (SoupSocket        *sock,
+               GSocketClientEvent event,
+               GIOStream         *connection,
+               gpointer           user_data)
+

Emitted when a network-related event occurs. See +“event” for more details.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

sock

the socket

 

event

the event that occurred

 

connection

the current connection state

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run Last

+

Since: 2.38

+
+
+
+

The “new-connection” signal

+
void
+user_function (SoupSocket *sock,
+               SoupSocket *new,
+               gpointer    user_data)
+

Emitted when a listening socket (set up with +soup_socket_listen()) receives a new connection.

+

You must ref the new + if you want to keep it; otherwise it +will be destroyed after the signal is emitted.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

sock

the socket

 

new

the new socket

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+
+
+
+

The “readable” signal

+
void
+user_function (SoupSocket *sock,
+               gpointer    user_data)
+

Emitted when an async socket is readable. See +soup_socket_read(), soup_socket_read_until() and +“non-blocking”.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

sock

the socket

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run Last

+
+
+
+

The “writable” signal

+
void
+user_function (SoupSocket *sock,
+               gpointer    user_data)
+

Emitted when an async socket is writable. See +soup_socket_write() and “non-blocking”.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

sock

the socket

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run Last

+
+
+
+ + + \ No newline at end of file diff --git a/docs/reference/html/SoupURI.html b/docs/reference/html/SoupURI.html new file mode 100644 index 0000000..6c6ad71 --- /dev/null +++ b/docs/reference/html/SoupURI.html @@ -0,0 +1,1672 @@ + + + + +SoupURI: libsoup Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

SoupURI

+

SoupURI — URIs

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+SoupURI * + +soup_uri_new_with_base () +
+SoupURI * + +soup_uri_new () +
+char * + +soup_uri_to_string () +
+SoupURI * + +soup_uri_copy () +
+SoupURI * + +soup_uri_copy_host () +
+gboolean + +soup_uri_equal () +
+gboolean + +soup_uri_host_equal () +
+guint + +soup_uri_host_hash () +
+void + +soup_uri_free () +
+char * + +soup_uri_encode () +
+char * + +soup_uri_decode () +
+char * + +soup_uri_normalize () +
+gboolean + +soup_uri_uses_default_port () +
#define +SOUP_URI_IS_VALID() +
#define +SOUP_URI_VALID_FOR_HTTP() +
+void + +soup_uri_set_scheme () +
const char * + +soup_uri_get_scheme () +
+void + +soup_uri_set_user () +
const char * + +soup_uri_get_user () +
+void + +soup_uri_set_password () +
const char * + +soup_uri_get_password () +
+void + +soup_uri_set_host () +
const char * + +soup_uri_get_host () +
+void + +soup_uri_set_port () +
+guint + +soup_uri_get_port () +
+void + +soup_uri_set_path () +
const char * + +soup_uri_get_path () +
+void + +soup_uri_set_query () +
+void + +soup_uri_set_query_from_form () +
+void + +soup_uri_set_query_from_fields () +
const char * + +soup_uri_get_query () +
+void + +soup_uri_set_fragment () +
const char * + +soup_uri_get_fragment () +
+
+
+

Types and Values

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 SoupURI
#defineSOUP_URI_SCHEME_HTTP
#defineSOUP_URI_SCHEME_HTTPS
#defineSOUP_URI_SCHEME_DATA
#defineSOUP_URI_SCHEME_FILE
#defineSOUP_URI_SCHEME_FTP
#defineSOUP_URI_SCHEME_RESOURCE
#defineSOUP_URI_SCHEME_WS
#defineSOUP_URI_SCHEME_WSS
+
+
+

Object Hierarchy

+
    GBoxed
+    ╰── SoupURI
+
+
+
+

Includes

+
#include <libsoup/soup.h>
+
+
+
+

Description

+

A SoupURI represents a (parsed) URI.

+

Many applications will not need to use SoupURI directly at all; on +the client side, soup_message_new() takes a stringified URI, and on +the server side, the path and query components are provided for you +in the server callback.

+
+
+

Functions

+
+

soup_uri_new_with_base ()

+
SoupURI *
+soup_uri_new_with_base (SoupURI *base,
+                        const char *uri_string);
+

Parses uri_string + relative to base +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

base

a base URI

 

uri_string

the URI

 
+
+
+

Returns

+

a parsed SoupURI.

+
+
+
+
+

soup_uri_new ()

+
SoupURI *
+soup_uri_new (const char *uri_string);
+

Parses an absolute URI.

+

You can also pass NULL for uri_string + if you want to get back an +"empty" SoupURI that you can fill in by hand. (You will need to +call at least soup_uri_set_scheme() and soup_uri_set_path(), since +those fields are required.)

+
+

Parameters

+
+++++ + + + + + +

uri_string

a URI.

[allow-none]
+
+
+

Returns

+

a SoupURI, or NULL if the given string +was found to be invalid.

+

[nullable]

+
+
+
+
+

soup_uri_to_string ()

+
char *
+soup_uri_to_string (SoupURI *uri,
+                    gboolean just_path_and_query);
+

Returns a string representing uri +.

+

If just_path_and_query + is TRUE, this concatenates the path and query +together. That is, it constructs the string that would be needed in +the Request-Line of an HTTP request for uri +.

+

Note that the output will never contain a password, even if uri + +does.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

uri

a SoupURI

 

just_path_and_query

if TRUE, output just the path and query portions

 
+
+
+

Returns

+

a string representing uri +, which the caller must free.

+
+
+
+
+

soup_uri_copy ()

+
SoupURI *
+soup_uri_copy (SoupURI *uri);
+

Copies uri +

+
+

Parameters

+
+++++ + + + + + +

uri

a SoupURI

 
+
+
+

Returns

+

a copy of uri +, which must be freed with soup_uri_free()

+
+
+
+
+

soup_uri_copy_host ()

+
SoupURI *
+soup_uri_copy_host (SoupURI *uri);
+

Makes a copy of uri +, considering only the protocol, host, and port

+
+

Parameters

+
+++++ + + + + + +

uri

a SoupURI

 
+
+
+

Returns

+

the new SoupURI

+
+

Since: 2.28

+
+
+
+

soup_uri_equal ()

+
gboolean
+soup_uri_equal (SoupURI *uri1,
+                SoupURI *uri2);
+

Tests whether or not uri1 + and uri2 + are equal in all parts

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

uri1

a SoupURI

 

uri2

another SoupURI

 
+
+
+

Returns

+

TRUE or FALSE

+
+
+
+
+

soup_uri_host_equal ()

+
gboolean
+soup_uri_host_equal (gconstpointer v1,
+                     gconstpointer v2);
+

Compares v1 + and v2 +, considering only the scheme, host, and port.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

v1

a SoupURI with a non-NULL host +member.

[type Soup.URI]

v2

a SoupURI with a non-NULL host +member.

[type Soup.URI]
+
+
+

Returns

+

whether or not the URIs are equal in scheme, host, +and port.

+
+

Since: 2.28

+
+
+
+

soup_uri_host_hash ()

+
guint
+soup_uri_host_hash (gconstpointer key);
+

Hashes key +, considering only the scheme, host, and port.

+
+

Parameters

+
+++++ + + + + + +

key

a SoupURI with a non-NULL host +member.

[type Soup.URI]
+
+
+

Returns

+

a hash

+
+

Since: 2.28

+
+
+
+

soup_uri_free ()

+
void
+soup_uri_free (SoupURI *uri);
+

Frees uri +.

+
+

Parameters

+
+++++ + + + + + +

uri

a SoupURI

 
+
+
+
+
+

soup_uri_encode ()

+
char *
+soup_uri_encode (const char *part,
+                 const char *escape_extra);
+

This %-encodes the given URI part and returns the escaped +version in allocated memory, which the caller must free when it is +done.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

part

a URI part

 

escape_extra

additional reserved characters to +escape (or NULL).

[allow-none]
+
+
+

Returns

+

the encoded URI part

+
+
+
+
+

soup_uri_decode ()

+
char *
+soup_uri_decode (const char *part);
+

Fully %-decodes part +.

+

In the past, this would return NULL if part + contained invalid +percent-encoding, but now it just ignores the problem (as +soup_uri_new() already did).

+
+

Parameters

+
+++++ + + + + + +

part

a URI part

 
+
+
+

Returns

+

the decoded URI part.

+
+
+
+
+

soup_uri_normalize ()

+
char *
+soup_uri_normalize (const char *part,
+                    const char *unescape_extra);
+

%-decodes any "unreserved" characters (or characters in +unescape_extra +) in part +, and %-encodes any non-ASCII +characters, spaces, and non-printing characters in part +.

+

"Unreserved" characters are those that are not allowed to be used +for punctuation according to the URI spec. For example, letters are +unreserved, so soup_uri_normalize() will turn +http://example.com/foo/b%61r into +http://example.com/foo/bar, which is guaranteed +to mean the same thing. However, "/" is "reserved", so +http://example.com/foo%2Fbar would not +be changed, because it might mean something different to the +server.

+

In the past, this would return NULL if part + contained invalid +percent-encoding, but now it just ignores the problem (as +soup_uri_new() already did).

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

part

a URI part

 

unescape_extra

reserved characters to unescape (or NULL).

[allow-none]
+
+
+

Returns

+

the normalized URI part

+
+
+
+
+

soup_uri_uses_default_port ()

+
gboolean
+soup_uri_uses_default_port (SoupURI *uri);
+

Tests if uri + uses the default port for its scheme. (Eg, 80 for +http.) (This only works for http, https and ftp; libsoup does not know +the default ports of other protocols.)

+
+

Parameters

+
+++++ + + + + + +

uri

a SoupURI

 
+
+
+

Returns

+

TRUE or FALSE

+
+
+
+
+

SOUP_URI_IS_VALID()

+
#define   SOUP_URI_IS_VALID(uri)       ((uri) && (uri)->scheme && (uri)->path)
+
+

Tests whether uri + is a valid SoupURI; that is, that it is non-NULL +and its scheme + and path + members are also non-NULL.

+

This macro does not check whether http and https URIs have a non-NULL +host + member.

+
+

Parameters

+
+++++ + + + + + +

uri

a SoupURI

 
+
+
+

Returns

+

TRUE if uri +is valid for use.

+
+

Since: 2.38

+
+
+
+

SOUP_URI_VALID_FOR_HTTP()

+
#define   SOUP_URI_VALID_FOR_HTTP(uri) ((uri) && ((uri)->scheme == SOUP_URI_SCHEME_HTTP || (uri)->scheme == SOUP_URI_SCHEME_HTTPS) && (uri)->host && (uri)->path)
+
+

Tests if uri + is a valid SoupURI for HTTP communication; that is, if +it can be used to construct a SoupMessage.

+
+

Parameters

+
+++++ + + + + + +

uri

a SoupURI

 
+
+
+

Returns

+

TRUE if uri +is a valid "http" or "https" URI.

+
+

Since: 2.24

+
+
+
+

soup_uri_set_scheme ()

+
void
+soup_uri_set_scheme (SoupURI *uri,
+                     const char *scheme);
+

Sets uri +'s scheme to scheme +. This will also set uri +'s port to +the default port for scheme +, if known.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

uri

a SoupURI

 

scheme

the URI scheme

 
+
+
+
+
+

soup_uri_get_scheme ()

+
const char *
+soup_uri_get_scheme (SoupURI *uri);
+

Gets uri +'s scheme.

+
+

Parameters

+
+++++ + + + + + +

uri

a SoupURI

 
+
+
+

Returns

+

uri +'s scheme.

+
+

Since: 2.32

+
+
+
+

soup_uri_set_user ()

+
void
+soup_uri_set_user (SoupURI *uri,
+                   const char *user);
+

Sets uri +'s user to user +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

uri

a SoupURI

 

user

the username, or NULL.

[allow-none]
+
+
+
+
+

soup_uri_get_user ()

+
const char *
+soup_uri_get_user (SoupURI *uri);
+

Gets uri +'s user.

+
+

Parameters

+
+++++ + + + + + +

uri

a SoupURI

 
+
+
+

Returns

+

uri +'s user.

+
+

Since: 2.32

+
+
+
+

soup_uri_set_password ()

+
void
+soup_uri_set_password (SoupURI *uri,
+                       const char *password);
+

Sets uri +'s password to password +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

uri

a SoupURI

 

password

the password, or NULL.

[allow-none]
+
+
+
+
+

soup_uri_get_password ()

+
const char *
+soup_uri_get_password (SoupURI *uri);
+

Gets uri +'s password.

+
+

Parameters

+
+++++ + + + + + +

uri

a SoupURI

 
+
+
+

Returns

+

uri +'s password.

+
+

Since: 2.32

+
+
+
+

soup_uri_set_host ()

+
void
+soup_uri_set_host (SoupURI *uri,
+                   const char *host);
+

Sets uri +'s host to host +.

+

If host + is an IPv6 IP address, it should not include the brackets +required by the URI syntax; they will be added automatically when +converting uri + to a string.

+

http and https URIs should not have a NULL host +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

uri

a SoupURI

 

host

the hostname or IP address, or NULL.

[allow-none]
+
+
+
+
+

soup_uri_get_host ()

+
const char *
+soup_uri_get_host (SoupURI *uri);
+

Gets uri +'s host.

+
+

Parameters

+
+++++ + + + + + +

uri

a SoupURI

 
+
+
+

Returns

+

uri +'s host.

+
+

Since: 2.32

+
+
+
+

soup_uri_set_port ()

+
void
+soup_uri_set_port (SoupURI *uri,
+                   guint port);
+

Sets uri +'s port to port +. If port + is 0, uri + will not have an +explicitly-specified port.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

uri

a SoupURI

 

port

the port, or 0

 
+
+
+
+
+

soup_uri_get_port ()

+
guint
+soup_uri_get_port (SoupURI *uri);
+

Gets uri +'s port.

+
+

Parameters

+
+++++ + + + + + +

uri

a SoupURI

 
+
+
+

Returns

+

uri +'s port.

+
+

Since: 2.32

+
+
+
+

soup_uri_set_path ()

+
void
+soup_uri_set_path (SoupURI *uri,
+                   const char *path);
+

Sets uri +'s path to path +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

uri

a SoupURI

 

path

the non-NULL path

 
+
+
+
+
+

soup_uri_get_path ()

+
const char *
+soup_uri_get_path (SoupURI *uri);
+

Gets uri +'s path.

+
+

Parameters

+
+++++ + + + + + +

uri

a SoupURI

 
+
+
+

Returns

+

uri +'s path.

+
+

Since: 2.32

+
+
+
+

soup_uri_set_query ()

+
void
+soup_uri_set_query (SoupURI *uri,
+                    const char *query);
+

Sets uri +'s query to query +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

uri

a SoupURI

 

query

the query.

[allow-none]
+
+
+
+
+

soup_uri_set_query_from_form ()

+
void
+soup_uri_set_query_from_form (SoupURI *uri,
+                              GHashTable *form);
+

Sets uri +'s query to the result of encoding form + according to the +HTML form rules. See soup_form_encode_hash() for more information.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

uri

a SoupURI

 

form

a GHashTable containing HTML form +information.

[element-type utf8 utf8]
+
+
+
+
+

soup_uri_set_query_from_fields ()

+
void
+soup_uri_set_query_from_fields (SoupURI *uri,
+                                const char *first_field,
+                                ...);
+

Sets uri +'s query to the result of encoding the given form fields +and values according to the * HTML form rules. See +soup_form_encode() for more information.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

uri

a SoupURI

 

first_field

name of the first form field to encode into query

 

...

value of first_field +, followed by additional field names +and values, terminated by NULL.

 
+
+
+
+
+

soup_uri_get_query ()

+
const char *
+soup_uri_get_query (SoupURI *uri);
+

Gets uri +'s query.

+
+

Parameters

+
+++++ + + + + + +

uri

a SoupURI

 
+
+
+

Returns

+

uri +'s query.

+
+

Since: 2.32

+
+
+
+

soup_uri_set_fragment ()

+
void
+soup_uri_set_fragment (SoupURI *uri,
+                       const char *fragment);
+

Sets uri +'s fragment to fragment +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

uri

a SoupURI

 

fragment

the fragment.

[allow-none]
+
+
+
+
+

soup_uri_get_fragment ()

+
const char *
+soup_uri_get_fragment (SoupURI *uri);
+

Gets uri +'s fragment.

+
+

Parameters

+
+++++ + + + + + +

uri

a SoupURI

 
+
+
+

Returns

+

uri +'s fragment.

+
+

Since: 2.32

+
+
+
+

Types and Values

+
+

SoupURI

+
typedef struct {
+	const char *scheme;
+
+	char       *user;
+	char       *password;
+
+	char       *host;
+	guint       port;
+
+	char       *path;
+	char       *query;
+
+	char       *fragment;
+} SoupURI;
+
+

A SoupURI represents a (parsed) URI. SoupURI supports RFC 3986 +(URI Generic Syntax), and can parse any valid URI. However, libsoup +only uses "http" and "https" URIs internally; You can use +SOUP_URI_VALID_FOR_HTTP() to test if a SoupURI is a valid HTTP +URI.

+

scheme + will always be set in any URI. It is an interned string and +is always all lowercase. (If you parse a URI with a non-lowercase +scheme, it will be converted to lowercase.) The macros +SOUP_URI_SCHEME_HTTP and SOUP_URI_SCHEME_HTTPS provide the +interned values for "http" and "https" and can be compared against +URI scheme + values.

+

user + and password + are parsed as defined in the older URI specs +(ie, separated by a colon; RFC 3986 only talks about a single +"userinfo" field). Note that password + is not included in the +output of soup_uri_to_string(). libsoup does not normally use these +fields; authentication is handled via SoupSession signals.

+

host + contains the hostname, and port + the port specified in the +URI. If the URI doesn't contain a hostname, host + will be NULL, +and if it doesn't specify a port, port + may be 0. However, for +"http" and "https" URIs, host + is guaranteed to be non-NULL +(trying to parse an http URI with no host + will return NULL), and +port + will always be non-0 (because libsoup knows the default value +to use when it is not specified in the URI).

+

path + is always non-NULL. For http/https URIs, path + will never be +an empty string either; if the input URI has no path, the parsed +SoupURI will have a path + of "/".

+

query + and fragment + are optional for all URI types. +soup_form_decode() may be useful for parsing query +.

+

Note that path +, query +, and fragment + may contain +%-encoded characters. soup_uri_new() calls +soup_uri_normalize() on them, but not soup_uri_decode(). This is +necessary to ensure that soup_uri_to_string() will generate a URI +that has exactly the same meaning as the original. (In theory, +SoupURI should leave user +, password +, and host + partially-encoded +as well, but this would be more annoying than useful.)

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

const char *scheme;

the URI scheme (eg, "http")

 

char *user;

a username, or NULL

 

char *password;

a password, or NULL

 

char *host;

the hostname or IP address, or NULL

 

guint port;

the port number on host +

 

char *path;

the path on host +

 

char *query;

a query for path +, or NULL

 

char *fragment;

a fragment identifier within path +, or NULL

 
+
+
+
+
+

SOUP_URI_SCHEME_HTTP

+
#define SOUP_URI_SCHEME_HTTP     _SOUP_ATOMIC_INTERN_STRING (_SOUP_URI_SCHEME_HTTP, "http")
+
+

"http" as an interned string; you can compare this directly to a +SoupURI's scheme field using +==.

+
+
+
+

SOUP_URI_SCHEME_HTTPS

+
#define SOUP_URI_SCHEME_HTTPS    _SOUP_ATOMIC_INTERN_STRING (_SOUP_URI_SCHEME_HTTPS, "https")
+
+

"https" as an interned string; you can compare this directly to a +SoupURI's scheme field using +==.

+
+
+
+

SOUP_URI_SCHEME_DATA

+
#define SOUP_URI_SCHEME_DATA     _SOUP_ATOMIC_INTERN_STRING (_SOUP_URI_SCHEME_DATA, "data")
+
+

"data" as an interned string; you can compare this directly to a +SoupURI's scheme field using +==.

+

Since: 2.30

+
+
+
+

SOUP_URI_SCHEME_FILE

+
#define SOUP_URI_SCHEME_FILE     _SOUP_ATOMIC_INTERN_STRING (_SOUP_URI_SCHEME_FILE, "file")
+
+

"file" as an interned string; you can compare this directly to a +SoupURI's scheme field using +==.

+

Since: 2.30

+
+
+
+

SOUP_URI_SCHEME_FTP

+
#define SOUP_URI_SCHEME_FTP      _SOUP_ATOMIC_INTERN_STRING (_SOUP_URI_SCHEME_FTP, "ftp")
+
+

"ftp" as an interned string; you can compare this directly to a +SoupURI's scheme field using +==.

+

Since: 2.30

+
+
+
+

SOUP_URI_SCHEME_RESOURCE

+
#define SOUP_URI_SCHEME_RESOURCE _SOUP_ATOMIC_INTERN_STRING (_SOUP_URI_SCHEME_RESOURCE, "resource")
+
+

"data" as an interned string; you can compare this directly to a +SoupURI's scheme field using +==.

+

Since: 2.42

+
+
+
+

SOUP_URI_SCHEME_WS

+
#define SOUP_URI_SCHEME_WS       _SOUP_ATOMIC_INTERN_STRING (_SOUP_URI_SCHEME_WS, "ws")
+
+

"ws" (WebSocket) as an interned string; you can compare this +directly to a SoupURI's scheme field using +==.

+

Since: 2.50

+
+
+
+

SOUP_URI_SCHEME_WSS

+
#define SOUP_URI_SCHEME_WSS      _SOUP_ATOMIC_INTERN_STRING (_SOUP_URI_SCHEME_WSS, "wss")
+
+

"wss" (WebSocket over TLS) as an interned string; you can compare +this directly to a SoupURI's scheme field using +==.

+

Since: 2.50

+
+
+
+ + + \ No newline at end of file diff --git a/docs/reference/html/annotation-glossary.html b/docs/reference/html/annotation-glossary.html new file mode 100644 index 0000000..8b5d180 --- /dev/null +++ b/docs/reference/html/annotation-glossary.html @@ -0,0 +1,80 @@ + + + + +Annotation Glossary: libsoup Reference Manual + + + + + + + + + + + + + + + +
+

+Annotation Glossary

+

A

+
allow-none
+

NULL is OK, both for passing and for returning.

+
array
+

Parameter points to an array of items.

+

E

+
element-type
+

Generics and defining elements of containers and arrays.

+

I

+
inout
+

Parameter for input and for returning results. Default is transfer full.

+

N

+
nullable
+

NULL may be passed as the value in, out, in-out; or as a return value.

+

O

+
optional
+

NULL may be passed instead of a pointer to a location.

+
out
+

Parameter for returning results. Default is transfer full.

+

R

+
rename-to
+

Rename the original symbol's name to SYMBOL.

+

S

+
scope async
+

The callback is valid until first called.

+
scope call
+

The callback is valid only during the call to the method.

+
skip
+

Exposed in C code, not necessarily available in other languages.

+

T

+
transfer container
+

Free data container after the code is done.

+
transfer full
+

Free data after the code is done.

+
transfer none
+

Don't free data after the code is done.

+
type
+

Override the parsed C type with given type.

+
+ + + \ No newline at end of file diff --git a/docs/reference/html/ch01.html b/docs/reference/html/ch01.html new file mode 100644 index 0000000..4836816 --- /dev/null +++ b/docs/reference/html/ch01.html @@ -0,0 +1,48 @@ + + + + +Tutorial: libsoup Reference Manual + + + + + + + + + + + + + + + + +
+

+Tutorial

+
+
+Compiling with libsoup — Notes on compiling +
+
+libsoup Client Basics — Client-side tutorial +
+
+libsoup Client SoupRequest API — Using +libsoup with a mix of http and non-http URIs. +
+
+Porting to the new SoupSession — Notes on +porting from SoupSessionAsync and SoupSessionSync to SoupSession +
+
+libsoup Server Basics — Server-side tutorial +
+
+
+ + + \ No newline at end of file diff --git a/docs/reference/html/ch02.html b/docs/reference/html/ch02.html new file mode 100644 index 0000000..f2f15dd --- /dev/null +++ b/docs/reference/html/ch02.html @@ -0,0 +1,111 @@ + + + + +Core API: libsoup Reference Manual + + + + + + + + + + + + + + + + +
+

+Core API

+
+
+SoupAuth — HTTP client-side authentication support +
+
+SoupAuthDomain — Server-side authentication +
+
+SoupAuthDomainBasic — Server-side "Basic" authentication +
+
+SoupAuthDomainDigest — Server-side "Digest" authentication +
+
+SoupCache — Caching support +
+
+SoupCookie — HTTP Cookies +
+
+SoupMessage — An HTTP request and response. +
+
+SoupMessageHeaders — HTTP message headers +
+
+SoupMessageBody — HTTP message body +
+
+soup-method — HTTP method definitions +
+
+Soup Miscellaneous Utilities — Miscellaneous functions +
+
+SoupMultipart — multipart HTTP message bodies +
+
+SoupMultipartInputStream — Multipart input handling stream +
+
+SoupRequest — Protocol-independent streaming request interface +
+
+SoupRequestHTTP — SoupRequest support for "http" and "https" URIs +
+
+SoupRequestFile — SoupRequest support for "file" and "resource" URIs +
+
+SoupRequestData — SoupRequest support for "data" URIs +
+
+SoupServer — HTTP server +
+
+SoupServer deprecated API +
+
+SoupSession — Soup session state object +
+
+SoupSessionAsync — SoupSession for asynchronous (main-loop-based) I/O +(deprecated). +
+
+SoupSessionSync — SoupSession for blocking I/O in multithreaded programs +(deprecated). +
+
+soup-status — HTTP (and libsoup) status codes +
+
+Top Level Domain utils — Top-Level Domain Utilities +
+
+SoupURI — URIs +
+
+Version Information — Variables and functions to check the libsoup version +
+
+
+ + + \ No newline at end of file diff --git a/docs/reference/html/ch03.html b/docs/reference/html/ch03.html new file mode 100644 index 0000000..6c2f5af --- /dev/null +++ b/docs/reference/html/ch03.html @@ -0,0 +1,58 @@ + + + + +Additional Features: libsoup Reference Manual + + + + + + + + + + + + + + + + +
+

+Additional Features

+
+
+SoupSessionFeature — Interface for miscellaneous session features +
+
+SoupAuthManager — HTTP client-side authentication handler +
+
+SoupContentDecoder — Content-Encoding handler +
+
+SoupContentSniffer — Content sniffing for SoupSession +
+
+SoupCookieJar — Automatic cookie handling for SoupSession +
+
+SoupCookieJarText — Text-file-based ("cookies.txt") Cookie Jar +
+
+SoupCookieJarDB — Database-based Cookie Jar +
+
+SoupLogger — Debug logging support +
+
+SoupProxyResolverDefault — System proxy configuration integration +
+
+
+ + + \ No newline at end of file diff --git a/docs/reference/html/ch04.html b/docs/reference/html/ch04.html new file mode 100644 index 0000000..645bbe1 --- /dev/null +++ b/docs/reference/html/ch04.html @@ -0,0 +1,40 @@ + + + + +Web Services APIs: libsoup Reference Manual + + + + + + + + + + + + + + + + +
+

+Web Services APIs

+
+
+HTML Form Support — HTML form handling +
+
+XMLRPC Support — XML-RPC support +
+
+WebSockets — The WebSocket Protocol +
+
+
+ + + \ No newline at end of file diff --git a/docs/reference/html/ch05.html b/docs/reference/html/ch05.html new file mode 100644 index 0000000..12099f3 --- /dev/null +++ b/docs/reference/html/ch05.html @@ -0,0 +1,37 @@ + + + + +Low-level Networking API: libsoup Reference Manual + + + + + + + + + + + + + + + + +
+

+Low-level Networking API

+
+
+SoupAddress — DNS support +
+
+SoupSocket — A network socket +
+
+
+ + + \ No newline at end of file diff --git a/docs/reference/html/home.png b/docs/reference/html/home.png new file mode 100644 index 0000000..9346b33 Binary files /dev/null and b/docs/reference/html/home.png differ diff --git a/docs/reference/html/index.html b/docs/reference/html/index.html new file mode 100644 index 0000000..fd6bde9 --- /dev/null +++ b/docs/reference/html/index.html @@ -0,0 +1,180 @@ + + + + +libsoup Reference Manual: libsoup Reference Manual + + + + + + + +
+
+
+
+
+
+
Tutorial
+
+
+Compiling with libsoup — Notes on compiling +
+
+libsoup Client Basics — Client-side tutorial +
+
+libsoup Client SoupRequest API — Using +libsoup with a mix of http and non-http URIs. +
+
+Porting to the new SoupSession — Notes on +porting from SoupSessionAsync and SoupSessionSync to SoupSession +
+
+libsoup Server Basics — Server-side tutorial +
+
+
Core API
+
+
+SoupAuth — HTTP client-side authentication support +
+
+SoupAuthDomain — Server-side authentication +
+
+SoupAuthDomainBasic — Server-side "Basic" authentication +
+
+SoupAuthDomainDigest — Server-side "Digest" authentication +
+
+SoupCache — Caching support +
+
+SoupCookie — HTTP Cookies +
+
+SoupMessage — An HTTP request and response. +
+
+SoupMessageHeaders — HTTP message headers +
+
+SoupMessageBody — HTTP message body +
+
+soup-method — HTTP method definitions +
+
+Soup Miscellaneous Utilities — Miscellaneous functions +
+
+SoupMultipart — multipart HTTP message bodies +
+
+SoupMultipartInputStream — Multipart input handling stream +
+
+SoupRequest — Protocol-independent streaming request interface +
+
+SoupRequestHTTP — SoupRequest support for "http" and "https" URIs +
+
+SoupRequestFile — SoupRequest support for "file" and "resource" URIs +
+
+SoupRequestData — SoupRequest support for "data" URIs +
+
+SoupServer — HTTP server +
+
+SoupServer deprecated API +
+
+SoupSession — Soup session state object +
+
+SoupSessionAsync — SoupSession for asynchronous (main-loop-based) I/O +(deprecated). +
+
+SoupSessionSync — SoupSession for blocking I/O in multithreaded programs +(deprecated). +
+
+soup-status — HTTP (and libsoup) status codes +
+
+Top Level Domain utils — Top-Level Domain Utilities +
+
+SoupURI — URIs +
+
+Version Information — Variables and functions to check the libsoup version +
+
+
Additional Features
+
+
+SoupSessionFeature — Interface for miscellaneous session features +
+
+SoupAuthManager — HTTP client-side authentication handler +
+
+SoupContentDecoder — Content-Encoding handler +
+
+SoupContentSniffer — Content sniffing for SoupSession +
+
+SoupCookieJar — Automatic cookie handling for SoupSession +
+
+SoupCookieJarText — Text-file-based ("cookies.txt") Cookie Jar +
+
+SoupCookieJarDB — Database-based Cookie Jar +
+
+SoupLogger — Debug logging support +
+
+SoupProxyResolverDefault — System proxy configuration integration +
+
+
Web Services APIs
+
+
+HTML Form Support — HTML form handling +
+
+XMLRPC Support — XML-RPC support +
+
+WebSockets — The WebSocket Protocol +
+
+
Low-level Networking API
+
+
+SoupAddress — DNS support +
+
+SoupSocket — A network socket +
+
+
Index
+
Annotation Glossary
+
+
+ + + \ No newline at end of file diff --git a/docs/reference/html/ix01.html b/docs/reference/html/ix01.html new file mode 100644 index 0000000..39981bd --- /dev/null +++ b/docs/reference/html/ix01.html @@ -0,0 +1,1602 @@ + + + + +Index: libsoup Reference Manual + + + + + + + + + + + + + + + + +
+

+Index

+
+

S

+
+
SoupAddress, SoupAddress +
+
SoupAddress:family, The “family” property +
+
SoupAddress:name, The “name” property +
+
SoupAddress:physical, The “physical” property +
+
SoupAddress:port, The “port” property +
+
SoupAddress:protocol, The “protocol” property +
+
SoupAddress:sockaddr, The “sockaddr” property +
+
SoupAddressCallback, SoupAddressCallback () +
+
SoupAddressFamily, enum SoupAddressFamily +
+
SoupAuth, SoupAuth +
+
SoupAuth:host, The “host” property +
+
SoupAuth:is-authenticated, The “is-authenticated” property +
+
SoupAuth:is-for-proxy, The “is-for-proxy” property +
+
SoupAuth:realm, The “realm” property +
+
SoupAuth:scheme-name, The “scheme-name” property +
+
SoupAuthDomain, SoupAuthDomain +
+
SoupAuthDomain:add-path, The “add-path” property +
+
SoupAuthDomain:filter, The “filter” property +
+
SoupAuthDomain:filter-data, The “filter-data” property +
+
SoupAuthDomain:generic-auth-callback, The “generic-auth-callback” property +
+
SoupAuthDomain:generic-auth-data, The “generic-auth-data” property +
+
SoupAuthDomain:proxy, The “proxy” property +
+
SoupAuthDomain:realm, The “realm” property +
+
SoupAuthDomain:remove-path, The “remove-path” property +
+
SoupAuthDomainBasic, SoupAuthDomainBasic +
+
SoupAuthDomainBasic:auth-callback, The “auth-callback” property +
+
SoupAuthDomainBasic:auth-data, The “auth-data” property +
+
SoupAuthDomainBasicAuthCallback, SoupAuthDomainBasicAuthCallback () +
+
SoupAuthDomainDigest, SoupAuthDomainDigest +
+
SoupAuthDomainDigest:auth-callback, The “auth-callback” property +
+
SoupAuthDomainDigest:auth-data, The “auth-data” property +
+
SoupAuthDomainDigestAuthCallback, SoupAuthDomainDigestAuthCallback () +
+
SoupAuthDomainFilter, SoupAuthDomainFilter () +
+
SoupAuthDomainGenericAuthCallback, SoupAuthDomainGenericAuthCallback () +
+
SoupAuthManager, SoupAuthManager +
+
SoupAuthManager::authenticate, The “authenticate” signal +
+
SoupBuffer, SoupBuffer +
+
SoupCache, struct SoupCache +
+
SoupCache:cache-dir, The “cache-dir” property +
+
SoupCache:cache-type, The “cache-type” property +
+
SoupCacheType, enum SoupCacheType +
+
SoupChunkAllocator, SoupChunkAllocator () +
+
SoupClientContext, SoupServer +
+
SoupContentDecoder, SoupContentDecoder +
+
SoupContentSniffer, SoupContentSniffer +
+
SoupCookie, SoupCookie +
+
SoupCookieJar, SoupCookieJar +
+
SoupCookieJar::changed, The “changed” signal +
+
SoupCookieJar:accept-policy, The “accept-policy” property +
+
SoupCookieJar:read-only, The “read-only” property +
+
SoupCookieJarAcceptPolicy, enum SoupCookieJarAcceptPolicy +
+
SoupCookieJarDB, SoupCookieJarDB +
+
SoupCookieJarDB:filename, The “filename” property +
+
SoupCookieJarText, SoupCookieJarText +
+
SoupCookieJarText:filename, The “filename” property +
+
SoupDate, SoupDate +
+
SoupDateFormat, enum SoupDateFormat +
+
SoupEncoding, enum SoupEncoding +
+
SoupExpectation, enum SoupExpectation +
+
SoupHTTPVersion, enum SoupHTTPVersion +
+
SoupLogger, SoupLogger +
+
SoupLogger:level, The “level” property +
+
SoupLogger:max-body-size, The “max-body-size” property +
+
SoupLoggerFilter, SoupLoggerFilter () +
+
SoupLoggerLogLevel, enum SoupLoggerLogLevel +
+
SoupLoggerPrinter, SoupLoggerPrinter () +
+
SoupMemoryUse, enum SoupMemoryUse +
+
SoupMessage, SoupMessage +
+
SoupMessage::content-sniffed, The “content-sniffed” signal +
+
SoupMessage::finished, The “finished” signal +
+
SoupMessage::got-body, The “got-body” signal +
+
SoupMessage::got-chunk, The “got-chunk” signal +
+
SoupMessage::got-headers, The “got-headers” signal +
+
SoupMessage::got-informational, The “got-informational” signal +
+
SoupMessage::network-event, The “network-event” signal +
+
SoupMessage::restarted, The “restarted” signal +
+
SoupMessage::starting, The “starting” signal +
+
SoupMessage::wrote-body, The “wrote-body” signal +
+
SoupMessage::wrote-body-data, The “wrote-body-data” signal +
+
SoupMessage::wrote-chunk, The “wrote-chunk” signal +
+
SoupMessage::wrote-headers, The “wrote-headers” signal +
+
SoupMessage::wrote-informational, The “wrote-informational” signal +
+
SoupMessage:first-party, The “first-party” property +
+
SoupMessage:flags, The “flags” property +
+
SoupMessage:http-version, The “http-version” property +
+
SoupMessage:method, The “method” property +
+
SoupMessage:priority, The “priority” property +
+
SoupMessage:reason-phrase, The “reason-phrase” property +
+
SoupMessage:request-body, The “request-body” property +
+
SoupMessage:request-body-data, The “request-body-data” property +
+
SoupMessage:request-headers, The “request-headers” property +
+
SoupMessage:response-body, The “response-body” property +
+
SoupMessage:response-body-data, The “response-body-data” property +
+
SoupMessage:response-headers, The “response-headers” property +
+
SoupMessage:server-side, The “server-side” property +
+
SoupMessage:status-code, The “status-code” property +
+
SoupMessage:tls-certificate, The “tls-certificate” property +
+
SoupMessage:tls-errors, The “tls-errors” property +
+
SoupMessage:uri, The “uri” property +
+
SoupMessageBody, SoupMessageBody +
+
SoupMessageFlags, enum SoupMessageFlags +
+
SoupMessageHeaders, SoupMessageHeaders +
+
SoupMessageHeadersForeachFunc, SoupMessageHeadersForeachFunc () +
+
SoupMessageHeadersIter, SoupMessageHeadersIter +
+
SoupMessageHeadersType, enum SoupMessageHeadersType +
+
SoupMessagePriority, enum SoupMessagePriority +
+
SoupMultipart, SoupMultipart +
+
SoupMultipartInputStream, struct SoupMultipartInputStream +
+
SoupMultipartInputStream:message, The “message” property +
+
SoupProxyResolverDefault, SoupProxyResolverDefault +
+
SoupProxyResolverDefault:gproxy-resolver, The “gproxy-resolver” property +
+
SoupRange, SoupRange +
+
SoupRequest, SoupRequest +
+
SoupRequest:session, The “session” property +
+
SoupRequest:uri, The “uri” property +
+
SoupRequestData, SoupRequestData +
+
SoupRequestError, enum SoupRequestError +
+
SoupRequestFile, SoupRequestFile +
+
SoupRequestHTTP, SoupRequestHTTP +
+
SoupServer, SoupServer +
+
SoupServer::request-aborted, The “request-aborted” signal +
+
SoupServer::request-finished, The “request-finished” signal +
+
SoupServer::request-read, The “request-read” signal +
+
SoupServer::request-started, The “request-started” signal +
+
SoupServer:async-context, The “async-context” property +
+
SoupServer:http-aliases, The “http-aliases” property +
+
SoupServer:https-aliases, The “https-aliases” property +
+
SoupServer:interface, The “interface” property +
+
SoupServer:port, The “port” property +
+
SoupServer:raw-paths, The “raw-paths” property +
+
SoupServer:server-header, The “server-header” property +
+
SoupServer:ssl-cert-file, The “ssl-cert-file” property +
+
SoupServer:ssl-key-file, The “ssl-key-file” property +
+
SoupServer:tls-certificate, The “tls-certificate” property +
+
SoupServerCallback, SoupServerCallback () +
+
SoupServerListenOptions, enum SoupServerListenOptions +
+
SoupServerWebsocketCallback, SoupServerWebsocketCallback () +
+
SoupSession, SoupSession +
+
SoupSession::authenticate, The “authenticate” signal +
+
SoupSession::connection-created, The “connection-created” signal +
+
SoupSession::request-queued, The “request-queued” signal +
+
SoupSession::request-started, The “request-started” signal +
+
SoupSession::request-unqueued, The “request-unqueued” signal +
+
SoupSession::tunneling, The “tunneling” signal +
+
SoupSession:accept-language, The “accept-language” property +
+
SoupSession:accept-language-auto, The “accept-language-auto” property +
+
SoupSession:add-feature, The “add-feature” property +
+
SoupSession:add-feature-by-type, The “add-feature-by-type” property +
+
SoupSession:async-context, The “async-context” property +
+
SoupSession:http-aliases, The “http-aliases” property +
+
SoupSession:https-aliases, The “https-aliases” property +
+
SoupSession:idle-timeout, The “idle-timeout” property +
+
SoupSession:local-address, The “local-address” property +
+
SoupSession:max-conns, The “max-conns” property +
+
SoupSession:max-conns-per-host, The “max-conns-per-host” property +
+
SoupSession:proxy-resolver, The “proxy-resolver” property +
+
SoupSession:proxy-uri, The “proxy-uri” property +
+
SoupSession:remove-feature-by-type, The “remove-feature-by-type” property +
+
SoupSession:ssl-ca-file, The “ssl-ca-file” property +
+
SoupSession:ssl-strict, The “ssl-strict” property +
+
SoupSession:ssl-use-system-ca-file, The “ssl-use-system-ca-file” property +
+
SoupSession:timeout, The “timeout” property +
+
SoupSession:tls-database, The “tls-database” property +
+
SoupSession:tls-interaction, The “tls-interaction” property +
+
SoupSession:use-ntlm, The “use-ntlm” property +
+
SoupSession:use-thread-context, The “use-thread-context” property +
+
SoupSession:user-agent, The “user-agent” property +
+
SoupSessionAsync, SoupSessionAsync +
+
SoupSessionCallback, SoupSessionCallback () +
+
SoupSessionConnectProgressCallback, SoupSessionConnectProgressCallback () +
+
SoupSessionFeature, SoupSessionFeature +
+
SoupSessionFeatureInterface, SoupSessionFeatureInterface +
+
SoupSessionSync, SoupSessionSync +
+
SoupSocket, SoupSocket +
+
SoupSocket::disconnected, The “disconnected” signal +
+
SoupSocket::event, The “event” signal +
+
SoupSocket::new-connection, The “new-connection” signal +
+
SoupSocket::readable, The “readable” signal +
+
SoupSocket::writable, The “writable” signal +
+
SoupSocket:async-context, The “async-context” property +
+
SoupSocket:fd, The “fd” property +
+
SoupSocket:gsocket, The “gsocket” property +
+
SoupSocket:iostream, The “iostream” property +
+
SoupSocket:ipv6-only, The “ipv6-only” property +
+
SoupSocket:is-server, The “is-server” property +
+
SoupSocket:local-address, The “local-address” property +
+
SoupSocket:non-blocking, The “non-blocking” property +
+
SoupSocket:remote-address, The “remote-address” property +
+
SoupSocket:socket-properties, The “socket-properties” property +
+
SoupSocket:ssl-creds, The “ssl-creds” property +
+
SoupSocket:ssl-fallback, The “ssl-fallback” property +
+
SoupSocket:ssl-strict, The “ssl-strict” property +
+
SoupSocket:timeout, The “timeout” property +
+
SoupSocket:tls-certificate, The “tls-certificate” property +
+
SoupSocket:tls-errors, The “tls-errors” property +
+
SoupSocket:trusted-certificate, The “trusted-certificate” property +
+
SoupSocket:use-thread-context, The “use-thread-context” property +
+
SoupSocketCallback, SoupSocketCallback () +
+
SoupSocketIOStatus, enum SoupSocketIOStatus +
+
SoupStatus, enum SoupStatus +
+
SoupTLDError, enum SoupTLDError +
+
SoupURI, SoupURI +
+
SoupWebsocketCloseCode, enum SoupWebsocketCloseCode +
+
SoupWebsocketConnection, SoupWebsocketConnection +
+
SoupWebsocketConnection::closed, The “closed” signal +
+
SoupWebsocketConnection::closing, The “closing” signal +
+
SoupWebsocketConnection::error, The “error” signal +
+
SoupWebsocketConnection::message, The “message” signal +
+
SoupWebsocketConnection::pong, The “pong” signal +
+
SoupWebsocketConnection:connection-type, The “connection-type” property +
+
SoupWebsocketConnection:io-stream, The “io-stream” property +
+
SoupWebsocketConnection:keepalive-interval, The “keepalive-interval” property +
+
SoupWebsocketConnection:max-incoming-payload-size, The “max-incoming-payload-size” property +
+
SoupWebsocketConnection:origin, The “origin” property +
+
SoupWebsocketConnection:protocol, The “protocol” property +
+
SoupWebsocketConnection:state, The “state” property +
+
SoupWebsocketConnection:uri, The “uri” property +
+
SoupWebsocketConnectionType, enum SoupWebsocketConnectionType +
+
SoupWebsocketDataType, enum SoupWebsocketDataType +
+
SoupWebsocketError, enum SoupWebsocketError +
+
SoupWebsocketState, enum SoupWebsocketState +
+
SoupXMLRPCError, enum SoupXMLRPCError +
+
SoupXMLRPCFault, enum SoupXMLRPCFault +
+
SoupXMLRPCParams, SoupXMLRPCParams +
+
SOUP_ADDRESS_ANY_PORT, SOUP_ADDRESS_ANY_PORT +
+
soup_address_equal_by_ip, soup_address_equal_by_ip () +
+
soup_address_equal_by_name, soup_address_equal_by_name () +
+
SOUP_ADDRESS_FAMILY, SOUP_ADDRESS_FAMILY +
+
soup_address_get_gsockaddr, soup_address_get_gsockaddr () +
+
soup_address_get_name, soup_address_get_name () +
+
soup_address_get_physical, soup_address_get_physical () +
+
soup_address_get_port, soup_address_get_port () +
+
soup_address_get_sockaddr, soup_address_get_sockaddr () +
+
soup_address_hash_by_ip, soup_address_hash_by_ip () +
+
soup_address_hash_by_name, soup_address_hash_by_name () +
+
soup_address_is_resolved, soup_address_is_resolved () +
+
SOUP_ADDRESS_NAME, SOUP_ADDRESS_NAME +
+
soup_address_new, soup_address_new () +
+
soup_address_new_any, soup_address_new_any () +
+
soup_address_new_from_sockaddr, soup_address_new_from_sockaddr () +
+
SOUP_ADDRESS_PHYSICAL, SOUP_ADDRESS_PHYSICAL +
+
SOUP_ADDRESS_PORT, SOUP_ADDRESS_PORT +
+
SOUP_ADDRESS_PROTOCOL, SOUP_ADDRESS_PROTOCOL +
+
soup_address_resolve_async, soup_address_resolve_async () +
+
soup_address_resolve_sync, soup_address_resolve_sync () +
+
SOUP_ADDRESS_SOCKADDR, SOUP_ADDRESS_SOCKADDR +
+
soup_add_completion, soup_add_completion () +
+
soup_add_idle, soup_add_idle () +
+
soup_add_io_watch, soup_add_io_watch () +
+
soup_add_timeout, soup_add_timeout () +
+
soup_auth_authenticate, soup_auth_authenticate () +
+
soup_auth_can_authenticate, soup_auth_can_authenticate () +
+
soup_auth_domain_accepts, soup_auth_domain_accepts () +
+
soup_auth_domain_add_path, soup_auth_domain_add_path () +
+
SOUP_AUTH_DOMAIN_ADD_PATH, SOUP_AUTH_DOMAIN_ADD_PATH +
+
SOUP_AUTH_DOMAIN_BASIC_AUTH_CALLBACK, SOUP_AUTH_DOMAIN_BASIC_AUTH_CALLBACK +
+
SOUP_AUTH_DOMAIN_BASIC_AUTH_DATA, SOUP_AUTH_DOMAIN_BASIC_AUTH_DATA +
+
soup_auth_domain_basic_new, soup_auth_domain_basic_new () +
+
soup_auth_domain_basic_set_auth_callback, soup_auth_domain_basic_set_auth_callback () +
+
soup_auth_domain_challenge, soup_auth_domain_challenge () +
+
soup_auth_domain_check_password, soup_auth_domain_check_password () +
+
soup_auth_domain_covers, soup_auth_domain_covers () +
+
SOUP_AUTH_DOMAIN_DIGEST_AUTH_CALLBACK, SOUP_AUTH_DOMAIN_DIGEST_AUTH_CALLBACK +
+
SOUP_AUTH_DOMAIN_DIGEST_AUTH_DATA, SOUP_AUTH_DOMAIN_DIGEST_AUTH_DATA +
+
soup_auth_domain_digest_encode_password, soup_auth_domain_digest_encode_password () +
+
soup_auth_domain_digest_new, soup_auth_domain_digest_new () +
+
soup_auth_domain_digest_set_auth_callback, soup_auth_domain_digest_set_auth_callback () +
+
SOUP_AUTH_DOMAIN_FILTER, SOUP_AUTH_DOMAIN_FILTER +
+
SOUP_AUTH_DOMAIN_FILTER_DATA, SOUP_AUTH_DOMAIN_FILTER_DATA +
+
SOUP_AUTH_DOMAIN_GENERIC_AUTH_CALLBACK, SOUP_AUTH_DOMAIN_GENERIC_AUTH_CALLBACK +
+
SOUP_AUTH_DOMAIN_GENERIC_AUTH_DATA, SOUP_AUTH_DOMAIN_GENERIC_AUTH_DATA +
+
soup_auth_domain_get_realm, soup_auth_domain_get_realm () +
+
SOUP_AUTH_DOMAIN_PROXY, SOUP_AUTH_DOMAIN_PROXY +
+
SOUP_AUTH_DOMAIN_REALM, SOUP_AUTH_DOMAIN_REALM +
+
soup_auth_domain_remove_path, soup_auth_domain_remove_path () +
+
SOUP_AUTH_DOMAIN_REMOVE_PATH, SOUP_AUTH_DOMAIN_REMOVE_PATH +
+
soup_auth_domain_set_filter, soup_auth_domain_set_filter () +
+
soup_auth_domain_set_generic_auth_callback, soup_auth_domain_set_generic_auth_callback () +
+
soup_auth_free_protection_space, soup_auth_free_protection_space () +
+
soup_auth_get_authorization, soup_auth_get_authorization () +
+
soup_auth_get_host, soup_auth_get_host () +
+
soup_auth_get_info, soup_auth_get_info () +
+
soup_auth_get_protection_space, soup_auth_get_protection_space () +
+
soup_auth_get_realm, soup_auth_get_realm () +
+
soup_auth_get_scheme_name, soup_auth_get_scheme_name () +
+
SOUP_AUTH_HOST, SOUP_AUTH_HOST +
+
soup_auth_is_authenticated, soup_auth_is_authenticated () +
+
SOUP_AUTH_IS_AUTHENTICATED, SOUP_AUTH_IS_AUTHENTICATED +
+
soup_auth_is_for_proxy, soup_auth_is_for_proxy () +
+
SOUP_AUTH_IS_FOR_PROXY, SOUP_AUTH_IS_FOR_PROXY +
+
soup_auth_is_ready, soup_auth_is_ready () +
+
soup_auth_manager_clear_cached_credentials, soup_auth_manager_clear_cached_credentials () +
+
soup_auth_manager_use_auth, soup_auth_manager_use_auth () +
+
soup_auth_negotiate_supported, soup_auth_negotiate_supported () +
+
soup_auth_new, soup_auth_new () +
+
SOUP_AUTH_REALM, SOUP_AUTH_REALM +
+
SOUP_AUTH_SCHEME_NAME, SOUP_AUTH_SCHEME_NAME +
+
soup_auth_update, soup_auth_update () +
+
soup_buffer_copy, soup_buffer_copy () +
+
soup_buffer_free, soup_buffer_free () +
+
soup_buffer_get_as_bytes, soup_buffer_get_as_bytes () +
+
soup_buffer_get_data, soup_buffer_get_data () +
+
soup_buffer_get_owner, soup_buffer_get_owner () +
+
soup_buffer_new, soup_buffer_new () +
+
soup_buffer_new_subbuffer, soup_buffer_new_subbuffer () +
+
soup_buffer_new_take, soup_buffer_new_take () +
+
soup_buffer_new_with_owner, soup_buffer_new_with_owner () +
+
soup_cache_clear, soup_cache_clear () +
+
soup_cache_dump, soup_cache_dump () +
+
soup_cache_flush, soup_cache_flush () +
+
soup_cache_get_max_size, soup_cache_get_max_size () +
+
soup_cache_load, soup_cache_load () +
+
soup_cache_new, soup_cache_new () +
+
soup_cache_set_max_size, soup_cache_set_max_size () +
+
soup_check_version, soup_check_version () +
+
SOUP_CHECK_VERSION, SOUP_CHECK_VERSION() +
+
soup_client_context_get_address, soup_client_context_get_address () +
+
soup_client_context_get_auth_domain, soup_client_context_get_auth_domain () +
+
soup_client_context_get_auth_user, soup_client_context_get_auth_user () +
+
soup_client_context_get_gsocket, soup_client_context_get_gsocket () +
+
soup_client_context_get_host, soup_client_context_get_host () +
+
soup_client_context_get_local_address, soup_client_context_get_local_address () +
+
soup_client_context_get_remote_address, soup_client_context_get_remote_address () +
+
soup_client_context_get_socket, soup_client_context_get_socket () +
+
soup_client_context_steal_connection, soup_client_context_steal_connection () +
+
soup_content_sniffer_get_buffer_size, soup_content_sniffer_get_buffer_size () +
+
soup_content_sniffer_new, soup_content_sniffer_new () +
+
soup_content_sniffer_sniff, soup_content_sniffer_sniff () +
+
soup_cookies_free, soup_cookies_free () +
+
soup_cookies_from_request, soup_cookies_from_request () +
+
soup_cookies_from_response, soup_cookies_from_response () +
+
soup_cookies_to_cookie_header, soup_cookies_to_cookie_header () +
+
soup_cookies_to_request, soup_cookies_to_request () +
+
soup_cookies_to_response, soup_cookies_to_response () +
+
soup_cookie_applies_to_uri, soup_cookie_applies_to_uri () +
+
soup_cookie_copy, soup_cookie_copy () +
+
soup_cookie_domain_matches, soup_cookie_domain_matches () +
+
soup_cookie_free, soup_cookie_free () +
+
soup_cookie_get_domain, soup_cookie_get_domain () +
+
soup_cookie_get_expires, soup_cookie_get_expires () +
+
soup_cookie_get_http_only, soup_cookie_get_http_only () +
+
soup_cookie_get_name, soup_cookie_get_name () +
+
soup_cookie_get_path, soup_cookie_get_path () +
+
soup_cookie_get_secure, soup_cookie_get_secure () +
+
soup_cookie_get_value, soup_cookie_get_value () +
+
SOUP_COOKIE_JAR_ACCEPT_POLICY, SOUP_COOKIE_JAR_ACCEPT_POLICY +
+
soup_cookie_jar_add_cookie, soup_cookie_jar_add_cookie () +
+
soup_cookie_jar_add_cookie_with_first_party, soup_cookie_jar_add_cookie_with_first_party () +
+
soup_cookie_jar_all_cookies, soup_cookie_jar_all_cookies () +
+
SOUP_COOKIE_JAR_DB_FILENAME, SOUP_COOKIE_JAR_DB_FILENAME +
+
soup_cookie_jar_db_new, soup_cookie_jar_db_new () +
+
soup_cookie_jar_delete_cookie, soup_cookie_jar_delete_cookie () +
+
soup_cookie_jar_get_accept_policy, soup_cookie_jar_get_accept_policy () +
+
soup_cookie_jar_get_cookies, soup_cookie_jar_get_cookies () +
+
soup_cookie_jar_get_cookie_list, soup_cookie_jar_get_cookie_list () +
+
soup_cookie_jar_is_persistent, soup_cookie_jar_is_persistent () +
+
soup_cookie_jar_new, soup_cookie_jar_new () +
+
SOUP_COOKIE_JAR_READ_ONLY, SOUP_COOKIE_JAR_READ_ONLY +
+
soup_cookie_jar_set_accept_policy, soup_cookie_jar_set_accept_policy () +
+
soup_cookie_jar_set_cookie, soup_cookie_jar_set_cookie () +
+
soup_cookie_jar_set_cookie_with_first_party, soup_cookie_jar_set_cookie_with_first_party () +
+
SOUP_COOKIE_JAR_TEXT_FILENAME, SOUP_COOKIE_JAR_TEXT_FILENAME +
+
soup_cookie_jar_text_new, soup_cookie_jar_text_new () +
+
SOUP_COOKIE_MAX_AGE_ONE_DAY, SOUP_COOKIE_MAX_AGE_ONE_DAY +
+
SOUP_COOKIE_MAX_AGE_ONE_HOUR, SOUP_COOKIE_MAX_AGE_ONE_HOUR +
+
SOUP_COOKIE_MAX_AGE_ONE_WEEK, SOUP_COOKIE_MAX_AGE_ONE_WEEK +
+
SOUP_COOKIE_MAX_AGE_ONE_YEAR, SOUP_COOKIE_MAX_AGE_ONE_YEAR +
+
soup_cookie_new, soup_cookie_new () +
+
soup_cookie_parse, soup_cookie_parse () +
+
soup_cookie_set_domain, soup_cookie_set_domain () +
+
soup_cookie_set_expires, soup_cookie_set_expires () +
+
soup_cookie_set_http_only, soup_cookie_set_http_only () +
+
soup_cookie_set_max_age, soup_cookie_set_max_age () +
+
soup_cookie_set_name, soup_cookie_set_name () +
+
soup_cookie_set_path, soup_cookie_set_path () +
+
soup_cookie_set_secure, soup_cookie_set_secure () +
+
soup_cookie_set_value, soup_cookie_set_value () +
+
soup_cookie_to_cookie_header, soup_cookie_to_cookie_header () +
+
soup_cookie_to_set_cookie_header, soup_cookie_to_set_cookie_header () +
+
soup_date_free, soup_date_free () +
+
soup_date_get_day, soup_date_get_day () +
+
soup_date_get_hour, soup_date_get_hour () +
+
soup_date_get_minute, soup_date_get_minute () +
+
soup_date_get_month, soup_date_get_month () +
+
soup_date_get_offset, soup_date_get_offset () +
+
soup_date_get_second, soup_date_get_second () +
+
soup_date_get_utc, soup_date_get_utc () +
+
soup_date_get_year, soup_date_get_year () +
+
soup_date_is_past, soup_date_is_past () +
+
soup_date_new, soup_date_new () +
+
soup_date_new_from_now, soup_date_new_from_now () +
+
soup_date_new_from_string, soup_date_new_from_string () +
+
soup_date_new_from_time_t, soup_date_new_from_time_t () +
+
soup_date_to_string, soup_date_to_string () +
+
soup_date_to_timeval, soup_date_to_timeval () +
+
soup_date_to_time_t, soup_date_to_time_t () +
+
soup_form_decode, soup_form_decode () +
+
soup_form_decode_multipart, soup_form_decode_multipart () +
+
soup_form_encode, soup_form_encode () +
+
soup_form_encode_datalist, soup_form_encode_datalist () +
+
soup_form_encode_hash, soup_form_encode_hash () +
+
soup_form_encode_valist, soup_form_encode_valist () +
+
SOUP_FORM_MIME_TYPE_MULTIPART, SOUP_FORM_MIME_TYPE_MULTIPART +
+
SOUP_FORM_MIME_TYPE_URLENCODED, SOUP_FORM_MIME_TYPE_URLENCODED +
+
soup_form_request_new, soup_form_request_new () +
+
soup_form_request_new_from_datalist, soup_form_request_new_from_datalist () +
+
soup_form_request_new_from_hash, soup_form_request_new_from_hash () +
+
soup_form_request_new_from_multipart, soup_form_request_new_from_multipart () +
+
soup_get_major_version, soup_get_major_version () +
+
soup_get_micro_version, soup_get_micro_version () +
+
soup_get_minor_version, soup_get_minor_version () +
+
soup_headers_parse, soup_headers_parse () +
+
soup_headers_parse_request, soup_headers_parse_request () +
+
soup_headers_parse_response, soup_headers_parse_response () +
+
soup_headers_parse_status_line, soup_headers_parse_status_line () +
+
soup_header_contains, soup_header_contains () +
+
soup_header_free_list, soup_header_free_list () +
+
soup_header_free_param_list, soup_header_free_param_list () +
+
soup_header_g_string_append_param, soup_header_g_string_append_param () +
+
soup_header_g_string_append_param_quoted, soup_header_g_string_append_param_quoted () +
+
soup_header_parse_list, soup_header_parse_list () +
+
soup_header_parse_param_list, soup_header_parse_param_list () +
+
soup_header_parse_quality_list, soup_header_parse_quality_list () +
+
soup_header_parse_semi_param_list, soup_header_parse_semi_param_list () +
+
SOUP_HTTP_ERROR, SOUP_HTTP_ERROR +
+
soup_logger_new, soup_logger_new () +
+
soup_logger_set_printer, soup_logger_set_printer () +
+
soup_logger_set_request_filter, soup_logger_set_request_filter () +
+
soup_logger_set_response_filter, soup_logger_set_response_filter () +
+
SOUP_MAJOR_VERSION, SOUP_MAJOR_VERSION +
+
soup_message_add_header_handler, soup_message_add_header_handler () +
+
soup_message_add_status_code_handler, soup_message_add_status_code_handler () +
+
soup_message_body_append, soup_message_body_append () +
+
soup_message_body_append_buffer, soup_message_body_append_buffer () +
+
soup_message_body_append_take, soup_message_body_append_take () +
+
soup_message_body_complete, soup_message_body_complete () +
+
soup_message_body_flatten, soup_message_body_flatten () +
+
soup_message_body_free, soup_message_body_free () +
+
soup_message_body_get_accumulate, soup_message_body_get_accumulate () +
+
soup_message_body_get_chunk, soup_message_body_get_chunk () +
+
soup_message_body_got_chunk, soup_message_body_got_chunk () +
+
soup_message_body_new, soup_message_body_new () +
+
soup_message_body_set_accumulate, soup_message_body_set_accumulate () +
+
soup_message_body_truncate, soup_message_body_truncate () +
+
soup_message_body_wrote_chunk, soup_message_body_wrote_chunk () +
+
soup_message_disable_feature, soup_message_disable_feature () +
+
SOUP_MESSAGE_FIRST_PARTY, SOUP_MESSAGE_FIRST_PARTY +
+
SOUP_MESSAGE_FLAGS, SOUP_MESSAGE_FLAGS +
+
soup_message_get_address, soup_message_get_address () +
+
soup_message_get_first_party, soup_message_get_first_party () +
+
soup_message_get_flags, soup_message_get_flags () +
+
soup_message_get_https_status, soup_message_get_https_status () +
+
soup_message_get_http_version, soup_message_get_http_version () +
+
soup_message_get_priority, soup_message_get_priority () +
+
soup_message_get_soup_request, soup_message_get_soup_request () +
+
soup_message_get_uri, soup_message_get_uri () +
+
soup_message_headers_append, soup_message_headers_append () +
+
soup_message_headers_clean_connection_headers, soup_message_headers_clean_connection_headers () +
+
soup_message_headers_clear, soup_message_headers_clear () +
+
soup_message_headers_foreach, soup_message_headers_foreach () +
+
soup_message_headers_free, soup_message_headers_free () +
+
soup_message_headers_free_ranges, soup_message_headers_free_ranges () +
+
soup_message_headers_get_content_disposition, soup_message_headers_get_content_disposition () +
+
soup_message_headers_get_content_length, soup_message_headers_get_content_length () +
+
soup_message_headers_get_content_range, soup_message_headers_get_content_range () +
+
soup_message_headers_get_content_type, soup_message_headers_get_content_type () +
+
soup_message_headers_get_encoding, soup_message_headers_get_encoding () +
+
soup_message_headers_get_expectations, soup_message_headers_get_expectations () +
+
soup_message_headers_get_headers_type, soup_message_headers_get_headers_type () +
+
soup_message_headers_get_list, soup_message_headers_get_list () +
+
soup_message_headers_get_one, soup_message_headers_get_one () +
+
soup_message_headers_get_ranges, soup_message_headers_get_ranges () +
+
soup_message_headers_header_contains, soup_message_headers_header_contains () +
+
soup_message_headers_header_equals, soup_message_headers_header_equals () +
+
soup_message_headers_iter_init, soup_message_headers_iter_init () +
+
soup_message_headers_iter_next, soup_message_headers_iter_next () +
+
soup_message_headers_new, soup_message_headers_new () +
+
soup_message_headers_remove, soup_message_headers_remove () +
+
soup_message_headers_replace, soup_message_headers_replace () +
+
soup_message_headers_set_content_disposition, soup_message_headers_set_content_disposition () +
+
soup_message_headers_set_content_length, soup_message_headers_set_content_length () +
+
soup_message_headers_set_content_range, soup_message_headers_set_content_range () +
+
soup_message_headers_set_content_type, soup_message_headers_set_content_type () +
+
soup_message_headers_set_encoding, soup_message_headers_set_encoding () +
+
soup_message_headers_set_expectations, soup_message_headers_set_expectations () +
+
soup_message_headers_set_range, soup_message_headers_set_range () +
+
soup_message_headers_set_ranges, soup_message_headers_set_ranges () +
+
SOUP_MESSAGE_HTTP_VERSION, SOUP_MESSAGE_HTTP_VERSION +
+
soup_message_is_keepalive, soup_message_is_keepalive () +
+
SOUP_MESSAGE_METHOD, SOUP_MESSAGE_METHOD +
+
soup_message_new, soup_message_new () +
+
soup_message_new_from_uri, soup_message_new_from_uri () +
+
SOUP_MESSAGE_PRIORITY, SOUP_MESSAGE_PRIORITY +
+
SOUP_MESSAGE_REASON_PHRASE, SOUP_MESSAGE_REASON_PHRASE +
+
SOUP_MESSAGE_REQUEST_BODY, SOUP_MESSAGE_REQUEST_BODY +
+
SOUP_MESSAGE_REQUEST_BODY_DATA, SOUP_MESSAGE_REQUEST_BODY_DATA +
+
SOUP_MESSAGE_REQUEST_HEADERS, SOUP_MESSAGE_REQUEST_HEADERS +
+
SOUP_MESSAGE_RESPONSE_BODY, SOUP_MESSAGE_RESPONSE_BODY +
+
SOUP_MESSAGE_RESPONSE_BODY_DATA, SOUP_MESSAGE_RESPONSE_BODY_DATA +
+
SOUP_MESSAGE_RESPONSE_HEADERS, SOUP_MESSAGE_RESPONSE_HEADERS +
+
SOUP_MESSAGE_SERVER_SIDE, SOUP_MESSAGE_SERVER_SIDE +
+
soup_message_set_first_party, soup_message_set_first_party () +
+
soup_message_set_flags, soup_message_set_flags () +
+
soup_message_set_http_version, soup_message_set_http_version () +
+
soup_message_set_priority, soup_message_set_priority () +
+
soup_message_set_redirect, soup_message_set_redirect () +
+
soup_message_set_request, soup_message_set_request () +
+
soup_message_set_response, soup_message_set_response () +
+
soup_message_set_status, soup_message_set_status () +
+
soup_message_set_status_full, soup_message_set_status_full () +
+
soup_message_set_uri, soup_message_set_uri () +
+
SOUP_MESSAGE_STATUS_CODE, SOUP_MESSAGE_STATUS_CODE +
+
SOUP_MESSAGE_TLS_CERTIFICATE, SOUP_MESSAGE_TLS_CERTIFICATE +
+
SOUP_MESSAGE_TLS_ERRORS, SOUP_MESSAGE_TLS_ERRORS +
+
SOUP_MESSAGE_URI, SOUP_MESSAGE_URI +
+
SOUP_METHOD_CONNECT, SOUP_METHOD_CONNECT +
+
SOUP_METHOD_COPY, SOUP_METHOD_COPY +
+
SOUP_METHOD_DELETE, SOUP_METHOD_DELETE +
+
SOUP_METHOD_GET, SOUP_METHOD_GET +
+
SOUP_METHOD_HEAD, SOUP_METHOD_HEAD +
+
SOUP_METHOD_LOCK, SOUP_METHOD_LOCK +
+
SOUP_METHOD_MKCOL, SOUP_METHOD_MKCOL +
+
SOUP_METHOD_MOVE, SOUP_METHOD_MOVE +
+
SOUP_METHOD_OPTIONS, SOUP_METHOD_OPTIONS +
+
SOUP_METHOD_POST, SOUP_METHOD_POST +
+
SOUP_METHOD_PROPFIND, SOUP_METHOD_PROPFIND +
+
SOUP_METHOD_PROPPATCH, SOUP_METHOD_PROPPATCH +
+
SOUP_METHOD_PUT, SOUP_METHOD_PUT +
+
SOUP_METHOD_TRACE, SOUP_METHOD_TRACE +
+
SOUP_METHOD_UNLOCK, SOUP_METHOD_UNLOCK +
+
SOUP_MICRO_VERSION, SOUP_MICRO_VERSION +
+
SOUP_MINOR_VERSION, SOUP_MINOR_VERSION +
+
soup_multipart_append_form_file, soup_multipart_append_form_file () +
+
soup_multipart_append_form_string, soup_multipart_append_form_string () +
+
soup_multipart_append_part, soup_multipart_append_part () +
+
soup_multipart_free, soup_multipart_free () +
+
soup_multipart_get_length, soup_multipart_get_length () +
+
soup_multipart_get_part, soup_multipart_get_part () +
+
soup_multipart_input_stream_get_headers, soup_multipart_input_stream_get_headers () +
+
soup_multipart_input_stream_new, soup_multipart_input_stream_new () +
+
soup_multipart_input_stream_next_part, soup_multipart_input_stream_next_part () +
+
soup_multipart_input_stream_next_part_async, soup_multipart_input_stream_next_part_async () +
+
soup_multipart_input_stream_next_part_finish, soup_multipart_input_stream_next_part_finish () +
+
soup_multipart_new, soup_multipart_new () +
+
soup_multipart_new_from_message, soup_multipart_new_from_message () +
+
soup_multipart_to_message, soup_multipart_to_message () +
+
SOUP_REQUEST_ERROR, SOUP_REQUEST_ERROR +
+
soup_request_file_get_file, soup_request_file_get_file () +
+
soup_request_get_content_length, soup_request_get_content_length () +
+
soup_request_get_content_type, soup_request_get_content_type () +
+
soup_request_get_session, soup_request_get_session () +
+
soup_request_get_uri, soup_request_get_uri () +
+
soup_request_http_get_message, soup_request_http_get_message () +
+
soup_request_send, soup_request_send () +
+
soup_request_send_async, soup_request_send_async () +
+
soup_request_send_finish, soup_request_send_finish () +
+
SOUP_REQUEST_SESSION, SOUP_REQUEST_SESSION +
+
SOUP_REQUEST_URI, SOUP_REQUEST_URI +
+
soup_server_accept_iostream, soup_server_accept_iostream () +
+
soup_server_add_auth_domain, soup_server_add_auth_domain () +
+
soup_server_add_early_handler, soup_server_add_early_handler () +
+
soup_server_add_handler, soup_server_add_handler () +
+
soup_server_add_websocket_handler, soup_server_add_websocket_handler () +
+
SOUP_SERVER_ASYNC_CONTEXT, SOUP_SERVER_ASYNC_CONTEXT +
+
soup_server_disconnect, soup_server_disconnect () +
+
soup_server_get_async_context, soup_server_get_async_context () +
+
soup_server_get_listener, soup_server_get_listener () +
+
soup_server_get_listeners, soup_server_get_listeners () +
+
soup_server_get_port, soup_server_get_port () +
+
soup_server_get_uris, soup_server_get_uris () +
+
SOUP_SERVER_HTTPS_ALIASES, SOUP_SERVER_HTTPS_ALIASES +
+
SOUP_SERVER_HTTP_ALIASES, SOUP_SERVER_HTTP_ALIASES +
+
SOUP_SERVER_INTERFACE, SOUP_SERVER_INTERFACE +
+
soup_server_is_https, soup_server_is_https () +
+
soup_server_listen, soup_server_listen () +
+
soup_server_listen_all, soup_server_listen_all () +
+
soup_server_listen_fd, soup_server_listen_fd () +
+
soup_server_listen_local, soup_server_listen_local () +
+
soup_server_listen_socket, soup_server_listen_socket () +
+
soup_server_new, soup_server_new () +
+
soup_server_pause_message, soup_server_pause_message () +
+
SOUP_SERVER_PORT, SOUP_SERVER_PORT +
+
soup_server_quit, soup_server_quit () +
+
SOUP_SERVER_RAW_PATHS, SOUP_SERVER_RAW_PATHS +
+
soup_server_remove_auth_domain, soup_server_remove_auth_domain () +
+
soup_server_remove_handler, soup_server_remove_handler () +
+
soup_server_run, soup_server_run () +
+
soup_server_run_async, soup_server_run_async () +
+
SOUP_SERVER_SERVER_HEADER, SOUP_SERVER_SERVER_HEADER +
+
soup_server_set_ssl_cert_file, soup_server_set_ssl_cert_file () +
+
SOUP_SERVER_SSL_CERT_FILE, SOUP_SERVER_SSL_CERT_FILE +
+
SOUP_SERVER_SSL_KEY_FILE, SOUP_SERVER_SSL_KEY_FILE +
+
SOUP_SERVER_TLS_CERTIFICATE, SOUP_SERVER_TLS_CERTIFICATE +
+
soup_server_unpause_message, soup_server_unpause_message () +
+
soup_session_abort, soup_session_abort () +
+
SOUP_SESSION_ACCEPT_LANGUAGE, SOUP_SESSION_ACCEPT_LANGUAGE +
+
SOUP_SESSION_ACCEPT_LANGUAGE_AUTO, SOUP_SESSION_ACCEPT_LANGUAGE_AUTO +
+
soup_session_add_feature, soup_session_add_feature () +
+
SOUP_SESSION_ADD_FEATURE, SOUP_SESSION_ADD_FEATURE +
+
soup_session_add_feature_by_type, soup_session_add_feature_by_type () +
+
SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_SESSION_ADD_FEATURE_BY_TYPE +
+
SOUP_SESSION_ASYNC_CONTEXT, SOUP_SESSION_ASYNC_CONTEXT +
+
soup_session_cancel_message, soup_session_cancel_message () +
+
soup_session_connect_async, soup_session_connect_async () +
+
soup_session_connect_finish, soup_session_connect_finish () +
+
soup_session_get_async_context, soup_session_get_async_context () +
+
soup_session_get_feature, soup_session_get_feature () +
+
soup_session_get_features, soup_session_get_features () +
+
soup_session_get_feature_for_message, soup_session_get_feature_for_message () +
+
soup_session_has_feature, soup_session_has_feature () +
+
SOUP_SESSION_HTTPS_ALIASES, SOUP_SESSION_HTTPS_ALIASES +
+
SOUP_SESSION_HTTP_ALIASES, SOUP_SESSION_HTTP_ALIASES +
+
SOUP_SESSION_IDLE_TIMEOUT, SOUP_SESSION_IDLE_TIMEOUT +
+
SOUP_SESSION_LOCAL_ADDRESS, SOUP_SESSION_LOCAL_ADDRESS +
+
SOUP_SESSION_MAX_CONNS, SOUP_SESSION_MAX_CONNS +
+
SOUP_SESSION_MAX_CONNS_PER_HOST, SOUP_SESSION_MAX_CONNS_PER_HOST +
+
soup_session_new, soup_session_new () +
+
soup_session_new_with_options, soup_session_new_with_options () +
+
soup_session_pause_message, soup_session_pause_message () +
+
soup_session_prefetch_dns, soup_session_prefetch_dns () +
+
SOUP_SESSION_PROXY_RESOLVER, SOUP_SESSION_PROXY_RESOLVER +
+
SOUP_SESSION_PROXY_URI, SOUP_SESSION_PROXY_URI +
+
soup_session_queue_message, soup_session_queue_message () +
+
soup_session_redirect_message, soup_session_redirect_message () +
+
soup_session_remove_feature, soup_session_remove_feature () +
+
soup_session_remove_feature_by_type, soup_session_remove_feature_by_type () +
+
SOUP_SESSION_REMOVE_FEATURE_BY_TYPE, SOUP_SESSION_REMOVE_FEATURE_BY_TYPE +
+
soup_session_request, soup_session_request () +
+
soup_session_request_http, soup_session_request_http () +
+
soup_session_request_http_uri, soup_session_request_http_uri () +
+
soup_session_request_uri, soup_session_request_uri () +
+
soup_session_requeue_message, soup_session_requeue_message () +
+
soup_session_send, soup_session_send () +
+
soup_session_send_async, soup_session_send_async () +
+
soup_session_send_finish, soup_session_send_finish () +
+
soup_session_send_message, soup_session_send_message () +
+
SOUP_SESSION_SSL_CA_FILE, SOUP_SESSION_SSL_CA_FILE +
+
SOUP_SESSION_SSL_STRICT, SOUP_SESSION_SSL_STRICT +
+
SOUP_SESSION_SSL_USE_SYSTEM_CA_FILE, SOUP_SESSION_SSL_USE_SYSTEM_CA_FILE +
+
soup_session_steal_connection, soup_session_steal_connection () +
+
SOUP_SESSION_TIMEOUT, SOUP_SESSION_TIMEOUT +
+
SOUP_SESSION_TLS_DATABASE, SOUP_SESSION_TLS_DATABASE +
+
SOUP_SESSION_TLS_INTERACTION, SOUP_SESSION_TLS_INTERACTION +
+
soup_session_unpause_message, soup_session_unpause_message () +
+
SOUP_SESSION_USER_AGENT, SOUP_SESSION_USER_AGENT +
+
SOUP_SESSION_USE_THREAD_CONTEXT, SOUP_SESSION_USE_THREAD_CONTEXT +
+
soup_session_websocket_connect_async, soup_session_websocket_connect_async () +
+
soup_session_websocket_connect_finish, soup_session_websocket_connect_finish () +
+
soup_session_would_redirect, soup_session_would_redirect () +
+
SOUP_SOCKET_ASYNC_CONTEXT, SOUP_SOCKET_ASYNC_CONTEXT +
+
soup_socket_connect_async, soup_socket_connect_async () +
+
soup_socket_connect_sync, soup_socket_connect_sync () +
+
soup_socket_disconnect, soup_socket_disconnect () +
+
SOUP_SOCKET_FLAG_NONBLOCKING, SOUP_SOCKET_FLAG_NONBLOCKING +
+
soup_socket_get_fd, soup_socket_get_fd () +
+
soup_socket_get_local_address, soup_socket_get_local_address () +
+
soup_socket_get_remote_address, soup_socket_get_remote_address () +
+
soup_socket_is_connected, soup_socket_is_connected () +
+
SOUP_SOCKET_IS_SERVER, SOUP_SOCKET_IS_SERVER +
+
soup_socket_is_ssl, soup_socket_is_ssl () +
+
soup_socket_listen, soup_socket_listen () +
+
SOUP_SOCKET_LOCAL_ADDRESS, SOUP_SOCKET_LOCAL_ADDRESS +
+
soup_socket_new, soup_socket_new () +
+
soup_socket_read, soup_socket_read () +
+
soup_socket_read_until, soup_socket_read_until () +
+
SOUP_SOCKET_REMOTE_ADDRESS, SOUP_SOCKET_REMOTE_ADDRESS +
+
SOUP_SOCKET_SSL_CREDENTIALS, SOUP_SOCKET_SSL_CREDENTIALS +
+
SOUP_SOCKET_SSL_FALLBACK, SOUP_SOCKET_SSL_FALLBACK +
+
SOUP_SOCKET_SSL_STRICT, SOUP_SOCKET_SSL_STRICT +
+
soup_socket_start_proxy_ssl, soup_socket_start_proxy_ssl () +
+
soup_socket_start_ssl, soup_socket_start_ssl () +
+
SOUP_SOCKET_TIMEOUT, SOUP_SOCKET_TIMEOUT +
+
SOUP_SOCKET_TLS_CERTIFICATE, SOUP_SOCKET_TLS_CERTIFICATE +
+
SOUP_SOCKET_TLS_ERRORS, SOUP_SOCKET_TLS_ERRORS +
+
SOUP_SOCKET_TRUSTED_CERTIFICATE, SOUP_SOCKET_TRUSTED_CERTIFICATE +
+
SOUP_SOCKET_USE_THREAD_CONTEXT, SOUP_SOCKET_USE_THREAD_CONTEXT +
+
soup_socket_write, soup_socket_write () +
+
soup_status_get_phrase, soup_status_get_phrase () +
+
SOUP_STATUS_IS_CLIENT_ERROR, SOUP_STATUS_IS_CLIENT_ERROR() +
+
SOUP_STATUS_IS_INFORMATIONAL, SOUP_STATUS_IS_INFORMATIONAL() +
+
SOUP_STATUS_IS_REDIRECTION, SOUP_STATUS_IS_REDIRECTION() +
+
SOUP_STATUS_IS_SERVER_ERROR, SOUP_STATUS_IS_SERVER_ERROR() +
+
SOUP_STATUS_IS_SUCCESSFUL, SOUP_STATUS_IS_SUCCESSFUL() +
+
SOUP_STATUS_IS_TRANSPORT_ERROR, SOUP_STATUS_IS_TRANSPORT_ERROR() +
+
soup_status_proxify, soup_status_proxify () +
+
soup_str_case_equal, soup_str_case_equal () +
+
soup_str_case_hash, soup_str_case_hash () +
+
soup_tld_domain_is_public_suffix, soup_tld_domain_is_public_suffix () +
+
SOUP_TLD_ERROR, SOUP_TLD_ERROR +
+
soup_tld_get_base_domain, soup_tld_get_base_domain () +
+
SOUP_TYPE_AUTH_BASIC, SOUP_TYPE_AUTH_BASIC +
+
SOUP_TYPE_AUTH_DIGEST, SOUP_TYPE_AUTH_DIGEST +
+
SOUP_TYPE_AUTH_MANAGER, SOUP_TYPE_AUTH_MANAGER +
+
SOUP_TYPE_AUTH_NEGOTIATE, SOUP_TYPE_AUTH_NEGOTIATE +
+
SOUP_TYPE_AUTH_NTLM, SOUP_TYPE_AUTH_NTLM +
+
soup_uri_copy, soup_uri_copy () +
+
soup_uri_copy_host, soup_uri_copy_host () +
+
soup_uri_decode, soup_uri_decode () +
+
soup_uri_encode, soup_uri_encode () +
+
soup_uri_equal, soup_uri_equal () +
+
soup_uri_free, soup_uri_free () +
+
soup_uri_get_fragment, soup_uri_get_fragment () +
+
soup_uri_get_host, soup_uri_get_host () +
+
soup_uri_get_password, soup_uri_get_password () +
+
soup_uri_get_path, soup_uri_get_path () +
+
soup_uri_get_port, soup_uri_get_port () +
+
soup_uri_get_query, soup_uri_get_query () +
+
soup_uri_get_scheme, soup_uri_get_scheme () +
+
soup_uri_get_user, soup_uri_get_user () +
+
soup_uri_host_equal, soup_uri_host_equal () +
+
soup_uri_host_hash, soup_uri_host_hash () +
+
SOUP_URI_IS_VALID, SOUP_URI_IS_VALID() +
+
soup_uri_new, soup_uri_new () +
+
soup_uri_new_with_base, soup_uri_new_with_base () +
+
soup_uri_normalize, soup_uri_normalize () +
+
SOUP_URI_SCHEME_DATA, SOUP_URI_SCHEME_DATA +
+
SOUP_URI_SCHEME_FILE, SOUP_URI_SCHEME_FILE +
+
SOUP_URI_SCHEME_FTP, SOUP_URI_SCHEME_FTP +
+
SOUP_URI_SCHEME_HTTP, SOUP_URI_SCHEME_HTTP +
+
SOUP_URI_SCHEME_HTTPS, SOUP_URI_SCHEME_HTTPS +
+
SOUP_URI_SCHEME_RESOURCE, SOUP_URI_SCHEME_RESOURCE +
+
SOUP_URI_SCHEME_WS, SOUP_URI_SCHEME_WS +
+
SOUP_URI_SCHEME_WSS, SOUP_URI_SCHEME_WSS +
+
soup_uri_set_fragment, soup_uri_set_fragment () +
+
soup_uri_set_host, soup_uri_set_host () +
+
soup_uri_set_password, soup_uri_set_password () +
+
soup_uri_set_path, soup_uri_set_path () +
+
soup_uri_set_port, soup_uri_set_port () +
+
soup_uri_set_query, soup_uri_set_query () +
+
soup_uri_set_query_from_fields, soup_uri_set_query_from_fields () +
+
soup_uri_set_query_from_form, soup_uri_set_query_from_form () +
+
soup_uri_set_scheme, soup_uri_set_scheme () +
+
soup_uri_set_user, soup_uri_set_user () +
+
soup_uri_to_string, soup_uri_to_string () +
+
soup_uri_uses_default_port, soup_uri_uses_default_port () +
+
SOUP_URI_VALID_FOR_HTTP, SOUP_URI_VALID_FOR_HTTP() +
+
SOUP_VERSION_2_24, SOUP_VERSION_2_24 +
+
SOUP_VERSION_2_26, SOUP_VERSION_2_26 +
+
SOUP_VERSION_2_28, SOUP_VERSION_2_28 +
+
SOUP_VERSION_2_30, SOUP_VERSION_2_30 +
+
SOUP_VERSION_2_32, SOUP_VERSION_2_32 +
+
SOUP_VERSION_2_34, SOUP_VERSION_2_34 +
+
SOUP_VERSION_2_36, SOUP_VERSION_2_36 +
+
SOUP_VERSION_2_38, SOUP_VERSION_2_38 +
+
SOUP_VERSION_2_40, SOUP_VERSION_2_40 +
+
SOUP_VERSION_2_42, SOUP_VERSION_2_42 +
+
SOUP_VERSION_2_44, SOUP_VERSION_2_44 +
+
SOUP_VERSION_2_46, SOUP_VERSION_2_46 +
+
SOUP_VERSION_2_48, SOUP_VERSION_2_48 +
+
SOUP_VERSION_2_50, SOUP_VERSION_2_50 +
+
SOUP_VERSION_2_52, SOUP_VERSION_2_52 +
+
SOUP_VERSION_MAX_ALLOWED, SOUP_VERSION_MAX_ALLOWED +
+
SOUP_VERSION_MIN_REQUIRED, SOUP_VERSION_MIN_REQUIRED +
+
soup_websocket_client_prepare_handshake, soup_websocket_client_prepare_handshake () +
+
soup_websocket_client_verify_handshake, soup_websocket_client_verify_handshake () +
+
soup_websocket_connection_close, soup_websocket_connection_close () +
+
soup_websocket_connection_get_close_code, soup_websocket_connection_get_close_code () +
+
soup_websocket_connection_get_close_data, soup_websocket_connection_get_close_data () +
+
soup_websocket_connection_get_connection_type, soup_websocket_connection_get_connection_type () +
+
soup_websocket_connection_get_io_stream, soup_websocket_connection_get_io_stream () +
+
soup_websocket_connection_get_origin, soup_websocket_connection_get_origin () +
+
soup_websocket_connection_get_protocol, soup_websocket_connection_get_protocol () +
+
soup_websocket_connection_get_state, soup_websocket_connection_get_state () +
+
soup_websocket_connection_get_uri, soup_websocket_connection_get_uri () +
+
soup_websocket_connection_new, soup_websocket_connection_new () +
+
soup_websocket_connection_send_binary, soup_websocket_connection_send_binary () +
+
soup_websocket_connection_send_text, soup_websocket_connection_send_text () +
+
SOUP_WEBSOCKET_ERROR, SOUP_WEBSOCKET_ERROR +
+
soup_websocket_server_check_handshake, soup_websocket_server_check_handshake () +
+
soup_websocket_server_process_handshake, soup_websocket_server_process_handshake () +
+
soup_xmlrpc_build_fault, soup_xmlrpc_build_fault () +
+
soup_xmlrpc_build_request, soup_xmlrpc_build_request () +
+
soup_xmlrpc_build_response, soup_xmlrpc_build_response () +
+
SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR +
+
SOUP_XMLRPC_FAULT, SOUP_XMLRPC_FAULT +
+
soup_xmlrpc_message_new, soup_xmlrpc_message_new () +
+
soup_xmlrpc_message_set_fault, soup_xmlrpc_message_set_fault () +
+
soup_xmlrpc_message_set_response, soup_xmlrpc_message_set_response () +
+
soup_xmlrpc_params_free, soup_xmlrpc_params_free () +
+
soup_xmlrpc_params_parse, soup_xmlrpc_params_parse () +
+
soup_xmlrpc_parse_request, soup_xmlrpc_parse_request () +
+
soup_xmlrpc_parse_response, soup_xmlrpc_parse_response () +
+
soup_xmlrpc_variant_get_datetime, soup_xmlrpc_variant_get_datetime () +
+
soup_xmlrpc_variant_new_datetime, soup_xmlrpc_variant_new_datetime () +
+
+
+
+ + + \ No newline at end of file diff --git a/docs/reference/html/left-insensitive.png b/docs/reference/html/left-insensitive.png new file mode 100644 index 0000000..3269393 Binary files /dev/null and b/docs/reference/html/left-insensitive.png differ diff --git a/docs/reference/html/left.png b/docs/reference/html/left.png new file mode 100644 index 0000000..2abde03 Binary files /dev/null and b/docs/reference/html/left.png differ diff --git a/docs/reference/html/libsoup-2.4-HTML-Form-Support.html b/docs/reference/html/libsoup-2.4-HTML-Form-Support.html new file mode 100644 index 0000000..e823d17 --- /dev/null +++ b/docs/reference/html/libsoup-2.4-HTML-Form-Support.html @@ -0,0 +1,640 @@ + + + + +HTML Form Support: libsoup Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

HTML Form Support

+

HTML Form Support — HTML form handling

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+GHashTable * + +soup_form_decode () +
+GHashTable * + +soup_form_decode_multipart () +
+char * + +soup_form_encode () +
+char * + +soup_form_encode_datalist () +
+char * + +soup_form_encode_hash () +
+char * + +soup_form_encode_valist () +
+SoupMessage * + +soup_form_request_new () +
+SoupMessage * + +soup_form_request_new_from_datalist () +
+SoupMessage * + +soup_form_request_new_from_hash () +
+SoupMessage * + +soup_form_request_new_from_multipart () +
+
+
+

Types and Values

+
++++ + + + + + + + + + + +
#defineSOUP_FORM_MIME_TYPE_MULTIPART
#defineSOUP_FORM_MIME_TYPE_URLENCODED
+
+
+

Includes

+
#include <libsoup/soup.h>
+
+
+
+

Description

+

libsoup contains several help methods for processing HTML forms as +defined by the +HTML 4.01 specification.

+
+
+

Functions

+
+

soup_form_decode ()

+
GHashTable *
+soup_form_decode (const char *encoded_form);
+

Decodes form +, which is an urlencoded dataset as defined in the +HTML 4.01 spec.

+
+

Parameters

+
+++++ + + + + + +

encoded_form

data of type "application/x-www-form-urlencoded"

 
+
+
+

Returns

+

a hash +table containing the name/value pairs from encoded_form +, which you +can free with g_hash_table_destroy().

+

[element-type utf8 utf8][transfer container]

+
+
+
+
+

soup_form_decode_multipart ()

+
GHashTable *
+soup_form_decode_multipart (SoupMessage *msg,
+                            const char *file_control_name,
+                            char **filename,
+                            char **content_type,
+                            SoupBuffer **file);
+

Decodes the "multipart/form-data" request in msg +; this is a +convenience method for the case when you have a single file upload +control in a form. (Or when you don't have any file upload +controls, but are still using "multipart/form-data" anyway.) Pass +the name of the file upload control in file_control_name +, and +soup_form_decode_multipart() will extract the uploaded file data +into filename +, content_type +, and file +. All of the other form +control data will be returned (as strings, as with +soup_form_decode()) in the returned GHashTable.

+

You may pass NULL for filename +, content_type + and/or file + if you do not +care about those fields. soup_form_decode_multipart() may also +return NULL in those fields if the client did not provide that +information. You must free the returned filename and content-type +with g_free(), and the returned file data with soup_buffer_free().

+

If you have a form with more than one file upload control, you will +need to decode it manually, using soup_multipart_new_from_message() +and soup_multipart_get_part().

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

msg

a SoupMessage containing a "multipart/form-data" request body

 

file_control_name

the name of the HTML file upload control, or NULL.

[allow-none]

filename

return location for the name of the uploaded file, or NULL.

[out][allow-none]

content_type

return location for the MIME type of the uploaded file, or NULL.

[out][allow-none]

file

return location for the uploaded file data, or NULL.

[out][allow-none]
+
+
+

Returns

+

a hash table containing the name/value pairs (other than +file_control_name +) from msg +, which you can free with +g_hash_table_destroy(). On error, it will return NULL.

+

[nullable][element-type utf8 utf8][transfer container]

+
+

Since: 2.26

+
+
+
+

soup_form_encode ()

+
char *
+soup_form_encode (const char *first_field,
+                  ...);
+

Encodes the given field names and values into a value of type +"application/x-www-form-urlencoded", as defined in the HTML 4.01 +spec.

+

This method requires you to know the names of the form fields (or +at the very least, the total number of fields) at compile time; for +working with dynamic forms, use soup_form_encode_hash() or +soup_form_encode_datalist().

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

first_field

name of the first form field

 

...

value of first_field +, followed by additional field names +and values, terminated by NULL.

 
+
+
+

Returns

+

the encoded form

+
+
+
+
+

soup_form_encode_datalist ()

+
char *
+soup_form_encode_datalist (GData **form_data_set);
+

Encodes form_data_set + into a value of type +"application/x-www-form-urlencoded", as defined in the HTML 4.01 +spec. Unlike soup_form_encode_hash(), this preserves the ordering +of the form elements, which may be required in some situations.

+
+

Parameters

+
+++++ + + + + + +

form_data_set

a datalist containing name/value pairs

 
+
+
+

Returns

+

the encoded form

+
+
+
+
+

soup_form_encode_hash ()

+
char *
+soup_form_encode_hash (GHashTable *form_data_set);
+

Encodes form_data_set + into a value of type +"application/x-www-form-urlencoded", as defined in the HTML 4.01 +spec.

+

Note that the HTML spec states that "The control names/values are +listed in the order they appear in the document." Since this method +takes a hash table, it cannot enforce that; if you care about the +ordering of the form fields, use soup_form_encode_datalist().

+
+

Parameters

+
+++++ + + + + + +

form_data_set

a hash table containing +name/value pairs (as strings).

[element-type utf8 utf8]
+
+
+

Returns

+

the encoded form

+
+
+
+
+

soup_form_encode_valist ()

+
char *
+soup_form_encode_valist (const char *first_field,
+                         va_list args);
+

See soup_form_encode(). This is mostly an internal method, used by +various other methods such as soup_uri_set_query_from_fields() and +soup_form_request_new().

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

first_field

name of the first form field

 

args

pointer to additional values, as in soup_form_encode()

 
+
+
+

Returns

+

the encoded form

+
+
+
+
+

soup_form_request_new ()

+
SoupMessage *
+soup_form_request_new (const char *method,
+                       const char *uri,
+                       const char *first_field,
+                       ...);
+

Creates a new SoupMessage and sets it up to send the given data +to uri + via method +. (That is, if method + is "GET", it will encode +the form data into uri +'s query field, and if method + is "POST", it +will encode it into the SoupMessage's request_body.)

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

method

the HTTP method, either "GET" or "POST"

 

uri

the URI to send the form data to

 

first_field

name of the first form field

 

...

value of first_field +, followed by additional field names +and values, terminated by NULL.

 
+
+
+

Returns

+

the new SoupMessage.

+

[transfer full]

+
+
+
+
+

soup_form_request_new_from_datalist ()

+
SoupMessage *
+soup_form_request_new_from_datalist (const char *method,
+                                     const char *uri,
+                                     GData **form_data_set);
+

Creates a new SoupMessage and sets it up to send form_data_set + to +uri + via method +, as with soup_form_request_new().

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

method

the HTTP method, either "GET" or "POST"

 

uri

the URI to send the form data to

 

form_data_set

the data to send to uri +

 
+
+
+

Returns

+

the new SoupMessage.

+

[transfer full]

+
+
+
+
+

soup_form_request_new_from_hash ()

+
SoupMessage *
+soup_form_request_new_from_hash (const char *method,
+                                 const char *uri,
+                                 GHashTable *form_data_set);
+

Creates a new SoupMessage and sets it up to send form_data_set + to +uri + via method +, as with soup_form_request_new().

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

method

the HTTP method, either "GET" or "POST"

 

uri

the URI to send the form data to

 

form_data_set

the data to send to uri +.

[element-type utf8 utf8]
+
+
+

Returns

+

the new SoupMessage.

+

[transfer full]

+
+
+
+
+

soup_form_request_new_from_multipart ()

+
SoupMessage *
+soup_form_request_new_from_multipart (const char *uri,
+                                      SoupMultipart *multipart);
+

Creates a new SoupMessage and sets it up to send multipart + to +uri + via POST.

+

To send a "multipart/form-data" POST, first +create a SoupMultipart, using SOUP_FORM_MIME_TYPE_MULTIPART as +the MIME type. Then use soup_multipart_append_form_string() and +soup_multipart_append_form_file() to add the value of each form +control to the multipart. (These are just convenience methods, and +you can use soup_multipart_append_part() if you need greater +control over the part headers.) Finally, call +soup_form_request_new_from_multipart() to serialize the multipart +structure and create a SoupMessage.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

uri

the URI to send the form data to

 

multipart

a "multipart/form-data" SoupMultipart

 
+
+
+

Returns

+

the new SoupMessage.

+

[transfer full]

+
+

Since: 2.26

+
+
+
+

Types and Values

+
+

SOUP_FORM_MIME_TYPE_MULTIPART

+
#define SOUP_FORM_MIME_TYPE_MULTIPART  "multipart/form-data"
+
+

A macro containing the value +"multipart/form-data"; the MIME type used for +posting form data that contains files to be uploaded.

+

Since: 2.26

+
+
+
+

SOUP_FORM_MIME_TYPE_URLENCODED

+
#define SOUP_FORM_MIME_TYPE_URLENCODED "application/x-www-form-urlencoded"
+
+

A macro containing the value +"application/x-www-form-urlencoded"; the default +MIME type for POSTing HTML form data.

+

Since: 2.26

+
+
+
+

See Also

+

SoupMultipart

+
+
+ + + \ No newline at end of file diff --git a/docs/reference/html/libsoup-2.4-Soup-Miscellaneous-Utilities.html b/docs/reference/html/libsoup-2.4-Soup-Miscellaneous-Utilities.html new file mode 100644 index 0000000..4b8511c --- /dev/null +++ b/docs/reference/html/libsoup-2.4-Soup-Miscellaneous-Utilities.html @@ -0,0 +1,1934 @@ + + + + +Soup Miscellaneous Utilities: libsoup Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

Soup Miscellaneous Utilities

+

Soup Miscellaneous Utilities — Miscellaneous functions

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+SoupDate * + +soup_date_new () +
+SoupDate * + +soup_date_new_from_string () +
+SoupDate * + +soup_date_new_from_time_t () +
+SoupDate * + +soup_date_new_from_now () +
+char * + +soup_date_to_string () +
+time_t + +soup_date_to_time_t () +
+void + +soup_date_to_timeval () +
+gboolean + +soup_date_is_past () +
+int + +soup_date_get_day () +
+int + +soup_date_get_hour () +
+int + +soup_date_get_minute () +
+int + +soup_date_get_month () +
+int + +soup_date_get_offset () +
+int + +soup_date_get_second () +
+int + +soup_date_get_utc () +
+int + +soup_date_get_year () +
+void + +soup_date_free () +
+guint + +soup_headers_parse_request () +
+gboolean + +soup_headers_parse_response () +
+gboolean + +soup_headers_parse_status_line () +
+gboolean + +soup_headers_parse () +
+GSList * + +soup_header_parse_list () +
+GSList * + +soup_header_parse_quality_list () +
+void + +soup_header_free_list () +
+gboolean + +soup_header_contains () +
+GHashTable * + +soup_header_parse_param_list () +
+GHashTable * + +soup_header_parse_semi_param_list () +
+void + +soup_header_free_param_list () +
+void + +soup_header_g_string_append_param () +
+void + +soup_header_g_string_append_param_quoted () +
+gboolean + +soup_str_case_equal () +
+guint + +soup_str_case_hash () +
+GSource * + +soup_add_completion () +
+GSource * + +soup_add_idle () +
+GSource * + +soup_add_io_watch () +
+GSource * + +soup_add_timeout () +
+
+
+

Types and Values

+
++++ + + + + + + + + + + +
 SoupDate
enumSoupDateFormat
+
+
+

Object Hierarchy

+
    GBoxed
+    ╰── SoupDate
+
+
+
+

Includes

+
#include <libsoup/soup.h>
+
+
+
+

Description

+
+
+

Functions

+
+

soup_date_new ()

+
SoupDate *
+soup_date_new (int year,
+               int month,
+               int day,
+               int hour,
+               int minute,
+               int second);
+

Creates a SoupDate representing the indicated time, UTC.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

year

the year (1-9999)

 

month

the month (1-12)

 

day

the day of the month (1-31, as appropriate for month +)

 

hour

the hour (0-23)

 

minute

the minute (0-59)

 

second

the second (0-59, or up to 61 for leap seconds)

 
+
+
+

Returns

+

a new SoupDate

+
+
+
+
+

soup_date_new_from_string ()

+
SoupDate *
+soup_date_new_from_string (const char *date_string);
+

Parses date_string + and tries to extract a date from it. This +recognizes all of the "HTTP-date" formats from RFC 2616, all ISO +8601 formats containing both a time and a date, RFC 2822 dates, +and reasonable approximations thereof. (Eg, it is lenient about +whitespace, leading "0"s, etc.)

+
+

Parameters

+
+++++ + + + + + +

date_string

the date in some plausible format

 
+
+
+

Returns

+

a new SoupDate, or NULL if date_string +could not be parsed.

+

[nullable]

+
+
+
+
+

soup_date_new_from_time_t ()

+
SoupDate *
+soup_date_new_from_time_t (time_t when);
+

Creates a SoupDate corresponding to when +

+
+

Parameters

+
+++++ + + + + + +

when

a time_t

 
+
+
+

Returns

+

a new SoupDate

+
+
+
+
+

soup_date_new_from_now ()

+
SoupDate *
+soup_date_new_from_now (int offset_seconds);
+

Creates a SoupDate representing a time offset_seconds + after the +current time (or before it, if offset_seconds + is negative). If +offset_seconds is 0, returns the current time.

+

If offset_seconds + would indicate a time not expressible as a

+time_t, the return value will be clamped into range. +
+

Parameters

+
+++++ + + + + + +

offset_seconds

offset from current time

 
+
+
+

Returns

+

a new SoupDate

+
+
+
+
+

soup_date_to_string ()

+
char *
+soup_date_to_string (SoupDate *date,
+                     SoupDateFormat format);
+

Converts date + to a string in the format described by format +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

date

a SoupDate

 

format

the format to generate the date in

 
+
+
+

Returns

+

date +as a string

+
+
+
+
+

soup_date_to_time_t ()

+
time_t
+soup_date_to_time_t (SoupDate *date);
+

Converts date + to a time_t.

+

If date + is not representable as a time_t, it will be +clamped into range. (In particular, some HTTP cookies have +expiration dates after "Y2.038k" (2038-01-19T03:14:07Z).)

+
+

Parameters

+
+++++ + + + + + +

date

a SoupDate

 
+
+
+

Returns

+

date +as a time_t

+
+
+
+
+

soup_date_to_timeval ()

+
void
+soup_date_to_timeval (SoupDate *date,
+                      GTimeVal *time);
+

Converts date + to a GTimeVal.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

date

a SoupDate

 

time

a GTimeVal structure in which to store the converted time.

[out]
+
+

Since: 2.24

+
+
+
+

soup_date_is_past ()

+
gboolean
+soup_date_is_past (SoupDate *date);
+

Determines if date + is in the past.

+
+

Parameters

+
+++++ + + + + + +

date

a SoupDate

 
+
+
+

Returns

+

TRUE if date +is in the past

+
+

Since: 2.24

+
+
+
+

soup_date_get_day ()

+
int
+soup_date_get_day (SoupDate *date);
+

Gets date +'s day.

+
+

Parameters

+
+++++ + + + + + +

date

a SoupDate

 
+
+
+

Returns

+

date +'s day

+
+

Since: 2.32

+
+
+
+

soup_date_get_hour ()

+
int
+soup_date_get_hour (SoupDate *date);
+

Gets date +'s hour.

+
+

Parameters

+
+++++ + + + + + +

date

a SoupDate

 
+
+
+

Returns

+

date +'s hour

+
+

Since: 2.32

+
+
+
+

soup_date_get_minute ()

+
int
+soup_date_get_minute (SoupDate *date);
+

Gets date +'s minute.

+
+

Parameters

+
+++++ + + + + + +

date

a SoupDate

 
+
+
+

Returns

+

date +'s minute

+
+

Since: 2.32

+
+
+
+

soup_date_get_month ()

+
int
+soup_date_get_month (SoupDate *date);
+

Gets date +'s month.

+
+

Parameters

+
+++++ + + + + + +

date

a SoupDate

 
+
+
+

Returns

+

date +'s month

+
+

Since: 2.32

+
+
+
+

soup_date_get_offset ()

+
int
+soup_date_get_offset (SoupDate *date);
+

Gets date +'s offset from UTC.

+
+

Parameters

+
+++++ + + + + + +

date

a SoupDate

 
+
+
+

Returns

+

date +'s offset from UTC. If soup_date_get_utc() +returns FALSE but soup_date_get_offset() returns 0, that means the +date is a "floating" time with no associated offset information.

+
+

Since: 2.32

+
+
+
+

soup_date_get_second ()

+
int
+soup_date_get_second (SoupDate *date);
+

Gets date +'s second.

+
+

Parameters

+
+++++ + + + + + +

date

a SoupDate

 
+
+
+

Returns

+

date +'s second

+
+

Since: 2.32

+
+
+
+

soup_date_get_utc ()

+
int
+soup_date_get_utc (SoupDate *date);
+

Gets date +'s UTC flag

+
+

Parameters

+
+++++ + + + + + +

date

a SoupDate

 
+
+
+

Returns

+

TRUE if date +is UTC.

+
+

Since: 2.32

+
+
+
+

soup_date_get_year ()

+
int
+soup_date_get_year (SoupDate *date);
+

Gets date +'s year.

+
+

Parameters

+
+++++ + + + + + +

date

a SoupDate

 
+
+
+

Returns

+

date +'s year

+
+

Since: 2.32

+
+
+
+

soup_date_free ()

+
void
+soup_date_free (SoupDate *date);
+

Frees date +.

+
+

Parameters

+
+++++ + + + + + +

date

a SoupDate

 
+
+

Since: 2.24

+
+
+
+

soup_headers_parse_request ()

+
guint
+soup_headers_parse_request (const char *str,
+                            int len,
+                            SoupMessageHeaders *req_headers,
+                            char **req_method,
+                            char **req_path,
+                            SoupHTTPVersion *ver);
+

Parses the headers of an HTTP request in str + and stores the +results in req_method +, req_path +, ver +, and req_headers +.

+

Beware that req_headers + may be modified even on failure.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

str

the headers (up to, but not including, the trailing blank line)

 

len

length of str +

 

req_headers

SoupMessageHeaders to store the header values in

 

req_method

if non-NULL, will be filled in with the +request method.

[out][allow-none]

req_path

if non-NULL, will be filled in with the +request path.

[out][allow-none]

ver

if non-NULL, will be filled in with the HTTP +version.

[out][allow-none]
+
+
+

Returns

+

SOUP_STATUS_OK if the headers could be parsed, or an +HTTP error to be returned to the client if they could not be.

+
+
+
+
+

soup_headers_parse_response ()

+
gboolean
+soup_headers_parse_response (const char *str,
+                             int len,
+                             SoupMessageHeaders *headers,
+                             SoupHTTPVersion *ver,
+                             guint *status_code,
+                             char **reason_phrase);
+

Parses the headers of an HTTP response in str + and stores the +results in ver +, status_code +, reason_phrase +, and headers +.

+

Beware that headers + may be modified even on failure.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

str

the headers (up to, but not including, the trailing blank line)

 

len

length of str +

 

headers

SoupMessageHeaders to store the header values in

 

ver

if non-NULL, will be filled in with the HTTP +version.

[out][allow-none]

status_code

if non-NULL, will be filled in with +the status code.

[out][allow-none]

reason_phrase

if non-NULL, will be filled in with +the reason phrase.

[out][allow-none]
+
+
+

Returns

+

success or failure.

+
+
+
+
+

soup_headers_parse_status_line ()

+
gboolean
+soup_headers_parse_status_line (const char *status_line,
+                                SoupHTTPVersion *ver,
+                                guint *status_code,
+                                char **reason_phrase);
+

Parses the HTTP Status-Line string in status_line + into ver +, +status_code +, and reason_phrase +. status_line + must be terminated by +either "\0" or "\r\n".

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

status_line

an HTTP Status-Line

 

ver

if non-NULL, will be filled in with the HTTP +version.

[out][allow-none]

status_code

if non-NULL, will be filled in with +the status code.

[out][allow-none]

reason_phrase

if non-NULL, will be filled in with +the reason phrase.

[out][allow-none]
+
+
+

Returns

+

TRUE if status_line +was parsed successfully.

+
+
+
+
+

soup_headers_parse ()

+
gboolean
+soup_headers_parse (const char *str,
+                    int len,
+                    SoupMessageHeaders *dest);
+

Parses the headers of an HTTP request or response in str + and +stores the results in dest +. Beware that dest + may be modified even +on failure.

+

This is a low-level method; normally you would use +soup_headers_parse_request() or soup_headers_parse_response().

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

str

the header string (including the Request-Line or Status-Line, +but not the trailing blank line)

 

len

length of str +

 

dest

SoupMessageHeaders to store the header values in

 
+
+
+

Returns

+

success or failure

+
+

Since: 2.26

+
+
+
+

soup_header_parse_list ()

+
GSList *
+soup_header_parse_list (const char *header);
+

Parses a header whose content is described by RFC2616 as +"something", where "something" does not itself contain commas, +except as part of quoted-strings.

+
+

Parameters

+
+++++ + + + + + +

header

a header value

 
+
+
+

Returns

+

a GSList of +list elements, as allocated strings.

+

[transfer full][element-type utf8]

+
+
+
+
+

soup_header_parse_quality_list ()

+
GSList *
+soup_header_parse_quality_list (const char *header,
+                                GSList **unacceptable);
+

Parses a header whose content is a list of items with optional +"qvalue"s (eg, Accept, Accept-Charset, Accept-Encoding, +Accept-Language, TE).

+

If unacceptable + is not NULL, then on return, it will contain the +items with qvalue 0. Either way, those items will be removed from +the main list.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

header

a header value

 

unacceptable

on +return, will contain a list of unacceptable values.

[out][allow-none][transfer full][element-type utf8]
+
+
+

Returns

+

a GSList of +acceptable values (as allocated strings), highest-qvalue first.

+

[transfer full][element-type utf8]

+
+
+
+
+

soup_header_free_list ()

+
void
+soup_header_free_list (GSList *list);
+

Frees list +.

+

[skip]

+
+

Parameters

+
+++++ + + + + + +

list

a GSList returned from soup_header_parse_list() or +soup_header_parse_quality_list()

 
+
+
+
+
+

soup_header_contains ()

+
gboolean
+soup_header_contains (const char *header,
+                      const char *token);
+

Parses header + to see if it contains the token token + (matched +case-insensitively). Note that this can't be used with lists +that have qvalues.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

header

An HTTP header suitable for parsing with +soup_header_parse_list()

 

token

a token

 
+
+
+

Returns

+

whether or not header +contains token +

+
+
+
+
+

soup_header_parse_param_list ()

+
GHashTable *
+soup_header_parse_param_list (const char *header);
+

Parses a header which is a comma-delimited list of something like: +token [ "=" ( token | quoted-string ) ].

+

Tokens that don't have an associated value will still be added to +the resulting hash table, but with a NULL value.

+

This also handles RFC5987 encoding (which in HTTP is mostly used +for giving UTF8-encoded filenames in the Content-Disposition +header).

+
+

Parameters

+
+++++ + + + + + +

header

a header value

 
+
+
+

Returns

+

a +GHashTable of list elements, which can be freed with +soup_header_free_param_list().

+

[element-type utf8 utf8][transfer full]

+
+
+
+
+

soup_header_parse_semi_param_list ()

+
GHashTable *
+soup_header_parse_semi_param_list (const char *header);
+

Parses a header which is a semicolon-delimited list of something +like: token [ "=" ( token | quoted-string ) ].

+

Tokens that don't have an associated value will still be added to +the resulting hash table, but with a NULL value.

+

This also handles RFC5987 encoding (which in HTTP is mostly used +for giving UTF8-encoded filenames in the Content-Disposition +header).

+
+

Parameters

+
+++++ + + + + + +

header

a header value

 
+
+
+

Returns

+

a +GHashTable of list elements, which can be freed with +soup_header_free_param_list().

+

[element-type utf8 utf8][transfer full]

+
+

Since: 2.24

+
+
+
+

soup_header_free_param_list ()

+
void
+soup_header_free_param_list (GHashTable *param_list);
+

Frees param_list +.

+
+

Parameters

+
+++++ + + + + + +

param_list

a GHashTable returned from soup_header_parse_param_list() +or soup_header_parse_semi_param_list().

[element-type utf8 utf8]
+
+
+
+
+

soup_header_g_string_append_param ()

+
void
+soup_header_g_string_append_param (GString *string,
+                                   const char *name,
+                                   const char *value);
+

Appends something like name +=value + to string +, +taking care to quote value + if needed, and if so, to escape any +quotes or backslashes in value +.

+

Alternatively, if value + is a non-ASCII UTF-8 string, it will be +appended using RFC5987 syntax. Although in theory this is supposed +to work anywhere in HTTP that uses this style of parameter, in +reality, it can only be used portably with the Content-Disposition +"filename" parameter.

+

If value + is NULL, this will just append name + to string +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

string

a GString being used to construct an HTTP header value

 

name

a parameter name

 

value

a parameter value, or NULL

 
+
+

Since: 2.26

+
+
+
+

soup_header_g_string_append_param_quoted ()

+
void
+soup_header_g_string_append_param_quoted
+                               (GString *string,
+                                const char *name,
+                                const char *value);
+

Appends something like name +="value +" to +string +, taking care to escape any quotes or backslashes in value +.

+

If value + is (non-ASCII) UTF-8, this will instead use RFC 5987 +encoding, just like soup_header_g_string_append_param().

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

string

a GString being used to construct an HTTP header value

 

name

a parameter name

 

value

a parameter value

 
+
+

Since: 2.30

+
+
+
+

soup_str_case_equal ()

+
gboolean
+soup_str_case_equal (gconstpointer v1,
+                     gconstpointer v2);
+

Compares v1 + and v2 + in a case-insensitive manner

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

v1

an ASCII string

 

v2

another ASCII string

 
+
+
+

Returns

+

TRUE if they are equal (modulo case)

+
+
+
+
+

soup_str_case_hash ()

+
guint
+soup_str_case_hash (gconstpointer key);
+

Hashes key + in a case-insensitive manner.

+
+

Parameters

+
+++++ + + + + + +

key

ASCII string to hash

 
+
+
+

Returns

+

the hash code.

+
+
+
+
+

soup_add_completion ()

+
GSource *
+soup_add_completion (GMainContext *async_context,
+                     GSourceFunc function,
+                     gpointer data);
+

Adds function + to be executed from inside async_context + with the +default priority. Use this when you want to complete an action in +async_context +'s main loop, as soon as possible.

+

[skip]

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

async_context

the GMainContext to dispatch the I/O +watch in, or NULL for the default context.

[allow-none]

function

the callback to invoke

 

data

user data to pass to function +

 
+
+
+

Returns

+

a GSource, which can be removed from async_context +with g_source_destroy().

+
+

Since: 2.24

+
+
+
+

soup_add_idle ()

+
GSource *
+soup_add_idle (GMainContext *async_context,
+               GSourceFunc function,
+               gpointer data);
+

Adds an idle event as with g_idle_add(), but using the given +async_context +.

+

If you want function + to run "right away", use +soup_add_completion(), since that sets a higher priority on the +GSource than soup_add_idle() does.

+

[skip]

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

async_context

the GMainContext to dispatch the I/O +watch in, or NULL for the default context.

[allow-none]

function

the callback to invoke at idle time

 

data

user data to pass to function +

 
+
+
+

Returns

+

a GSource, which can be removed from async_context +with g_source_destroy().

+
+
+
+
+

soup_add_io_watch ()

+
GSource *
+soup_add_io_watch (GMainContext *async_context,
+                   GIOChannel *chan,
+                   GIOCondition condition,
+                   GIOFunc function,
+                   gpointer data);
+

Adds an I/O watch as with g_io_add_watch(), but using the given +async_context +.

+

[skip]

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

async_context

the GMainContext to dispatch the I/O +watch in, or NULL for the default context.

[allow-none]

chan

the GIOChannel to watch

 

condition

the condition to watch for

 

function

the callback to invoke when condition +occurs

 

data

user data to pass to function +

 
+
+
+

Returns

+

a GSource, which can be removed from async_context +with g_source_destroy().

+
+
+
+
+

soup_add_timeout ()

+
GSource *
+soup_add_timeout (GMainContext *async_context,
+                  guint interval,
+                  GSourceFunc function,
+                  gpointer data);
+

Adds a timeout as with g_timeout_add(), but using the given +async_context +.

+

[skip]

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

async_context

the GMainContext to dispatch the I/O +watch in, or NULL for the default context.

[allow-none]

interval

the timeout interval, in milliseconds

 

function

the callback to invoke at timeout time

 

data

user data to pass to function +

 
+
+
+

Returns

+

a GSource, which can be removed from async_context +with g_source_destroy().

+
+
+
+
+

Types and Values

+
+

SoupDate

+
typedef struct {
+	int      year;
+	int      month;
+	int      day;
+
+	int      hour;
+	int      minute;
+	int      second;
+
+	gboolean utc;
+	int      offset;
+} SoupDate;
+
+

A date and time. The date is assumed to be in the (proleptic) +Gregorian calendar. The time is in UTC if utc + is TRUE. Otherwise, +the time is a local time, and offset + gives the offset from UTC in +minutes (such that adding offset + to the time would give the +correct UTC time). If utc + is FALSE and offset + is 0, then the +SoupDate represents a "floating" time with no associated timezone +information.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

int year;

the year, 1 to 9999

 

int month;

the month, 1 to 12

 

int day;

day of the month, 1 to 31

 

int hour;

hour of the day, 0 to 23

 

int minute;

minute, 0 to 59

 

int second;

second, 0 to 59 (or up to 61 in the case of leap seconds)

 

gboolean utc;

TRUE if the date is in UTC

 

int offset;

offset from UTC

 
+
+
+
+
+

enum SoupDateFormat

+

Date formats that soup_date_to_string() can use.

+

SOUP_DATE_HTTP + and SOUP_DATE_COOKIE + always coerce the time to +UTC. SOUP_DATE_ISO8601_XMLRPC + uses the time as given, ignoring the +offset completely. SOUP_DATE_RFC2822 + and the other ISO 8601 +variants use the local time, appending the offset information if +available.

+

This enum may be extended with more values in future releases.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

SOUP_DATE_HTTP

+

RFC 1123 format, used by the HTTP "Date" header. Eg +"Sun, 06 Nov 1994 08:49:37 GMT"

+
 

SOUP_DATE_COOKIE

+

The format for the "Expires" timestamp in the +Netscape cookie specification. Eg, "Sun, 06-Nov-1994 08:49:37 GMT".

+
 

SOUP_DATE_RFC2822

+

RFC 2822 format, eg "Sun, 6 Nov 1994 09:49:37 -0100"

+
 

SOUP_DATE_ISO8601_COMPACT

+

ISO 8601 date/time with no optional +punctuation. Eg, "19941106T094937-0100".

+
 

SOUP_DATE_ISO8601_FULL

+

ISO 8601 date/time with all optional +punctuation. Eg, "1994-11-06T09:49:37-01:00".

+
 

SOUP_DATE_ISO8601

+

An alias for SOUP_DATE_ISO8601_FULL +.

+
 

SOUP_DATE_ISO8601_XMLRPC

+

ISO 8601 date/time as used by XML-RPC. +Eg, "19941106T09:49:37".

+
 
+
+
+
+
+ + + \ No newline at end of file diff --git a/docs/reference/html/libsoup-2.4-SoupServer-deprecated-API.html b/docs/reference/html/libsoup-2.4-SoupServer-deprecated-API.html new file mode 100644 index 0000000..c0f4c35 --- /dev/null +++ b/docs/reference/html/libsoup-2.4-SoupServer-deprecated-API.html @@ -0,0 +1,515 @@ + + + + +SoupServer deprecated API: libsoup Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

SoupServer deprecated API

+

SoupServer deprecated API

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+guint + +soup_server_get_port () +
+SoupSocket * + +soup_server_get_listener () +
+void + +soup_server_run () +
+void + +soup_server_run_async () +
+void + +soup_server_quit () +
+GMainContext * + +soup_server_get_async_context () +
+SoupSocket * + +soup_client_context_get_socket () +
+SoupAddress * + +soup_client_context_get_address () +
+
+
+

Types and Values

+
++++ + + + + + + + + + + + + + + + + + + + + + + +
#defineSOUP_SERVER_PORT
#defineSOUP_SERVER_INTERFACE
#defineSOUP_SERVER_SSL_CERT_FILE
#defineSOUP_SERVER_SSL_KEY_FILE
#defineSOUP_SERVER_ASYNC_CONTEXT
+
+
+

Includes

+
#include <libsoup/soup.h>
+
+
+
+

Description

+
+
+

Functions

+
+

soup_server_get_port ()

+
guint
+soup_server_get_port (SoupServer *server);
+
+

soup_server_get_port is deprecated and should not be used in newly-written code.

+

If you are using soup_server_listen(), etc, then use +soup_server_get_uris() to get a list of all listening addresses.

+
+

Gets the TCP port that server + is listening on, if you are using +the old API.

+
+

Parameters

+
+++++ + + + + + +

server

a SoupServer

 
+
+
+

Returns

+

the port server +is listening on.

+
+
+
+
+

soup_server_get_listener ()

+
SoupSocket *
+soup_server_get_listener (SoupServer *server);
+
+

soup_server_get_listener is deprecated and should not be used in newly-written code.

+

If you are using soup_server_listen(), etc, then use +soup_server_get_listeners() to get a list of all listening sockets, +but note that that function returns GSockets, not SoupSockets.

+
+

Gets server +'s listening socket, if you are using the old API.

+

You should treat this socket as read-only; writing to it or +modifiying it may cause server + to malfunction.

+
+

Parameters

+
+++++ + + + + + +

server

a SoupServer

 
+
+
+

Returns

+

the listening socket.

+

[transfer none]

+
+
+
+
+

soup_server_run ()

+
void
+soup_server_run (SoupServer *server);
+
+

soup_server_run is deprecated and should not be used in newly-written code.

+

When using soup_server_listen(), etc, the server will +always listen for connections, and will process them whenever the +thread-default GMainContext is running.

+
+

Starts server +, if you are using the old API, causing it to listen +for and process incoming connections. Unlike +soup_server_run_async(), this creates a GMainLoop and runs it, and +it will not return until someone calls soup_server_quit() to stop +the server.

+
+

Parameters

+
+++++ + + + + + +

server

a SoupServer

 
+
+
+
+
+

soup_server_run_async ()

+
void
+soup_server_run_async (SoupServer *server);
+
+

soup_server_run_async is deprecated and should not be used in newly-written code.

+

When using soup_server_listen(), etc, the server will +always listen for connections, and will process them whenever the +thread-default GMainContext is running.

+
+

Starts server +, if you are using the old API, causing it to listen +for and process incoming connections.

+

The server runs in server +'s GMainContext. It will not actually +perform any processing unless the appropriate main loop is running. +In the simple case where you did not set the server's +SOUP_SERVER_ASYNC_CONTEXT property, this means the server will run +whenever the glib main loop is running.

+
+

Parameters

+
+++++ + + + + + +

server

a SoupServer

 
+
+
+
+
+

soup_server_quit ()

+
void
+soup_server_quit (SoupServer *server);
+
+

soup_server_quit is deprecated and should not be used in newly-written code.

+

When using soup_server_listen(), etc, the server will +always listen for connections, and will process them whenever the +thread-default GMainContext is running.

+
+

Stops processing for server +, if you are using the old API. Call +this to clean up after soup_server_run_async(), or to terminate a +call to soup_server_run().

+

Note that messages currently in progress will continue to be +handled, if the main loop associated with the server is resumed or +kept running.

+

server + is still in a working state after this call; you can start +and stop a server as many times as you want.

+
+

Parameters

+
+++++ + + + + + +

server

a SoupServer

 
+
+
+
+
+

soup_server_get_async_context ()

+
GMainContext *
+soup_server_get_async_context (SoupServer *server);
+
+

soup_server_get_async_context is deprecated and should not be used in newly-written code.

+

If you are using soup_server_listen(), etc, then +the server listens on the thread-default GMainContext, and this +property is ignored.

+
+

Gets server +'s async_context, if you are using the old API. (With +the new API, the server runs in the thread's thread-default +GMainContext, regardless of what this method returns.)

+

This does not add a ref to the context, so you will need to ref it +yourself if you want it to outlive its server.

+
+

Parameters

+
+++++ + + + + + +

server

a SoupServer

 
+
+
+

Returns

+

server +'s GMainContext, +which may be NULL.

+

[nullable][transfer none]

+
+
+
+
+

soup_client_context_get_socket ()

+
SoupSocket *
+soup_client_context_get_socket (SoupClientContext *client);
+
+

soup_client_context_get_socket is deprecated and should not be used in newly-written code.

+

use soup_client_context_get_gsocket(), which returns +a GSocket.

+
+

Retrieves the SoupSocket that client + is associated with.

+

If you are using this method to observe when multiple requests are +made on the same persistent HTTP connection (eg, as the ntlm-test +test program does), you will need to pay attention to socket +destruction as well (either by using weak references, or by +connecting to the “disconnected” signal), so that you do +not get fooled when the allocator reuses the memory address of a +previously-destroyed socket to represent a new socket.

+
+

Parameters

+
+++++ + + + + + +

client

a SoupClientContext

 
+
+
+

Returns

+

the SoupSocket that client +is +associated with.

+

[transfer none]

+
+
+
+
+

soup_client_context_get_address ()

+
SoupAddress *
+soup_client_context_get_address (SoupClientContext *client);
+
+

soup_client_context_get_address is deprecated and should not be used in newly-written code.

+

Use soup_client_context_get_remote_address(), which returns +a GSocketAddress.

+
+

Retrieves the SoupAddress associated with the remote end +of a connection.

+
+

Parameters

+
+++++ + + + + + +

client

a SoupClientContext

 
+
+
+

Returns

+

the SoupAddress +associated with the remote end of a connection, it may be +NULL if you used soup_server_accept_iostream().

+

[nullable][transfer none]

+
+
+
+
+

Types and Values

+
+

SOUP_SERVER_PORT

+
#define SOUP_SERVER_PORT          "port"
+
+
+

SOUP_SERVER_PORT is deprecated and should not be used in newly-written code.

+

SoupServers can listen on multiple interfaces +at once now. Use soup_server_listen(), etc, to listen on a +port, and soup_server_get_uris() to see what ports are +being listened on.

+
+

Alias for the deprecated “port” property, qv.

+
+
+
+

SOUP_SERVER_INTERFACE

+
#define SOUP_SERVER_INTERFACE     "interface"
+
+
+

SOUP_SERVER_INTERFACE is deprecated and should not be used in newly-written code.

+

SoupServers can listen on multiple interfaces +at once now. Use soup_server_listen(), etc, to listen on an +interface, and soup_server_get_uris() to see what addresses +are being listened on.

+
+

Alias for the “interface” property, qv.

+
+
+
+

SOUP_SERVER_SSL_CERT_FILE

+
#define SOUP_SERVER_SSL_CERT_FILE "ssl-cert-file"
+
+
+

SOUP_SERVER_SSL_CERT_FILE is deprecated and should not be used in newly-written code.

+

use “tls-certificate” or +soup_server_set_ssl_certificate().

+
+

Alias for the “ssl-cert-file” property, qv.

+
+
+
+

SOUP_SERVER_SSL_KEY_FILE

+
#define SOUP_SERVER_SSL_KEY_FILE  "ssl-key-file"
+
+
+

SOUP_SERVER_SSL_KEY_FILE is deprecated and should not be used in newly-written code.

+

use “tls-certificate” or +soup_server_set_ssl_certificate().

+
+

Alias for the “ssl-key-file” property, qv.

+
+
+
+

SOUP_SERVER_ASYNC_CONTEXT

+
#define SOUP_SERVER_ASYNC_CONTEXT "async-context"
+
+
+

SOUP_SERVER_ASYNC_CONTEXT is deprecated and should not be used in newly-written code.

+

The new API uses the thread-default GMainContext +rather than having an explicitly-specified one.

+
+

Alias for the deprecated “async-context” +property, qv.

+
+
+
+ + + \ No newline at end of file diff --git a/docs/reference/html/libsoup-2.4-Top-Level-Domain-utils.html b/docs/reference/html/libsoup-2.4-Top-Level-Domain-utils.html new file mode 100644 index 0000000..95a269f --- /dev/null +++ b/docs/reference/html/libsoup-2.4-Top-Level-Domain-utils.html @@ -0,0 +1,247 @@ + + + + +Top Level Domain utils: libsoup Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

Top Level Domain utils

+

Top Level Domain utils — Top-Level Domain Utilities

+
+
+

Functions

+
++++ + + + + + + + + + + +
const char * + +soup_tld_get_base_domain () +
+gboolean + +soup_tld_domain_is_public_suffix () +
+
+
+

Types and Values

+
++++ + + + + + + + + + + +
#defineSOUP_TLD_ERROR
enumSoupTLDError
+
+
+

Includes

+
#include <libsoup/soup.h>
+
+
+
+

Description

+

These functions can be used to parse hostnames to attempt to determine +what part of the name belongs to the domain owner, and what part is +simply a "public suffix" such as ".com".

+
+
+

Functions

+
+

soup_tld_get_base_domain ()

+
const char *
+soup_tld_get_base_domain (const char *hostname,
+                          GError **error);
+

Finds the base domain for a given hostname +. The base domain is +composed by the top level domain (such as .org, .com, .co.uk, etc) +plus the second level domain, for example for myhost.mydomain.com +it will return mydomain.com.

+

Note that NULL will be returned for private URLs (those not ending +with any well known TLD) because choosing a base domain for them +would be totally arbitrary.

+

Prior to libsoup 2.46, this function required that hostname + be in +UTF-8 if it was an IDN. From 2.46 on, the name can be in either +UTF-8 or ASCII format (and the return value will be in the same +format).

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

hostname

a hostname

 

error

return location for a GError, or NULL to ignore +errors. See SoupTLDError for the available error codes

 
+
+
+

Returns

+

a pointer to the start of the base domain in hostname +. If +an error occurs, NULL will be returned and error +set.

+
+

Since: 2.40

+
+
+
+

soup_tld_domain_is_public_suffix ()

+
gboolean
+soup_tld_domain_is_public_suffix (const char *domain);
+

Looks whether the domain + passed as argument is a public domain +suffix (.org, .com, .co.uk, etc) or not.

+

Prior to libsoup 2.46, this function required that domain + be in +UTF-8 if it was an IDN. From 2.46 on, the name can be in either +UTF-8 or ASCII format.

+
+

Parameters

+
+++++ + + + + + +

domain

a domain name

 
+
+
+

Returns

+

TRUE if it is a public domain, FALSE otherwise.

+
+

Since: 2.40

+
+
+
+

Types and Values

+
+

SOUP_TLD_ERROR

+
#define SOUP_TLD_ERROR soup_tld_error_quark()
+
+

The GError domain for soup-tld-related errors.

+

Since: 2.40

+
+
+
+

enum SoupTLDError

+

Error codes for SOUP_TLD_ERROR.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

SOUP_TLD_ERROR_INVALID_HOSTNAME

+

A hostname was syntactically + invalid.

+
 

SOUP_TLD_ERROR_IS_IP_ADDRESS

+

The passed-in "hostname" was + actually an IP address (and thus has no base domain or + public suffix).

+
 

SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS

+

The passed-in hostname + did not have enough components. Eg, calling + soup_tld_get_base_domain() on "co.uk".

+
 

SOUP_TLD_ERROR_NO_BASE_DOMAIN

+

The passed-in hostname has + no recognized public suffix.

+
 

SOUP_TLD_ERROR_NO_PSL_DATA

  
+
+

Since: 2.40

+
+
+
+ + + \ No newline at end of file diff --git a/docs/reference/html/libsoup-2.4-Version-Information.html b/docs/reference/html/libsoup-2.4-Version-Information.html new file mode 100644 index 0000000..4d95dfe --- /dev/null +++ b/docs/reference/html/libsoup-2.4-Version-Information.html @@ -0,0 +1,539 @@ + + + + +Version Information: libsoup Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

Version Information

+

Version Information — Variables and functions to check the libsoup version

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + +
+guint + +soup_get_major_version () +
+guint + +soup_get_minor_version () +
+guint + +soup_get_micro_version () +
+gboolean + +soup_check_version () +
#define +SOUP_CHECK_VERSION() +
+
+
+

Types and Values

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#defineSOUP_MAJOR_VERSION
#defineSOUP_MINOR_VERSION
#defineSOUP_MICRO_VERSION
#defineSOUP_VERSION_MIN_REQUIRED
#defineSOUP_VERSION_MAX_ALLOWED
#defineSOUP_VERSION_2_24
#defineSOUP_VERSION_2_26
#defineSOUP_VERSION_2_28
#defineSOUP_VERSION_2_30
#defineSOUP_VERSION_2_32
#defineSOUP_VERSION_2_34
#defineSOUP_VERSION_2_36
#defineSOUP_VERSION_2_38
#defineSOUP_VERSION_2_40
#defineSOUP_VERSION_2_42
#defineSOUP_VERSION_2_44
#defineSOUP_VERSION_2_46
#defineSOUP_VERSION_2_48
#defineSOUP_VERSION_2_50
#defineSOUP_VERSION_2_52
+
+
+

Includes

+
#include <libsoup/soup.h>
+
+
+
+

Description

+
+
+

Functions

+
+

soup_get_major_version ()

+
guint
+soup_get_major_version (void);
+

Returns the major version number of the libsoup library. +(e.g. in libsoup version 2.42.0 this is 2.)

+

This function is in the library, so it represents the libsoup library +your code is running against. Contrast with the SOUP_MAJOR_VERSION +macro, which represents the major version of the libsoup headers you +have included when compiling your code.

+
+

Returns

+

the major version number of the libsoup library

+
+

Since: 2.42

+
+
+
+

soup_get_minor_version ()

+
guint
+soup_get_minor_version (void);
+

Returns the minor version number of the libsoup library. +(e.g. in libsoup version 2.42.0 this is 42.)

+

This function is in the library, so it represents the libsoup library +your code is running against. Contrast with the SOUP_MINOR_VERSION +macro, which represents the minor version of the libsoup headers you +have included when compiling your code.

+
+

Returns

+

the minor version number of the libsoup library

+
+

Since: 2.42

+
+
+
+

soup_get_micro_version ()

+
guint
+soup_get_micro_version (void);
+

Returns the micro version number of the libsoup library. +(e.g. in libsoup version 2.42.0 this is 0.)

+

This function is in the library, so it represents the libsoup library +your code is running against. Contrast with the SOUP_MICRO_VERSION +macro, which represents the micro version of the libsoup headers you +have included when compiling your code.

+
+

Returns

+

the micro version number of the libsoup library

+
+

Since: 2.42

+
+
+
+

soup_check_version ()

+
gboolean
+soup_check_version (guint major,
+                    guint minor,
+                    guint micro);
+

Like SOUP_CHECK_VERSION, but the check for soup_check_version is +at runtime instead of compile time. This is useful for compiling +against older versions of libsoup, but using features from newer +versions.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

major

the major version to check

 

minor

the minor version to check

 

micro

the micro version to check

 
+
+
+

Returns

+

TRUE if the version of the libsoup currently loaded +is the same as or newer than the passed-in version.

+
+

Since: 2.42

+
+
+
+

SOUP_CHECK_VERSION()

+
#define             SOUP_CHECK_VERSION(major, minor, micro)
+

Macro to test the version of libsoup being compiled against.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

major

major version (e.g. 2 for version 2.42.0)

 

minor

minor version (e.g. 42 for version 2.42.0)

 

micro

micro version (e.g. 0 for version 2.42.0)

 
+
+
+

Returns

+

TRUE if the version of the libsoup header files +is the same as or newer than the passed-in version.

+
+

Since: 2.42

+
+
+
+

Types and Values

+
+

SOUP_MAJOR_VERSION

+
#define SOUP_MAJOR_VERSION (2)
+
+

Like soup_get_major_version(), but from the headers used at +application compile time, rather than from the library linked +against at application run time.

+

Since: 2.42

+
+
+
+

SOUP_MINOR_VERSION

+
#define SOUP_MINOR_VERSION (63)
+
+

Like soup_get_minor_version(), but from the headers used at +application compile time, rather than from the library linked +against at application run time.

+

Since: 2.42

+
+
+
+

SOUP_MICRO_VERSION

+
#define SOUP_MICRO_VERSION (90)
+
+

Like soup_get_micro_version(), but from the headers used at +application compile time, rather than from the library linked +against at application run time.

+

Since: 2.42

+
+
+
+

SOUP_VERSION_MIN_REQUIRED

+
# define SOUP_VERSION_MIN_REQUIRED (SOUP_VERSION_CUR_STABLE)
+
+

A macro that should be defined by the user prior to including +libsoup.h. The definition should be one of the predefined libsoup +version macros: SOUP_VERSION_2_24, SOUP_VERSION_2_26, ...

+

This macro defines the earliest version of libsoup that the package +is required to be able to compile against.

+

If the compiler is configured to warn about the use of deprecated +functions, then using functions that were deprecated in version +SOUP_VERSION_MIN_REQUIRED or earlier will cause warnings (but +using functions deprecated in later releases will not).

+

Since: 2.42

+
+
+
+

SOUP_VERSION_MAX_ALLOWED

+
# define SOUP_VERSION_MAX_ALLOWED (SOUP_VERSION_CUR_STABLE)
+
+

A macro that should be defined by the user prior to including +libsoup.h. The definition should be one of the predefined libsoup +version macros: SOUP_VERSION_2_24, SOUP_VERSION_2_26, ...

+

This macro defines the latest version of the libsoup API that the +package is allowed to make use of.

+

If the compiler is configured to warn about the use of deprecated +functions, then using functions added after version +SOUP_VERSION_MAX_ALLOWED will cause warnings.

+

Unless you are using SOUP_CHECK_VERSION() or the like to compile +different code depending on the libsoup version, then this should be +set to the same value as SOUP_VERSION_MIN_REQUIRED.

+

Since: 2.42

+
+
+
+

SOUP_VERSION_2_24

+
#define SOUP_VERSION_2_24 (G_ENCODE_VERSION (2, 24))
+
+

A macro that evaluates to the 2.24 version of libsoup, in a format +that can be used by SOUP_VERSION_MIN_REQUIRED and +SOUP_VERSION_MAX_ALLOWED.

+

Since: 2.42

+
+
+
+

SOUP_VERSION_2_26

+
#define SOUP_VERSION_2_26 (G_ENCODE_VERSION (2, 26))
+
+

A macro that evaluates to the 2.26 version of libsoup, in a format +that can be used by SOUP_VERSION_MIN_REQUIRED and +SOUP_VERSION_MAX_ALLOWED.

+

Since: 2.42

+
+
+
+

SOUP_VERSION_2_28

+
#define SOUP_VERSION_2_28 (G_ENCODE_VERSION (2, 28))
+
+

A macro that evaluates to the 2.28 version of libsoup, in a format +that can be used by SOUP_VERSION_MIN_REQUIRED and +SOUP_VERSION_MAX_ALLOWED.

+

Since: 2.42

+
+
+
+

SOUP_VERSION_2_30

+
#define SOUP_VERSION_2_30 (G_ENCODE_VERSION (2, 30))
+
+

A macro that evaluates to the 2.30 version of libsoup, in a format +that can be used by SOUP_VERSION_MIN_REQUIRED and +SOUP_VERSION_MAX_ALLOWED.

+

Since: 2.42

+
+
+
+

SOUP_VERSION_2_32

+
#define SOUP_VERSION_2_32 (G_ENCODE_VERSION (2, 32))
+
+

A macro that evaluates to the 2.32 version of libsoup, in a format +that can be used by SOUP_VERSION_MIN_REQUIRED and +SOUP_VERSION_MAX_ALLOWED.

+

Since: 2.42

+
+
+
+

SOUP_VERSION_2_34

+
#define SOUP_VERSION_2_34 (G_ENCODE_VERSION (2, 34))
+
+

A macro that evaluates to the 2.34 version of libsoup, in a format +that can be used by SOUP_VERSION_MIN_REQUIRED and +SOUP_VERSION_MAX_ALLOWED.

+

Since: 2.42

+
+
+
+

SOUP_VERSION_2_36

+
#define SOUP_VERSION_2_36 (G_ENCODE_VERSION (2, 36))
+
+

A macro that evaluates to the 2.36 version of libsoup, in a format +that can be used by SOUP_VERSION_MIN_REQUIRED and +SOUP_VERSION_MAX_ALLOWED.

+

Since: 2.42

+
+
+
+

SOUP_VERSION_2_38

+
#define SOUP_VERSION_2_38 (G_ENCODE_VERSION (2, 38))
+
+

A macro that evaluates to the 2.38 version of libsoup, in a format +that can be used by SOUP_VERSION_MIN_REQUIRED and +SOUP_VERSION_MAX_ALLOWED.

+

Since: 2.42

+
+
+
+

SOUP_VERSION_2_40

+
#define SOUP_VERSION_2_40 (G_ENCODE_VERSION (2, 40))
+
+

A macro that evaluates to the 2.40 version of libsoup, in a format +that can be used by SOUP_VERSION_MIN_REQUIRED and +SOUP_VERSION_MAX_ALLOWED.

+

Since: 2.42

+
+
+
+

SOUP_VERSION_2_42

+
#define SOUP_VERSION_2_42 (G_ENCODE_VERSION (2, 42))
+
+

A macro that evaluates to the 2.42 version of libsoup, in a format +that can be used by SOUP_VERSION_MIN_REQUIRED and +SOUP_VERSION_MAX_ALLOWED.

+

Since: 2.42

+
+
+
+

SOUP_VERSION_2_44

+
#define SOUP_VERSION_2_44 (G_ENCODE_VERSION (2, 44))
+
+

A macro that evaluates to the 2.44 version of libsoup, in a format +that can be used by SOUP_VERSION_MIN_REQUIRED and +SOUP_VERSION_MAX_ALLOWED.

+

Since: 2.44

+
+
+
+

SOUP_VERSION_2_46

+
#define SOUP_VERSION_2_46 (G_ENCODE_VERSION (2, 46))
+
+

A macro that evaluates to the 2.46 version of libsoup, in a format +that can be used by SOUP_VERSION_MIN_REQUIRED and +SOUP_VERSION_MAX_ALLOWED.

+

Since: 2.46

+
+
+
+

SOUP_VERSION_2_48

+
#define SOUP_VERSION_2_48 (G_ENCODE_VERSION (2, 48))
+
+

A macro that evaluates to the 2.48 version of libsoup, in a format +that can be used by SOUP_VERSION_MIN_REQUIRED and +SOUP_VERSION_MAX_ALLOWED.

+

Since: 2.48

+
+
+
+

SOUP_VERSION_2_50

+
#define SOUP_VERSION_2_50 (G_ENCODE_VERSION (2, 50))
+
+

A macro that evaluates to the 2.50 version of libsoup, in a format +that can be used by SOUP_VERSION_MIN_REQUIRED and +SOUP_VERSION_MAX_ALLOWED.

+

Since: 2.50

+
+
+
+

SOUP_VERSION_2_52

+
#define SOUP_VERSION_2_52 (G_ENCODE_VERSION (2, 52))
+
+

A macro that evaluates to the 2.52 version of libsoup, in a format +that can be used by SOUP_VERSION_MIN_REQUIRED and +SOUP_VERSION_MAX_ALLOWED.

+

Since: 2.52

+
+
+
+ + + \ No newline at end of file diff --git a/docs/reference/html/libsoup-2.4-WebSockets.html b/docs/reference/html/libsoup-2.4-WebSockets.html new file mode 100644 index 0000000..3577cc5 --- /dev/null +++ b/docs/reference/html/libsoup-2.4-WebSockets.html @@ -0,0 +1,1544 @@ + + + + +WebSockets: libsoup Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

WebSockets

+

WebSockets — The WebSocket Protocol

+
+
+

Functions

+ +
+
+

Properties

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SoupWebsocketConnectionTypeconnection-typeRead / Write / Construct Only
+GIOStream *io-streamRead / Write / Construct Only
guintkeepalive-intervalRead / Write / Construct
guint64max-incoming-payload-sizeRead / Write / Construct
+gchar *originRead / Write / Construct Only
+gchar *protocolRead / Write / Construct Only
SoupWebsocketStatestateRead
+SoupURI *uriRead / Write / Construct Only
+
+
+

Signals

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
voidclosedRun First
voidclosingRun Last
voiderrorRun First
voidmessageRun First
voidpongRun First
+
+
+

Types and Values

+ +
+
+

Object Hierarchy

+
    GObject
+    ╰── SoupWebsocketConnection
+
+
+
+

Includes

+
#include <libsoup/soup.h>
+
+
+
+

Description

+

SoupWebsocketConnection provides support for the WebSocket protocol.

+

To connect to a WebSocket server, create a SoupSession and call +soup_session_websocket_connect_async(). To accept WebSocket +connections, create a SoupServer and add a handler to it with +soup_server_add_websocket_handler().

+

(Lower-level support is available via +soup_websocket_client_prepare_handshake() and +soup_websocket_client_verify_handshake(), for handling the client +side of the WebSocket handshake, and +soup_websocket_server_process_handshake() for handling the server +side.)

+

SoupWebsocketConnection handles the details of WebSocket +communication. You can use soup_websocket_connection_send_text() +and soup_websocket_connection_send_binary() to send data, and the +“message” signal to receive data. +(SoupWebsocketConnection currently only supports asynchronous +I/O.)

+
+
+

Functions

+
+

soup_websocket_client_prepare_handshake ()

+
void
+soup_websocket_client_prepare_handshake
+                               (SoupMessage *msg,
+                                const char *origin,
+                                char **protocols);
+

Adds the necessary headers to msg + to request a WebSocket +handshake. The message body and non-WebSocket-related headers are +not modified.

+

This is a low-level function; if you use +soup_session_websocket_connect_async() to create a WebSocket +connection, it will call this for you.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

msg

a SoupMessage

 

origin

the "Origin" header to set.

[allow-none]

protocols

list of +protocols to offer.

[allow-none][array zero-terminated=1]
+
+

Since: 2.50

+
+
+
+

soup_websocket_client_verify_handshake ()

+
gboolean
+soup_websocket_client_verify_handshake
+                               (SoupMessage *msg,
+                                GError **error);
+

Looks at the response status code and headers in msg + and +determines if they contain a valid WebSocket handshake response +(given the handshake request in msg +'s request headers).

+

This is a low-level function; if you use +soup_session_websocket_connect_async() to create a WebSocket +connection, it will call this for you.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

msg

SoupMessage containing both client and server sides of a +WebSocket handshake

 

error

return location for a GError

 
+
+
+

Returns

+

TRUE if msg +contains a completed valid WebSocket +handshake, FALSE and an error if not.

+
+

Since: 2.50

+
+
+
+

soup_websocket_server_check_handshake ()

+
gboolean
+soup_websocket_server_check_handshake (SoupMessage *msg,
+                                       const char *origin,
+                                       char **protocols,
+                                       GError **error);
+

Examines the method and request headers in msg + and determines +whether msg + contains a valid handshake request.

+

If origin + is non-NULL, then only requests containing a matching +"Origin" header will be accepted. If protocols + is non-NULL, then +only requests containing a compatible "Sec-WebSocket-Protocols" +header will be accepted.

+

Normally soup_websocket_server_process_handshake() will take care +of this for you, and if you use soup_server_add_websocket_handler() +to handle accepting WebSocket connections, it will call that for +you. However, this function may be useful if you need to perform +more complicated validation; eg, accepting multiple different Origins, +or handling different protocols depending on the path.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

msg

SoupMessage containing the client side of a WebSocket handshake

 

origin

expected Origin header.

[allow-none]

protocols

allowed WebSocket +protocols.

[allow-none][array zero-terminated=1]

error

return location for a GError

 
+
+
+

Returns

+

TRUE if msg +contained a valid WebSocket handshake, +FALSE and an error if not.

+
+

Since: 2.50

+
+
+
+

soup_websocket_server_process_handshake ()

+
gboolean
+soup_websocket_server_process_handshake
+                               (SoupMessage *msg,
+                                const char *expected_origin,
+                                char **protocols);
+

Examines the method and request headers in msg + and (assuming msg + +contains a valid handshake request), fills in the handshake +response.

+

If expected_origin + is non-NULL, then only requests containing a matching +"Origin" header will be accepted. If protocols + is non-NULL, then +only requests containing a compatible "Sec-WebSocket-Protocols" +header will be accepted.

+

This is a low-level function; if you use +soup_server_add_websocket_handler() to handle accepting WebSocket +connections, it will call this for you.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

msg

SoupMessage containing the client side of a WebSocket handshake

 

expected_origin

expected Origin header.

[allow-none]

protocols

allowed WebSocket +protocols.

[allow-none][array zero-terminated=1]
+
+
+

Returns

+

TRUE if msg +contained a valid WebSocket handshake +request and was updated to contain a handshake response. FALSE if not.

+
+

Since: 2.50

+
+
+
+

soup_websocket_connection_new ()

+
SoupWebsocketConnection *
+soup_websocket_connection_new (GIOStream *stream,
+                               SoupURI *uri,
+                               SoupWebsocketConnectionType type,
+                               const char *origin,
+                               const char *protocol);
+

Creates a SoupWebsocketConnection on stream +. This should be +called after completing the handshake to begin using the WebSocket +protocol.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

stream

a GIOStream connected to the WebSocket server

 

uri

the URI of the connection

 

type

the type of connection (client/side)

 

origin

the Origin of the client.

[allow-none]

protocol

the subprotocol in use.

[allow-none]
+
+
+

Returns

+

a new SoupWebsocketConnection

+
+

Since: 2.50

+
+
+
+

soup_websocket_connection_get_io_stream ()

+
GIOStream *
+soup_websocket_connection_get_io_stream
+                               (SoupWebsocketConnection *self);
+

Get the I/O stream the WebSocket is communicating over.

+
+

Parameters

+
+++++ + + + + + +

self

the WebSocket

 
+
+
+

Returns

+

the WebSocket's I/O stream.

+

[transfer none]

+
+

Since: 2.50

+
+
+
+

soup_websocket_connection_get_connection_type ()

+
SoupWebsocketConnectionType
+soup_websocket_connection_get_connection_type
+                               (SoupWebsocketConnection *self);
+

Get the connection type (client/server) of the connection.

+
+

Parameters

+
+++++ + + + + + +

self

the WebSocket

 
+
+
+

Returns

+

the connection type

+
+

Since: 2.50

+
+
+
+

soup_websocket_connection_get_uri ()

+
SoupURI *
+soup_websocket_connection_get_uri (SoupWebsocketConnection *self);
+

Get the URI of the WebSocket.

+

For servers this represents the address of the WebSocket, and +for clients it is the address connected to.

+
+

Parameters

+
+++++ + + + + + +

self

the WebSocket

 
+
+
+

Returns

+

the URI.

+

[transfer none]

+
+

Since: 2.50

+
+
+
+

soup_websocket_connection_get_origin ()

+
const char *
+soup_websocket_connection_get_origin (SoupWebsocketConnection *self);
+

Get the origin of the WebSocket.

+
+

Parameters

+
+++++ + + + + + +

self

the WebSocket

 
+
+
+

Returns

+

the origin, or NULL.

+

[nullable]

+
+

Since: 2.50

+
+
+
+

soup_websocket_connection_get_protocol ()

+
const char *
+soup_websocket_connection_get_protocol
+                               (SoupWebsocketConnection *self);
+

Get the protocol chosen via negotiation with the peer.

+
+

Parameters

+
+++++ + + + + + +

self

the WebSocket

 
+
+
+

Returns

+

the chosen protocol, or NULL.

+

[nullable]

+
+

Since: 2.50

+
+
+
+

soup_websocket_connection_get_state ()

+
SoupWebsocketState
+soup_websocket_connection_get_state (SoupWebsocketConnection *self);
+

Get the current state of the WebSocket.

+
+

Parameters

+
+++++ + + + + + +

self

the WebSocket

 
+
+
+

Returns

+

the state

+
+

Since: 2.50

+
+
+
+

soup_websocket_connection_send_text ()

+
void
+soup_websocket_connection_send_text (SoupWebsocketConnection *self,
+                                     const char *text);
+

Send a text (UTF-8) message to the peer.

+

The message is queued to be sent and will be sent when the main loop +is run.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

self

the WebSocket

 

text

the message contents

 
+
+

Since: 2.50

+
+
+
+

soup_websocket_connection_send_binary ()

+
void
+soup_websocket_connection_send_binary (SoupWebsocketConnection *self,
+                                       gconstpointer data,
+                                       gsize length);
+

Send a binary message to the peer.

+

The message is queued to be sent and will be sent when the main loop +is run.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

self

the WebSocket

 

data

the message contents.

[array length=length][element-type guint8]

length

the length of data +

 
+
+

Since: 2.50

+
+
+
+

soup_websocket_connection_close ()

+
void
+soup_websocket_connection_close (SoupWebsocketConnection *self,
+                                 gushort code,
+                                 const char *data);
+

Close the connection in an orderly fashion.

+

Note that until the “closed” signal fires, the connection +is not yet completely closed. The close message is not even sent until the +main loop runs.

+

The code + and data + are sent to the peer along with the close request. +Note that the data + must be UTF-8 valid.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

self

the WebSocket

 

code

close code

 

data

close data.

[allow-none]
+
+

Since: 2.50

+
+
+
+

soup_websocket_connection_get_close_code ()

+
gushort
+soup_websocket_connection_get_close_code
+                               (SoupWebsocketConnection *self);
+

Get the close code received from the WebSocket peer.

+

This only becomes valid once the WebSocket is in the +SOUP_WEBSOCKET_STATE_CLOSED state. The value will often be in the +SoupWebsocketCloseCode enumeration, but may also be an application +defined close code.

+
+

Parameters

+
+++++ + + + + + +

self

the WebSocket

 
+
+
+

Returns

+

the close code or zero.

+
+

Since: 2.50

+
+
+
+

soup_websocket_connection_get_close_data ()

+
const char *
+soup_websocket_connection_get_close_data
+                               (SoupWebsocketConnection *self);
+

Get the close data received from the WebSocket peer.

+

This only becomes valid once the WebSocket is in the +SOUP_WEBSOCKET_STATE_CLOSED state. The data may be freed once +the main loop is run, so copy it if you need to keep it around.

+
+

Parameters

+
+++++ + + + + + +

self

the WebSocket

 
+
+
+

Returns

+

the close data or NULL

+
+

Since: 2.50

+
+
+
+

Types and Values

+
+

SoupWebsocketConnection

+
typedef struct _SoupWebsocketConnection SoupWebsocketConnection;
+

A class representing a WebSocket connection.

+

Since: 2.50

+
+
+
+

enum SoupWebsocketConnectionType

+

The type of a SoupWebsocketConnection.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + +

SOUP_WEBSOCKET_CONNECTION_UNKNOWN

+

unknown/invalid connection

+
 

SOUP_WEBSOCKET_CONNECTION_CLIENT

+

a client-side connection

+
 

SOUP_WEBSOCKET_CONNECTION_SERVER

+

a server-side connection

+
 
+
+

Since: 2.50

+
+
+
+

enum SoupWebsocketState

+

The state of the WebSocket connection.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + +

SOUP_WEBSOCKET_STATE_OPEN

+

the connection is ready to send messages

+
 

SOUP_WEBSOCKET_STATE_CLOSING

+

the connection is in the process of + closing down; messages may be received, but not sent

+
 

SOUP_WEBSOCKET_STATE_CLOSED

+

the connection is completely closed down

+
 
+
+

Since: 2.50

+
+
+
+

enum SoupWebsocketDataType

+

The type of data contained in a “message” +signal.

+
+

Members

+
+++++ + + + + + + + + + + + + +

SOUP_WEBSOCKET_DATA_TEXT

+

UTF-8 text

+
 

SOUP_WEBSOCKET_DATA_BINARY

+

binary data

+
 
+
+

Since: 2.50

+
+
+
+

enum SoupWebsocketCloseCode

+

Pre-defined close codes that can be passed to +soup_websocket_connection_close() or received from +soup_websocket_connection_get_close_code(). (However, other codes +are also allowed.)

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

SOUP_WEBSOCKET_CLOSE_NORMAL

+

a normal, non-error close

+
 

SOUP_WEBSOCKET_CLOSE_GOING_AWAY

+

the client/server is going away

+
 

SOUP_WEBSOCKET_CLOSE_PROTOCOL_ERROR

+

a protocol error occurred

+
 

SOUP_WEBSOCKET_CLOSE_UNSUPPORTED_DATA

+

the endpoint received data + of a type that it does not support.

+
 

SOUP_WEBSOCKET_CLOSE_NO_STATUS

+

reserved value indicating that + no close code was present; must not be sent.

+
 

SOUP_WEBSOCKET_CLOSE_ABNORMAL

+

reserved value indicating that + the connection was closed abnormally; must not be sent.

+
 

SOUP_WEBSOCKET_CLOSE_BAD_DATA

+

the endpoint received data that + was invalid (eg, non-UTF-8 data in a text message).

+
 

SOUP_WEBSOCKET_CLOSE_POLICY_VIOLATION

+

generic error code + indicating some sort of policy violation.

+
 

SOUP_WEBSOCKET_CLOSE_TOO_BIG

+

the endpoint received a message + that is too big to process.

+
 

SOUP_WEBSOCKET_CLOSE_NO_EXTENSION

+

the client is closing the + connection because the server failed to negotiate a required + extension.

+
 

SOUP_WEBSOCKET_CLOSE_SERVER_ERROR

+

the server is closing the + connection because it was unable to fulfill the request.

+
 

SOUP_WEBSOCKET_CLOSE_TLS_HANDSHAKE

+

reserved value indicating that + the TLS handshake failed; must not be sent.

+
 
+
+

Since: 2.50

+
+
+
+

enum SoupWebsocketError

+

WebSocket-related errors.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

SOUP_WEBSOCKET_ERROR_FAILED

+

a generic error

+
 

SOUP_WEBSOCKET_ERROR_NOT_WEBSOCKET

+

attempted to handshake with a + server that does not appear to understand WebSockets.

+
 

SOUP_WEBSOCKET_ERROR_BAD_HANDSHAKE

+

the WebSocket handshake failed + because some detail was invalid (eg, incorrect accept key).

+
 

SOUP_WEBSOCKET_ERROR_BAD_ORIGIN

+

the WebSocket handshake failed + because the "Origin" header was not an allowed value.

+
 
+
+

Since: 2.50

+
+
+
+

SOUP_WEBSOCKET_ERROR

+
#define SOUP_WEBSOCKET_ERROR (soup_websocket_error_get_quark ())
+
+

A GError domain for WebSocket-related errors. Used with +SoupWebsocketError.

+

Since: 2.50

+
+
+
+

Property Details

+
+

The “connection-type” property

+
  “connection-type”          SoupWebsocketConnectionType
+

The type of connection (client/server).

+

Flags: Read / Write / Construct Only

+

Default value: SOUP_WEBSOCKET_CONNECTION_UNKNOWN

+

Since: 2.50

+
+
+
+

The “io-stream” property

+
  “io-stream”                GIOStream *
+

The underlying IO stream the WebSocket is communicating +over.

+

The input and output streams must be pollable streams.

+

Flags: Read / Write / Construct Only

+

Since: 2.50

+
+
+
+

The “keepalive-interval” property

+
  “keepalive-interval”       guint
+

Interval in seconds on when to send a ping message which will +serve as a keepalive message. If set to 0 the keepalive message is +disabled.

+

Flags: Read / Write / Construct

+

Default value: 0

+

Since: 2.58

+
+
+
+

The “max-incoming-payload-size” property

+
  “max-incoming-payload-size” guint64
+

The maximum payload size for incoming packets the protocol expects +or 0 to not limit it.

+

Flags: Read / Write / Construct

+

Default value: 131072

+

Since: 2.56

+
+
+
+

The “origin” property

+
  “origin”                   gchar *
+

The client's Origin.

+

Flags: Read / Write / Construct Only

+

Default value: NULL

+

Since: 2.50

+
+
+
+

The “protocol” property

+
  “protocol”                 gchar *
+

The chosen protocol, or NULL if a protocol was not agreed +upon.

+

Flags: Read / Write / Construct Only

+

Default value: NULL

+

Since: 2.50

+
+
+
+

The “state” property

+
  “state”                    SoupWebsocketState
+

The current state of the WebSocket.

+

Flags: Read

+

Default value: SOUP_WEBSOCKET_STATE_OPEN

+

Since: 2.50

+
+
+
+

The “uri” property

+
  “uri”                      SoupURI *
+

The URI of the WebSocket.

+

For servers this represents the address of the WebSocket, +and for clients it is the address connected to.

+

Flags: Read / Write / Construct Only

+

Since: 2.50

+
+
+
+

Signal Details

+
+

The “closed” signal

+
void
+user_function (SoupWebsocketConnection *self,
+               gpointer                 user_data)
+

Emitted when the connection has completely closed, either +due to an orderly close from the peer, one initiated via +soup_websocket_connection_close() or a fatal error +condition that caused a close.

+

This signal will be emitted once.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

self

the WebSocket

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+

Since: 2.50

+
+
+
+

The “closing” signal

+
void
+user_function (SoupWebsocketConnection *self,
+               gpointer                 user_data)
+

This signal will be emitted during an orderly close.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

self

the WebSocket

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run Last

+

Since: 2.50

+
+
+
+

The “error” signal

+
void
+user_function (SoupWebsocketConnection *self,
+               GError                  *error,
+               gpointer                 user_data)
+

Emitted when an error occurred on the WebSocket. This may +be fired multiple times. Fatal errors will be followed by +the “closed” signal being emitted.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

self

the WebSocket

 

error

the error that occured

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+

Since: 2.50

+
+
+
+

The “message” signal

+
void
+user_function (SoupWebsocketConnection *self,
+               gint                     type,
+               GBytes                  *message,
+               gpointer                 user_data)
+

Emitted when we receive a message from the peer.

+

As a convenience, the message + data will always be +NUL-terminated, but the NUL byte will not be included in +the length count.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

self

the WebSocket

 

type

the type of message contents

 

message

the message data

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+

Since: 2.50

+
+
+
+

The “pong” signal

+
void
+user_function (SoupWebsocketConnection *self,
+               GBytes                  *message,
+               gpointer                 user_data)
+

Emitted when we receive a Pong frame (solicited or +unsolicited) from the peer.

+

As a convenience, the message + data will always be +NUL-terminated, but the NUL byte will not be included in +the length count.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

self

the WebSocket

 

message

the application data (if any)

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+

Since: 2.60

+
+
+
+

See Also

+

soup_session_websocket_connect_async(), + soup_server_add_websocket_handler()

+
+
+ + + \ No newline at end of file diff --git a/docs/reference/html/libsoup-2.4-XMLRPC-Support.html b/docs/reference/html/libsoup-2.4-XMLRPC-Support.html new file mode 100644 index 0000000..5216443 --- /dev/null +++ b/docs/reference/html/libsoup-2.4-XMLRPC-Support.html @@ -0,0 +1,921 @@ + + + + +XMLRPC Support: libsoup Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

XMLRPC Support

+

XMLRPC Support — XML-RPC support

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+char * + +soup_xmlrpc_build_request () +
+SoupMessage * + +soup_xmlrpc_message_new () +
+GVariant * + +soup_xmlrpc_parse_response () +
+GVariant * + +soup_xmlrpc_variant_new_datetime () +
+SoupDate * + +soup_xmlrpc_variant_get_datetime () +
+void + +soup_xmlrpc_params_free () +
+GVariant * + +soup_xmlrpc_params_parse () +
+char * + +soup_xmlrpc_parse_request () +
+char * + +soup_xmlrpc_build_response () +
+char * + +soup_xmlrpc_build_fault () +
+gboolean + +soup_xmlrpc_message_set_response () +
+void + +soup_xmlrpc_message_set_fault () +
+
+
+

Types and Values

+
++++ + + + + + + + + + + + + + + + + + + + + + + +
#defineSOUP_XMLRPC_ERROR
enumSoupXMLRPCError
#defineSOUP_XMLRPC_FAULT
enumSoupXMLRPCFault
 SoupXMLRPCParams
+
+
+

Includes

+
#include <libsoup/soup.h>
+
+
+
+

Description

+
+
+

Functions

+
+

soup_xmlrpc_build_request ()

+
char *
+soup_xmlrpc_build_request (const char *method_name,
+                           GVariant *params,
+                           GError **error);
+

This creates an XML-RPC methodCall and returns it as a string. +This is the low-level method that soup_xmlrpc_message_new() is +built on.

+

params + is a GVariant tuple representing the method parameters.

+

Serialization details:

+
    +
  • "a{s*}" and "{s*}" are serialized as <struct>

  • +
  • "ay" is serialized as <base64>

  • +
  • Other arrays and tuples are serialized as <array>

  • +
  • booleans are serialized as <boolean>

  • +
  • byte, int16, uint16 and int32 are serialized as <int>

  • +
  • uint32 and int64 are serialized as the nonstandard <i8> type

  • +
  • doubles are serialized as <double>

  • +
  • Strings are serialized as <string>

  • +
  • Variants (i.e. "v" type) are unwrapped and their child is serialized.

  • +
  • GVariants created by soup_xmlrpc_variant_new_datetime() are serialized as +<dateTime.iso8601>

  • +
  • Other types are not supported and will return NULL and set error +. +This notably includes: object-paths, signatures, uint64, handles, maybes +and dictionaries with non-string keys.

  • +
+

If params + is floating, it is consumed.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

method_name

the name of the XML-RPC method

 

params

a GVariant tuple

 

error

a GError, or NULL

 
+
+
+

Returns

+

the text of the methodCall, or NULL on error.

+
+

Since: 2.52

+
+
+
+

soup_xmlrpc_message_new ()

+
SoupMessage *
+soup_xmlrpc_message_new (const char *uri,
+                         const char *method_name,
+                         GVariant *params,
+                         GError **error);
+

Creates an XML-RPC methodCall and returns a SoupMessage, ready +to send, for that method call.

+

See soup_xmlrpc_build_request() for serialization details.

+

If params + is floating, it is consumed.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

uri

URI of the XML-RPC service

 

method_name

the name of the XML-RPC method to invoke at uri +

 

params

a GVariant tuple

 

error

a GError, or NULL

 
+
+
+

Returns

+

a SoupMessage encoding the +indicated XML-RPC request, or NULL on error.

+

[transfer full]

+
+

Since: 2.52

+
+
+
+

soup_xmlrpc_parse_response ()

+
GVariant *
+soup_xmlrpc_parse_response (const char *method_response,
+                            int length,
+                            const char *signature,
+                            GError **error);
+

Parses method_response + and returns the return value. If +method_response + is a fault, NULL is returned, and error + +will be set to an error in the SOUP_XMLRPC_FAULT domain, with the error +code containing the fault code, and the error message containing +the fault string. If method_response + cannot be parsed, NULL is returned, +and error + will be set to an error in the SOUP_XMLRPC_ERROR domain.

+

See soup_xmlrpc_params_parse() for deserialization details.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

method_response

the XML-RPC methodResponse string

 

length

the length of method_response +, or -1 if it is NUL-terminated

 

signature

A valid GVariant type string, or NULL.

[allow-none]

error

a GError, or NULL

 
+
+
+

Returns

+

a new (non-floating) GVariant, or NULL.

+

[transfer full]

+
+

Since: 2.52

+
+
+
+

soup_xmlrpc_variant_new_datetime ()

+
GVariant *
+soup_xmlrpc_variant_new_datetime (SoupDate *date);
+

Construct a special GVariant used to serialize a <dateTime.iso8601> +node. See soup_xmlrpc_build_request().

+

The actual type of the returned GVariant is unspecified and "v" or "*" +should be used in variant format strings. For example:

+
+ + + + + + + +
1
args = g_variant_new ("(v)", soup_xmlrpc_variant_new_datetime (date));
+
+ +
+

Parameters

+
+++++ + + + + + +

date

a SoupDate

 
+
+
+

Returns

+

a floating GVariant.

+
+

Since: 2.52

+
+
+
+

soup_xmlrpc_variant_get_datetime ()

+
SoupDate *
+soup_xmlrpc_variant_get_datetime (GVariant *variant,
+                                  GError **error);
+

Get the SoupDate from special GVariant created by +soup_xmlrpc_variant_new_datetime() or by parsing a <dateTime.iso8601> +node. See soup_xmlrpc_params_parse().

+

If variant + does not contain a datetime it will return an error but it is not +considered a programmer error because it generally means parameters received +are not in the expected type.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

variant

a GVariant

 

error

a GError, or NULL

 
+
+
+

Returns

+

a new SoupDate, or NULL on error.

+
+

Since: 2.52

+
+
+
+

soup_xmlrpc_params_free ()

+
void
+soup_xmlrpc_params_free (SoupXMLRPCParams *self);
+

Free a SoupXMLRPCParams returned by soup_xmlrpc_parse_request().

+
+

Parameters

+
+++++ + + + + + +

self

a SoupXMLRPCParams

 
+
+

Since: 2.52

+
+
+
+

soup_xmlrpc_params_parse ()

+
GVariant *
+soup_xmlrpc_params_parse (SoupXMLRPCParams *self,
+                          const char *signature,
+                          GError **error);
+

Parse method parameters returned by soup_xmlrpc_parse_request().

+

Deserialization details:

+
    +
  • If signature + is provided, <int> and <i4> can be deserialized +to byte, int16, uint16, int32, uint32, int64 or uint64. Otherwise +it will be deserialized to int32. If the value is out of range +for the target type it will return an error.

  • +
  • <struct> will be deserialized to "a{sv}". signature + could define +another value type (e.g. "a{ss}").

  • +
  • <array> will be deserialized to "av". signature + could define +another element type (e.g. "as") or could be a tuple (e.g. "(ss)").

  • +
  • <base64> will be deserialized to "ay".

  • +
  • <string> will be deserialized to "s".

  • +
  • <dateTime.iso8601> will be deserialized to an unspecified variant +type. If signature + is provided it must have the generic "v" type, which +means there is no guarantee that it's actually a datetime that has been +received. soup_xmlrpc_variant_get_datetime() must be used to parse and +type check this special variant.

  • +
  • signature + must not have maybes, otherwise an error is returned.

  • +
  • Dictionaries must have string keys, otherwise an error is returned.

  • +
+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

self

A SoupXMLRPCParams

 

signature

A valid GVariant type string, or NULL.

[allow-none]

error

a GError, or NULL

 
+
+
+

Returns

+

a new (non-floating) GVariant, or NULL.

+

[transfer full]

+
+

Since: 2.52

+
+
+
+

soup_xmlrpc_parse_request ()

+
char *
+soup_xmlrpc_parse_request (const char *method_call,
+                           int length,
+                           SoupXMLRPCParams **params,
+                           GError **error);
+

Parses method_call + and return the method name. Method parameters can be +parsed later using soup_xmlrpc_params_parse().

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

method_call

the XML-RPC methodCall string

 

length

the length of method_call +, or -1 if it is NUL-terminated

 

params

on success, a new SoupXMLRPCParams.

[out]

error

a GError, or NULL

 
+
+
+

Returns

+

method's name, or NULL on error.

+

[transfer full]

+
+

Since: 2.52

+
+
+
+

soup_xmlrpc_build_response ()

+
char *
+soup_xmlrpc_build_response (GVariant *value,
+                            GError **error);
+

This creates a (successful) XML-RPC methodResponse and returns it +as a string. To create a fault response, use soup_xmlrpc_build_fault(). This +is the low-level method that soup_xmlrpc_message_set_response() is built on.

+

See soup_xmlrpc_build_request() for serialization details, but note +that since a method can only have a single return value, value + +should not be a tuple here (unless the return value is an array).

+

If value + is floating, it is consumed.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

value

the return value

 

error

a GError, or NULL

 
+
+
+

Returns

+

the text of the methodResponse, or NULL on error.

+
+

Since: 2.52

+
+
+
+

soup_xmlrpc_build_fault ()

+
char *
+soup_xmlrpc_build_fault (int fault_code,
+                         const char *fault_format,
+                         ...);
+

This creates an XML-RPC fault response and returns it as a string. +(To create a successful response, use +soup_xmlrpc_build_method_response().)

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

fault_code

the fault code

 

fault_format

a printf()-style format string

 

...

the parameters to fault_format +

 
+
+
+

Returns

+

the text of the fault

+
+
+
+
+

soup_xmlrpc_message_set_response ()

+
gboolean
+soup_xmlrpc_message_set_response (SoupMessage *msg,
+                                  GVariant *value,
+                                  GError **error);
+

Sets the status code and response body of msg + to indicate a +successful XML-RPC call, with a return value given by value +. To set a +fault response, use soup_xmlrpc_message_set_fault().

+

See soup_xmlrpc_build_request() for serialization details.

+

If value + is floating, it is consumed.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

msg

an XML-RPC request

 

value

a GVariant

 

error

a GError, or NULL

 
+
+
+

Returns

+

TRUE on success, FALSE otherwise.

+
+

Since: 2.52

+
+
+
+

soup_xmlrpc_message_set_fault ()

+
void
+soup_xmlrpc_message_set_fault (SoupMessage *msg,
+                               int fault_code,
+                               const char *fault_format,
+                               ...);
+

Sets the status code and response body of msg + to indicate an +unsuccessful XML-RPC call, with the error described by fault_code + +and fault_format +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

msg

an XML-RPC request

 

fault_code

the fault code

 

fault_format

a printf()-style format string

 

...

the parameters to fault_format +

 
+
+

Since: 2.52

+
+
+
+

Types and Values

+
+

SOUP_XMLRPC_ERROR

+
#define SOUP_XMLRPC_ERROR soup_xmlrpc_error_quark()
+
+
+
+
+

enum SoupXMLRPCError

+
+

Members

+
+++++ + + + + + + + + + + + + +

SOUP_XMLRPC_ERROR_ARGUMENTS

  

SOUP_XMLRPC_ERROR_RETVAL

  
+
+
+
+
+

SOUP_XMLRPC_FAULT

+
#define SOUP_XMLRPC_FAULT soup_xmlrpc_fault_quark()
+
+

A GError domain representing an XML-RPC fault code. Used with +SoupXMLRPCFault (although servers may also return fault codes not +in that enumeration).

+
+
+
+

enum SoupXMLRPCFault

+

Pre-defined XML-RPC fault codes from http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php. +These are an extension, not part of the XML-RPC spec; you can't +assume servers will use them.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

SOUP_XMLRPC_FAULT_PARSE_ERROR_NOT_WELL_FORMED

+

request was not + well-formed

+
 

SOUP_XMLRPC_FAULT_PARSE_ERROR_UNSUPPORTED_ENCODING

+

request was in + an unsupported encoding

+
 

SOUP_XMLRPC_FAULT_PARSE_ERROR_INVALID_CHARACTER_FOR_ENCODING

+

request contained an invalid character

+
 

SOUP_XMLRPC_FAULT_SERVER_ERROR_INVALID_XML_RPC

+

request was not + valid XML-RPC

+
 

SOUP_XMLRPC_FAULT_SERVER_ERROR_REQUESTED_METHOD_NOT_FOUND

+

method + not found

+
 

SOUP_XMLRPC_FAULT_SERVER_ERROR_INVALID_METHOD_PARAMETERS

+

invalid + parameters

+
 

SOUP_XMLRPC_FAULT_SERVER_ERROR_INTERNAL_XML_RPC_ERROR

+

internal + error

+
 

SOUP_XMLRPC_FAULT_APPLICATION_ERROR

+

start of reserved range for + application error codes

+
 

SOUP_XMLRPC_FAULT_SYSTEM_ERROR

+

start of reserved range for + system error codes

+
 

SOUP_XMLRPC_FAULT_TRANSPORT_ERROR

+

start of reserved range for + transport error codes

+
 
+
+
+
+
+

SoupXMLRPCParams

+
typedef struct _SoupXMLRPCParams SoupXMLRPCParams;
+

Opaque structure containing XML-RPC methodCall parameter values. +Can be parsed using soup_xmlrpc_params_parse() and freed with +soup_xmlrpc_params_free().

+

Since: 2.52

+
+
+
+ + + \ No newline at end of file diff --git a/docs/reference/html/libsoup-2.4-soup-method.html b/docs/reference/html/libsoup-2.4-soup-method.html new file mode 100644 index 0000000..17bd595 --- /dev/null +++ b/docs/reference/html/libsoup-2.4-soup-method.html @@ -0,0 +1,254 @@ + + + + +soup-method: libsoup Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

soup-method

+

soup-method — HTTP method definitions

+
+
+

Types and Values

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#defineSOUP_METHOD_OPTIONS
#defineSOUP_METHOD_GET
#defineSOUP_METHOD_HEAD
#defineSOUP_METHOD_PUT
#defineSOUP_METHOD_POST
#defineSOUP_METHOD_DELETE
#defineSOUP_METHOD_TRACE
#defineSOUP_METHOD_CONNECT
#defineSOUP_METHOD_PROPFIND
#defineSOUP_METHOD_PROPPATCH
#defineSOUP_METHOD_MKCOL
#defineSOUP_METHOD_COPY
#defineSOUP_METHOD_MOVE
#defineSOUP_METHOD_LOCK
#defineSOUP_METHOD_UNLOCK
+
+
+

Includes

+
#include <libsoup/soup.h>
+
+
+
+

Description

+

soup-method.h contains a number of defines for standard HTTP and +WebDAV headers. You do not need to use these defines; you can pass +arbitrary strings to soup_message_new() if you prefer.

+

The thing that these defines are useful for is +performing quick comparisons against SoupMessage's method field; +because that field always contains an interned string, and these +macros return interned strings, you can compare method directly +against these macros rather than needing to use strcmp(). This is +most useful in SoupServer handlers. Eg:

+
+ + + + + + + +
1
+2
+3
+4
if (msg->method != SOUP_METHOD_GET && msg->method != SOUP_METHOD_HEAD) {
+	soup_message_set_status (msg, SOUP_METHOD_NOT_IMPLEMENTED);
+	return;
+}
+
+ +
+
+

Functions

+

+
+
+

Types and Values

+
+

SOUP_METHOD_OPTIONS

+
#define SOUP_METHOD_OPTIONS   _SOUP_INTERN_METHOD (OPTIONS)
+
+

"OPTIONS" as an interned string.

+
+
+
+

SOUP_METHOD_GET

+
#define SOUP_METHOD_GET       _SOUP_INTERN_METHOD (GET)
+
+

"GET" as an interned string.

+
+
+
+

SOUP_METHOD_HEAD

+
#define SOUP_METHOD_HEAD      _SOUP_INTERN_METHOD (HEAD)
+
+

"HEAD" as an interned string.

+
+
+
+

SOUP_METHOD_PUT

+
#define SOUP_METHOD_PUT       _SOUP_INTERN_METHOD (PUT)
+
+

"PUT" as an interned string.

+
+
+
+

SOUP_METHOD_POST

+
#define SOUP_METHOD_POST      _SOUP_INTERN_METHOD (POST)
+
+

"POST" as an interned string.

+
+
+
+

SOUP_METHOD_DELETE

+
#define SOUP_METHOD_DELETE    _SOUP_INTERN_METHOD (DELETE)
+
+

"DELETE" as an interned string.

+
+
+
+

SOUP_METHOD_TRACE

+
#define SOUP_METHOD_TRACE     _SOUP_INTERN_METHOD (TRACE)
+
+

"TRACE" as an interned string.

+
+
+
+

SOUP_METHOD_CONNECT

+
#define SOUP_METHOD_CONNECT   _SOUP_INTERN_METHOD (CONNECT)
+
+

"CONNECT" as an interned string.

+
+
+
+

SOUP_METHOD_PROPFIND

+
#define SOUP_METHOD_PROPFIND  _SOUP_INTERN_METHOD (PROPFIND)
+
+

"PROPFIND" as an interned string.

+
+
+
+

SOUP_METHOD_PROPPATCH

+
#define SOUP_METHOD_PROPPATCH _SOUP_INTERN_METHOD (PROPPATCH)
+
+

"PROPPATCH" as an interned string.

+
+
+
+

SOUP_METHOD_MKCOL

+
#define SOUP_METHOD_MKCOL     _SOUP_INTERN_METHOD (MKCOL)
+
+

"MKCOL" as an interned string.

+
+
+
+

SOUP_METHOD_COPY

+
#define SOUP_METHOD_COPY      _SOUP_INTERN_METHOD (COPY)
+
+

"COPY" as an interned string.

+
+
+
+

SOUP_METHOD_MOVE

+
#define SOUP_METHOD_MOVE      _SOUP_INTERN_METHOD (MOVE)
+
+

"MOVE" as an interned string.

+
+
+
+

SOUP_METHOD_LOCK

+
#define SOUP_METHOD_LOCK      _SOUP_INTERN_METHOD (LOCK)
+
+

"LOCK" as an interned string.

+
+
+
+

SOUP_METHOD_UNLOCK

+
#define SOUP_METHOD_UNLOCK    _SOUP_INTERN_METHOD (UNLOCK)
+
+

"UNLOCK" as an interned string.

+
+
+
+ + + \ No newline at end of file diff --git a/docs/reference/html/libsoup-2.4-soup-status.html b/docs/reference/html/libsoup-2.4-soup-status.html new file mode 100644 index 0000000..562c097 --- /dev/null +++ b/docs/reference/html/libsoup-2.4-soup-status.html @@ -0,0 +1,851 @@ + + + + +soup-status: libsoup Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

soup-status

+

soup-status — HTTP (and libsoup) status codes

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#define +SOUP_STATUS_IS_TRANSPORT_ERROR() +
#define +SOUP_STATUS_IS_INFORMATIONAL() +
#define +SOUP_STATUS_IS_SUCCESSFUL() +
#define +SOUP_STATUS_IS_REDIRECTION() +
#define +SOUP_STATUS_IS_CLIENT_ERROR() +
#define +SOUP_STATUS_IS_SERVER_ERROR() +
const char * + +soup_status_get_phrase () +
+guint + +soup_status_proxify () +
+
+
+

Types and Values

+
++++ + + + + + + + + + + +
enumSoupStatus
#defineSOUP_HTTP_ERROR
+
+
+

Includes

+
#include <libsoup/soup.h>
+
+
+
+

Description

+
+
+

Functions

+
+

SOUP_STATUS_IS_TRANSPORT_ERROR()

+
#define SOUP_STATUS_IS_TRANSPORT_ERROR(status) ((status) >  0   && (status) < 100)
+
+

Tests if status + is a libsoup transport error.

+
+

Parameters

+
+++++ + + + + + +

status

a status code

 
+
+
+

Returns

+

TRUE or FALSE

+
+
+
+
+

SOUP_STATUS_IS_INFORMATIONAL()

+
#define SOUP_STATUS_IS_INFORMATIONAL(status)   ((status) >= 100 && (status) < 200)
+
+

Tests if status + is an Informational (1xx) response.

+
+

Parameters

+
+++++ + + + + + +

status

an HTTP status code

 
+
+
+

Returns

+

TRUE or FALSE

+
+
+
+
+

SOUP_STATUS_IS_SUCCESSFUL()

+
#define SOUP_STATUS_IS_SUCCESSFUL(status)      ((status) >= 200 && (status) < 300)
+
+

Tests if status + is a Successful (2xx) response.

+
+

Parameters

+
+++++ + + + + + +

status

an HTTP status code

 
+
+
+

Returns

+

TRUE or FALSE

+
+
+
+
+

SOUP_STATUS_IS_REDIRECTION()

+
#define SOUP_STATUS_IS_REDIRECTION(status)     ((status) >= 300 && (status) < 400)
+
+

Tests if status + is a Redirection (3xx) response.

+
+

Parameters

+
+++++ + + + + + +

status

an HTTP status code

 
+
+
+

Returns

+

TRUE or FALSE

+
+
+
+
+

SOUP_STATUS_IS_CLIENT_ERROR()

+
#define SOUP_STATUS_IS_CLIENT_ERROR(status)    ((status) >= 400 && (status) < 500)
+
+

Tests if status + is a Client Error (4xx) response.

+
+

Parameters

+
+++++ + + + + + +

status

an HTTP status code

 
+
+
+

Returns

+

TRUE or FALSE

+
+
+
+
+

SOUP_STATUS_IS_SERVER_ERROR()

+
#define SOUP_STATUS_IS_SERVER_ERROR(status)    ((status) >= 500 && (status) < 600)
+
+

Tests if status + is a Server Error (5xx) response.

+
+

Parameters

+
+++++ + + + + + +

status

an HTTP status code

 
+
+
+

Returns

+

TRUE or FALSE

+
+
+
+
+

soup_status_get_phrase ()

+
const char *
+soup_status_get_phrase (guint status_code);
+

Looks up the stock HTTP description of status_code +. This is used +by soup_message_set_status() to get the correct text to go with a +given status code.

+

There is no reason for you to ever use this +function. If you wanted the textual description for the +“status_code” of a given SoupMessage, you should just +look at the message's “reason_phrase”. However, you +should only do that for use in debugging messages; HTTP reason +phrases are not localized, and are not generally very descriptive +anyway, and so they should never be presented to the user directly. +Instead, you should create you own error messages based on the +status code, and on what you were trying to do.

+
+

Parameters

+
+++++ + + + + + +

status_code

an HTTP status code

 
+
+
+

Returns

+

the (terse, English) description of status_code +

+
+
+
+
+

soup_status_proxify ()

+
guint
+soup_status_proxify (guint status_code);
+

Turns SOUP_STATUS_CANT_RESOLVE into +SOUP_STATUS_CANT_RESOLVE_PROXY and SOUP_STATUS_CANT_CONNECT into +SOUP_STATUS_CANT_CONNECT_PROXY. Other status codes are passed +through unchanged.

+
+

Parameters

+
+++++ + + + + + +

status_code

a status code

 
+
+
+

Returns

+

the "proxified" equivalent of status_code +.

+
+

Since: 2.26

+
+
+
+

Types and Values

+
+

enum SoupStatus

+

These represent the known HTTP status code values, plus various +network and internal errors.

+

Note that no libsoup functions take or return this type directly; +any function that works with status codes will accept unrecognized +status codes as well.

+

Prior to 2.44 this type was called +SoupKnownStatusCode, but the individual values +have always had the names they have now.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

SOUP_STATUS_NONE

+

No status available. (Eg, the message has not +been sent yet)

+
 

SOUP_STATUS_CANCELLED

+

Message was cancelled locally

+
 

SOUP_STATUS_CANT_RESOLVE

+

Unable to resolve destination host name

+
 

SOUP_STATUS_CANT_RESOLVE_PROXY

+

Unable to resolve proxy host name

+
 

SOUP_STATUS_CANT_CONNECT

+

Unable to connect to remote host

+
 

SOUP_STATUS_CANT_CONNECT_PROXY

+

Unable to connect to proxy

+
 

SOUP_STATUS_SSL_FAILED

+

SSL/TLS negotiation failed

+
 

SOUP_STATUS_IO_ERROR

+

A network error occurred, or the other end +closed the connection unexpectedly

+
 

SOUP_STATUS_MALFORMED

+

Malformed data (usually a programmer error)

+
 

SOUP_STATUS_TRY_AGAIN

+

Used internally

+
 

SOUP_STATUS_TOO_MANY_REDIRECTS

+

There were too many redirections

+
 

SOUP_STATUS_TLS_FAILED

+

Used internally

+
 

SOUP_STATUS_CONTINUE

+

100 Continue (HTTP)

+
 

SOUP_STATUS_SWITCHING_PROTOCOLS

+

101 Switching Protocols (HTTP)

+
 

SOUP_STATUS_PROCESSING

+

102 Processing (WebDAV)

+
 

SOUP_STATUS_OK

+

200 Success (HTTP). Also used by many lower-level +soup routines to indicate success.

+
 

SOUP_STATUS_CREATED

+

201 Created (HTTP)

+
 

SOUP_STATUS_ACCEPTED

+

202 Accepted (HTTP)

+
 

SOUP_STATUS_NON_AUTHORITATIVE

+

203 Non-Authoritative Information +(HTTP)

+
 

SOUP_STATUS_NO_CONTENT

+

204 No Content (HTTP)

+
 

SOUP_STATUS_RESET_CONTENT

+

205 Reset Content (HTTP)

+
 

SOUP_STATUS_PARTIAL_CONTENT

+

206 Partial Content (HTTP)

+
 

SOUP_STATUS_MULTI_STATUS

+

207 Multi-Status (WebDAV)

+
 

SOUP_STATUS_MULTIPLE_CHOICES

+

300 Multiple Choices (HTTP)

+
 

SOUP_STATUS_MOVED_PERMANENTLY

+

301 Moved Permanently (HTTP)

+
 

SOUP_STATUS_FOUND

+

302 Found (HTTP)

+
 

SOUP_STATUS_MOVED_TEMPORARILY

+

302 Moved Temporarily (old name, +RFC 2068)

+
 

SOUP_STATUS_SEE_OTHER

+

303 See Other (HTTP)

+
 

SOUP_STATUS_NOT_MODIFIED

+

304 Not Modified (HTTP)

+
 

SOUP_STATUS_USE_PROXY

+

305 Use Proxy (HTTP)

+
 

SOUP_STATUS_NOT_APPEARING_IN_THIS_PROTOCOL

+

306 [Unused] (HTTP)

+
 

SOUP_STATUS_TEMPORARY_REDIRECT

+

307 Temporary Redirect (HTTP)

+
 

SOUP_STATUS_BAD_REQUEST

+

400 Bad Request (HTTP)

+
 

SOUP_STATUS_UNAUTHORIZED

+

401 Unauthorized (HTTP)

+
 

SOUP_STATUS_PAYMENT_REQUIRED

+

402 Payment Required (HTTP)

+
 

SOUP_STATUS_FORBIDDEN

+

403 Forbidden (HTTP)

+
 

SOUP_STATUS_NOT_FOUND

+

404 Not Found (HTTP)

+
 

SOUP_STATUS_METHOD_NOT_ALLOWED

+

405 Method Not Allowed (HTTP)

+
 

SOUP_STATUS_NOT_ACCEPTABLE

+

406 Not Acceptable (HTTP)

+
 

SOUP_STATUS_PROXY_AUTHENTICATION_REQUIRED

+

407 Proxy Authentication +Required (HTTP)

+
 

SOUP_STATUS_PROXY_UNAUTHORIZED

+

shorter alias for +SOUP_STATUS_PROXY_AUTHENTICATION_REQUIRED

+
 

SOUP_STATUS_REQUEST_TIMEOUT

+

408 Request Timeout (HTTP)

+
 

SOUP_STATUS_CONFLICT

+

409 Conflict (HTTP)

+
 

SOUP_STATUS_GONE

+

410 Gone (HTTP)

+
 

SOUP_STATUS_LENGTH_REQUIRED

+

411 Length Required (HTTP)

+
 

SOUP_STATUS_PRECONDITION_FAILED

+

412 Precondition Failed (HTTP)

+
 

SOUP_STATUS_REQUEST_ENTITY_TOO_LARGE

+

413 Request Entity Too Large +(HTTP)

+
 

SOUP_STATUS_REQUEST_URI_TOO_LONG

+

414 Request-URI Too Long (HTTP)

+
 

SOUP_STATUS_UNSUPPORTED_MEDIA_TYPE

+

415 Unsupported Media Type +(HTTP)

+
 

SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE

+

416 Requested Range +Not Satisfiable (HTTP)

+
 

SOUP_STATUS_INVALID_RANGE

+

shorter alias for +SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE

+
 

SOUP_STATUS_EXPECTATION_FAILED

+

417 Expectation Failed (HTTP)

+
 

SOUP_STATUS_UNPROCESSABLE_ENTITY

+

422 Unprocessable Entity +(WebDAV)

+
 

SOUP_STATUS_LOCKED

+

423 Locked (WebDAV)

+
 

SOUP_STATUS_FAILED_DEPENDENCY

+

424 Failed Dependency (WebDAV)

+
 

SOUP_STATUS_INTERNAL_SERVER_ERROR

+

500 Internal Server Error +(HTTP)

+
 

SOUP_STATUS_NOT_IMPLEMENTED

+

501 Not Implemented (HTTP)

+
 

SOUP_STATUS_BAD_GATEWAY

+

502 Bad Gateway (HTTP)

+
 

SOUP_STATUS_SERVICE_UNAVAILABLE

+

503 Service Unavailable (HTTP)

+
 

SOUP_STATUS_GATEWAY_TIMEOUT

+

504 Gateway Timeout (HTTP)

+
 

SOUP_STATUS_HTTP_VERSION_NOT_SUPPORTED

+

505 HTTP Version Not +Supported (HTTP)

+
 

SOUP_STATUS_INSUFFICIENT_STORAGE

+

507 Insufficient Storage +(WebDAV)

+
 

SOUP_STATUS_NOT_EXTENDED

+

510 Not Extended (RFC 2774)

+
 
+
+
+
+
+

SOUP_HTTP_ERROR

+
#define SOUP_HTTP_ERROR soup_http_error_quark()
+
+

A GError domain representing an HTTP status. Use a SoupStatus for +the code value.

+
+
+
+ + + \ No newline at end of file diff --git a/docs/reference/html/libsoup-2.4.devhelp2 b/docs/reference/html/libsoup-2.4.devhelp2 new file mode 100644 index 0000000..ebe33c4 --- /dev/null +++ b/docs/reference/html/libsoup-2.4.devhelp2 @@ -0,0 +1,1058 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/reference/html/libsoup-build-howto.html b/docs/reference/html/libsoup-build-howto.html new file mode 100644 index 0000000..c98f680 --- /dev/null +++ b/docs/reference/html/libsoup-build-howto.html @@ -0,0 +1,135 @@ + + + + +Compiling with libsoup: libsoup Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

Compiling with libsoup

+

Compiling with libsoup — Notes on compiling

+
+
+

Using pkg-config

+

+Like other GNOME libraries, libsoup uses +pkg-config to provide compiler options. The +package name is "libsoup-2.4". So in your +configure script, you might specify something like: +

+
+ + + + + + + +
1
+2
+3
PKG_CHECK_MODULES(LIBSOUP, [libsoup-2.4 >= 2.26])
+AC_SUBST(LIBSOUP_CFLAGS)
+AC_SUBST(LIBSOUP_LIBS)
+
+ +

+The "2.4" in the package name is the "API version" +(indicating "the version of the libsoup API +that first appeared in version 2.4") and is essentially just part of +the package name. +

+
+
+
+

API Availability and Deprecation Warnings

+

+If you want to restrict your program to a particular +libsoup version or range of versions, you +can define SOUP_VERSION_MIN_REQUIRED +and/or SOUP_VERSION_MAX_ALLOWED. +Eg: +

+
+ + + + + + + +
1
+2
LIBSOUP_CFLAGS="$LIBSOUP_CFLAGS -DSOUP_VERSION_MIN_REQUIRED=SOUP_VERSION_2_36"
+LIBSOUP_CFLAGS="$LIBSOUP_CFLAGS -DSOUP_VERSION_MAX_ALLOWED=SOUP_VERSION_2_40"
+
+ +

+The SOUP_VERSION_MIN_REQUIRED declaration states +that the code is not expected to compile on versions of +libsoup older than the indicated version +(here, 2.36), and so the compiler should print warnings if the code +uses functions that were deprecated as of that release. +

+

+The SOUP_VERSION_MAX_ALLOWED declaration states +that the code is expected to compile on versions +of libsoup up to the indicated version +(here, 2.40), and so, when compiling the program against a newer +version than that, the compiler should print warnings if the code uses +functions that did not yet exist in the max-allowed release. +

+

+You can use SOUP_CHECK_VERSION +to check the version of libsoup at compile time, to compile different +code for different libsoup versions. (If +you are setting SOUP_VERSION_MIN_REQUIRED and +SOUP_VERSION_MAX_ALLOWED to different versions, as +in the example above, then you almost certainly need to be doing +this.) +

+
+
+
+

Headers

+

+Code using libsoup should do: +

+
+ + + + + + + +
1
#include <libsoup/soup.h>
+
+ +

+Including individual headers rather than soup.h is not +recommended. +

+
+
+ + + \ No newline at end of file diff --git a/docs/reference/html/libsoup-client-howto.html b/docs/reference/html/libsoup-client-howto.html new file mode 100644 index 0000000..df2524f --- /dev/null +++ b/docs/reference/html/libsoup-client-howto.html @@ -0,0 +1,603 @@ + + + + +libsoup Client Basics: libsoup Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

libsoup Client Basics

+

libsoup Client Basics — Client-side tutorial

+
+
+

+This section explains how to use libsoup as +an HTTP client using several new APIs introduced in version 2.42. If +you want to be compatible with older versions of +libsoup, consult the documentation for that +version. +

+
+
+
+

Creating a SoupSession +

+

+The first step in using the client API is to create a SoupSession. The session object +encapsulates all of the state that libsoup +is keeping on behalf of your program; cached HTTP connections, +authentication information, etc. +

+

+When you create the session with soup_session_new_with_options, +you can specify various additional options: +

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

SOUP_SESSION_MAX_CONNS

+ Allows you to set the maximum total number of connections + the session will have open at one time. (Once it reaches + this limit, it will either close idle connections, or + wait for existing connections to free up before starting + new requests.) The default value is 10. +

SOUP_SESSION_MAX_CONNS_PER_HOST

+ Allows you to set the maximum total number of connections + the session will have open to a single + host at one time. The default value is 2. +

SOUP_SESSION_USER_AGENT

+ Allows you to set a User-Agent string that will be sent + on all outgoing requests. +

SOUP_SESSION_ACCEPT_LANGUAGE + and SOUP_SESSION_ACCEPT_LANGUAGE_AUTO

+ Allow you to set an Accept-Language header on all outgoing + requests. SOUP_SESSION_ACCEPT_LANGUAGE + takes a list of language tags to use, while + SOUP_SESSION_ACCEPT_LANGUAGE_AUTO + automatically generates the list from the user's locale + settings. +

SOUP_SESSION_HTTP_ALIASES + and SOUP_SESSION_HTTPS_ALIASES

+ Allow you to tell the session to recognize additional URI + schemes as aliases for "http" or + https. You can set this if you are + using URIs with schemes like "dav" or + "webcal" (and in particular, you need + to set this if the server you are talking to might return + redirects with such a scheme). +

SOUP_SESSION_PROXY_RESOLVER and SOUP_SESSION_PROXY_URI

+

+ SOUP_SESSION_PROXY_RESOLVER + specifies a GProxyResolver + to use to determine the HTTP proxies to use. By default, + this is set to the resolver returned by g_proxy_resolver_get_default, + so you do not need to set it yourself. +

+

+ Alternatively, if you want all requests to go through a + single proxy, you can set SOUP_SESSION_PROXY_URI. +

+

SOUP_SESSION_ADD_FEATURE and SOUP_SESSION_ADD_FEATURE_BY_TYPE

+ These allow you to specify SoupSessionFeatures + (discussed below) + to add at construct-time. +

+

+Other properties are also available; see the SoupSession documentation for +more details. +

+

+If you don't need to specify any options, you can just use soup_session_new, +which takes no arguments. +

+
+
+
+

Session features

+

+Additional session functionality is provided as SoupSessionFeatures, +which can be added to a session, via the SOUP_SESSION_ADD_FEATURE +and SOUP_SESSION_ADD_FEATURE_BY_TYPE +options at session-construction-time, or afterward via the soup_session_add_feature +and soup_session_add_feature_by_type +functions. +

+

+A SoupContentDecoder is +added for you automatically. This advertises to servers that the +client supports compression, and automatically decompresses compressed +responses. +

+

+Some other available features that you can add include: +

+
++++ + + + + + + + + + + + + + + +

SoupLogger

+ A debugging aid, which logs all of libsoup's HTTP traffic + to stdout (or another place you specify). +

+ SoupCookieJar, + SoupCookieJarText, + and SoupCookieJarDB +

+ Support for HTTP cookies. SoupCookieJar + provides non-persistent cookie storage, while + SoupCookieJarText uses a text file to keep + track of cookies between sessions, and + SoupCookieJarDB uses a + SQLite database. +

SoupContentSniffer

+ Uses the HTML5 sniffing rules to attempt to + determine the Content-Type of a response when the + server does not identify the Content-Type, or appears to + have provided an incorrect one. +

+

+Use the "add_feature_by_type" property/function to add features that +don't require any configuration (such as SoupContentSniffer), +and the "add_feature" property/function to add features that must be +constructed first (such as SoupLogger). For example, an +application might do something like the following: +

+
+ + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
session = soup_session_new_with_options (
+	SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_CONTENT_SNIFFER,
+	NULL);
+
+if (debug_level) {
+	SoupLogger *logger;
+
+	logger = soup_logger_new (debug_level, -1);
+	soup_session_add_feature (session, SOUP_SESSION_FEATURE (logger));
+	g_object_unref (logger);
+}
+
+ +
+
+
+

Creating and Sending SoupMessages

+

+Once you have a session, you send HTTP requests using SoupMessage. In the simplest +case, you only need to create the message and it's ready to send: +

+
+ + + + + + + +
1
+2
+3
SoupMessage *msg;
+
+msg = soup_message_new ("GET", "http://example.com/");
+
+ +

+In more complicated cases, you can use various SoupMessage, SoupMessageHeaders, and SoupMessageBody methods to set the +request headers and body of the message: +

+
+ + + + + + + +
1
+2
+3
+4
+5
+6
SoupMessage *msg;
+
+msg = soup_message_new ("POST", "http://example.com/form.cgi");
+soup_message_set_request (msg, "application/x-www-form-urlencoded",
+                          SOUP_MEMORY_COPY, formdata, strlen (formdata));
+soup_message_headers_append (msg->request_headers, "Referer", referring_url);
+
+ +

+(Although this is a bad example, because +libsoup actually has convenience methods +for dealing with HTML +forms, as well as XML-RPC.) +

+

+You can also use soup_message_set_flags +to change some default behaviors. For example, by default, +SoupSession automatically handles responses from the +server that redirect to another URL. If you would like to handle these +yourself, you can set the SOUP_MESSAGE_NO_REDIRECT +flag. +

+
+

Sending a Message Synchronously

+

+To send a message and wait for the response, use soup_session_send: +

+
+ + + + + + + +
1
+2
+3
+4
GInputStream *stream;
+GError *error = NULL;
+
+stream = soup_session_send (session, msg, cancellable, &error);
+
+ +

+At the point when soup_session_send returns, the +request will have been sent, and the response headers read back in; +you can examine the message's status_code, +reason_phrase, and +response_headers fields to see the response +metadata. To get the response body, read from the returned GInputStream, and close it +when you are done. +

+

+Note that soup_session_send only returns an error +if a transport-level problem occurs (eg, it could not connect to the +host, or the request was cancelled). Use the message's +status_code field to determine whether the +request was successful or not at the HTTP level (ie, "200 +OK" vs "401 Bad Request"). +

+

+If you would prefer to have libsoup gather +the response body for you and then return it all at once, you can use +the older +soup_session_send_message +API: +

+
+ + + + + + + +
1
+2
+3
guint status;
+
+status = soup_session_send_message (session, msg);
+
+ +

+In this case, the response body will be available in the message's +response_body field, and transport-level +errors will be indicated in the status_code +field via special pseudo-HTTP-status codes like SOUP_STATUS_CANT_CONNECT. +

+
+
+

Sending a Message Asynchronously

+

+To send a message asynchronously, use soup_session_send_async: +

+
+ + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
{
+	...
+	soup_session_send_async (session, msg, cancellable, my_callback, my_callback_data);
+	...
+}
+
+static void
+my_callback (GObject *object, GAsyncResult *result, gpointer user_data)
+{
+	GInputStream *stream;
+	GError *error = NULL;
+
+	stream = soup_session_send_finish (SOUP_SESSION (object), result, &error);
+	...
+}
+
+ +

+The message will be added to the session's queue, and eventually (when +control is returned back to the main loop), it will be sent and the +response be will be read. When the message has been sent, and its +headers received, the callback will be invoked, in the standard +GAsyncReadyCallback +style. +

+

+As with synchronous sending, there is also an alternate API, soup_session_queue_message, +in which your callback is not invoked until the response has been +completely read: +

+
+ + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
{
+	...
+	soup_session_queue_message (session, msg, my_callback, my_callback_data);
+	...
+}
+
+static void
+my_callback (SoupSession *session, SoupMessage *msg, gpointer user_data)
+{
+	/* msg->response_body contains the response */
+}
+
+ +

+soup_session_queue_message +is slightly unusual in that it steals a reference to the message +object, and unrefs it after the last callback is invoked on it. So +when using this API, you should not unref the message yourself. +

+
+
+
+
+

Processing the Response

+

+Once you have received the initial response from the server, +synchronously or asynchronously, streaming or not, you can look at the +response fields in the SoupMessage to decide what +to do next. The status_code and +reason_phrase fields contain the numeric +status and textual status response from the server. +response_headers contains the response +headers, which you can investigate using soup_message_headers_get +and soup_message_headers_foreach. +

+

+SoupMessageHeaders +automatically parses several important headers in +response_headers for you and provides +specialized accessors for them. Eg, soup_message_headers_get_content_type. +There are several generic methods such as soup_header_parse_param_list +(for parsing an attribute-list-type header) and soup_header_contains +(for quickly testing if a list-type header contains a particular +token). These handle the various syntactical oddities of parsing HTTP +headers much better than functions like +g_strsplit or strstr. +

+
+
+
+

Handling Authentication

+

+SoupSession handles most of the details of HTTP +authentication for you. If it receives a 401 ("Unauthorized") or 407 +("Proxy Authentication Required") response, the session will emit the +authenticate signal, +providing you with a SoupAuth object indicating the +authentication type ("Basic", "Digest", or "NTLM") and the realm name +provided by the server. If you have a username and password available +(or can generate one), call soup_auth_authenticate +to give the information to libsoup. The session will automatically +requeue the message and try it again with that authentication +information. (If you don't call +soup_auth_authenticate, the session will just +return the message to the application with its 401 or 407 status.) +

+

+If the server doesn't accept the username and password provided, the +session will emit authenticate again, with the +retrying parameter set to TRUE. This lets the +application know that the information it provided earlier was +incorrect, and gives it a chance to try again. If this +username/password pair also doesn't work, the session will contine to +emit authenticate again and again until the +provided username/password successfully authenticates, or until the +signal handler fails to call soup_auth_authenticate, +at which point libsoup will allow the +message to fail (with status 401 or 407). +

+

+If you need to handle authentication asynchronously (eg, to pop up a +password dialog without recursively entering the main loop), you can +do that as well. Just call soup_session_pause_message +on the message before returning from the signal handler, and +g_object_ref the SoupAuth. Then, +later on, after calling soup_auth_authenticate +(or deciding not to), call soup_session_unpause_message +to resume the paused message. +

+

+By default, NTLM authentication is not enabled. To add NTLM support to +a session, call: +

+
+ + + + + + + +
1
soup_session_add_feature_by_type (session, SOUP_TYPE_AUTH_NTLM);
+
+ +

+(You can also disable Basic or Digest authentication by calling soup_session_remove_feature_by_type +on SOUP_TYPE_AUTH_BASIC +or SOUP_TYPE_AUTH_DIGEST.) +

+
+
+
+

Multi-threaded usage

+

+A SoupSession can be +used from multiple threads. However, if you are using the async APIs, +then each thread you use the session from must have its own +thread-default GMainContext. +

+

+SoupMessage is +not thread-safe, so once you send a message on +the session, you must not interact with it from any thread other than +the one where it was sent. +

+
+
+
+

Sample Programs

+

+A few sample programs are available in the +libsoup sources, in the +examples directory: +

+
    +
  • + get is a simple command-line + HTTP GET utility using the asynchronous API. +

  • +
  • + simple-proxy uses both the + client and server APIs to create a simple (and not very + RFC-compliant) proxy server. It shows how to use the SOUP_MESSAGE_OVERWRITE_CHUNKS + flag when reading a message to save memory by processing each + chunk of the message as it is read, rather than accumulating + them all into a single buffer to process all at the end. +

  • +
+

+More complicated examples are available in GNOME git. +

+
+
+ + + \ No newline at end of file diff --git a/docs/reference/html/libsoup-request-howto.html b/docs/reference/html/libsoup-request-howto.html new file mode 100644 index 0000000..3403daf --- /dev/null +++ b/docs/reference/html/libsoup-request-howto.html @@ -0,0 +1,171 @@ + + + + +libsoup Client SoupRequest API: libsoup Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

libsoup Client SoupRequest API

+

libsoup Client SoupRequest API — Using +libsoup with a mix of http and non-http URIs.

+
+
+

SoupRequest

+

+SoupRequest is an +abstract type representing a request for a particular URI. The +SoupRequest API is an alternative to the SoupMessage-based SoupSession APIs which may be +useful to programs that want to deal with multiple kinds of URIs. +

+

+SoupRequest officially became part of the +libsoup API in 2.42 with the addition of +soup_session_request +and the related functions. However, parts of it are also available as +far back as libsoup 2.34 via the +(now-deprecated) SoupRequester session feature, if you +define LIBSOUP_USE_UNSTABLE_REQUEST_API before +including the libsoup headers. +

+

+Additionally, before libsoup 2.42, the +SoupRequest API was the only way to stream an HTTP +response body via GInputStream. As of 2.42, +there are streaming APIs based on SoupMessage (soup_session_send +and soup_session_send_async), +so applications that are using SoupRequest with only +http and https URIs can be +ported to those APIs now. +

+
+
+
+

Creating a SoupRequest

+

+There are four SoupSession methods for creating +SoupRequests: +

+
+
+
+
+

Sending a SoupRequest

+

+Once you have created a SoupRequest, you can send it with +either soup_request_send +or soup_request_send_async. +This will provide you with a GInputStream which you can +read to get the response body. +

+

+After sending, you can use soup_request_get_content_length +and soup_request_get_content_type +to get information about the response body. +

+

+As with the streaming SoupMessage-based APIs, +soup_request_send and +soup_request_send_async only return errors if a +transport-level problem occurs (eg, it could not connect to the host, +or the request was cancelled). In the case of an HTTP request, use the +message's status_code field to determine +whether the request was successful or not at the HTTP level (ie, "200 +OK" vs "401 Bad Request"). (You can call soup_request_http_get_message +to get the request's corresponding SoupMessage, to look at the +status code or other HTTP metadata.) +

+
+
+
+

Supported URI types, and adding your own

+

+Different URI types are implemented by different subclasses of +SoupRequest. libsoup currently +implements three SoupRequest classes: +

+
++++ + + + + + + + + + + + + + + +

SoupRequestHTTP

+ Handles http and + https URI. +

SoupRequestData

+ Handles data URIs containing inline data. +

SoupRequestFile

+ Handles file and + resource URIs. + If you request a URI corresponding to a directory, this + will generate an HTML listing of the directory. +

+

+You can add additional URI types by implementing your own +SoupRequest subclass; set the +SoupRequestClass's schemes +field to point to a NULL-terminated array of scheme +names, implement the various SoupRequest methods, and +then register the type with your SoupSession by calling +soup_session_add_feature_by_type +and passing the GType of +your request class. +

+
+
+ + + \ No newline at end of file diff --git a/docs/reference/html/libsoup-server-howto.html b/docs/reference/html/libsoup-server-howto.html new file mode 100644 index 0000000..80d4649 --- /dev/null +++ b/docs/reference/html/libsoup-server-howto.html @@ -0,0 +1,484 @@ + + + + +libsoup Server Basics: libsoup Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

libsoup Server Basics

+

libsoup Server Basics — Server-side tutorial

+
+
+

Creating a SoupServer

+

+As with the client API, there is a single object that will encapsulate +most of your interactions with libsoup. In this case, SoupServer. +

+

+You create the server with soup_server_new, +and as with the SoupSession constructor, you can specify +a few additional options: +

+
++++ + + + + + + + + + + + + + + + + + + +

SOUP_SERVER_TLS_CERTIFICATE

+ A GTlsCertificate + (containing a private key) that will be used when handling + HTTPS requests on the server. +

SOUP_SERVER_RAW_PATHS

+ Set this to TRUE if you don't want + libsoup to decode %-encoding + in the Request-URI. (Eg, because you need to treat + "/foo/bar" and + "/foo%2Fbar" as different paths. +

SOUP_SERVER_SERVER_HEADER

+ Allows you to set a Server header string that will be sent + on all responses. +

SOUP_SERVER_HTTP_ALIASES + and SOUP_SERVER_HTTPS_ALIASES

+ Allow you to tell the server to recognize additional URI + schemes as aliases for "http" or + https. You can set this if you are + serving URIs with schemes like "dav" or + "webcal". +

+
+
+
+

Adding Listening Sockets

+

+ To tell the server where to listen, call soup_server_listen + (to listen on a specific GSocketAddress), soup_server_listen_all + (to listen on a given port on all network interfaces), or soup_server_listen_local + (to listen to a given port on the loopback interface only). You can + call any of these functions multiple times, to set up multiple + listening sockets. +

+

+ To set up an HTTPS server, you must first either set the SOUP_SERVER_TLS_CERTIFICATE + property, or else call soup_server_set_ssl_cert_file. + After that you can pass the SOUP_SERVER_LISTEN_HTTPS + option to soup_server_listen, + etc. +

+

+ By default, servers listen for both IPv4 and IPv6 connections; if + you don't want this, use the SOUP_SERVER_LISTEN_IPV4_ONLY + or SOUP_SERVER_LISTEN_IPV6_ONLY + options. +

+

+ The server runs asynchronously, in the thread-default + GMainContext of the + thread in which the "listen" calls were made. +

+
+
+
+

The Old SoupServer Listening API

+

+soup_server_listen, +etc, are available only in libsoup 2.46 and +later. In earlier versions, there was a simpler API, in which a server +could only listen on a single port, determined at construct time +either by passing the SOUP_SERVER_INTERFACE +property (to specify a SoupAddress to listen on), +or the SOUP_SERVER_PORT +property (to specify a port to listen on, on all interfaces). The SOUP_SERVER_SSL_CERT_FILE +and SOUP_SERVER_SSL_KEY_FILE +properties could be used to create an HTTP server. +

+

+When using this API, if SoupServer is unable to bind +the listening socket, or unable to read the provided certificate or +key files, then it will return NULL from its +constructor (with no further indication of what exactly went wrong). +

+

+Additionally, when using this API, it is necessary to call soup_server_run +or soup_server_run_async +to start the server after creating it. +

+
+
+
+

Adding Handlers

+

+By default, SoupServer +returns "404 Not Found" in response to all requests (except ones that +it can't parse, which get "400 Bad Request"). To override this +behavior, call soup_server_add_handler +to set a callback to handle certain URI paths. +

+
+ + + + + + + +
1
+2
soup_server_add_handler (server, "/foo", server_callback,
+                         data, destroy_notify);
+
+ +

+The "/foo" indicates the base path for this +handler. When a request comes in, if there is a handler registered for +exactly the path in the request's Request-URI, then +that handler will be called. Otherwise +libsoup will strip path components one by +one until it finds a matching handler. So for example, a request of +the form +"GET /foo/bar/baz.html?a=1&b=2 HTTP/1.1" +would look for handlers for "/foo/bar/baz.html", +"/foo/bar", and "/foo". If a +handler has been registered with a NULL base path, +then it is used as the default handler for any request that doesn't +match any other handler. +

+
+
+
+

Responding to Requests

+

+A handler callback looks something like this: +

+
+ + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
static void
+server_callback (SoupServer        *server,
+                 SoupMessage       *msg, 
+                 const char        *path,
+                 GHashTable        *query,
+                 SoupClientContext *client,
+                 gpointer           user_data)
+{
+	...
+}
+
+ +

+msg is the request that has been received and +user_data is the data that was passed to soup_server_add_handler. +path is the path (from msg's +URI), and query contains the result of parsing the +URI query field. (It is NULL if there was no +query.) client is a SoupClientContext, +which contains additional information about the client (including its +IP address, and whether or not it used HTTP authentication). +

+

+By default, libsoup assumes that you have +completely finished processing the message when you return from the +callback, and that it can therefore begin sending the response. If you +are not ready to send a response immediately (eg, you have to contact +another server, or wait for data from a database), you must call soup_server_pause_message +on the message before returning from the callback. This will delay +sending a response until you call soup_server_unpause_message. +(You must also connect to the finished signal on the message +in this case, so that you can break off processing if the client +unexpectedly disconnects before you start sending the data.) +

+

+To set the response status, call soup_message_set_status +or soup_message_set_status_full. +If the response requires a body, you must decide whether to use +Content-Length encoding (the default), or +chunked encoding. +

+
+

Responding with Content-Length +Encoding

+

+This is the simpler way to set a response body, if you have all of the +data available at once. +

+
+ + + + + + + +
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
+26
+27
+28
+29
+30
+31
static void
+server_callback (SoupServer        *server,
+                 SoupMessage       *msg, 
+                 const char        *path,
+                 GHashTable        *query,
+                 SoupClientContext *client,
+                 gpointer           user_data)
+{
+	MyServerData *server_data = user_data;
+	const char *mime_type;
+	GByteArray *body;
+
+	if (msg->method != SOUP_METHOD_GET) {
+		soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED);
+		return;
+	}
+
+	/* This is somewhat silly. Presumably your server will do
+	 * something more interesting.
+	 */
+	body = g_hash_table_lookup (server_data->bodies, path);
+	mime_type = g_hash_table_lookup (server_data->mime_types, path);
+	if (!body || !mime_type) {
+		soup_message_set_status (msg, SOUP_STATUS_NOT_FOUND);
+		return;
+	}
+
+	soup_message_set_status (msg, SOUP_STATUS_OK);
+	soup_message_set_response (msg, mime_type, SOUP_MEMORY_COPY,
+	                           body->data, body->len);
+}
+
+ +
+
+

Responding with chunked Encoding

+

+If you want to supply the response body in chunks as it becomes +available, use chunked encoding instead. In this +case, first call soup_message_headers_set_encoding (msg->response_headers, SOUP_ENCODING_CHUNKED) +to tell libsoup that you'll be using +chunked encoding. Then call soup_message_body_append +(or soup_message_body_append_buffer) +on msg->response_body with each chunk of the +response body as it becomes available, and call soup_message_body_complete +when the response is complete. After each of these calls, you must +also call soup_server_unpause_message +to cause the chunk to be sent. (You do not normally need to call soup_server_pause_message, +because I/O is automatically paused when doing a +chunked transfer if no chunks are available.) +

+

+When using chunked encoding, you must also connect to the finished signal on the message, +so that you will be notified if the client disconnects between two +chunks; SoupServer will unref the message if that +happens, so you must stop adding new chunks to the response at that +point. (An alternate possibility is to write each new chunk only when +the wrote_chunk signal +is emitted indicating that the previous one was written successfully.) +

+

+The simple-proxy +example in the examples/ directory gives an example of +using chunked encoding. +

+
+
+
+
+

Handling Authentication

+

+To have SoupServer +handle HTTP authentication for you, create a SoupAuthDomainBasic +or SoupAuthDomainDigest, +and pass it to soup_server_add_auth_domain: +

+
+ + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
SoupAuthDomain *domain;
+
+domain = soup_auth_domain_basic_new (
+	SOUP_AUTH_DOMAIN_REALM, "My Realm",
+	SOUP_AUTH_DOMAIN_BASIC_AUTH_CALLBACK, auth_callback,
+	SOUP_AUTH_DOMAIN_BASIC_AUTH_DATA, auth_data,
+	SOUP_AUTH_DOMAIN_ADD_PATH, "/foo",
+	SOUP_AUTH_DOMAIN_ADD_PATH, "/bar/private",
+	NULL);
+soup_server_add_auth_domain (server, domain);
+g_object_unref (domain);
+
+ +

+Then, every request under one of the auth domain's paths will be +passed to the auth_callback first before being +passed to the server_callback: +

+
+ + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
static gboolean
+auth_callback (SoupAuthDomain *domain, SoupMessage *msg,
+               const char *username, const char *password,
+               gpointer user_data)
+{
+	MyServerData *server_data = user_data;
+	MyUserData *user;
+
+	user = my_server_data_lookup_user (server_data, username);
+	if (!user)
+		return FALSE;
+
+	/* FIXME: Don't do this. Keeping a cleartext password database
+	 * is bad.
+	 */
+	return strcmp (password, user->password) == 0;
+}
+
+ +

+The SoupAuthDomainBasicAuthCallback +is given the username and password from the +Authorization header and must determine, in some +server-specific manner, whether or not to accept them. (In this +example we compare the password against a cleartext password database, +but it would be better to store the password somehow encoded, as in +the UNIX password database. Alternatively, you may need to delegate +the password check to PAM or some other service.) +

+

+If you are using Digest authentication, note that SoupAuthDomainDigestAuthCallback +works completely differently (since the server doesn't receive the +cleartext password from the client in that case, so there's no way to +compare it directly). See the documentation for SoupAuthDomainDigest +for more details. +

+

+You can have multiple SoupAuthDomains attached to a +SoupServer, either in separate parts of the path +hierarchy, or overlapping. (Eg, you might want to accept either Basic +or Digest authentication for a given path.) When more than one auth +domain covers a given path, the request will be accepted if the user +authenticates successfully against any of the +domains. +

+

+If you want to require authentication for some requests under a +certain path, but not all of them (eg, you want to authenticate +PUT requests, but not GET +requests), use a SoupAuthDomainFilter. +

+
+
+ + + \ No newline at end of file diff --git a/docs/reference/html/libsoup-session-porting.html b/docs/reference/html/libsoup-session-porting.html new file mode 100644 index 0000000..a177034 --- /dev/null +++ b/docs/reference/html/libsoup-session-porting.html @@ -0,0 +1,217 @@ + + + + +Porting to the new SoupSession: libsoup Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

Porting to the new SoupSession

+

Porting to the new SoupSession — Notes on +porting from SoupSessionAsync and SoupSessionSync to SoupSession

+
+
+

Introduction

+

+As of libsoup 2.42, SoupSession is no longer an +abstract class, and the base SoupSession class is now +preferred over its traditional subclasses, SoupSessionAsync and +SoupSessionSync. +

+

+There are several changes in behavior between the old and new sessions +to be aware of. +

+
+
+
+

Different defaults

+

+The new SoupSession +has different (and hopefully better) defaults than SoupSessionAsync and +SoupSessionSync: +

+
    +
  • +

    + The system TLS/SSL certificate database is used by default to + validate https certificates, and sites with invalid certificates + will refuse to load with a + SOUP_STATUS_SSL_FAILED + error. +

    +

    + You can still override the CA database as before, by setting the + "ssl-ca-file" + property, although the + "tls-database" + property is preferred, since it allows you to do proper error + handling. +

    +

    + If you want to accept all certificates, set + "ssl-strict" to + FALSE. Note that libsoup will still check + certificates, it will just continue with the HTTP request even + if the certificate fails to validate. You can use + soup_message_get_https_status() + to look at the certificate after the fact. +

    +
  • +
  • + The + "timeout" + and + "idle-timeout" + properties both default to 60 seconds. +

  • +
  • + The + "http-aliases" + property defaults to NULL, meaning that URI + schemes like "webcal" and + "dav" (and "ftp") are not + considered to be aliases for "http", and so + libsoup will not accept requests for such URIs, and will not + follow redirects to such URIs. +

  • +
  • + The new + "proxy-resolver" + property is now initialized to the default + GProxyResolver, + meaning that it will automatically use the user's system proxy + configuration. This replaces the use of the + SoupProxyResolverDefault, + session feature in earlier releases. You can set this property to + NULL if you don't want to use proxies, and the + "proxy-uri" + property still works if you want to use a single proxy for all requests. +

  • +
  • + Every session gets a + SoupContentDecoder + attached to it by default, meaning that it will automatically + handle (and request) "gzip"- and "deflate"-encoded response + bodies. +

  • +
+
+
+
+

Differences in feature behavior

+

+If you are using NTLM authentication, the new SoupSession +behaves slightly differently from the old session types. +

+

+First, the deprecated SOUP_SESSION_USE_NTLM +property is no longer supported. If you want to add support for NTLM +to a session, call soup_session_add_feature_by_type(), +passing SOUP_TYPE_AUTH_NTLM. +

+

+Second, with the old session types, enabling NTLM would cause all +(otherwise-unauthenticated) requests to be sent with an NTLM request +in the Authorization header. That is, libsoup would +assume that all servers supported NTLM, and would attempt to begin +negotiating NTLM authentication before the server ever returned a 401 +response. With the plain SoupSession, this no longer +happens. If you want the old behavior, you need to call soup_auth_manager_use_auth() +for each host to "preload" the NTLM authentication: +

+
+ + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
SoupAuthManager *auth_manager;
+SoupAuth *auth;
+SoupURI *uri;
+
+auth_manager = SOUP_AUTH_MANAGER (soup_session_get_feature (session, SOUP_TYPE_AUTH_MANAGER));
+auth = g_object_new (SOUP_TYPE_AUTH_NTLM, NULL);
+uri = soup_uri_new ("http://ntlm-using-host.example.com/");
+soup_auth_manager_use_auth (auth_manager, uri, auth);
+g_object_unref (auth);
+soup_uri_free (auth);
+
+ +
+
+
+

Differences in SoupMessage-sending APIs

+

+SoupSessionAsync always uses asynchronous I/O, and +SoupSessionSync always uses blocking I/O, regardless of +the operation. In the new SoupSession, soup_session_queue_message() +uses asynchronous I/O (like SoupSessionAsync), and soup_session_send_message() +uses blocking I/O (like SoupSessionSync). There is no API +on the plain SoupSession that simulates the effect of +calling soup_session_send_message() on a +SoupSessionAsync (ie, running the main loop internally), +or of calling soup_session_queue_message() on a +SoupSessionSync (ie, automatically sending the request in +another thread). +

+
+
+
+

Differences in Asynchronous I/O

+

+As compared to SoupSessionAsync, SoupSession behaves more +like gio with respect to asynchronous I/O. +

+

+In particular, the "async-context" +and "use-thread-context" +properties are now effectively unused, and the session always queues +asynchronous requests in the GMainContext that was is +the thread default when the asynchronous operation is started. Session +bookkeeping tasks (like closing idle connections) happen in the +context that was thread default when the session was created. +

+

+Additionally, soup_session_cancel_message() +now acts asynchronously when you cancel an asynchronous request; +rather than having the request's callback be called from inside +soup_session_cancel_message(), it just gets called +when you need return to the main loop. +

+
+
+ + + \ No newline at end of file diff --git a/docs/reference/html/right-insensitive.png b/docs/reference/html/right-insensitive.png new file mode 100644 index 0000000..4c95785 Binary files /dev/null and b/docs/reference/html/right-insensitive.png differ diff --git a/docs/reference/html/right.png b/docs/reference/html/right.png new file mode 100644 index 0000000..76260ec Binary files /dev/null and b/docs/reference/html/right.png differ diff --git a/docs/reference/html/style.css b/docs/reference/html/style.css new file mode 100644 index 0000000..4be4ede --- /dev/null +++ b/docs/reference/html/style.css @@ -0,0 +1,483 @@ +body +{ + font-family: cantarell, sans-serif; +} +.synopsis, .classsynopsis +{ + /* tango:aluminium 1/2 */ + background: #eeeeec; + background: rgba(238, 238, 236, 0.5); + border: solid 1px rgb(238, 238, 236); + padding: 0.5em; +} +.programlisting +{ + /* tango:sky blue 0/1 */ + /* fallback for no rgba support */ + background: #e6f3ff; + border: solid 1px #729fcf; + background: rgba(114, 159, 207, 0.1); + border: solid 1px rgba(114, 159, 207, 0.2); + padding: 0.5em; +} +.variablelist +{ + padding: 4px; + margin-left: 3em; +} +.variablelist td:first-child +{ + vertical-align: top; +} + +span.nowrap { + white-space: nowrap; +} + +div.gallery-float +{ + float: left; + padding: 10px; +} +div.gallery-float img +{ + border-style: none; +} +div.gallery-spacer +{ + clear: both; +} + +a, a:visited +{ + text-decoration: none; + /* tango:sky blue 2 */ + color: #3465a4; +} +a:hover +{ + text-decoration: underline; + /* tango:sky blue 1 */ + color: #729fcf; +} + +div.informaltable table +{ + border-collapse: separate; + border-spacing: 1em 0.3em; + border: none; +} + +div.informaltable table td, div.informaltable table th +{ + vertical-align: top; +} + +.function_type, +.variable_type, +.property_type, +.signal_type, +.parameter_name, +.struct_member_name, +.union_member_name, +.define_keyword, +.datatype_keyword, +.typedef_keyword +{ + text-align: right; +} + +/* dim non-primary columns */ +.c_punctuation, +.function_type, +.variable_type, +.property_type, +.signal_type, +.define_keyword, +.datatype_keyword, +.typedef_keyword, +.property_flags, +.signal_flags, +.parameter_annotations, +.enum_member_annotations, +.struct_member_annotations, +.union_member_annotations +{ + color: #888a85; +} + +.function_type a, +.function_type a:visited, +.function_type a:hover, +.property_type a, +.property_type a:visited, +.property_type a:hover, +.signal_type a, +.signal_type a:visited, +.signal_type a:hover, +.signal_flags a, +.signal_flags a:visited, +.signal_flags a:hover +{ + color: #729fcf; +} + +td p +{ + margin: 0.25em; +} + +div.table table +{ + border-collapse: collapse; + border-spacing: 0px; + /* tango:aluminium 3 */ + border: solid 1px #babdb6; +} + +div.table table td, div.table table th +{ + /* tango:aluminium 3 */ + border: solid 1px #babdb6; + padding: 3px; + vertical-align: top; +} + +div.table table th +{ + /* tango:aluminium 2 */ + background-color: #d3d7cf; +} + +h4 +{ + color: #555753; + margin-top: 1em; + margin-bottom: 1em; +} + +hr +{ + /* tango:aluminium 1 */ + color: #d3d7cf; + background: #d3d7cf; + border: none 0px; + height: 1px; + clear: both; + margin: 2.0em 0em 2.0em 0em; +} + +dl.toc dt +{ + padding-bottom: 0.25em; +} + +dl.toc > dt +{ + padding-top: 0.25em; + padding-bottom: 0.25em; + font-weight: bold; +} + +dl.toc > dl +{ + padding-bottom: 0.5em; +} + +.parameter +{ + font-style: normal; +} + +.footer +{ + padding-top: 3.5em; + /* tango:aluminium 3 */ + color: #babdb6; + text-align: center; + font-size: 80%; +} + +.informalfigure, +.figure +{ + margin: 1em; +} + +.informalexample, +.example +{ + margin-top: 1em; + margin-bottom: 1em; +} + +.warning +{ + /* tango:orange 0/1 */ + background: #ffeed9; + background: rgba(252, 175, 62, 0.1); + border-color: #ffb04f; + border-color: rgba(252, 175, 62, 0.2); +} +.note +{ + /* tango:chameleon 0/0.5 */ + background: #d8ffb2; + background: rgba(138, 226, 52, 0.1); + border-color: #abf562; + border-color: rgba(138, 226, 52, 0.2); +} +div.blockquote +{ + border-color: #eeeeec; +} +.note, .warning, div.blockquote +{ + padding: 0.5em; + border-width: 1px; + border-style: solid; + margin: 2em; +} +.note p, .warning p +{ + margin: 0; +} + +div.warning h3.title, +div.note h3.title +{ + display: none; +} + +p + div.section +{ + margin-top: 1em; +} + +div.refnamediv, +div.refsynopsisdiv, +div.refsect1, +div.refsect2, +div.toc, +div.section +{ + margin-bottom: 1em; +} + +/* blob links */ +h2 .extralinks, h3 .extralinks +{ + float: right; + /* tango:aluminium 3 */ + color: #babdb6; + font-size: 80%; + font-weight: normal; +} + +.lineart +{ + color: #d3d7cf; + font-weight: normal; +} + +.annotation +{ + /* tango:aluminium 5 */ + color: #555753; + font-weight: normal; +} + +.structfield +{ + font-style: normal; + font-weight: normal; +} + +acronym,abbr +{ + border-bottom: 1px dotted gray; +} + +/* code listings */ + +.listing_code .programlisting .normal, +.listing_code .programlisting .normal a, +.listing_code .programlisting .number, +.listing_code .programlisting .cbracket, +.listing_code .programlisting .symbol { color: #555753; } +.listing_code .programlisting .comment, +.listing_code .programlisting .linenum { color: #babdb6; } /* tango: aluminium 3 */ +.listing_code .programlisting .function, +.listing_code .programlisting .function a, +.listing_code .programlisting .preproc { color: #204a87; } /* tango: sky blue 3 */ +.listing_code .programlisting .string { color: #ad7fa8; } /* tango: plum */ +.listing_code .programlisting .keyword, +.listing_code .programlisting .usertype, +.listing_code .programlisting .type, +.listing_code .programlisting .type a { color: #4e9a06; } /* tango: chameleon 3 */ + +.listing_frame { + /* tango:sky blue 1 */ + border: solid 1px #729fcf; + border: solid 1px rgba(114, 159, 207, 0.2); + padding: 0px; +} + +.listing_lines, .listing_code { + margin-top: 0px; + margin-bottom: 0px; + padding: 0.5em; +} +.listing_lines { + /* tango:sky blue 0.5 */ + background: #a6c5e3; + background: rgba(114, 159, 207, 0.2); + /* tango:aluminium 6 */ + color: #2e3436; +} +.listing_code { + /* tango:sky blue 0 */ + background: #e6f3ff; + background: rgba(114, 159, 207, 0.1); +} +.listing_code .programlisting { + /* override from previous */ + border: none 0px; + padding: 0px; + background: none; +} +.listing_lines pre, .listing_code pre { + margin: 0px; +} + +@media screen { + /* these have a as a first child, but since there are no parent selectors + * we can't use that. */ + a.footnote + { + position: relative; + top: 0em ! important; + } + /* this is needed so that the local anchors are displayed below the naviagtion */ + div.footnote a[name], div.refnamediv a[name], div.refsect1 a[name], div.refsect2 a[name], div.index a[name], div.glossary a[name], div.sect1 a[name] + { + display: inline-block; + position: relative; + top:-5em; + } + /* this seems to be a bug in the xsl style sheets when generating indexes */ + div.index div.index + { + top: 0em; + } + /* make space for the fixed navigation bar and add space at the bottom so that + * link targets appear somewhat close to top + */ + body + { + padding-top: 2.5em; + padding-bottom: 500px; + max-width: 60em; + } + p + { + max-width: 60em; + } + /* style and size the navigation bar */ + table.navigation#top + { + position: fixed; + background: #e2e2e2; + border-bottom: solid 1px #babdb6; + border-spacing: 5px; + margin-top: 0; + margin-bottom: 0; + top: 0; + left: 0; + z-index: 10; + } + table.navigation#top td + { + padding-left: 6px; + padding-right: 6px; + } + .navigation a, .navigation a:visited + { + /* tango:sky blue 3 */ + color: #204a87; + } + .navigation a:hover + { + /* tango:sky blue 2 */ + color: #3465a4; + } + td.shortcuts + { + /* tango:sky blue 2 */ + color: #3465a4; + font-size: 80%; + white-space: nowrap; + } + td.shortcuts .dim + { + color: #babdb6; + } + .navigation .title + { + font-size: 80%; + max-width: none; + margin: 0px; + font-weight: normal; + } +} +@media screen and (min-width: 60em) { + /* screen larger than 60em */ + body { margin: auto; } +} +@media screen and (max-width: 60em) { + /* screen less than 60em */ + #nav_hierarchy { display: none; } + #nav_interfaces { display: none; } + #nav_prerequisites { display: none; } + #nav_derived_interfaces { display: none; } + #nav_implementations { display: none; } + #nav_child_properties { display: none; } + #nav_style_properties { display: none; } + #nav_index { display: none; } + #nav_glossary { display: none; } + .gallery_image { display: none; } + .property_flags { display: none; } + .signal_flags { display: none; } + .parameter_annotations { display: none; } + .enum_member_annotations { display: none; } + .struct_member_annotations { display: none; } + .union_member_annotations { display: none; } + /* now that a column is hidden, optimize space */ + col.parameters_name { width: auto; } + col.parameters_description { width: auto; } + col.struct_members_name { width: auto; } + col.struct_members_description { width: auto; } + col.enum_members_name { width: auto; } + col.enum_members_description { width: auto; } + col.union_members_name { width: auto; } + col.union_members_description { width: auto; } + .listing_lines { display: none; } +} +@media print { + table.navigation { + visibility: collapse; + display: none; + } + div.titlepage table.navigation { + visibility: visible; + display: table; + background: #e2e2e2; + border: solid 1px #babdb6; + margin-top: 0; + margin-bottom: 0; + top: 0; + left: 0; + height: 3em; + } +} + diff --git a/docs/reference/html/up-insensitive.png b/docs/reference/html/up-insensitive.png new file mode 100644 index 0000000..f404986 Binary files /dev/null and b/docs/reference/html/up-insensitive.png differ diff --git a/docs/reference/html/up.png b/docs/reference/html/up.png new file mode 100644 index 0000000..80b4b37 Binary files /dev/null and b/docs/reference/html/up.png differ diff --git a/docs/reference/libsoup-2.4-docs.sgml b/docs/reference/libsoup-2.4-docs.sgml new file mode 100644 index 0000000..7bd4858 --- /dev/null +++ b/docs/reference/libsoup-2.4-docs.sgml @@ -0,0 +1,82 @@ + + + + + libsoup Reference Manual + + + + Tutorial + + + + + + + + + Core API + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Additional Features + + + + + + + + + + + + + Web Services APIs + + + + + + + Low-level Networking API + + + + + + Index + + + + + + + diff --git a/docs/reference/libsoup-2.4-overrides.txt b/docs/reference/libsoup-2.4-overrides.txt new file mode 100644 index 0000000..06826ca --- /dev/null +++ b/docs/reference/libsoup-2.4-overrides.txt @@ -0,0 +1,6 @@ + +soup_address_get_sockaddr +struct sockaddr * +SoupAddress *addr, +int *len + diff --git a/docs/reference/libsoup-2.4-sections.txt b/docs/reference/libsoup-2.4-sections.txt new file mode 100644 index 0000000..a9b2138 --- /dev/null +++ b/docs/reference/libsoup-2.4-sections.txt @@ -0,0 +1,1345 @@ +libsoup/soup.h +
+soup-message +SoupMessage +SoupMessage + +soup_message_new +soup_message_new_from_uri +soup_message_set_request +soup_message_set_response + +SoupHTTPVersion +soup_message_set_http_version +soup_message_get_http_version +soup_message_get_uri +soup_message_set_uri +soup_message_get_address + +soup_message_set_status +soup_message_set_status_full +soup_message_set_redirect +soup_message_is_keepalive +soup_message_get_https_status + +soup_message_set_first_party +soup_message_get_first_party + +soup_message_add_header_handler +soup_message_add_status_code_handler + +SoupMessageFlags +soup_message_set_flags +soup_message_get_flags +SoupChunkAllocator +soup_message_set_chunk_allocator + +soup_message_disable_feature +soup_message_get_soup_request + +SoupMessagePriority +soup_message_get_priority +soup_message_set_priority + +SOUP_MESSAGE_METHOD +SOUP_MESSAGE_URI +SOUP_MESSAGE_HTTP_VERSION +SOUP_MESSAGE_FLAGS +SOUP_MESSAGE_STATUS_CODE +SOUP_MESSAGE_REASON_PHRASE +SOUP_MESSAGE_SERVER_SIDE +SOUP_MESSAGE_FIRST_PARTY +SOUP_MESSAGE_PRIORITY +SOUP_MESSAGE_REQUEST_BODY +SOUP_MESSAGE_REQUEST_BODY_DATA +SOUP_MESSAGE_REQUEST_HEADERS +SOUP_MESSAGE_RESPONSE_BODY +SOUP_MESSAGE_RESPONSE_BODY_DATA +SOUP_MESSAGE_RESPONSE_HEADERS +SOUP_MESSAGE_TLS_CERTIFICATE +SOUP_MESSAGE_TLS_ERRORS + +SOUP_MESSAGE +SOUP_IS_MESSAGE +SOUP_TYPE_MESSAGE +soup_message_get_type +SOUP_MESSAGE_CLASS +SOUP_IS_MESSAGE_CLASS +SOUP_MESSAGE_GET_CLASS +SoupMessageClass + +soup_message_wrote_informational +soup_message_wrote_headers +soup_message_wrote_chunk +soup_message_wrote_body_data +soup_message_wrote_body +soup_message_got_informational +soup_message_got_headers +soup_message_content_sniffed +soup_message_got_chunk +soup_message_got_body +soup_message_finished +soup_message_restarted +soup_message_starting +
+ +
+soup-method +SOUP_METHOD_OPTIONS +SOUP_METHOD_GET +SOUP_METHOD_HEAD +SOUP_METHOD_PUT +SOUP_METHOD_POST +SOUP_METHOD_DELETE +SOUP_METHOD_TRACE +SOUP_METHOD_CONNECT + +SOUP_METHOD_PROPFIND +SOUP_METHOD_PROPPATCH +SOUP_METHOD_MKCOL +SOUP_METHOD_COPY +SOUP_METHOD_MOVE +SOUP_METHOD_LOCK +SOUP_METHOD_UNLOCK +
+ +
+soup-message-headers +SoupMessageHeaders +SoupMessageHeaders +SoupMessageHeadersType +soup_message_headers_new +soup_message_headers_free + +soup_message_headers_append +soup_message_headers_replace +soup_message_headers_remove +soup_message_headers_clear +soup_message_headers_clean_connection_headers +soup_message_headers_get_one +soup_message_headers_get_list +soup_message_headers_get +soup_message_headers_get_headers_type + +soup_message_headers_header_contains +soup_message_headers_header_equals + +SoupMessageHeadersForeachFunc +soup_message_headers_foreach + +SoupMessageHeadersIter +soup_message_headers_iter_init +soup_message_headers_iter_next + +SoupEncoding +soup_message_headers_get_encoding +soup_message_headers_set_encoding +soup_message_headers_get_content_length +soup_message_headers_set_content_length + +SoupExpectation +soup_message_headers_get_expectations +soup_message_headers_set_expectations + +soup_message_headers_get_content_type +soup_message_headers_set_content_type + +soup_message_headers_get_content_disposition +soup_message_headers_set_content_disposition + +SoupRange +soup_message_headers_get_ranges +soup_message_headers_set_ranges +soup_message_headers_set_range +soup_message_headers_free_ranges +soup_message_headers_get_content_range +soup_message_headers_set_content_range + +SOUP_TYPE_MESSAGE_HEADERS +soup_message_headers_get_type +
+ +
+soup-message-body +SoupMessageBody +SoupBuffer +SoupMemoryUse +soup_buffer_new +soup_buffer_new_subbuffer +soup_buffer_new_with_owner +soup_buffer_new_take +soup_buffer_get_owner +soup_buffer_get_data +soup_buffer_copy +soup_buffer_free +soup_buffer_get_as_bytes + +SoupMessageBody +soup_message_body_new +soup_message_body_free + +soup_message_body_set_accumulate +soup_message_body_get_accumulate + +soup_message_body_append +soup_message_body_append_buffer +soup_message_body_append_take +soup_message_body_truncate +soup_message_body_complete +soup_message_body_flatten +soup_message_body_get_chunk + +soup_message_body_got_chunk +soup_message_body_wrote_chunk + +SOUP_TYPE_BUFFER +soup_buffer_get_type +SOUP_TYPE_MESSAGE_BODY +soup_message_body_get_type +
+ +
+soup-status +SOUP_STATUS_IS_TRANSPORT_ERROR +SOUP_STATUS_IS_INFORMATIONAL +SOUP_STATUS_IS_SUCCESSFUL +SOUP_STATUS_IS_REDIRECTION +SOUP_STATUS_IS_CLIENT_ERROR +SOUP_STATUS_IS_SERVER_ERROR +SoupStatus +soup_status_get_phrase +soup_status_proxify + +SOUP_HTTP_ERROR + +soup_http_error_quark +SoupKnownStatusCode +
+ +
+soup-server +SoupServer +SoupServer +soup_server_new +soup_server_set_ssl_cert_file + +SoupServerListenOptions +soup_server_listen +soup_server_listen_all +soup_server_listen_local +soup_server_listen_socket +soup_server_listen_fd +soup_server_get_listeners +soup_server_get_uris +soup_server_disconnect +soup_server_is_https +soup_server_accept_iostream + +SoupServerCallback +soup_server_add_handler +soup_server_add_early_handler +soup_server_remove_handler + +SoupServerWebsocketCallback +soup_server_add_websocket_handler + +SoupClientContext +soup_client_context_get_local_address +soup_client_context_get_remote_address +soup_client_context_get_host +soup_client_context_get_auth_domain +soup_client_context_get_auth_user +soup_client_context_get_gsocket +soup_client_context_steal_connection + +soup_server_add_auth_domain +soup_server_remove_auth_domain + +soup_server_pause_message +soup_server_unpause_message + +SOUP_SERVER_TLS_CERTIFICATE +SOUP_SERVER_RAW_PATHS +SOUP_SERVER_SERVER_HEADER +SOUP_SERVER_HTTP_ALIASES +SOUP_SERVER_HTTPS_ALIASES + +SOUP_SERVER +SOUP_IS_SERVER +SOUP_TYPE_SERVER +soup_server_get_type +SOUP_SERVER_CLASS +SOUP_IS_SERVER_CLASS +SOUP_SERVER_GET_CLASS +SoupServerClass +SOUP_TYPE_CLIENT_CONTEXT +soup_client_context_get_type +
+ +
+soup-server-deprecated +SoupServer deprecated API +soup_server_get_port +soup_server_get_listener +soup_server_run +soup_server_run_async +soup_server_quit +soup_server_get_async_context + +soup_client_context_get_socket +soup_client_context_get_address + +SOUP_SERVER_PORT +SOUP_SERVER_INTERFACE +SOUP_SERVER_SSL_CERT_FILE +SOUP_SERVER_SSL_KEY_FILE +SOUP_SERVER_ASYNC_CONTEXT +
+ +
+soup-auth-domain +SoupAuthDomain +SoupAuthDomain + +soup_auth_domain_add_path +soup_auth_domain_remove_path +SoupAuthDomainFilter +soup_auth_domain_set_filter +soup_auth_domain_get_realm + +SoupAuthDomainGenericAuthCallback +soup_auth_domain_set_generic_auth_callback +soup_auth_domain_check_password + +soup_auth_domain_covers +soup_auth_domain_accepts +soup_auth_domain_challenge + +SOUP_AUTH_DOMAIN_REALM +SOUP_AUTH_DOMAIN_PROXY +SOUP_AUTH_DOMAIN_ADD_PATH +SOUP_AUTH_DOMAIN_REMOVE_PATH +SOUP_AUTH_DOMAIN_FILTER +SOUP_AUTH_DOMAIN_FILTER_DATA +SOUP_AUTH_DOMAIN_GENERIC_AUTH_CALLBACK +SOUP_AUTH_DOMAIN_GENERIC_AUTH_DATA + +soup_auth_domain_try_generic_auth_callback + +SOUP_AUTH_DOMAIN +SOUP_IS_AUTH_DOMAIN +SOUP_TYPE_AUTH_DOMAIN +soup_auth_domain_get_type +SOUP_AUTH_DOMAIN_CLASS +SOUP_IS_AUTH_DOMAIN_CLASS +SOUP_AUTH_DOMAIN_GET_CLASS +SoupAuthDomainClass +
+ +
+soup-auth-domain-basic +SoupAuthDomainBasic +SoupAuthDomainBasic +soup_auth_domain_basic_new + +SoupAuthDomainBasicAuthCallback +soup_auth_domain_basic_set_auth_callback + +SOUP_AUTH_DOMAIN_BASIC_AUTH_CALLBACK +SOUP_AUTH_DOMAIN_BASIC_AUTH_DATA + +SOUP_AUTH_DOMAIN_BASIC +SOUP_IS_AUTH_DOMAIN_BASIC +SOUP_TYPE_AUTH_DOMAIN_BASIC +soup_auth_domain_basic_get_type +SOUP_AUTH_DOMAIN_BASIC_CLASS +SOUP_IS_AUTH_DOMAIN_BASIC_CLASS +SOUP_AUTH_DOMAIN_BASIC_GET_CLASS +SoupAuthDomainBasicClass +
+ +
+soup-auth-domain-digest +SoupAuthDomainDigest +SoupAuthDomainDigest +soup_auth_domain_digest_new + +SoupAuthDomainDigestAuthCallback +soup_auth_domain_digest_set_auth_callback +soup_auth_domain_digest_encode_password + +SOUP_AUTH_DOMAIN_DIGEST_AUTH_CALLBACK +SOUP_AUTH_DOMAIN_DIGEST_AUTH_DATA + +SOUP_AUTH_DOMAIN_DIGEST +SOUP_IS_AUTH_DOMAIN_DIGEST +SOUP_TYPE_AUTH_DOMAIN_DIGEST +soup_auth_domain_digest_get_type +SOUP_AUTH_DOMAIN_DIGEST_CLASS +SOUP_IS_AUTH_DOMAIN_DIGEST_CLASS +SOUP_AUTH_DOMAIN_DIGEST_GET_CLASS +SoupAuthDomainDigestClass +
+ +
+soup-address +SoupAddress +SoupAddress +SoupAddressFamily +SOUP_ADDRESS_ANY_PORT +soup_address_new +soup_address_new_from_sockaddr +soup_address_new_any + +SoupAddressCallback +soup_address_resolve_async +soup_address_resolve_sync +soup_address_is_resolved + +soup_address_get_name +soup_address_get_sockaddr +soup_address_get_gsockaddr +soup_address_get_physical +soup_address_get_port + +soup_address_equal_by_name +soup_address_hash_by_name +soup_address_equal_by_ip +soup_address_hash_by_ip + +SOUP_ADDRESS_FAMILY +SOUP_ADDRESS_NAME +SOUP_ADDRESS_PHYSICAL +SOUP_ADDRESS_PORT +SOUP_ADDRESS_SOCKADDR +SOUP_ADDRESS_PROTOCOL + +SOUP_ADDRESS +SOUP_IS_ADDRESS +SOUP_TYPE_ADDRESS +soup_address_get_type +SOUP_ADDRESS_CLASS +SOUP_IS_ADDRESS_CLASS +SOUP_ADDRESS_GET_CLASS +SoupAddressClass +
+ +
+soup-session +SoupSession +SoupSession + +soup_session_new +soup_session_new_with_options + +soup_session_request +soup_session_request_uri +soup_session_request_http +soup_session_request_http_uri +SoupRequestError +SOUP_REQUEST_ERROR + +SoupSessionCallback +soup_session_queue_message +soup_session_requeue_message +soup_session_send_message +soup_session_cancel_message + +soup_session_send +soup_session_send_async +soup_session_send_finish + +soup_session_websocket_connect_async +soup_session_websocket_connect_finish + +soup_session_prefetch_dns +soup_session_prepare_for_uri +soup_session_abort + +soup_session_would_redirect +soup_session_redirect_message + +soup_session_pause_message +soup_session_unpause_message + +soup_session_get_async_context + +soup_session_add_feature +soup_session_add_feature_by_type +soup_session_remove_feature +soup_session_remove_feature_by_type +soup_session_get_features +soup_session_get_feature +soup_session_get_feature_for_message +soup_session_has_feature + +soup_session_steal_connection + +SoupSessionConnectProgressCallback +soup_session_connect_async +soup_session_connect_finish + +SOUP_SESSION_PROXY_URI +SOUP_SESSION_PROXY_RESOLVER +SOUP_SESSION_MAX_CONNS +SOUP_SESSION_MAX_CONNS_PER_HOST +SOUP_SESSION_TLS_DATABASE +SOUP_SESSION_SSL_USE_SYSTEM_CA_FILE +SOUP_SESSION_SSL_CA_FILE +SOUP_SESSION_SSL_STRICT +SOUP_SESSION_TLS_INTERACTION +SOUP_SESSION_ASYNC_CONTEXT +SOUP_SESSION_USE_THREAD_CONTEXT +SOUP_SESSION_TIMEOUT +SOUP_SESSION_IDLE_TIMEOUT +SOUP_SESSION_USER_AGENT +SOUP_SESSION_ADD_FEATURE +SOUP_SESSION_ADD_FEATURE_BY_TYPE +SOUP_SESSION_REMOVE_FEATURE_BY_TYPE +SOUP_SESSION_ACCEPT_LANGUAGE +SOUP_SESSION_ACCEPT_LANGUAGE_AUTO +SOUP_SESSION_HTTP_ALIASES +SOUP_SESSION_HTTPS_ALIASES +SOUP_SESSION_LOCAL_ADDRESS + +SOUP_IS_SESSION +SOUP_IS_SESSION_CLASS +SOUP_SESSION +SOUP_SESSION_CLASS +SOUP_SESSION_GET_CLASS +SOUP_TYPE_SESSION +SoupSessionClass +soup_session_get_type +soup_request_error_quark + +SoupConnection +SoupConnectionState +SoupMessageQueue +SoupMessageQueueItem +SOUP_SESSION_USE_NTLM +
+ +
+soup-session-async +SoupSessionAsync +SoupSessionAsync +soup_session_async_new +soup_session_async_new_with_options + +SOUP_IS_SESSION_ASYNC +SOUP_IS_SESSION_ASYNC_CLASS +SOUP_SESSION_ASYNC +SOUP_SESSION_ASYNC_CLASS +SOUP_SESSION_ASYNC_GET_CLASS +SOUP_TYPE_SESSION_ASYNC +SoupSessionAsyncClass +soup_session_async_get_type +
+ +
+soup-session-sync +SoupSessionSync +SoupSessionSync +soup_session_sync_new +soup_session_sync_new_with_options + +SOUP_IS_SESSION_SYNC +SOUP_IS_SESSION_SYNC_CLASS +SOUP_SESSION_SYNC +SOUP_SESSION_SYNC_CLASS +SOUP_SESSION_SYNC_GET_CLASS +SOUP_TYPE_SESSION_SYNC +SoupSessionSyncClass +soup_session_sync_get_type +
+ +
+soup-session-feature +SoupSessionFeature +SoupSessionFeature +SoupSessionFeatureInterface + +soup_session_feature_get_type +SOUP_SESSION_FEATURE +SOUP_SESSION_FEATURE_CLASS +SOUP_SESSION_FEATURE_GET_CLASS +SOUP_IS_SESSION_FEATURE +SOUP_IS_SESSION_FEATURE_CLASS +SOUP_TYPE_SESSION_FEATURE + +soup_session_feature_attach +soup_session_feature_detach +soup_session_feature_add_feature +soup_session_feature_has_feature +soup_session_feature_remove_feature +
+ +
+soup-auth +SoupAuth +SoupAuth +soup_auth_new +soup_auth_update + +SOUP_TYPE_AUTH_BASIC +SOUP_TYPE_AUTH_DIGEST +SOUP_TYPE_AUTH_NTLM +SOUP_TYPE_AUTH_NEGOTIATE +soup_auth_negotiate_supported + +soup_auth_is_for_proxy +soup_auth_get_scheme_name +soup_auth_get_host +soup_auth_get_realm +soup_auth_get_info + +soup_auth_authenticate +soup_auth_can_authenticate +soup_auth_is_authenticated +soup_auth_is_ready + +soup_auth_get_authorization +soup_auth_get_protection_space +soup_auth_free_protection_space + +SOUP_AUTH_SCHEME_NAME +SOUP_AUTH_REALM +SOUP_AUTH_HOST +SOUP_AUTH_IS_FOR_PROXY +SOUP_AUTH_IS_AUTHENTICATED + +SOUP_AUTH +SOUP_IS_AUTH +SOUP_TYPE_AUTH +soup_auth_get_type +SOUP_AUTH_CLASS +SOUP_IS_AUTH_CLASS +SOUP_AUTH_GET_CLASS +SoupAuthClass +soup_auth_basic_get_type +soup_auth_digest_get_type +soup_auth_ntlm_get_type +soup_auth_negotiate_get_type + +soup_auth_get_saved_password +soup_auth_get_saved_users +soup_auth_has_saved_password +soup_auth_save_password +
+ +
+soup-auth-manager +SoupAuthManager +SoupAuthManager +SOUP_TYPE_AUTH_MANAGER +soup_auth_manager_use_auth +soup_auth_manager_clear_cached_credentials + +SoupAuthManagerPrivate +SoupAuthManagerClass +SOUP_AUTH_MANAGER +SOUP_IS_AUTH_MANAGER +SOUP_AUTH_MANAGER_CLASS +SOUP_IS_AUTH_MANAGER_CLASS +SOUP_AUTH_MANAGER_GET_CLASS +soup_auth_manager_get_type +
+ +
+soup-socket +SoupSocket +SoupSocket +soup_socket_new + +SoupSocketCallback +soup_socket_connect_async +soup_socket_connect_sync + +soup_socket_listen + +soup_socket_start_ssl +soup_socket_start_proxy_ssl +soup_socket_is_ssl + +soup_socket_disconnect +soup_socket_is_connected + +soup_socket_get_local_address +soup_socket_get_remote_address +soup_socket_get_fd + +SoupSocketIOStatus +soup_socket_read +soup_socket_read_until +soup_socket_write + +SOUP_SOCKET_LOCAL_ADDRESS +SOUP_SOCKET_REMOTE_ADDRESS +SOUP_SOCKET_FLAG_NONBLOCKING +SOUP_SOCKET_IS_SERVER +SOUP_SOCKET_SSL_CREDENTIALS +SOUP_SOCKET_ASYNC_CONTEXT +SOUP_SOCKET_TIMEOUT +SOUP_SOCKET_SSL_FALLBACK +SOUP_SOCKET_SSL_STRICT +SOUP_SOCKET_TLS_CERTIFICATE +SOUP_SOCKET_TLS_ERRORS +SOUP_SOCKET_TRUSTED_CERTIFICATE +SOUP_SOCKET_USE_THREAD_CONTEXT + +SOUP_SOCKET +SOUP_IS_SOCKET +SOUP_TYPE_SOCKET +soup_socket_get_type +SOUP_SOCKET_CLASS +SOUP_IS_SOCKET_CLASS +SOUP_SOCKET_GET_CLASS +SoupSocketClass +
+ +
+soup-uri +SoupURI +SoupURI +soup_uri_new_with_base +soup_uri_new +soup_uri_to_string + +soup_uri_copy +soup_uri_copy_host +soup_uri_equal +soup_uri_host_equal +soup_uri_host_hash +soup_uri_free + +soup_uri_encode +soup_uri_decode +soup_uri_normalize + +SOUP_URI_SCHEME_HTTP +SOUP_URI_SCHEME_HTTPS +SOUP_URI_SCHEME_DATA +SOUP_URI_SCHEME_FILE +SOUP_URI_SCHEME_FTP +SOUP_URI_SCHEME_RESOURCE +SOUP_URI_SCHEME_WS +SOUP_URI_SCHEME_WSS +soup_uri_uses_default_port +SOUP_URI_IS_VALID +SOUP_URI_VALID_FOR_HTTP + +soup_uri_set_scheme +soup_uri_get_scheme +soup_uri_set_user +soup_uri_get_user +soup_uri_set_password +soup_uri_get_password +soup_uri_set_host +soup_uri_get_host +soup_uri_set_port +soup_uri_get_port +soup_uri_set_path +soup_uri_get_path +soup_uri_set_query +soup_uri_set_query_from_form +soup_uri_set_query_from_fields +soup_uri_get_query +soup_uri_set_fragment +soup_uri_get_fragment + +SOUP_TYPE_URI +soup_uri_get_type +
+ +
+soup-misc +Soup Miscellaneous Utilities +SoupDate +SoupDateFormat +soup_date_new +soup_date_new_from_string +soup_date_new_from_time_t +soup_date_new_from_now +soup_date_to_string +soup_date_to_time_t +soup_date_to_timeval +soup_date_is_past +soup_date_get_day +soup_date_get_hour +soup_date_get_minute +soup_date_get_month +soup_date_get_offset +soup_date_get_second +soup_date_get_utc +soup_date_get_year +soup_date_free + +soup_headers_parse_request +soup_headers_parse_response +soup_headers_parse_status_line +soup_headers_parse + +soup_header_parse_list +soup_header_parse_quality_list +soup_header_free_list +soup_header_contains +soup_header_parse_param_list +soup_header_parse_semi_param_list +soup_header_free_param_list +soup_header_g_string_append_param +soup_header_g_string_append_param_quoted + +soup_str_case_equal +soup_str_case_hash + +soup_add_completion +soup_add_idle +soup_add_io_watch +soup_add_timeout + +soup_date_copy +SOUP_TYPE_DATE +soup_date_get_type +soup_char_is_token +soup_char_is_uri_gen_delims +soup_char_is_uri_percent_encoded +soup_char_is_uri_sub_delims +soup_char_is_uri_unreserved +SOUP_CHAR_HTTP_CTL +SOUP_CHAR_HTTP_SEPARATOR +SOUP_CHAR_URI_GEN_DELIMS +SOUP_CHAR_URI_PERCENT_ENCODED +SOUP_CHAR_URI_SUB_DELIMS +soup_ssl_supported +
+ +
+soup-form +HTML Form Support + +SOUP_FORM_MIME_TYPE_MULTIPART +SOUP_FORM_MIME_TYPE_URLENCODED +soup_form_decode +soup_form_decode_multipart +soup_form_encode +soup_form_encode_datalist +soup_form_encode_hash +soup_form_encode_valist +soup_form_request_new +soup_form_request_new_from_datalist +soup_form_request_new_from_hash +soup_form_request_new_from_multipart + +soup_form_decode_urlencoded +soup_form_encode_urlencoded +soup_form_encode_urlencoded_list +
+ +
+soup-xmlrpc +XMLRPC Support + +SOUP_XMLRPC_ERROR +SoupXMLRPCError +SOUP_XMLRPC_FAULT +SoupXMLRPCFault + +soup_xmlrpc_build_request +soup_xmlrpc_message_new +soup_xmlrpc_parse_response +soup_xmlrpc_variant_new_datetime +soup_xmlrpc_variant_get_datetime + +SoupXMLRPCParams +soup_xmlrpc_params_free +soup_xmlrpc_params_parse +soup_xmlrpc_parse_request +soup_xmlrpc_build_response +soup_xmlrpc_build_fault +soup_xmlrpc_message_set_response +soup_xmlrpc_message_set_fault + +soup_xmlrpc_error_quark +soup_xmlrpc_fault_quark +
+ +
+soup-logger +SoupLogger +SoupLogger +SoupLoggerLogLevel +soup_logger_new +soup_logger_attach +soup_logger_detach + +SoupLoggerFilter +soup_logger_set_request_filter +soup_logger_set_response_filter + +SoupLoggerPrinter +soup_logger_set_printer + +SoupLoggerClass +soup_logger_get_type +SOUP_IS_LOGGER +SOUP_IS_LOGGER_CLASS +SOUP_LOGGER +SOUP_LOGGER_CLASS +SOUP_LOGGER_GET_CLASS +SOUP_TYPE_LOGGER +
+ +
+soup-cookie +SoupCookie +SoupCookie +soup_cookie_new +soup_cookie_parse +soup_cookie_copy +soup_cookie_free + +soup_cookie_set_name +soup_cookie_get_name +soup_cookie_set_value +soup_cookie_get_value +soup_cookie_set_domain +soup_cookie_get_domain +soup_cookie_set_path +soup_cookie_get_path +soup_cookie_set_max_age +SOUP_COOKIE_MAX_AGE_ONE_HOUR +SOUP_COOKIE_MAX_AGE_ONE_DAY +SOUP_COOKIE_MAX_AGE_ONE_WEEK +SOUP_COOKIE_MAX_AGE_ONE_YEAR +soup_cookie_set_expires +soup_cookie_get_expires +soup_cookie_set_secure +soup_cookie_get_secure +soup_cookie_set_http_only +soup_cookie_get_http_only + +soup_cookie_applies_to_uri +soup_cookie_domain_matches + +soup_cookie_to_cookie_header +soup_cookie_to_set_cookie_header + +soup_cookies_from_request +soup_cookies_from_response +soup_cookies_to_request +soup_cookies_to_response +soup_cookies_to_cookie_header +soup_cookies_free + +SOUP_TYPE_COOKIE +soup_cookie_get_type + +soup_cookie_equal +
+ +
+soup-cookie-jar +SoupCookieJar +SoupCookieJar +soup_cookie_jar_new +soup_cookie_jar_get_cookies +soup_cookie_jar_get_cookie_list +soup_cookie_jar_set_cookie +soup_cookie_jar_set_cookie_with_first_party + +soup_cookie_jar_add_cookie +soup_cookie_jar_add_cookie_with_first_party +soup_cookie_jar_delete_cookie +soup_cookie_jar_all_cookies + +SoupCookieJarAcceptPolicy +soup_cookie_jar_get_accept_policy +soup_cookie_jar_set_accept_policy + +soup_cookie_jar_is_persistent + +SOUP_COOKIE_JAR_READ_ONLY +SOUP_COOKIE_JAR_ACCEPT_POLICY + +SoupCookieJarClass +SOUP_COOKIE_JAR +SOUP_COOKIE_JAR_CLASS +SOUP_COOKIE_JAR_GET_CLASS +SOUP_IS_COOKIE_JAR +SOUP_IS_COOKIE_JAR_CLASS +SOUP_TYPE_COOKIE_JAR +soup_cookie_jar_get_type +soup_cookie_jar_save +
+ +
+soup-multipart +SoupMultipart +SoupMultipart +soup_multipart_new +soup_multipart_new_from_message +soup_multipart_free + +soup_multipart_get_length +soup_multipart_get_part +soup_multipart_append_part +soup_multipart_append_form_string +soup_multipart_append_form_file +soup_multipart_to_message + +SOUP_TYPE_MULTIPART +soup_multipart_get_type +
+ +
+soup-multipart-input-stream +SoupMultipartInputStream +SoupMultipartInputStream +soup_multipart_input_stream_new + +soup_multipart_input_stream_get_headers +soup_multipart_input_stream_next_part +soup_multipart_input_stream_next_part_async +soup_multipart_input_stream_next_part_finish + +SOUP_IS_MULTIPART_INPUT_STREAM +SOUP_IS_MULTIPART_INPUT_STREAM_CLASS +SOUP_MULTIPART_INPUT_STREAM +SOUP_MULTIPART_INPUT_STREAM_CLASS +SOUP_MULTIPART_INPUT_STREAM_GET_CLASS +SOUP_TYPE_MULTIPART_INPUT_STREAM +soup_multipart_input_stream_get_type +SoupMultipartInputStreamPrivate +
+ +
+soup-cookie-jar-text +SoupCookieJarText +SoupCookieJarText +soup_cookie_jar_text_new + +SOUP_COOKIE_JAR_TEXT_FILENAME + +SoupCookieJarTextClass +SOUP_COOKIE_JAR_TEXT +SOUP_COOKIE_JAR_TEXT_CLASS +SOUP_COOKIE_JAR_TEXT_GET_CLASS +SOUP_TYPE_COOKIE_JAR_TEXT +SOUP_IS_COOKIE_JAR_TEXT +SOUP_IS_COOKIE_JAR_TEXT_CLASS +soup_cookie_jar_text_get_type +
+ +
+soup-cookie-jar-db +SoupCookieJarDB +SoupCookieJarDB +soup_cookie_jar_db_new + +SOUP_COOKIE_JAR_DB_FILENAME + +SoupCookieJarDBClass +SOUP_COOKIE_JAR_DB +SOUP_COOKIE_JAR_DB_CLASS +SOUP_COOKIE_JAR_DB_GET_CLASS +SOUP_TYPE_COOKIE_JAR_DB +SOUP_IS_COOKIE_JAR_DB +SOUP_IS_COOKIE_JAR_DB_CLASS +soup_cookie_jar_db_get_type +
+ +
+soup-content-sniffer +SoupContentSniffer +SoupContentSniffer +soup_content_sniffer_new +soup_content_sniffer_sniff +soup_content_sniffer_get_buffer_size + +SOUP_CONTENT_SNIFFER +SOUP_CONTENT_SNIFFER_CLASS +SOUP_CONTENT_SNIFFER_GET_CLASS +SOUP_IS_CONTENT_SNIFFER +SOUP_IS_CONTENT_SNIFFER_CLASS +SOUP_TYPE_CONTENT_SNIFFER +SoupContentSnifferClass +SoupContentSnifferPrivate +soup_content_sniffer_get_type +
+ +
+soup-cache +SoupCache +SoupCache +SoupCacheType +soup_cache_new +soup_cache_flush +soup_cache_clear +soup_cache_dump +soup_cache_load +soup_cache_get_max_size +soup_cache_set_max_size + +SOUP_TYPE_CACHE +SOUP_IS_CACHE +SOUP_IS_CACHE_CLASS +SOUP_CACHE +SOUP_CACHE_CLASS +SOUP_CACHE_GET_CLASS +SoupCacheClass +SoupCachePrivate + +soup_cache_get_type +SoupCacheResponse +SoupCacheability +
+ +
+soup-content-decoder +SoupContentDecoder +SoupContentDecoder + +SOUP_TYPE_CONTENT_DECODER +SOUP_IS_CONTENT_DECODER +SOUP_IS_CONTENT_DECODER_CLASS +SOUP_CONTENT_DECODER +SOUP_CONTENT_DECODER_CLASS +SOUP_CONTENT_DECODER_GET_CLASS +SoupContentDecoderClass +SoupContentDecoderPrivate +soup_content_decoder_get_type +
+ +
+soup-proxy-resolver-default +SoupProxyResolverDefault +SoupProxyResolverDefault + +soup_proxy_resolver_default_get_type +SoupProxyResolverDefaultClass +SOUP_TYPE_PROXY_RESOLVER_DEFAULT +SOUP_PROXY_RESOLVER_DEFAULT +SOUP_PROXY_RESOLVER_DEFAULT_CLASS +SOUP_PROXY_RESOLVER_DEFAULT_GET_CLASS +SOUP_IS_PROXY_RESOLVER_DEFAULT +SOUP_IS_PROXY_RESOLVER_DEFAULT_CLASS +
+ +
+soup-request +SoupRequest +SoupRequest +soup_request_send +soup_request_send_async +soup_request_send_finish + +soup_request_get_content_length +soup_request_get_content_type +soup_request_get_session +soup_request_get_uri + +SOUP_REQUEST_SESSION +SOUP_REQUEST_URI + +SOUP_IS_REQUEST +SOUP_IS_REQUEST_CLASS +SOUP_REQUEST +SOUP_REQUEST_CLASS +SOUP_REQUEST_GET_CLASS +SOUP_TYPE_REQUEST +SoupRequestClass +SoupRequestPrivate +soup_request_get_type +
+ +
+soup-request-data +SoupRequestData +SoupRequestData + +SOUP_IS_REQUEST_DATA +SOUP_IS_REQUEST_DATA_CLASS +SOUP_REQUEST_DATA +SOUP_REQUEST_DATA_CLASS +SOUP_REQUEST_DATA_GET_CLASS +SOUP_TYPE_REQUEST_DATA +SoupRequestDataClass +SoupRequestDataPrivate +soup_request_data_get_type +
+ +
+soup-request-file +SoupRequestFile +SoupRequestFile +soup_request_file_get_file + +SOUP_IS_REQUEST_FILE +SOUP_IS_REQUEST_FILE_CLASS +SOUP_REQUEST_FILE +SOUP_REQUEST_FILE_CLASS +SOUP_REQUEST_FILE_GET_CLASS +SOUP_TYPE_REQUEST_FILE +SoupRequestFileClass +SoupRequestFilePrivate +soup_request_file_get_type +
+ +
+soup-request-http +SoupRequestHTTP +SoupRequestHTTP +soup_request_http_get_message + +SOUP_IS_REQUEST_HTTP +SOUP_IS_REQUEST_HTTP_CLASS +SOUP_REQUEST_HTTP +SOUP_REQUEST_HTTP_CLASS +SOUP_REQUEST_HTTP_GET_CLASS +SOUP_TYPE_REQUEST_HTTP +SoupRequestHTTPClass +SoupRequestHTTPPrivate +soup_request_http_get_type +
+ +
+soup-tld +Top Level Domain utils + +soup_tld_get_base_domain +soup_tld_domain_is_public_suffix + +SOUP_TLD_ERROR +SoupTLDError + +soup_tld_error_quark +
+ +
+soup-version +Version Information +soup_get_major_version +soup_get_minor_version +soup_get_micro_version +soup_check_version + +SOUP_MAJOR_VERSION +SOUP_MINOR_VERSION +SOUP_MICRO_VERSION +SOUP_CHECK_VERSION + +SOUP_VERSION_MIN_REQUIRED +SOUP_VERSION_MAX_ALLOWED +SOUP_VERSION_2_24 +SOUP_VERSION_2_26 +SOUP_VERSION_2_28 +SOUP_VERSION_2_30 +SOUP_VERSION_2_32 +SOUP_VERSION_2_34 +SOUP_VERSION_2_36 +SOUP_VERSION_2_38 +SOUP_VERSION_2_40 +SOUP_VERSION_2_42 +SOUP_VERSION_2_44 +SOUP_VERSION_2_46 +SOUP_VERSION_2_48 +SOUP_VERSION_2_50 +SOUP_VERSION_2_52 + +SOUP_AVAILABLE_IN_2_24 +SOUP_AVAILABLE_IN_2_26 +SOUP_AVAILABLE_IN_2_28 +SOUP_AVAILABLE_IN_2_30 +SOUP_AVAILABLE_IN_2_32 +SOUP_AVAILABLE_IN_2_34 +SOUP_AVAILABLE_IN_2_36 +SOUP_AVAILABLE_IN_2_38 +SOUP_AVAILABLE_IN_2_40 +SOUP_AVAILABLE_IN_2_42 +SOUP_AVAILABLE_IN_2_44 +SOUP_AVAILABLE_IN_2_46 +SOUP_AVAILABLE_IN_2_48 +SOUP_AVAILABLE_IN_2_50 +SOUP_AVAILABLE_IN_2_52 +SOUP_DEPRECATED_IN_2_24 +SOUP_DEPRECATED_IN_2_24_FOR +SOUP_DEPRECATED_IN_2_26 +SOUP_DEPRECATED_IN_2_26_FOR +SOUP_DEPRECATED_IN_2_28 +SOUP_DEPRECATED_IN_2_28_FOR +SOUP_DEPRECATED_IN_2_30 +SOUP_DEPRECATED_IN_2_30_FOR +SOUP_DEPRECATED_IN_2_32 +SOUP_DEPRECATED_IN_2_32_FOR +SOUP_DEPRECATED_IN_2_34 +SOUP_DEPRECATED_IN_2_34_FOR +SOUP_DEPRECATED_IN_2_36 +SOUP_DEPRECATED_IN_2_36_FOR +SOUP_DEPRECATED_IN_2_38 +SOUP_DEPRECATED_IN_2_38_FOR +SOUP_DEPRECATED_IN_2_40 +SOUP_DEPRECATED_IN_2_40_FOR +SOUP_DEPRECATED_IN_2_42 +SOUP_DEPRECATED_IN_2_42_FOR +SOUP_DEPRECATED_IN_2_44 +SOUP_DEPRECATED_IN_2_44_FOR +SOUP_DEPRECATED_IN_2_46 +SOUP_DEPRECATED_IN_2_46_FOR +SOUP_DEPRECATED_IN_2_48 +SOUP_DEPRECATED_IN_2_48_FOR +SOUP_DEPRECATED_IN_2_50 +SOUP_DEPRECATED_IN_2_50_FOR +SOUP_DEPRECATED_IN_2_52 +SOUP_DEPRECATED_IN_2_52_FOR +SOUP_ENCODE_VERSION +SOUP_VERSION_CUR_STABLE +SOUP_VERSION_PREV_STABLE +
+ +
+soup-websocket +WebSockets + +soup_websocket_client_prepare_handshake +soup_websocket_client_verify_handshake + +soup_websocket_server_check_handshake +soup_websocket_server_process_handshake + +SoupWebsocketConnection +SoupWebsocketConnectionType +soup_websocket_connection_new +soup_websocket_connection_get_io_stream +soup_websocket_connection_get_connection_type +soup_websocket_connection_get_uri +soup_websocket_connection_get_origin +soup_websocket_connection_get_protocol +SoupWebsocketState +soup_websocket_connection_get_state +SoupWebsocketDataType +soup_websocket_connection_send_text +soup_websocket_connection_send_binary +SoupWebsocketCloseCode +soup_websocket_connection_close +soup_websocket_connection_get_close_code +soup_websocket_connection_get_close_data + +SoupWebsocketError +SOUP_WEBSOCKET_ERROR + +SoupWebsocketConnectionClass +SoupWebsocketConnectionPrivate +SOUP_IS_WEBSOCKET_CONNECTION +SOUP_IS_WEBSOCKET_CONNECTION_CLASS +SOUP_TYPE_WEBSOCKET_CONNECTION +SOUP_WEBSOCKET_CONNECTION +SOUP_WEBSOCKET_CONNECTION_CLASS +SOUP_WEBSOCKET_CONNECTION_GET_CLASS +soup_websocket_close_code_get_type +soup_websocket_connection_get_type +soup_websocket_connection_type_get_type +soup_websocket_data_type_get_type +soup_websocket_error_get_quark +soup_websocket_error_get_type +soup_websocket_state_get_type +
diff --git a/docs/reference/libsoup-2.4.types b/docs/reference/libsoup-2.4.types new file mode 100644 index 0000000..3375817 --- /dev/null +++ b/docs/reference/libsoup-2.4.types @@ -0,0 +1,39 @@ +soup_address_get_type +soup_auth_basic_get_type +soup_auth_digest_get_type +soup_auth_domain_basic_get_type +soup_auth_domain_digest_get_type +soup_auth_domain_get_type +soup_auth_get_type +soup_auth_manager_get_type +soup_auth_negotiate_get_type +soup_auth_ntlm_get_type +soup_buffer_get_type +soup_cache_get_type +soup_client_context_get_type +soup_content_decoder_get_type +soup_content_sniffer_get_type +soup_cookie_get_type +soup_cookie_jar_db_get_type +soup_cookie_jar_get_type +soup_cookie_jar_text_get_type +soup_date_get_type +soup_logger_get_type +soup_message_body_get_type +soup_message_get_type +soup_message_headers_get_type +soup_multipart_get_type +soup_multipart_input_stream_get_type +soup_proxy_resolver_default_get_type +soup_request_data_get_type +soup_request_file_get_type +soup_request_get_type +soup_request_http_get_type +soup_server_get_type +soup_session_async_get_type +soup_session_feature_get_type +soup_session_get_type +soup_session_sync_get_type +soup_socket_get_type +soup_uri_get_type +soup_websocket_connection_get_type diff --git a/docs/reference/request-howto.xml b/docs/reference/request-howto.xml new file mode 100644 index 0000000..55a4643 --- /dev/null +++ b/docs/reference/request-howto.xml @@ -0,0 +1,184 @@ + + + + +libsoup Client SoupRequest API +3 +LIBSOUP Library + + + +libsoup Client SoupRequest APIUsing +libsoup with a mix of http and non-http URIs. + + + +<type>SoupRequest</type> + + +SoupRequest is an +abstract type representing a request for a particular URI. The +SoupRequest API is an alternative to the SoupMessage-based SoupSession APIs which may be +useful to programs that want to deal with multiple kinds of URIs. + + + +SoupRequest officially became part of the +libsoup API in 2.42 with the addition of +soup_session_request +and the related functions. However, parts of it are also available as +far back as libsoup 2.34 via the +(now-deprecated) SoupRequester session feature, if you +define LIBSOUP_USE_UNSTABLE_REQUEST_API before +including the libsoup headers. + + + +Additionally, before libsoup 2.42, the +SoupRequest API was the only way to stream an HTTP +response body via GInputStream. As of 2.42, +there are streaming APIs based on SoupMessage (soup_session_send +and soup_session_send_async), +so applications that are using SoupRequest with only +http and https URIs can be +ported to those APIs now. + + + + + +Creating a SoupRequest + + +There are four SoupSession methods for creating +SoupRequests: + + + + + + soup_session_request + takes an arbitrary URI as a string, and returns a SoupRequest. + + + + + soup_session_request_uri + takes an arbitrary URI as a SoupURI, + and returns a SoupRequest. + + + + + soup_session_request_http + takes an HTTP method and an http or https URI as a string, and returns a SoupRequestHTTP. + + + + + soup_session_request_http_uri + takes an HTTP method and an http or https URI as a SoupURI, + and returns a SoupRequestHTTP. + + + + + + + +Sending a SoupRequest + + +Once you have created a SoupRequest, you can send it with +either soup_request_send +or soup_request_send_async. +This will provide you with a GInputStream which you can +read to get the response body. + + + +After sending, you can use soup_request_get_content_length +and soup_request_get_content_type +to get information about the response body. + + + +As with the streaming SoupMessage-based APIs, +soup_request_send and +soup_request_send_async only return errors if a +transport-level problem occurs (eg, it could not connect to the host, +or the request was cancelled). In the case of an HTTP request, use the +message's status_code field to determine +whether the request was successful or not at the HTTP level (ie, "200 +OK" vs "401 Bad Request"). (You can call soup_request_http_get_message +to get the request's corresponding SoupMessage, to look at the +status code or other HTTP metadata.) + + + + + +Supported URI types, and adding your own + + +Different URI types are implemented by different subclasses of +SoupRequest. libsoup currently +implements three SoupRequest classes: + + + + + SoupRequestHTTP + + Handles http and + https URI. + + + + SoupRequestData + + Handles data URIs containing inline data. + + + + SoupRequestFile + + Handles file and + resource URIs. + If you request a URI corresponding to a directory, this + will generate an HTML listing of the directory. + + + + + +You can add additional URI types by implementing your own +SoupRequest subclass; set the +SoupRequestClass's schemes +field to point to a NULL-terminated array of scheme +names, implement the various SoupRequest methods, and +then register the type with your SoupSession by calling +soup_session_add_feature_by_type +and passing the GType of +your request class. + + + + + diff --git a/docs/reference/server-howto.xml b/docs/reference/server-howto.xml new file mode 100644 index 0000000..336a2af --- /dev/null +++ b/docs/reference/server-howto.xml @@ -0,0 +1,438 @@ + + + + +libsoup Server Basics +3 +LIBSOUP Library + + + +libsoup Server BasicsServer-side tutorial + + + +Creating a SoupServer + + +As with the client API, there is a single object that will encapsulate +most of your interactions with libsoup. In this case, SoupServer. + + + +You create the server with soup_server_new, +and as with the SoupSession constructor, you can specify +a few additional options: + + + + + SOUP_SERVER_TLS_CERTIFICATE + + A GTlsCertificate + (containing a private key) that will be used when handling + HTTPS requests on the server. + + + + SOUP_SERVER_RAW_PATHS + + Set this to TRUE if you don't want + libsoup to decode %-encoding + in the Request-URI. (Eg, because you need to treat + "/foo/bar" and + "/foo%2Fbar" as different paths. + + + + SOUP_SERVER_SERVER_HEADER + + Allows you to set a Server header string that will be sent + on all responses. + + + + SOUP_SERVER_HTTP_ALIASES + and SOUP_SERVER_HTTPS_ALIASES + + Allow you to tell the server to recognize additional URI + schemes as aliases for "http" or + https. You can set this if you are + serving URIs with schemes like "dav" or + "webcal". + + + + + + + +Adding Listening Sockets + + + To tell the server where to listen, call soup_server_listen + (to listen on a specific GSocketAddress), soup_server_listen_all + (to listen on a given port on all network interfaces), or soup_server_listen_local + (to listen to a given port on the loopback interface only). You can + call any of these functions multiple times, to set up multiple + listening sockets. + + + + To set up an HTTPS server, you must first either set the SOUP_SERVER_TLS_CERTIFICATE + property, or else call soup_server_set_ssl_cert_file. + After that you can pass the SOUP_SERVER_LISTEN_HTTPS + option to soup_server_listen, + etc. + + + + By default, servers listen for both IPv4 and IPv6 connections; if + you don't want this, use the SOUP_SERVER_LISTEN_IPV4_ONLY + or SOUP_SERVER_LISTEN_IPV6_ONLY + options. + + + + The server runs asynchronously, in the thread-default + GMainContext of the + thread in which the "listen" calls were made. + + + + +The Old SoupServer Listening API + + +soup_server_listen, +etc, are available only in libsoup 2.46 and +later. In earlier versions, there was a simpler API, in which a server +could only listen on a single port, determined at construct time +either by passing the SOUP_SERVER_INTERFACE +property (to specify a SoupAddress to listen on), +or the SOUP_SERVER_PORT +property (to specify a port to listen on, on all interfaces). The SOUP_SERVER_SSL_CERT_FILE +and SOUP_SERVER_SSL_KEY_FILE +properties could be used to create an HTTP server. + + + +When using this API, if SoupServer is unable to bind +the listening socket, or unable to read the provided certificate or +key files, then it will return NULL from its +constructor (with no further indication of what exactly went wrong). + + + +Additionally, when using this API, it is necessary to call soup_server_run +or soup_server_run_async +to start the server after creating it. + + + + + +Adding Handlers + + +By default, SoupServer +returns "404 Not Found" in response to all requests (except ones that +it can't parse, which get "400 Bad Request"). To override this +behavior, call soup_server_add_handler +to set a callback to handle certain URI paths. + + + + soup_server_add_handler (server, "/foo", server_callback, + data, destroy_notify); + + + +The "/foo" indicates the base path for this +handler. When a request comes in, if there is a handler registered for +exactly the path in the request's Request-URI, then +that handler will be called. Otherwise +libsoup will strip path components one by +one until it finds a matching handler. So for example, a request of +the form +"GET /foo/bar/baz.html?a=1&b=2 HTTP/1.1" +would look for handlers for "/foo/bar/baz.html", +"/foo/bar", and "/foo". If a +handler has been registered with a NULL base path, +then it is used as the default handler for any request that doesn't +match any other handler. + + + + + +Responding to Requests + + +A handler callback looks something like this: + + + +static void +server_callback (SoupServer *server, + SoupMessage *msg, + const char *path, + GHashTable *query, + SoupClientContext *client, + gpointer user_data) +{ + ... +} + + + +msg is the request that has been received and +user_data is the data that was passed to soup_server_add_handler. +path is the path (from msg's +URI), and query contains the result of parsing the +URI query field. (It is NULL if there was no +query.) client is a SoupClientContext, +which contains additional information about the client (including its +IP address, and whether or not it used HTTP authentication). + + + +By default, libsoup assumes that you have +completely finished processing the message when you return from the +callback, and that it can therefore begin sending the response. If you +are not ready to send a response immediately (eg, you have to contact +another server, or wait for data from a database), you must call soup_server_pause_message +on the message before returning from the callback. This will delay +sending a response until you call soup_server_unpause_message. +(You must also connect to the finished signal on the message +in this case, so that you can break off processing if the client +unexpectedly disconnects before you start sending the data.) + + + +To set the response status, call soup_message_set_status +or soup_message_set_status_full. +If the response requires a body, you must decide whether to use +Content-Length encoding (the default), or +chunked encoding. + + + +Responding with <literal>Content-Length</literal> +Encoding + + +This is the simpler way to set a response body, if you have all of the +data available at once. + + + +static void +server_callback (SoupServer *server, + SoupMessage *msg, + const char *path, + GHashTable *query, + SoupClientContext *client, + gpointer user_data) +{ + MyServerData *server_data = user_data; + const char *mime_type; + GByteArray *body; + + if (msg->method != SOUP_METHOD_GET) { + soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED); + return; + } + + /* This is somewhat silly. Presumably your server will do + * something more interesting. + */ + body = g_hash_table_lookup (server_data->bodies, path); + mime_type = g_hash_table_lookup (server_data->mime_types, path); + if (!body || !mime_type) { + soup_message_set_status (msg, SOUP_STATUS_NOT_FOUND); + return; + } + + soup_message_set_status (msg, SOUP_STATUS_OK); + soup_message_set_response (msg, mime_type, SOUP_MEMORY_COPY, + body->data, body->len); +} + + + + + +Responding with <literal>chunked</literal> Encoding + + +If you want to supply the response body in chunks as it becomes +available, use chunked encoding instead. In this +case, first call soup_message_headers_set_encoding (msg->response_headers, SOUP_ENCODING_CHUNKED) +to tell libsoup that you'll be using +chunked encoding. Then call soup_message_body_append +(or soup_message_body_append_buffer) +on msg->response_body with each chunk of the +response body as it becomes available, and call soup_message_body_complete +when the response is complete. After each of these calls, you must +also call soup_server_unpause_message +to cause the chunk to be sent. (You do not normally need to call soup_server_pause_message, +because I/O is automatically paused when doing a +chunked transfer if no chunks are available.) + + + +When using chunked encoding, you must also connect to the finished signal on the message, +so that you will be notified if the client disconnects between two +chunks; SoupServer will unref the message if that +happens, so you must stop adding new chunks to the response at that +point. (An alternate possibility is to write each new chunk only when +the wrote_chunk signal +is emitted indicating that the previous one was written successfully.) + + + +The simple-proxy +example in the examples/ directory gives an example of +using chunked encoding. + + + + + + + +Handling Authentication + + +To have SoupServer +handle HTTP authentication for you, create a SoupAuthDomainBasic +or SoupAuthDomainDigest, +and pass it to soup_server_add_auth_domain: + + + + SoupAuthDomain *domain; + + domain = soup_auth_domain_basic_new ( + SOUP_AUTH_DOMAIN_REALM, "My Realm", + SOUP_AUTH_DOMAIN_BASIC_AUTH_CALLBACK, auth_callback, + SOUP_AUTH_DOMAIN_BASIC_AUTH_DATA, auth_data, + SOUP_AUTH_DOMAIN_ADD_PATH, "/foo", + SOUP_AUTH_DOMAIN_ADD_PATH, "/bar/private", + NULL); + soup_server_add_auth_domain (server, domain); + g_object_unref (domain); + + + +Then, every request under one of the auth domain's paths will be +passed to the auth_callback first before being +passed to the server_callback: + + + +static gboolean +auth_callback (SoupAuthDomain *domain, SoupMessage *msg, + const char *username, const char *password, + gpointer user_data) +{ + MyServerData *server_data = user_data; + MyUserData *user; + + user = my_server_data_lookup_user (server_data, username); + if (!user) + return FALSE; + + /* FIXME: Don't do this. Keeping a cleartext password database + * is bad. + */ + return strcmp (password, user->password) == 0; +} + + + +The SoupAuthDomainBasicAuthCallback +is given the username and password from the +Authorization header and must determine, in some +server-specific manner, whether or not to accept them. (In this +example we compare the password against a cleartext password database, +but it would be better to store the password somehow encoded, as in +the UNIX password database. Alternatively, you may need to delegate +the password check to PAM or some other service.) + + + +If you are using Digest authentication, note that SoupAuthDomainDigestAuthCallback +works completely differently (since the server doesn't receive the +cleartext password from the client in that case, so there's no way to +compare it directly). See the documentation for SoupAuthDomainDigest +for more details. + + + +You can have multiple SoupAuthDomains attached to a +SoupServer, either in separate parts of the path +hierarchy, or overlapping. (Eg, you might want to accept either Basic +or Digest authentication for a given path.) When more than one auth +domain covers a given path, the request will be accepted if the user +authenticates successfully against any of the +domains. + + + +If you want to require authentication for some requests under a +certain path, but not all of them (eg, you want to authenticate +PUT requests, but not GET +requests), use a SoupAuthDomainFilter. + + + + + diff --git a/docs/reference/session-porting.xml b/docs/reference/session-porting.xml new file mode 100644 index 0000000..67a433a --- /dev/null +++ b/docs/reference/session-porting.xml @@ -0,0 +1,221 @@ + + + + +Porting to the new SoupSession +3 +LIBSOUP Library + + + +Porting to the new SoupSessionNotes on +porting from SoupSessionAsync and SoupSessionSync to SoupSession + + + +Introduction + + +As of libsoup 2.42, SoupSession is no longer an +abstract class, and the base SoupSession class is now +preferred over its traditional subclasses, SoupSessionAsync and +SoupSessionSync. + + + +There are several changes in behavior between the old and new sessions +to be aware of. + + + + + +Different defaults + + +The new SoupSession +has different (and hopefully better) defaults than SoupSessionAsync and +SoupSessionSync: + + + + + + The system TLS/SSL certificate database is used by default to + validate https certificates, and sites with invalid certificates + will refuse to load with a + SOUP_STATUS_SSL_FAILED + error. + + + You can still override the CA database as before, by setting the + "ssl-ca-file" + property, although the + "tls-database" + property is preferred, since it allows you to do proper error + handling. + + + If you want to accept all certificates, set + "ssl-strict" to + FALSE. Note that libsoup will still check + certificates, it will just continue with the HTTP request even + if the certificate fails to validate. You can use + soup_message_get_https_status() + to look at the certificate after the fact. + + + + + The + "timeout" + and + "idle-timeout" + properties both default to 60 seconds. + + + + + The + "http-aliases" + property defaults to NULL, meaning that URI + schemes like "webcal" and + "dav" (and "ftp") are not + considered to be aliases for "http", and so + libsoup will not accept requests for such URIs, and will not + follow redirects to such URIs. + + + + + The new + "proxy-resolver" + property is now initialized to the default + GProxyResolver, + meaning that it will automatically use the user's system proxy + configuration. This replaces the use of the + SoupProxyResolverDefault, + session feature in earlier releases. You can set this property to + NULL if you don't want to use proxies, and the + "proxy-uri" + property still works if you want to use a single proxy for all requests. + + + + + Every session gets a + SoupContentDecoder + attached to it by default, meaning that it will automatically + handle (and request) "gzip"- and "deflate"-encoded response + bodies. + + + + + + + +Differences in feature behavior + + +If you are using NTLM authentication, the new SoupSession +behaves slightly differently from the old session types. + + + +First, the deprecated SOUP_SESSION_USE_NTLM +property is no longer supported. If you want to add support for NTLM +to a session, call soup_session_add_feature_by_type(), +passing SOUP_TYPE_AUTH_NTLM. + + + +Second, with the old session types, enabling NTLM would cause all +(otherwise-unauthenticated) requests to be sent with an NTLM request +in the Authorization header. That is, libsoup would +assume that all servers supported NTLM, and would attempt to begin +negotiating NTLM authentication before the server ever returned a 401 +response. With the plain SoupSession, this no longer +happens. If you want the old behavior, you need to call soup_auth_manager_use_auth() +for each host to "preload" the NTLM authentication: + + + + SoupAuthManager *auth_manager; + SoupAuth *auth; + SoupURI *uri; + + auth_manager = SOUP_AUTH_MANAGER (soup_session_get_feature (session, SOUP_TYPE_AUTH_MANAGER)); + auth = g_object_new (SOUP_TYPE_AUTH_NTLM, NULL); + uri = soup_uri_new ("http://ntlm-using-host.example.com/"); + soup_auth_manager_use_auth (auth_manager, uri, auth); + g_object_unref (auth); + soup_uri_free (auth); + + + + + +Differences in SoupMessage-sending APIs + + +SoupSessionAsync always uses asynchronous I/O, and +SoupSessionSync always uses blocking I/O, regardless of +the operation. In the new SoupSession, soup_session_queue_message() +uses asynchronous I/O (like SoupSessionAsync), and soup_session_send_message() +uses blocking I/O (like SoupSessionSync). There is no API +on the plain SoupSession that simulates the effect of +calling soup_session_send_message() on a +SoupSessionAsync (ie, running the main loop internally), +or of calling soup_session_queue_message() on a +SoupSessionSync (ie, automatically sending the request in +another thread). + + + + + +Differences in Asynchronous I/O + + +As compared to SoupSessionAsync, SoupSession behaves more +like gio with respect to asynchronous I/O. + + + +In particular, the "async-context" +and "use-thread-context" +properties are now effectively unused, and the session always queues +asynchronous requests in the GMainContext that was is +the thread default when the asynchronous operation is started. Session +bookkeeping tasks (like closing idle connections) happen in the +context that was thread default when the session was created. + + + +Additionally, soup_session_cancel_message() +now acts asynchronously when you cancel an asynchronous request; +rather than having the request's callback be called from inside +soup_session_cancel_message(), it just gets called +when you need return to the main loop. + + + + + diff --git a/examples/Makefile.am b/examples/Makefile.am new file mode 100644 index 0000000..1609ff2 --- /dev/null +++ b/examples/Makefile.am @@ -0,0 +1,14 @@ +AM_CPPFLAGS = \ + -I$(top_srcdir) \ + -DSRCDIR=\""$(abs_srcdir)"\" \ + -DBUILDDIR=\""$(builddir)"\" \ + $(GLIB_CFLAGS) + +LIBS = \ + $(top_builddir)/libsoup/libsoup-2.4.la \ + $(GLIB_LIBS) + +noinst_PROGRAMS = \ + get \ + simple-httpd \ + simple-proxy diff --git a/examples/Makefile.in b/examples/Makefile.in new file mode 100644 index 0000000..04cb0da --- /dev/null +++ b/examples/Makefile.in @@ -0,0 +1,695 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +noinst_PROGRAMS = get$(EXEEXT) simple-httpd$(EXEEXT) \ + simple-proxy$(EXEEXT) +subdir = examples +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_code_coverage.m4 \ + $(top_srcdir)/m4/glibtests.m4 $(top_srcdir)/m4/gtk-doc.m4 \ + $(top_srcdir)/m4/intltool.m4 $(top_srcdir)/m4/introspection.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/vapigen.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +PROGRAMS = $(noinst_PROGRAMS) +get_SOURCES = get.c +get_OBJECTS = get.$(OBJEXT) +get_LDADD = $(LDADD) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +simple_httpd_SOURCES = simple-httpd.c +simple_httpd_OBJECTS = simple-httpd.$(OBJEXT) +simple_httpd_LDADD = $(LDADD) +simple_proxy_SOURCES = simple-proxy.c +simple_proxy_OBJECTS = simple-proxy.$(OBJEXT) +simple_proxy_LDADD = $(LDADD) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = get.c simple-httpd.c simple-proxy.c +DIST_SOURCES = get.c simple-httpd.c simple-proxy.c +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in \ + $(top_srcdir)/build-aux/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALL_LINGUAS = @ALL_LINGUAS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +APACHE_HTTPD = @APACHE_HTTPD@ +APACHE_MODULE_DIR = @APACHE_MODULE_DIR@ +APACHE_PHP_MODULE_DIR = @APACHE_PHP_MODULE_DIR@ +APACHE_SSL_MODULE_DIR = @APACHE_SSL_MODULE_DIR@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CODE_COVERAGE_CFLAGS = @CODE_COVERAGE_CFLAGS@ +CODE_COVERAGE_CPPFLAGS = @CODE_COVERAGE_CPPFLAGS@ +CODE_COVERAGE_CXXFLAGS = @CODE_COVERAGE_CXXFLAGS@ +CODE_COVERAGE_ENABLED = @CODE_COVERAGE_ENABLED@ +CODE_COVERAGE_LDFLAGS = @CODE_COVERAGE_LDFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CURL = @CURL@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GCOV = @GCOV@ +GENHTML = @GENHTML@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_COMPILE_RESOURCES = @GLIB_COMPILE_RESOURCES@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MAKEFILE = @GLIB_MAKEFILE@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GMSGFMT = @GMSGFMT@ +GOBJECT_QUERY = @GOBJECT_QUERY@ +GREP = @GREP@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +HAVE_GNOME = @HAVE_GNOME@ +HTML_DIR = @HTML_DIR@ +IF_HAVE_MOD_UNIXD = @IF_HAVE_MOD_UNIXD@ +IF_HAVE_PHP = @IF_HAVE_PHP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ +INTLTOOL_MERGE = @INTLTOOL_MERGE@ +INTLTOOL_PERL = @INTLTOOL_PERL@ +INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ +INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@ +INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@ +INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@ +INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LCOV = @LCOV@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = \ + $(top_builddir)/libsoup/libsoup-2.4.la \ + $(GLIB_LIBS) + +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PHP = @PHP@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOUP_AGE = @SOUP_AGE@ +SOUP_API_VERSION = @SOUP_API_VERSION@ +SOUP_CURRENT = @SOUP_CURRENT@ +SOUP_DEBUG_FLAGS = @SOUP_DEBUG_FLAGS@ +SOUP_HIDDEN_VISIBILITY_CFLAGS = @SOUP_HIDDEN_VISIBILITY_CFLAGS@ +SOUP_MAJOR_VERSION = @SOUP_MAJOR_VERSION@ +SOUP_MICRO_VERSION = @SOUP_MICRO_VERSION@ +SOUP_MINOR_VERSION = @SOUP_MINOR_VERSION@ +SOUP_REVISION = @SOUP_REVISION@ +SQLITE_CFLAGS = @SQLITE_CFLAGS@ +SQLITE_LIBS = @SQLITE_LIBS@ +STRIP = @STRIP@ +USE_NLS = @USE_NLS@ +VALAC = @VALAC@ +VAPIDIR = @VAPIDIR@ +VAPIGEN = @VAPIGEN@ +VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@ +VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@ +VERSION = @VERSION@ +XGETTEXT = @XGETTEXT@ +XML_CFLAGS = @XML_CFLAGS@ +XML_LIBS = @XML_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +installed_test_metadir = @installed_test_metadir@ +installed_testdir = @installed_testdir@ +intltool__v_merge_options_ = @intltool__v_merge_options_@ +intltool__v_merge_options_0 = @intltool__v_merge_options_0@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +ntlm_auth = @ntlm_auth@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AM_CPPFLAGS = \ + -I$(top_srcdir) \ + -DSRCDIR=\""$(abs_srcdir)"\" \ + -DBUILDDIR=\""$(builddir)"\" \ + $(GLIB_CFLAGS) + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign examples/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign examples/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +get$(EXEEXT): $(get_OBJECTS) $(get_DEPENDENCIES) $(EXTRA_get_DEPENDENCIES) + @rm -f get$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(get_OBJECTS) $(get_LDADD) $(LIBS) + +simple-httpd$(EXEEXT): $(simple_httpd_OBJECTS) $(simple_httpd_DEPENDENCIES) $(EXTRA_simple_httpd_DEPENDENCIES) + @rm -f simple-httpd$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(simple_httpd_OBJECTS) $(simple_httpd_LDADD) $(LIBS) + +simple-proxy$(EXEEXT): $(simple_proxy_OBJECTS) $(simple_proxy_DEPENDENCIES) $(EXTRA_simple_proxy_DEPENDENCIES) + @rm -f simple-proxy$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(simple_proxy_OBJECTS) $(simple_proxy_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/get.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/simple-httpd.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/simple-proxy.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstPROGRAMS cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/examples/get.c b/examples/get.c new file mode 100644 index 0000000..f3380b5 --- /dev/null +++ b/examples/get.c @@ -0,0 +1,295 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2001-2003, Ximian, Inc. + * Copyright (C) 2013 Igalia, S.L. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include + +static SoupSession *session; +static GMainLoop *loop; +static gboolean debug, head, quiet; +static const gchar *output_file_path = NULL; + +static void +finished (SoupSession *session, SoupMessage *msg, gpointer loop) +{ + g_main_loop_quit (loop); +} + +static void +get_url (const char *url) +{ + const char *name; + SoupMessage *msg; + const char *header; + FILE *output_file = NULL; + + msg = soup_message_new (head ? "HEAD" : "GET", url); + soup_message_set_flags (msg, SOUP_MESSAGE_NO_REDIRECT); + + if (loop) { + g_object_ref (msg); + soup_session_queue_message (session, msg, finished, loop); + g_main_loop_run (loop); + } else + soup_session_send_message (session, msg); + + name = soup_message_get_uri (msg)->path; + + if (!debug) { + if (msg->status_code == SOUP_STATUS_SSL_FAILED) { + GTlsCertificateFlags flags; + + if (soup_message_get_https_status (msg, NULL, &flags)) + g_print ("%s: %d %s (0x%x)\n", name, msg->status_code, msg->reason_phrase, flags); + else + g_print ("%s: %d %s (no handshake status)\n", name, msg->status_code, msg->reason_phrase); + } else if (!quiet || SOUP_STATUS_IS_TRANSPORT_ERROR (msg->status_code)) + g_print ("%s: %d %s\n", name, msg->status_code, msg->reason_phrase); + } + + if (SOUP_STATUS_IS_REDIRECTION (msg->status_code)) { + header = soup_message_headers_get_one (msg->response_headers, + "Location"); + if (header) { + SoupURI *uri; + char *uri_string; + + if (!debug && !quiet) + g_print (" -> %s\n", header); + + uri = soup_uri_new_with_base (soup_message_get_uri (msg), header); + uri_string = soup_uri_to_string (uri, FALSE); + get_url (uri_string); + g_free (uri_string); + soup_uri_free (uri); + } + } else if (!head && SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) { + if (output_file_path) { + output_file = fopen (output_file_path, "w"); + if (!output_file) + g_printerr ("Error trying to create file %s.\n", output_file_path); + } else if (!quiet) + output_file = stdout; + + if (output_file) { + fwrite (msg->response_body->data, + 1, + msg->response_body->length, + output_file); + + if (output_file_path) + fclose (output_file); + } + } + g_object_unref (msg); +} + +/* Inline class for providing a pre-configured client certificate */ +typedef struct _GetTlsCertInteraction GetTlsCertInteraction; +typedef struct _GetTlsCertInteractionClass GetTlsCertInteractionClass; + +static GType _get_tls_cert_interaction_get_type (void) G_GNUC_CONST; +static GetTlsCertInteraction * _get_tls_cert_interaction_new (GTlsCertificate *cert); + +struct _GetTlsCertInteraction +{ + GTlsInteraction parent_instance; + GTlsCertificate *cert; +}; + +struct _GetTlsCertInteractionClass +{ + GTlsInteractionClass parent_class; +}; + +G_DEFINE_TYPE (GetTlsCertInteraction, _get_tls_cert_interaction, G_TYPE_TLS_INTERACTION); + +static GTlsInteractionResult +request_certificate (GTlsInteraction *interaction, + GTlsConnection *connection, + GTlsCertificateRequestFlags flags, + GCancellable *cancellable, + GError **error) +{ + GetTlsCertInteraction *self = (GetTlsCertInteraction*)interaction; + g_tls_connection_set_certificate (connection, self->cert); + return G_TLS_INTERACTION_HANDLED; +} + +static void +_get_tls_cert_interaction_init (GetTlsCertInteraction *interaction) +{ +} + +static void +_get_tls_cert_interaction_class_init (GetTlsCertInteractionClass *klass) +{ + GTlsInteractionClass *interaction_class = G_TLS_INTERACTION_CLASS (klass); + interaction_class->request_certificate = request_certificate; +} + +GetTlsCertInteraction * +_get_tls_cert_interaction_new (GTlsCertificate *cert) +{ + GetTlsCertInteraction *self = g_object_new (_get_tls_cert_interaction_get_type (), NULL); + self->cert = g_object_ref (cert); + return self; +} + +static const char *ca_file, *proxy; +static char *client_cert_file, *client_key_file; +static gboolean synchronous, ntlm; +static gboolean negotiate; + +static GOptionEntry entries[] = { + { "ca-file", 'c', 0, + G_OPTION_ARG_STRING, &ca_file, + "Use FILE as the TLS CA file", "FILE" }, + { "cert", 0, 0, + G_OPTION_ARG_STRING, &client_cert_file, + "Use FILE as the TLS client certificate file", "FILE" }, + { "key", 0, 0, + G_OPTION_ARG_STRING, &client_key_file, + "Use FILE as the TLS client key file", "FILE" }, + { "debug", 'd', 0, + G_OPTION_ARG_NONE, &debug, + "Show HTTP headers", NULL }, + { "head", 'h', 0, + G_OPTION_ARG_NONE, &head, + "Do HEAD rather than GET", NULL }, + { "ntlm", 'n', 0, + G_OPTION_ARG_NONE, &ntlm, + "Use NTLM authentication", NULL }, + { "output", 'o', 0, + G_OPTION_ARG_STRING, &output_file_path, + "Write the received data to FILE instead of stdout", "FILE" }, + { "proxy", 'p', 0, + G_OPTION_ARG_STRING, &proxy, + "Use URL as an HTTP proxy", "URL" }, + { "quiet", 'q', 0, + G_OPTION_ARG_NONE, &quiet, + "Don't show HTTP status code", NULL }, + { "sync", 's', 0, + G_OPTION_ARG_NONE, &synchronous, + "Use SoupSessionSync rather than SoupSessionAsync", NULL }, + { NULL } +}; + +static GOptionEntry negotiate_entries[] = { + { "negotiate", 'N', 0, + G_OPTION_ARG_NONE, &negotiate, + "Use Negotiate authentication", NULL }, + { NULL } +}; + +int +main (int argc, char **argv) +{ + GOptionContext *opts; + const char *url; + SoupURI *proxy_uri, *parsed; + GError *error = NULL; + SoupLogger *logger = NULL; + + opts = g_option_context_new (NULL); + g_option_context_add_main_entries (opts, entries, NULL); + if (soup_auth_negotiate_supported()) + g_option_context_add_main_entries (opts, negotiate_entries, NULL); + if (!g_option_context_parse (opts, &argc, &argv, &error)) { + g_printerr ("Could not parse arguments: %s\n", + error->message); + g_printerr ("%s", + g_option_context_get_help (opts, TRUE, NULL)); + exit (1); + } + + if (argc != 2) { + g_printerr ("%s", + g_option_context_get_help (opts, TRUE, NULL)); + exit (1); + } + g_option_context_free (opts); + + url = argv[1]; + parsed = soup_uri_new (url); + if (!parsed) { + g_printerr ("Could not parse '%s' as a URL\n", url); + exit (1); + } + soup_uri_free (parsed); + + session = g_object_new (SOUP_TYPE_SESSION, + SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_CONTENT_DECODER, + SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_COOKIE_JAR, + SOUP_SESSION_USER_AGENT, "get ", + SOUP_SESSION_ACCEPT_LANGUAGE_AUTO, TRUE, + NULL); + if (ntlm) + soup_session_add_feature_by_type (session, SOUP_TYPE_AUTH_NTLM); + if (ca_file) + g_object_set (session, "ssl-ca-file", ca_file, NULL); + + if (client_cert_file) { + GTlsCertificate *client_cert; + GetTlsCertInteraction *interaction; + if (!client_key_file) { + g_printerr ("--key is required with --cert\n"); + exit (1); + } + client_cert = g_tls_certificate_new_from_files (client_cert_file, client_key_file, &error); + if (!client_cert) { + g_printerr ("%s\n", error->message); + exit (1); + } + interaction = _get_tls_cert_interaction_new (client_cert); + g_object_set (session, SOUP_SESSION_TLS_INTERACTION, interaction, NULL); + } + + if (debug) { + logger = soup_logger_new (SOUP_LOGGER_LOG_BODY, -1); + soup_session_add_feature (session, SOUP_SESSION_FEATURE (logger)); + g_object_unref (logger); + } + + if (proxy) { + proxy_uri = soup_uri_new (proxy); + if (!proxy_uri) { + g_printerr ("Could not parse '%s' as URI\n", + proxy); + exit (1); + } + + g_object_set (G_OBJECT (session), + SOUP_SESSION_PROXY_URI, proxy_uri, + NULL); + soup_uri_free (proxy_uri); + } + +#ifdef LIBSOUP_HAVE_GSSAPI + if (negotiate) { + soup_session_add_feature_by_type (session, + SOUP_TYPE_AUTH_NEGOTIATE); + } +#endif /* LIBSOUP_HAVE_GSSAPI */ + + if (!synchronous) + loop = g_main_loop_new (NULL, TRUE); + + get_url (url); + + if (!synchronous) + g_main_loop_unref (loop); + + g_object_unref (session); + + return 0; +} diff --git a/examples/simple-httpd.c b/examples/simple-httpd.c new file mode 100644 index 0000000..0458203 --- /dev/null +++ b/examples/simple-httpd.c @@ -0,0 +1,298 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2001-2003, Ximian, Inc. + */ + +#include +#include +#include +#include +#include + +#include +#include + +static int +compare_strings (gconstpointer a, gconstpointer b) +{ + const char **sa = (const char **)a; + const char **sb = (const char **)b; + + return strcmp (*sa, *sb); +} + +static GString * +get_directory_listing (const char *path) +{ + GPtrArray *entries; + GString *listing; + char *escaped; + GDir *dir; + const gchar *d_name; + int i; + + entries = g_ptr_array_new (); + dir = g_dir_open (path, 0, NULL); + if (dir) { + while ((d_name = g_dir_read_name (dir))) { + if (!strcmp (d_name, ".") || + (!strcmp (d_name, "..") && + !strcmp (path, "./"))) + continue; + escaped = g_markup_escape_text (d_name, -1); + g_ptr_array_add (entries, escaped); + } + g_dir_close (dir); + } + + g_ptr_array_sort (entries, (GCompareFunc)compare_strings); + + listing = g_string_new ("\r\n"); + escaped = g_markup_escape_text (strchr (path, '/'), -1); + g_string_append_printf (listing, "Index of %s\r\n", escaped); + g_string_append_printf (listing, "

Index of %s

\r\n

\r\n", escaped); + g_free (escaped); + for (i = 0; i < entries->len; i++) { + g_string_append_printf (listing, "%s
\r\n", + (char *)entries->pdata[i], + (char *)entries->pdata[i]); + g_free (entries->pdata[i]); + } + g_string_append (listing, "\r\n\r\n"); + + g_ptr_array_free (entries, TRUE); + return listing; +} + +static void +do_get (SoupServer *server, SoupMessage *msg, const char *path) +{ + char *slash; + GStatBuf st; + + if (g_stat (path, &st) == -1) { + if (errno == EPERM) + soup_message_set_status (msg, SOUP_STATUS_FORBIDDEN); + else if (errno == ENOENT) + soup_message_set_status (msg, SOUP_STATUS_NOT_FOUND); + else + soup_message_set_status (msg, SOUP_STATUS_INTERNAL_SERVER_ERROR); + return; + } + + if (g_file_test (path, G_FILE_TEST_IS_DIR)) { + GString *listing; + char *index_path; + + slash = strrchr (path, '/'); + if (!slash || slash[1]) { + char *redir_uri; + + redir_uri = g_strdup_printf ("%s/", soup_message_get_uri (msg)->path); + soup_message_set_redirect (msg, SOUP_STATUS_MOVED_PERMANENTLY, + redir_uri); + g_free (redir_uri); + return; + } + + index_path = g_strdup_printf ("%s/index.html", path); + if (g_stat (path, &st) != -1) { + do_get (server, msg, index_path); + g_free (index_path); + return; + } + g_free (index_path); + + listing = get_directory_listing (path); + soup_message_set_response (msg, "text/html", + SOUP_MEMORY_TAKE, + listing->str, listing->len); + soup_message_set_status (msg, SOUP_STATUS_OK); + g_string_free (listing, FALSE); + return; + } + + if (msg->method == SOUP_METHOD_GET) { + GMappedFile *mapping; + SoupBuffer *buffer; + + mapping = g_mapped_file_new (path, FALSE, NULL); + if (!mapping) { + soup_message_set_status (msg, SOUP_STATUS_INTERNAL_SERVER_ERROR); + return; + } + + buffer = soup_buffer_new_with_owner (g_mapped_file_get_contents (mapping), + g_mapped_file_get_length (mapping), + mapping, (GDestroyNotify)g_mapped_file_unref); + soup_message_body_append_buffer (msg->response_body, buffer); + soup_buffer_free (buffer); + } else /* msg->method == SOUP_METHOD_HEAD */ { + char *length; + + /* We could just use the same code for both GET and + * HEAD (soup-message-server-io.c will fix things up). + * But we'll optimize and avoid the extra I/O. + */ + length = g_strdup_printf ("%lu", (gulong)st.st_size); + soup_message_headers_append (msg->response_headers, + "Content-Length", length); + g_free (length); + } + + soup_message_set_status (msg, SOUP_STATUS_OK); +} + +static void +do_put (SoupServer *server, SoupMessage *msg, const char *path) +{ + GStatBuf st; + FILE *f; + gboolean created = TRUE; + + if (g_stat (path, &st) != -1) { + const char *match = soup_message_headers_get_one (msg->request_headers, "If-None-Match"); + if (match && !strcmp (match, "*")) { + soup_message_set_status (msg, SOUP_STATUS_CONFLICT); + return; + } + + if (!g_file_test (path, G_FILE_TEST_IS_REGULAR)) { + soup_message_set_status (msg, SOUP_STATUS_FORBIDDEN); + return; + } + + created = FALSE; + } + + f = fopen (path, "w"); + if (!f) { + soup_message_set_status (msg, SOUP_STATUS_INTERNAL_SERVER_ERROR); + return; + } + + fwrite (msg->request_body->data, 1, msg->request_body->length, f); + fclose (f); + + soup_message_set_status (msg, created ? SOUP_STATUS_CREATED : SOUP_STATUS_OK); +} + +static void +server_callback (SoupServer *server, SoupMessage *msg, + const char *path, GHashTable *query, + SoupClientContext *context, gpointer data) +{ + char *file_path; + SoupMessageHeadersIter iter; + const char *name, *value; + + g_print ("%s %s HTTP/1.%d\n", msg->method, path, + soup_message_get_http_version (msg)); + soup_message_headers_iter_init (&iter, msg->request_headers); + while (soup_message_headers_iter_next (&iter, &name, &value)) + g_print ("%s: %s\n", name, value); + if (msg->request_body->length) + g_print ("%s\n", msg->request_body->data); + + file_path = g_strdup_printf (".%s", path); + + if (msg->method == SOUP_METHOD_GET || msg->method == SOUP_METHOD_HEAD) + do_get (server, msg, file_path); + else if (msg->method == SOUP_METHOD_PUT) + do_put (server, msg, file_path); + else + soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED); + + g_free (file_path); + g_print (" -> %d %s\n\n", msg->status_code, msg->reason_phrase); +} + +static void +quit (int sig) +{ + /* Exit cleanly on ^C in case we're valgrinding. */ + exit (0); +} + +static int port; +static const char *tls_cert_file, *tls_key_file; + +static GOptionEntry entries[] = { + { "cert-file", 'c', 0, + G_OPTION_ARG_STRING, &tls_cert_file, + "Use FILE as the TLS certificate file", "FILE" }, + { "key-file", 'k', 0, + G_OPTION_ARG_STRING, &tls_key_file, + "Use FILE as the TLS private key file", "FILE" }, + { "port", 'p', 0, + G_OPTION_ARG_INT, &port, + "Port to listen on", NULL }, + { NULL } +}; + +int +main (int argc, char **argv) +{ + GOptionContext *opts; + GMainLoop *loop; + SoupServer *server; + GSList *uris, *u; + char *str; + GTlsCertificate *cert; + GError *error = NULL; + + opts = g_option_context_new (NULL); + g_option_context_add_main_entries (opts, entries, NULL); + if (!g_option_context_parse (opts, &argc, &argv, &error)) { + g_printerr ("Could not parse arguments: %s\n", + error->message); + g_printerr ("%s", + g_option_context_get_help (opts, TRUE, NULL)); + exit (1); + } + if (argc != 1) { + g_printerr ("%s", + g_option_context_get_help (opts, TRUE, NULL)); + exit (1); + } + g_option_context_free (opts); + + signal (SIGINT, quit); + + if (tls_cert_file && tls_key_file) { + cert = g_tls_certificate_new_from_files (tls_cert_file, tls_key_file, &error); + if (error) { + g_printerr ("Unable to create server: %s\n", error->message); + exit (1); + } + server = soup_server_new (SOUP_SERVER_SERVER_HEADER, "simple-httpd ", + SOUP_SERVER_TLS_CERTIFICATE, cert, + NULL); + g_object_unref (cert); + + soup_server_listen_all (server, port, SOUP_SERVER_LISTEN_HTTPS, &error); + } else { + server = soup_server_new (SOUP_SERVER_SERVER_HEADER, "simple-httpd ", + NULL); + soup_server_listen_all (server, port, 0, &error); + } + + soup_server_add_handler (server, NULL, + server_callback, NULL, NULL); + + uris = soup_server_get_uris (server); + for (u = uris; u; u = u->next) { + str = soup_uri_to_string (u->data, FALSE); + g_print ("Listening on %s\n", str); + g_free (str); + soup_uri_free (u->data); + } + g_slist_free (uris); + + g_print ("\nWaiting for requests...\n"); + + loop = g_main_loop_new (NULL, TRUE); + g_main_loop_run (loop); + + return 0; +} diff --git a/examples/simple-proxy.c b/examples/simple-proxy.c new file mode 100644 index 0000000..e585490 --- /dev/null +++ b/examples/simple-proxy.c @@ -0,0 +1,417 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2001-2003, Ximian, Inc. + */ + +#include +#include + +#include + +/* WARNING: this is really really really not especially compliant with + * RFC 2616. But it does work for basic stuff. + */ + +static SoupSession *session; +static SoupServer *server; + +typedef struct { + GIOStream *iostream; + GInputStream *istream; + GOutputStream *ostream; + + gssize nread, nwrote; + guchar *buffer; +} TunnelEnd; + +typedef struct { + SoupServer *self; + SoupMessage *msg; + SoupClientContext *context; + GCancellable *cancellable; + + TunnelEnd client, server; +} Tunnel; + +#define BUFSIZE 8192 + +static void tunnel_read_cb (GObject *object, + GAsyncResult *result, + gpointer user_data); + +static void +tunnel_close (Tunnel *tunnel) +{ + if (tunnel->cancellable) { + g_cancellable_cancel (tunnel->cancellable); + g_object_unref (tunnel->cancellable); + } + + if (tunnel->client.iostream) { + g_io_stream_close (tunnel->client.iostream, NULL, NULL); + g_object_unref (tunnel->client.iostream); + } + if (tunnel->server.iostream) { + g_io_stream_close (tunnel->server.iostream, NULL, NULL); + g_object_unref (tunnel->server.iostream); + } + + g_free (tunnel->client.buffer); + g_free (tunnel->server.buffer); + + g_object_unref (tunnel->self); + g_object_unref (tunnel->msg); + + g_free (tunnel); +} + +static void +tunnel_wrote_cb (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + Tunnel *tunnel = user_data; + TunnelEnd *write_end, *read_end; + GError *error = NULL; + gssize nwrote; + + nwrote = g_output_stream_write_finish (G_OUTPUT_STREAM (object), result, &error); + if (nwrote <= 0) { + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + g_error_free (error); + return; + } else if (error) { + g_print ("Tunnel write failed: %s\n", error->message); + g_error_free (error); + } + tunnel_close (tunnel); + return; + } + + if (object == (GObject *)tunnel->client.ostream) { + write_end = &tunnel->client; + read_end = &tunnel->server; + } else { + write_end = &tunnel->server; + read_end = &tunnel->client; + } + + write_end->nwrote += nwrote; + if (write_end->nwrote < read_end->nread) { + g_output_stream_write_async (write_end->ostream, + read_end->buffer + write_end->nwrote, + read_end->nread - write_end->nwrote, + G_PRIORITY_DEFAULT, tunnel->cancellable, + tunnel_wrote_cb, tunnel); + } else { + g_input_stream_read_async (read_end->istream, + read_end->buffer, BUFSIZE, + G_PRIORITY_DEFAULT, tunnel->cancellable, + tunnel_read_cb, tunnel); + } +} + +static void +tunnel_read_cb (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + Tunnel *tunnel = user_data; + TunnelEnd *read_end, *write_end; + GError *error = NULL; + gssize nread; + + nread = g_input_stream_read_finish (G_INPUT_STREAM (object), result, &error); + if (nread <= 0) { + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + g_error_free (error); + return; + } else if (error) { + g_print ("Tunnel read failed: %s\n", error->message); + g_error_free (error); + } + tunnel_close (tunnel); + return; + } + + if (object == (GObject *)tunnel->client.istream) { + read_end = &tunnel->client; + write_end = &tunnel->server; + } else { + read_end = &tunnel->server; + write_end = &tunnel->client; + } + + read_end->nread = nread; + write_end->nwrote = 0; + g_output_stream_write_async (write_end->ostream, + read_end->buffer, read_end->nread, + G_PRIORITY_DEFAULT, tunnel->cancellable, + tunnel_wrote_cb, tunnel); +} + +static void +start_tunnel (SoupMessage *msg, gpointer user_data) +{ + Tunnel *tunnel = user_data; + + tunnel->client.iostream = soup_client_context_steal_connection (tunnel->context); + tunnel->client.istream = g_io_stream_get_input_stream (tunnel->client.iostream); + tunnel->client.ostream = g_io_stream_get_output_stream (tunnel->client.iostream); + + tunnel->client.buffer = g_malloc (BUFSIZE); + tunnel->server.buffer = g_malloc (BUFSIZE); + + tunnel->cancellable = g_cancellable_new (); + + g_input_stream_read_async (tunnel->client.istream, + tunnel->client.buffer, BUFSIZE, + G_PRIORITY_DEFAULT, tunnel->cancellable, + tunnel_read_cb, tunnel); + g_input_stream_read_async (tunnel->server.istream, + tunnel->server.buffer, BUFSIZE, + G_PRIORITY_DEFAULT, tunnel->cancellable, + tunnel_read_cb, tunnel); +} + + +static void +tunnel_connected_cb (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + Tunnel *tunnel = user_data; + GError *error = NULL; + + tunnel->server.iostream = (GIOStream *) + g_socket_client_connect_to_host_finish (G_SOCKET_CLIENT (object), result, &error); + if (!tunnel->server.iostream) { + soup_message_set_status (tunnel->msg, SOUP_STATUS_BAD_GATEWAY); + soup_message_set_response (tunnel->msg, "text/plain", + SOUP_MEMORY_COPY, + error->message, strlen (error->message)); + g_error_free (error); + soup_server_unpause_message (tunnel->self, tunnel->msg); + tunnel_close (tunnel); + return; + } + + tunnel->server.istream = g_io_stream_get_input_stream (tunnel->server.iostream); + tunnel->server.ostream = g_io_stream_get_output_stream (tunnel->server.iostream); + + soup_message_set_status (tunnel->msg, SOUP_STATUS_OK); + soup_server_unpause_message (tunnel->self, tunnel->msg); + g_signal_connect (tunnel->msg, "finished", + G_CALLBACK (start_tunnel), tunnel); +} + +static void +try_tunnel (SoupServer *server, SoupMessage *msg, SoupClientContext *context) +{ + Tunnel *tunnel; + SoupURI *dest_uri; + GSocketClient *sclient; + + soup_server_pause_message (server, msg); + + tunnel = g_new0 (Tunnel, 1); + tunnel->self = g_object_ref (server); + tunnel->msg = g_object_ref (msg); + tunnel->context = context; + + dest_uri = soup_message_get_uri (msg); + sclient = g_socket_client_new (); + g_socket_client_connect_to_host_async (sclient, dest_uri->host, dest_uri->port, + NULL, tunnel_connected_cb, tunnel); + g_object_unref (sclient); +} + +static void +copy_header (const char *name, const char *value, gpointer dest_headers) +{ + soup_message_headers_append (dest_headers, name, value); +} + +static void +send_headers (SoupMessage *from, SoupMessage *to) +{ + g_print ("[%p] HTTP/1.%d %d %s\n", to, + soup_message_get_http_version (from), + from->status_code, from->reason_phrase); + + soup_message_set_status_full (to, from->status_code, + from->reason_phrase); + soup_message_headers_foreach (from->response_headers, copy_header, + to->response_headers); + soup_message_headers_remove (to->response_headers, "Content-Length"); + soup_server_unpause_message (server, to); +} + +static void +send_chunk (SoupMessage *from, SoupBuffer *chunk, SoupMessage *to) +{ + g_print ("[%p] writing chunk of %lu bytes\n", to, + (unsigned long)chunk->length); + + soup_message_body_append_buffer (to->response_body, chunk); + soup_server_unpause_message (server, to); +} + +static void +client_msg_failed (SoupMessage *msg, gpointer msg2) +{ + soup_session_cancel_message (session, msg2, SOUP_STATUS_IO_ERROR); +} + +static void +finish_msg (SoupSession *session, SoupMessage *msg2, gpointer data) +{ + SoupMessage *msg = data; + + g_print ("[%p] done\n\n", msg); + g_signal_handlers_disconnect_by_func (msg, client_msg_failed, msg2); + + soup_message_body_complete (msg->response_body); + soup_server_unpause_message (server, msg); + g_object_unref (msg); +} + +static void +server_callback (SoupServer *server, SoupMessage *msg, + const char *path, GHashTable *query, + SoupClientContext *context, gpointer data) +{ + SoupMessage *msg2; + char *uristr; + + uristr = soup_uri_to_string (soup_message_get_uri (msg), FALSE); + g_print ("[%p] %s %s HTTP/1.%d\n", msg, msg->method, uristr, + soup_message_get_http_version (msg)); + + if (msg->method == SOUP_METHOD_CONNECT) { + try_tunnel (server, msg, context); + return; + } + + msg2 = soup_message_new (msg->method, uristr); + soup_message_headers_foreach (msg->request_headers, copy_header, + msg2->request_headers); + soup_message_headers_remove (msg2->request_headers, "Host"); + soup_message_headers_remove (msg2->request_headers, "Connection"); + + if (msg->request_body->length) { + SoupBuffer *request = soup_message_body_flatten (msg->request_body); + soup_message_body_append_buffer (msg2->request_body, request); + soup_buffer_free (request); + } + soup_message_headers_set_encoding (msg->response_headers, + SOUP_ENCODING_CHUNKED); + + g_signal_connect (msg2, "got_headers", + G_CALLBACK (send_headers), msg); + g_signal_connect (msg2, "got_chunk", + G_CALLBACK (send_chunk), msg); + + g_signal_connect (msg, "finished", G_CALLBACK (client_msg_failed), msg2); + + soup_session_queue_message (session, msg2, finish_msg, msg); + + g_object_ref (msg); + soup_server_pause_message (server, msg); +} + +static gboolean +auth_callback (SoupAuthDomain *auth_domain, SoupMessage *msg, + const char *username, const char *password, gpointer data) +{ + return !strcmp (username, "user") && !strcmp (password, "password"); +} + +static void +quit (int sig) +{ + /* Exit cleanly on ^C in case we're valgrinding. */ + exit (0); +} + +static int port; +static gboolean require_auth; + +static GOptionEntry entries[] = { + { "auth-domain", 'a', 0, + G_OPTION_ARG_NONE, &require_auth, + "Require authentication", NULL }, + { "port", 'p', 0, + G_OPTION_ARG_INT, &port, + "Port to listen on", NULL }, + { NULL } +}; + +int +main (int argc, char **argv) +{ + GOptionContext *opts; + GMainLoop *loop; + GSList *uris, *u; + char *str; + GError *error = NULL; + + opts = g_option_context_new (NULL); + g_option_context_add_main_entries (opts, entries, NULL); + if (!g_option_context_parse (opts, &argc, &argv, &error)) { + g_printerr ("Could not parse arguments: %s\n", + error->message); + g_printerr ("%s", + g_option_context_get_help (opts, TRUE, NULL)); + exit (1); + } + + if (argc != 1) { + g_printerr ("%s", + g_option_context_get_help (opts, TRUE, NULL)); + exit (1); + } + g_option_context_free (opts); + + signal (SIGINT, quit); + + server = g_object_new (SOUP_TYPE_SERVER, NULL); + soup_server_add_handler (server, NULL, + server_callback, NULL, NULL); + if (require_auth) { + SoupAuthDomain *auth_domain; + + auth_domain = soup_auth_domain_basic_new ( + SOUP_AUTH_DOMAIN_REALM, "simple-proxy", + SOUP_AUTH_DOMAIN_PROXY, TRUE, + SOUP_AUTH_DOMAIN_BASIC_AUTH_CALLBACK, auth_callback, + NULL); + soup_server_add_auth_domain (server, auth_domain); + g_object_unref (auth_domain); + } + + soup_server_listen_all (server, port, 0, &error); + if (error) { + g_printerr ("Unable to create server: %s\n", error->message); + exit (1); + } + + uris = soup_server_get_uris (server); + for (u = uris; u; u = u->next) { + str = soup_uri_to_string (u->data, FALSE); + g_print ("Listening on %s\n", str); + g_free (str); + soup_uri_free (u->data); + } + g_slist_free (uris); + + session = soup_session_new (); + + g_print ("\nWaiting for requests...\n"); + + loop = g_main_loop_new (NULL, TRUE); + g_main_loop_run (loop); + g_main_loop_unref (loop); + + return 0; +} diff --git a/glib-tap.mk b/glib-tap.mk new file mode 100644 index 0000000..c97bf3f --- /dev/null +++ b/glib-tap.mk @@ -0,0 +1,134 @@ +# GLIB - Library of useful C routines + +TESTS_ENVIRONMENT= \ + G_TEST_SRCDIR="$(abs_srcdir)" \ + G_TEST_BUILDDIR="$(abs_builddir)" \ + G_DEBUG=gc-friendly \ + MALLOC_CHECK_=2 \ + MALLOC_PERTURB_=$$(($${RANDOM:-256} % 256)) +LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) $(top_srcdir)/tap-driver.sh +LOG_COMPILER = $(top_srcdir)/tap-test + +NULL = + +# initialize variables for unconditional += appending +BUILT_SOURCES = +BUILT_EXTRA_DIST = +CLEANFILES = *.log *.trs +DISTCLEANFILES = +MAINTAINERCLEANFILES = +EXTRA_DIST = +TESTS = + +installed_test_LTLIBRARIES = +installed_test_PROGRAMS = +installed_test_SCRIPTS = +nobase_installed_test_DATA = + +noinst_LTLIBRARIES = +noinst_PROGRAMS = +noinst_SCRIPTS = +noinst_DATA = + +check_LTLIBRARIES = +check_PROGRAMS = +check_SCRIPTS = +check_DATA = + +# We support a fairly large range of possible variables. It is expected that all types of files in a test suite +# will belong in exactly one of the following variables. +# +# First, we support the usual automake suffixes, but in lowercase, with the customary meaning: +# +# test_programs, test_scripts, test_data, test_ltlibraries +# +# The above are used to list files that are involved in both uninstalled and installed testing. The +# test_programs and test_scripts are taken to be actual testcases and will be run as part of the test suite. +# Note that _data is always used with the nobase_ automake variable name to ensure that installed test data is +# installed in the same way as it appears in the package layout. +# +# In order to mark a particular file as being only for one type of testing, use 'installed' or 'uninstalled', +# like so: +# +# installed_test_programs, uninstalled_test_programs +# installed_test_scripts, uninstalled_test_scripts +# installed_test_data, uninstalled_test_data +# installed_test_ltlibraries, uninstalled_test_ltlibraries +# +# Additionally, we support 'extra' infixes for programs and scripts. This is used for support programs/scripts +# that should not themselves be run as testcases (but exist to be used from other testcases): +# +# test_extra_programs, installed_test_extra_programs, uninstalled_test_extra_programs +# test_extra_scripts, installed_test_extra_scripts, uninstalled_test_extra_scripts +# +# Additionally, for _scripts and _data, we support the customary dist_ prefix so that the named script or data +# file automatically end up in the tarball. +# +# dist_test_scripts, dist_test_data, dist_test_extra_scripts +# dist_installed_test_scripts, dist_installed_test_data, dist_installed_test_extra_scripts +# dist_uninstalled_test_scripts, dist_uninstalled_test_data, dist_uninstalled_test_extra_scripts +# +# Note that no file is automatically disted unless it appears in one of the dist_ variables. This follows the +# standard automake convention of not disting programs scripts or data by default. +# +# test_programs, test_scripts, uninstalled_test_programs and uninstalled_test_scripts (as well as their disted +# variants) will be run as part of the in-tree 'make check'. These are all assumed to be runnable under +# gtester. That's a bit strange for scripts, but it's possible. + +TESTS += $(test_programs) $(test_scripts) $(uninstalled_test_programs) $(uninstalled_test_scripts) \ + $(dist_test_scripts) $(dist_uninstalled_test_scripts) + +# Note: build even the installed-only targets during 'make check' to ensure that they still work. +# We need to do a bit of trickery here and manage disting via EXTRA_DIST instead of using dist_ prefixes to +# prevent automake from mistreating gmake functions like $(wildcard ...) and $(addprefix ...) as if they were +# filenames, including removing duplicate instances of the opening part before the space, eg. '$(addprefix'. +all_test_programs = $(test_programs) $(uninstalled_test_programs) $(installed_test_programs) \ + $(test_extra_programs) $(uninstalled_test_extra_programs) $(installed_test_extra_programs) +all_test_scripts = $(test_scripts) $(uninstalled_test_scripts) $(installed_test_scripts) \ + $(test_extra_scripts) $(uninstalled_test_extra_scripts) $(installed_test_extra_scripts) +all_dist_test_scripts = $(dist_test_scripts) $(dist_uninstalled_test_scripts) $(dist_installed_test_scripts) \ + $(dist_test_extra_scripts) $(dist_uninstalled_test_extra_scripts) $(dist_installed_test_extra_scripts) +all_test_scripts += $(all_dist_test_scripts) +EXTRA_DIST += $(all_dist_test_scripts) +all_test_data = $(test_data) $(uninstalled_test_data) $(installed_test_data) +all_dist_test_data = $(dist_test_data) $(dist_uninstalled_test_data) $(dist_installed_test_data) +all_test_data += $(all_dist_test_data) +EXTRA_DIST += $(all_dist_test_data) +all_test_ltlibs = $(test_ltlibraries) $(uninstalled_test_ltlibraries) $(installed_test_ltlibraries) + +if ENABLE_ALWAYS_BUILD_TESTS +noinst_LTLIBRARIES += $(all_test_ltlibs) +noinst_PROGRAMS += $(all_test_programs) +noinst_SCRIPTS += $(all_test_scripts) +noinst_DATA += $(all_test_data) +else +check_LTLIBRARIES += $(all_test_ltlibs) +check_PROGRAMS += $(all_test_programs) +check_SCRIPTS += $(all_test_scripts) +check_DATA += $(all_test_data) +endif + +if ENABLE_INSTALLED_TESTS +installed_test_PROGRAMS += $(test_programs) $(installed_test_programs) \ + $(test_extra_programs) $(installed_test_extra_programs) +installed_test_SCRIPTS += $(test_scripts) $(installed_test_scripts) \ + $(test_extra_scripts) $(test_installed_extra_scripts) +installed_test_SCRIPTS += $(dist_test_scripts) $(dist_test_extra_scripts) \ + $(dist_installed_test_scripts) $(dist_installed_test_extra_scripts) +nobase_installed_test_DATA += $(test_data) $(installed_test_data) +nobase_installed_test_DATA += $(dist_test_data) $(dist_installed_test_data) +installed_test_LTLIBRARIES += $(test_ltlibraries) $(installed_test_ltlibraries) +installed_testcases = $(test_programs) $(installed_test_programs) \ + $(test_scripts) $(installed_test_scripts) \ + $(dist_test_scripts) $(dist_installed_test_scripts) + +installed_test_meta_DATA = $(installed_testcases:=.test) + +%.test: %$(EXEEXT) Makefile + $(AM_V_GEN) (echo '[Test]' > $@.tmp; \ + echo 'Type=session' >> $@.tmp; \ + echo 'Exec=$(installed_testdir)/$<' >> $@.tmp; \ + mv $@.tmp $@) + +CLEANFILES += $(installed_test_meta_DATA) +endif diff --git a/gtk-doc.make b/gtk-doc.make new file mode 100644 index 0000000..7d9a27f --- /dev/null +++ b/gtk-doc.make @@ -0,0 +1,321 @@ +# -*- mode: makefile -*- +# +# gtk-doc.make - make rules for gtk-doc +# Copyright (C) 2003 James Henstridge +# 2004-2007 Damon Chaplin +# 2007-2017 Stefan Sauer +# +# 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 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 . + +#################################### +# Everything below here is generic # +#################################### + +if GTK_DOC_USE_LIBTOOL +GTKDOC_CC = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(INCLUDES) $(GTKDOC_DEPS_CFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +GTKDOC_LD = $(LIBTOOL) --tag=CC --mode=link $(CC) $(GTKDOC_DEPS_LIBS) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) +GTKDOC_RUN = $(LIBTOOL) --mode=execute +else +GTKDOC_CC = $(CC) $(INCLUDES) $(GTKDOC_DEPS_CFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +GTKDOC_LD = $(CC) $(GTKDOC_DEPS_LIBS) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) +GTKDOC_RUN = +endif + +# We set GPATH here; this gives us semantics for GNU make +# which are more like other make's VPATH, when it comes to +# whether a source that is a target of one rule is then +# searched for in VPATH/GPATH. +# +GPATH = $(srcdir) + +TARGET_DIR=$(HTML_DIR)/$(DOC_MODULE) + +SETUP_FILES = \ + $(content_files) \ + $(expand_content_files) \ + $(DOC_MAIN_SGML_FILE) \ + $(DOC_MODULE)-sections.txt \ + $(DOC_MODULE)-overrides.txt + +EXTRA_DIST = \ + $(HTML_IMAGES) \ + $(SETUP_FILES) + +DOC_STAMPS=setup-build.stamp scan-build.stamp sgml-build.stamp \ + html-build.stamp pdf-build.stamp \ + sgml.stamp html.stamp pdf.stamp + +SCANOBJ_FILES = \ + $(DOC_MODULE).args \ + $(DOC_MODULE).hierarchy \ + $(DOC_MODULE).interfaces \ + $(DOC_MODULE).prerequisites \ + $(DOC_MODULE).signals + +REPORT_FILES = \ + $(DOC_MODULE)-undocumented.txt \ + $(DOC_MODULE)-undeclared.txt \ + $(DOC_MODULE)-unused.txt + +gtkdoc-check.test: Makefile + $(AM_V_GEN)echo "#!/bin/sh -e" > $@; \ + echo "$(GTKDOC_CHECK_PATH) || exit 1" >> $@; \ + chmod +x $@ + +CLEANFILES = $(SCANOBJ_FILES) $(REPORT_FILES) $(DOC_STAMPS) gtkdoc-check.test + +if GTK_DOC_BUILD_HTML +HTML_BUILD_STAMP=html-build.stamp +else +HTML_BUILD_STAMP= +endif +if GTK_DOC_BUILD_PDF +PDF_BUILD_STAMP=pdf-build.stamp +else +PDF_BUILD_STAMP= +endif + +all-gtk-doc: $(HTML_BUILD_STAMP) $(PDF_BUILD_STAMP) +.PHONY: all-gtk-doc + +if ENABLE_GTK_DOC +all-local: all-gtk-doc +endif + +docs: $(HTML_BUILD_STAMP) $(PDF_BUILD_STAMP) + +$(REPORT_FILES): sgml-build.stamp + +#### setup #### + +GTK_DOC_V_SETUP=$(GTK_DOC_V_SETUP_@AM_V@) +GTK_DOC_V_SETUP_=$(GTK_DOC_V_SETUP_@AM_DEFAULT_V@) +GTK_DOC_V_SETUP_0=@echo " DOC Preparing build"; + +setup-build.stamp: + -$(GTK_DOC_V_SETUP)if test "$(abs_srcdir)" != "$(abs_builddir)" ; then \ + files=`echo $(SETUP_FILES) $(DOC_MODULE).types`; \ + if test "x$$files" != "x" ; then \ + for file in $$files ; do \ + destdir=`dirname $(abs_builddir)/$$file`; \ + test -d "$$destdir" || mkdir -p "$$destdir"; \ + test -f $(abs_srcdir)/$$file && \ + cp -pf $(abs_srcdir)/$$file $(abs_builddir)/$$file || true; \ + done; \ + fi; \ + fi + $(AM_V_at)touch setup-build.stamp + +#### scan #### + +GTK_DOC_V_SCAN=$(GTK_DOC_V_SCAN_@AM_V@) +GTK_DOC_V_SCAN_=$(GTK_DOC_V_SCAN_@AM_DEFAULT_V@) +GTK_DOC_V_SCAN_0=@echo " DOC Scanning header files"; + +GTK_DOC_V_INTROSPECT=$(GTK_DOC_V_INTROSPECT_@AM_V@) +GTK_DOC_V_INTROSPECT_=$(GTK_DOC_V_INTROSPECT_@AM_DEFAULT_V@) +GTK_DOC_V_INTROSPECT_0=@echo " DOC Introspecting gobjects"; + +scan-build.stamp: setup-build.stamp $(HFILE_GLOB) $(CFILE_GLOB) + $(GTK_DOC_V_SCAN)_source_dir='' ; \ + for i in $(DOC_SOURCE_DIR) ; do \ + _source_dir="$${_source_dir} --source-dir=$$i" ; \ + done ; \ + gtkdoc-scan --module=$(DOC_MODULE) --ignore-headers="$(IGNORE_HFILES)" $${_source_dir} $(SCAN_OPTIONS) $(EXTRA_HFILES) + $(GTK_DOC_V_INTROSPECT)if grep -l '^..*$$' $(DOC_MODULE).types > /dev/null 2>&1 ; then \ + scanobj_options=""; \ + gtkdoc-scangobj 2>&1 --help | grep >/dev/null "\-\-verbose"; \ + if test "$$?" = "0"; then \ + if test "x$(V)" = "x1"; then \ + scanobj_options="--verbose"; \ + fi; \ + fi; \ + CC="$(GTKDOC_CC)" LD="$(GTKDOC_LD)" RUN="$(GTKDOC_RUN)" CFLAGS="$(GTKDOC_CFLAGS) $(CFLAGS)" LDFLAGS="$(GTKDOC_LIBS) $(LDFLAGS)" \ + gtkdoc-scangobj $(SCANGOBJ_OPTIONS) $$scanobj_options --module=$(DOC_MODULE); \ + else \ + for i in $(SCANOBJ_FILES) ; do \ + test -f $$i || touch $$i ; \ + done \ + fi + $(AM_V_at)touch scan-build.stamp + +$(DOC_MODULE)-decl.txt $(SCANOBJ_FILES) $(DOC_MODULE)-sections.txt $(DOC_MODULE)-overrides.txt: scan-build.stamp + @true + +#### xml #### + +GTK_DOC_V_XML=$(GTK_DOC_V_XML_@AM_V@) +GTK_DOC_V_XML_=$(GTK_DOC_V_XML_@AM_DEFAULT_V@) +GTK_DOC_V_XML_0=@echo " DOC Building XML"; + +sgml-build.stamp: setup-build.stamp $(DOC_MODULE)-decl.txt $(SCANOBJ_FILES) $(HFILE_GLOB) $(CFILE_GLOB) $(DOC_MODULE)-sections.txt $(DOC_MODULE)-overrides.txt $(expand_content_files) xml/gtkdocentities.ent + $(GTK_DOC_V_XML)_source_dir='' ; \ + for i in $(DOC_SOURCE_DIR) ; do \ + _source_dir="$${_source_dir} --source-dir=$$i" ; \ + done ; \ + gtkdoc-mkdb --module=$(DOC_MODULE) --output-format=xml --expand-content-files="$(expand_content_files)" --main-sgml-file=$(DOC_MAIN_SGML_FILE) $${_source_dir} $(MKDB_OPTIONS) + $(AM_V_at)touch sgml-build.stamp + +sgml.stamp: sgml-build.stamp + @true + +$(DOC_MAIN_SGML_FILE): sgml-build.stamp + @true + +xml/gtkdocentities.ent: Makefile + $(GTK_DOC_V_XML)$(MKDIR_P) $(@D) && ( \ + echo ""; \ + echo ""; \ + echo ""; \ + echo ""; \ + echo ""; \ + echo ""; \ + echo ""; \ + ) > $@ + +#### html #### + +GTK_DOC_V_HTML=$(GTK_DOC_V_HTML_@AM_V@) +GTK_DOC_V_HTML_=$(GTK_DOC_V_HTML_@AM_DEFAULT_V@) +GTK_DOC_V_HTML_0=@echo " DOC Building HTML"; + +GTK_DOC_V_XREF=$(GTK_DOC_V_XREF_@AM_V@) +GTK_DOC_V_XREF_=$(GTK_DOC_V_XREF_@AM_DEFAULT_V@) +GTK_DOC_V_XREF_0=@echo " DOC Fixing cross-references"; + +html-build.stamp: sgml.stamp $(DOC_MAIN_SGML_FILE) $(content_files) $(expand_content_files) + $(GTK_DOC_V_HTML)rm -rf html && mkdir html && \ + mkhtml_options=""; \ + gtkdoc-mkhtml 2>&1 --help | grep >/dev/null "\-\-verbose"; \ + if test "$$?" = "0"; then \ + if test "x$(V)" = "x1"; then \ + mkhtml_options="$$mkhtml_options --verbose"; \ + fi; \ + fi; \ + gtkdoc-mkhtml 2>&1 --help | grep >/dev/null "\-\-path"; \ + if test "$$?" = "0"; then \ + mkhtml_options="$$mkhtml_options --path=\"$(abs_srcdir)\""; \ + fi; \ + cd html && gtkdoc-mkhtml $$mkhtml_options $(MKHTML_OPTIONS) $(DOC_MODULE) ../$(DOC_MAIN_SGML_FILE) + -@test "x$(HTML_IMAGES)" = "x" || \ + for file in $(HTML_IMAGES) ; do \ + test -f $(abs_srcdir)/$$file && cp $(abs_srcdir)/$$file $(abs_builddir)/html; \ + test -f $(abs_builddir)/$$file && cp $(abs_builddir)/$$file $(abs_builddir)/html; \ + test -f $$file && cp $$file $(abs_builddir)/html; \ + done; + $(GTK_DOC_V_XREF)gtkdoc-fixxref --module=$(DOC_MODULE) --module-dir=html --html-dir=$(HTML_DIR) $(FIXXREF_OPTIONS) + $(AM_V_at)touch html-build.stamp + +#### pdf #### + +GTK_DOC_V_PDF=$(GTK_DOC_V_PDF_@AM_V@) +GTK_DOC_V_PDF_=$(GTK_DOC_V_PDF_@AM_DEFAULT_V@) +GTK_DOC_V_PDF_0=@echo " DOC Building PDF"; + +pdf-build.stamp: sgml.stamp $(DOC_MAIN_SGML_FILE) $(content_files) $(expand_content_files) + $(GTK_DOC_V_PDF)rm -f $(DOC_MODULE).pdf && \ + mkpdf_options=""; \ + gtkdoc-mkpdf 2>&1 --help | grep >/dev/null "\-\-verbose"; \ + if test "$$?" = "0"; then \ + if test "x$(V)" = "x1"; then \ + mkpdf_options="$$mkpdf_options --verbose"; \ + fi; \ + fi; \ + if test "x$(HTML_IMAGES)" != "x"; then \ + for img in $(HTML_IMAGES); do \ + part=`dirname $$img`; \ + echo $$mkpdf_options | grep >/dev/null "\-\-imgdir=$$part "; \ + if test $$? != 0; then \ + mkpdf_options="$$mkpdf_options --imgdir=$$part"; \ + fi; \ + done; \ + fi; \ + gtkdoc-mkpdf --path="$(abs_srcdir)" $$mkpdf_options $(DOC_MODULE) $(DOC_MAIN_SGML_FILE) $(MKPDF_OPTIONS) + $(AM_V_at)touch pdf-build.stamp + +############## + +clean-local: + @rm -f *~ *.bak + @rm -rf .libs + @if echo $(SCAN_OPTIONS) | grep -q "\-\-rebuild-types" ; then \ + rm -f $(DOC_MODULE).types; \ + fi + @if echo $(SCAN_OPTIONS) | grep -q "\-\-rebuild-sections" ; then \ + rm -f $(DOC_MODULE)-sections.txt; \ + fi + +distclean-local: + @rm -rf xml html $(REPORT_FILES) $(DOC_MODULE).pdf \ + $(DOC_MODULE)-decl-list.txt $(DOC_MODULE)-decl.txt + @if test "$(abs_srcdir)" != "$(abs_builddir)" ; then \ + rm -f $(SETUP_FILES) $(DOC_MODULE).types; \ + fi + +maintainer-clean-local: + @rm -rf xml html + +install-data-local: + @installfiles=`echo $(builddir)/html/*`; \ + if test "$$installfiles" = '$(builddir)/html/*'; \ + then echo 1>&2 'Nothing to install' ; \ + else \ + if test -n "$(DOC_MODULE_VERSION)"; then \ + installdir="$(DESTDIR)$(TARGET_DIR)-$(DOC_MODULE_VERSION)"; \ + else \ + installdir="$(DESTDIR)$(TARGET_DIR)"; \ + fi; \ + $(mkinstalldirs) $${installdir} ; \ + for i in $$installfiles; do \ + echo ' $(INSTALL_DATA) '$$i ; \ + $(INSTALL_DATA) $$i $${installdir}; \ + done; \ + if test -n "$(DOC_MODULE_VERSION)"; then \ + mv -f $${installdir}/$(DOC_MODULE).devhelp2 \ + $${installdir}/$(DOC_MODULE)-$(DOC_MODULE_VERSION).devhelp2; \ + fi; \ + $(GTKDOC_REBASE) --relative --dest-dir=$(DESTDIR) --html-dir=$${installdir}; \ + fi + +uninstall-local: + @if test -n "$(DOC_MODULE_VERSION)"; then \ + installdir="$(DESTDIR)$(TARGET_DIR)-$(DOC_MODULE_VERSION)"; \ + else \ + installdir="$(DESTDIR)$(TARGET_DIR)"; \ + fi; \ + rm -rf $${installdir} + +# +# Require gtk-doc when making dist +# +if HAVE_GTK_DOC +dist-check-gtkdoc: docs +else +dist-check-gtkdoc: + @echo "*** gtk-doc is needed to run 'make dist'. ***" + @echo "*** gtk-doc was not found when 'configure' ran. ***" + @echo "*** please install gtk-doc and rerun 'configure'. ***" + @false +endif + +dist-hook: dist-check-gtkdoc all-gtk-doc dist-hook-local + @mkdir $(distdir)/html + @cp ./html/* $(distdir)/html + @-cp ./$(DOC_MODULE).pdf $(distdir)/ + @-cp ./$(DOC_MODULE).types $(distdir)/ + @-cp ./$(DOC_MODULE)-sections.txt $(distdir)/ + @cd $(distdir) && rm -f $(DISTCLEANFILES) + @$(GTKDOC_REBASE) --online --relative --html-dir=$(distdir)/html + +.PHONY : dist-hook-local docs diff --git a/install-sh b/install-sh new file mode 100755 index 0000000..59990a1 --- /dev/null +++ b/install-sh @@ -0,0 +1,508 @@ +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2014-09-12.12; # UTC + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# 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 AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# 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. + +tab=' ' +nl=' +' +IFS=" $tab$nl" + +# Set DOITPROG to "echo" to test this script. + +doit=${DOITPROG-} +doit_exec=${doit:-exec} + +# Put in absolute file names if you don't have them in your path; +# or use environment vars. + +chgrpprog=${CHGRPPROG-chgrp} +chmodprog=${CHMODPROG-chmod} +chownprog=${CHOWNPROG-chown} +cmpprog=${CMPPROG-cmp} +cpprog=${CPPROG-cp} +mkdirprog=${MKDIRPROG-mkdir} +mvprog=${MVPROG-mv} +rmprog=${RMPROG-rm} +stripprog=${STRIPPROG-strip} + +posix_mkdir= + +# Desired mode of installed file. +mode=0755 + +chgrpcmd= +chmodcmd=$chmodprog +chowncmd= +mvcmd=$mvprog +rmcmd="$rmprog -f" +stripcmd= + +src= +dst= +dir_arg= +dst_arg= + +copy_on_change=false +is_target_a_directory=possibly + +usage="\ +Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... + +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. + +Options: + --help display this help and exit. + --version display version info and exit. + + -c (ignored) + -C install only if different (preserve the last data modification time) + -d create directories instead of installing files. + -g GROUP $chgrpprog installed files to GROUP. + -m MODE $chmodprog installed files to MODE. + -o USER $chownprog installed files to USER. + -s $stripprog installed files. + -t DIRECTORY install into DIRECTORY. + -T report an error if DSTFILE is a directory. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG + RMPROG STRIPPROG +" + +while test $# -ne 0; do + case $1 in + -c) ;; + + -C) copy_on_change=true;; + + -d) dir_arg=true;; + + -g) chgrpcmd="$chgrpprog $2" + shift;; + + --help) echo "$usage"; exit $?;; + + -m) mode=$2 + case $mode in + *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*) + echo "$0: invalid mode: $mode" >&2 + exit 1;; + esac + shift;; + + -o) chowncmd="$chownprog $2" + shift;; + + -s) stripcmd=$stripprog;; + + -t) + is_target_a_directory=always + dst_arg=$2 + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + shift;; + + -T) is_target_a_directory=never;; + + --version) echo "$0 $scriptversion"; exit $?;; + + --) shift + break;; + + -*) echo "$0: invalid option: $1" >&2 + exit 1;; + + *) break;; + esac + shift +done + +# We allow the use of options -d and -T together, by making -d +# take the precedence; this is for compatibility with GNU install. + +if test -n "$dir_arg"; then + if test -n "$dst_arg"; then + echo "$0: target directory not allowed when installing a directory." >&2 + exit 1 + fi +fi + +if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then + # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dst_arg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dst_arg" + shift # fnord + fi + shift # arg + dst_arg=$arg + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + done +fi + +if test $# -eq 0; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call 'install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +if test -z "$dir_arg"; then + if test $# -gt 1 || test "$is_target_a_directory" = always; then + if test ! -d "$dst_arg"; then + echo "$0: $dst_arg: Is not a directory." >&2 + exit 1 + fi + fi +fi + +if test -z "$dir_arg"; then + do_exit='(exit $ret); exit $ret' + trap "ret=129; $do_exit" 1 + trap "ret=130; $do_exit" 2 + trap "ret=141; $do_exit" 13 + trap "ret=143; $do_exit" 15 + + # Set umask so as not to create temps with too-generous modes. + # However, 'strip' requires both read and write access to temps. + case $mode in + # Optimize common cases. + *644) cp_umask=133;; + *755) cp_umask=22;; + + *[0-7]) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw='% 200' + fi + cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; + *) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw=,u+rw + fi + cp_umask=$mode$u_plus_rw;; + esac +fi + +for src +do + # Protect names problematic for 'test' and other utilities. + case $src in + -* | [=\(\)!]) src=./$src;; + esac + + if test -n "$dir_arg"; then + dst=$src + dstdir=$dst + test -d "$dstdir" + dstdir_status=$? + else + + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dst_arg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + dst=$dst_arg + + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + if test "$is_target_a_directory" = never; then + echo "$0: $dst_arg: Is a directory" >&2 + exit 1 + fi + dstdir=$dst + dst=$dstdir/`basename "$src"` + dstdir_status=0 + else + dstdir=`dirname "$dst"` + test -d "$dstdir" + dstdir_status=$? + fi + fi + + obsolete_mkdir_used=false + + if test $dstdir_status != 0; then + case $posix_mkdir in + '') + # Create intermediate dirs using mode 755 as modified by the umask. + # This is like FreeBSD 'install' as of 1997-10-28. + umask=`umask` + case $stripcmd.$umask in + # Optimize common cases. + *[2367][2367]) mkdir_umask=$umask;; + .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; + + *[0-7]) + mkdir_umask=`expr $umask + 22 \ + - $umask % 100 % 40 + $umask % 20 \ + - $umask % 10 % 4 + $umask % 2 + `;; + *) mkdir_umask=$umask,go-w;; + esac + + # With -d, create the new directory with the user-specified mode. + # Otherwise, rely on $mkdir_umask. + if test -n "$dir_arg"; then + mkdir_mode=-m$mode + else + mkdir_mode= + fi + + posix_mkdir=false + case $umask in + *[123567][0-7][0-7]) + # POSIX mkdir -p sets u+wx bits regardless of umask, which + # is incompatible with FreeBSD 'install' when (umask & 300) != 0. + ;; + *) + # $RANDOM is not portable (e.g. dash); use it when possible to + # lower collision chance + tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ + trap 'ret=$?; rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null; exit $ret' 0 + + # As "mkdir -p" follows symlinks and we work in /tmp possibly; so + # create the $tmpdir first (and fail if unsuccessful) to make sure + # that nobody tries to guess the $tmpdir name. + if (umask $mkdir_umask && + $mkdirprog $mkdir_mode "$tmpdir" && + exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1 + then + if test -z "$dir_arg" || { + # Check for POSIX incompatibilities with -m. + # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or + # other-writable bit of parent directory when it shouldn't. + # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. + test_tmpdir="$tmpdir/a" + ls_ld_tmpdir=`ls -ld "$test_tmpdir"` + case $ls_ld_tmpdir in + d????-?r-*) different_mode=700;; + d????-?--*) different_mode=755;; + *) false;; + esac && + $mkdirprog -m$different_mode -p -- "$test_tmpdir" && { + ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"` + test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" + } + } + then posix_mkdir=: + fi + rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" + else + # Remove any dirs left behind by ancient mkdir implementations. + rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null + fi + trap '' 0;; + esac;; + esac + + if + $posix_mkdir && ( + umask $mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" + ) + then : + else + + # The umask is ridiculous, or mkdir does not conform to POSIX, + # or it failed possibly due to a race condition. Create the + # directory the slow way, step by step, checking for races as we go. + + case $dstdir in + /*) prefix='/';; + [-=\(\)!]*) prefix='./';; + *) prefix='';; + esac + + oIFS=$IFS + IFS=/ + set -f + set fnord $dstdir + shift + set +f + IFS=$oIFS + + prefixes= + + for d + do + test X"$d" = X && continue + + prefix=$prefix$d + if test -d "$prefix"; then + prefixes= + else + if $posix_mkdir; then + (umask=$mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break + # Don't fail if two instances are running concurrently. + test -d "$prefix" || exit 1 + else + case $prefix in + *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; + *) qprefix=$prefix;; + esac + prefixes="$prefixes '$qprefix'" + fi + fi + prefix=$prefix/ + done + + if test -n "$prefixes"; then + # Don't fail if two instances are running concurrently. + (umask $mkdir_umask && + eval "\$doit_exec \$mkdirprog $prefixes") || + test -d "$dstdir" || exit 1 + obsolete_mkdir_used=true + fi + fi + fi + + if test -n "$dir_arg"; then + { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && + { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || + test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 + else + + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + + # Copy the file name to the temp name. + (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && + + # 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 $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && + { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && + { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && + + # If -C, don't bother to copy if it wouldn't change the file. + if $copy_on_change && + old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && + new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && + set -f && + set X $old && old=:$2:$4:$5:$6 && + set X $new && new=:$2:$4:$5:$6 && + set +f && + test "$old" = "$new" && + $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 + then + rm -f "$dsttmp" + else + # Rename the file to the real destination. + $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || + + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + { + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + test ! -f "$dst" || + $doit $rmcmd -f "$dst" 2>/dev/null || + { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && + { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } + } || + { echo "$0: cannot unlink or rename $dst" >&2 + (exit 1); exit 1 + } + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dst" + } + fi || exit 1 + + trap '' 0 + fi +done + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/libsoup-2.4.pc.in b/libsoup-2.4.pc.in new file mode 100644 index 0000000..1394939 --- /dev/null +++ b/libsoup-2.4.pc.in @@ -0,0 +1,12 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: libsoup +Description: a glib-based HTTP library +Version: @VERSION@ +Requires: glib-2.0 gobject-2.0 gio-2.0 +Requires.private: libxml-2.0 +Libs: -L${libdir} -lsoup-2.4 +Cflags: -I${includedir}/libsoup-2.4 diff --git a/libsoup-gnome-2.4.pc.in b/libsoup-gnome-2.4.pc.in new file mode 100644 index 0000000..7238df2 --- /dev/null +++ b/libsoup-gnome-2.4.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: libsoup +Description: a glib-based HTTP library +Version: @VERSION@ +Requires: libsoup-2.4 +Libs: -L${libdir} -lsoup-gnome-2.4 +Cflags: -I${includedir}/libsoup-gnome-2.4 diff --git a/libsoup-zip.in b/libsoup-zip.in new file mode 100755 index 0000000..fc44fe5 --- /dev/null +++ b/libsoup-zip.in @@ -0,0 +1,24 @@ +#!/bin/sh + +# Build zipfiles for libsoup on Win32. Separate runtime and developer +# ones. After running make install, run this. + +ZIP=/tmp/libsoup-@VERSION@.zip +DEVZIP=/tmp/libsoup-dev-@VERSION@.zip + +cd @prefix@ +rm $ZIP + +current_minus_age=`expr @SOUP_CURRENT@ - @SOUP_AGE@` + +zip $ZIP -@ <\n\#define GLIB_MKENUMS_EXTERN _SOUP_EXTERN\n" + +# +# Introspection support +# +include $(INTROSPECTION_MAKEFILE) +INTROSPECTION_GIRS = +INTROSPECTION_SCANNER_ARGS = --add-include-path=. +INTROSPECTION_COMPILER_ARGS = --includedir=. + +if HAVE_INTROSPECTION + +SOUP_UNSTABLE_REQUEST_CFLAG = -DLIBSOUP_USE_UNSTABLE_REQUEST_API + +# Core library +gi_soup_files = \ + $(filter-out soup.h soup-enum-types.% soup-proxy-resolver.h,\ + $(soup_headers) $(filter-out %.h, $(libsoup_2_4_la_SOURCES))) +gi_built_soup_files = soup-enum-types.h soup-version.h + +Soup-2.4.gir: libsoup-2.4.la +Soup_2_4_gir_INCLUDES = Gio-2.0 +Soup_2_4_gir_CFLAGS = $(AM_CPPFLAGS) $(SOUP_UNSTABLE_REQUEST_CFLAG) +Soup_2_4_gir_LIBS = libsoup-2.4.la +Soup_2_4_gir_EXPORT_PACKAGES = libsoup-2.4 +Soup_2_4_gir_SCANNERFLAGS = --c-include "libsoup/soup.h" +Soup_2_4_gir_FILES = \ + $(addprefix $(srcdir)/, $(gi_soup_files)) \ + $(foreach f,$(gi_built_soup_files), \ + $(if $(shell test -f $(addprefix $(srcdir)/,$(f)) && echo yes), \ + $(addprefix $(srcdir)/,$(f)), \ + $(f))) + +INTROSPECTION_GIRS += Soup-2.4.gir + +if ENABLE_VAPIGEN +libsoup-2.4.vapi: Soup-2.4.gir Soup-2.4.metadata Soup-2.4-custom.vala + $(VAPIGEN) --metadatadir=$(top_srcdir)/libsoup --pkg gio-2.0 --library=libsoup-2.4 $^ + +vapidir=$(VAPIDIR) +vapi_DATA=libsoup-2.4.vapi libsoup-2.4.deps +CLEANFILES += libsoup-2.4.vapi +endif + +EXTRA_DIST += Soup-2.4.metadata Soup-2.4-custom.vala libsoup-2.4.deps + +if BUILD_LIBSOUP_GNOME + +SOUPGNOME_GIR_SCANNER_BASE_FLAGS = \ + --identifier-prefix=Soup \ + --symbol-prefix=soup + +# GNOME extensions +gi_soup_gnome_files = $(filter-out soup-gnome.h,\ + $(libsoupgnomeinclude_HEADERS) \ + $(filter-out %.h, $(libsoup_gnome_2_4_la_SOURCES))) +SoupGNOME-2.4.gir: libsoup-gnome-2.4.la Soup-2.4.gir +SoupGNOME_2_4_gir_SCANNERFLAGS = \ + $(SOUPGNOME_GIR_SCANNER_BASE_FLAGS) \ + --c-include "libsoup/soup-gnome.h" \ + --include-uninstalled=$(builddir)/Soup-2.4.gir +SoupGNOME_2_4_gir_CFLAGS = $(AM_CPPFLAGS) +SoupGNOME_2_4_gir_LIBS = libsoup-gnome-2.4.la libsoup-2.4.la +SoupGNOME_2_4_gir_FILES = $(addprefix $(srcdir)/,$(gi_soup_gnome_files)) +SoupGNOME_2_4_gir_EXPORT_PACKAGES = libsoup-gnome-2.4 + +INTROSPECTION_GIRS += SoupGNOME-2.4.gir + +endif + +girdir = $(datadir)/gir-1.0 +gir_DATA = $(INTROSPECTION_GIRS) + +typelibdir = $(libdir)/girepository-1.0 +typelib_DATA = $(INTROSPECTION_GIRS:.gir=.typelib) + +CLEANFILES+= $(gir_DATA) $(typelib_DATA) $(BUILT_SOURCES) + +endif + +# ------ MSVC Project File Generation ------ +MSVCPROJS = soup soup-gnome + +soup_FILES = $(libsoup_2_4_la_SOURCES) +soup_EXCLUDES = dummy + +soup_HEADERS_DIR = $(libsoupincludedir) +soup_HEADERS_INST = $(libsoupinclude_HEADERS) $(nodist_libsoupinclude_HEADERS) +soup_HEADERS_EXCLUDES = dummy + +soup_gnome_FILES = $(libsoup_gnome_2_4_la_SOURCES) +soup_gnome_EXCLUDES = dummy + +soup_gnome_HEADERS_DIR = $(libsoupgnomeincludedir) +soup_gnome_HEADERS_INST = $(libsoupgnomeinclude_HEADERS) +soup_gnome_HEADERS_EXCLUDES = dummy + +include $(top_srcdir)/win32/Makefile.msvcproj + +if HAVE_INTROSPECTION +# Introspection Items for MSVC +MSVC_INTROSPECT_GIRS = Soup-2.4.gir +if BUILD_LIBSOUP_GNOME +MSVC_INTROSPECT_GIRS += SoupGNOME-2.4.gir +endif + +BASE_MSVC_GIR_CFLAGS = \ + $(SOUP_COMMON_CPPFLAGS) \ + -I.. + +INTROSPECTION_INTERMEDIATE_ITEMS = \ + $(top_builddir)/win32/Soup-2.4.gir.msvc.introspect \ + $(top_builddir)/win32/Soup_2_4_gir_list \ + $(top_builddir)/win32/SoupGNOME-2.4.gir.msvc.introspect \ + $(top_builddir)/win32/SoupGNOME_2_4_gir_list + +# libsoup +Soup_2_4_gir_MSVC_FILES = $(gi_soup_files) $(gi_built_soup_files) +Soup_2_4_gir_MSVC_EXPORT_PACKAGES = $(Soup_2_4_gir_EXPORT_PACKAGES) +Soup_2_4_gir_MSVC_INCLUDE_GIRS = $(Soup_2_4_gir_INCLUDES) +Soup_2_4_gir_MSVC_LIBS = soup-2.4 +Soup_2_4_gir_MSVC_CFLAGS = $(BASE_MSVC_GIR_CFLAGS) $(SOUP_UNSTABLE_REQUEST_CFLAG) +Soup_2_4_gir_MSVC_SCANNERFLAGS = --c-include \"libsoup/soup.h\" + +if BUILD_LIBSOUP_GNOME +# libsoup-gnome +SoupGNOME_2_4_gir_MSVC_FILES = $(gi_soup_gnome_files) +SoupGNOME_2_4_gir_MSVC_GIR_DEPS = Soup-2.4.gir +SoupGNOME_2_4_gir_MSVC_EXPORT_PACKAGES = $(SoupGNOME_2_4_gir_EXPORT_PACKAGES) +SoupGNOME_2_4_gir_MSVC_LIBS = soup-gnome-2.4 soup-2.4 +SoupGNOME_2_4_gir_MSVC_CFLAGS = $(BASE_MSVC_GIR_CFLAGS) +SoupGNOME_2_4_gir_MSVC_SCANNERFLAGS = i \ + $(SOUPGNOME_GIR_SCANNER_BASE_FLAGS) \ + --c-include \"libsoup/soup-gnome.h\" \ + --include-uninstalled=./Soup-2.4.gir +endif + +include $(top_srcdir)/win32/Makefile.msvc-introspection +else +INTROSPECTION_INTERMEDIATE_ITEMS = +endif + +dist-hook: \ + $(top_builddir)/win32/vs9/soup.vcproj \ + $(top_builddir)/win32/vs9/soup.headers \ + $(top_builddir)/win32/vs9/soup-gnome.vcproj \ + $(top_builddir)/win32/vs9/soup-gnome.headers \ + $(INTROSPECTION_INTERMEDIATE_ITEMS) diff --git a/libsoup/Makefile.in b/libsoup/Makefile.in new file mode 100644 index 0000000..e8e0f23 --- /dev/null +++ b/libsoup/Makefile.in @@ -0,0 +1,2238 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Author: Fan, Chun-wei +# Common Autotools file used to generate Visual Studio 2008+ +# Projects from their templates + +# This autotools file, from GLib, can be used in other projects +# that have Visual Studio build support. + +# * Input variables: +# +# MSVCPROJS - List of Projects that should be generated +# +# * Simple tutorial +# +# Add this to Makefile.am where your library/program is built: +# include +# MSVCPROJS = YourProject (can be multiple projects in a single srcdir) +# YourProject_FILES = $(libyourlib_1_0_SOURCES) +# YourProject_EXCLUDES = ... # list of sources to exclude, separated by '|', wildcards allowed; use random unsed value if none +# (the following 3 lines if headers need to be installed) +# YourProject_HEADERS_DIR = $(libyourlibincludedir) +# YourProject_HEADERS_INST = $(libyourlib_1_0_HEADERS) +# YourProject_HEADERS_EXCLUDES = ... # +# +# dist-hook: \ # (or add to it if it is already there, note the vs9 items will also call the vs10 items in the process) +# $(top_builddir)/win32/vs9/YourProject.vcproj \ +# $(top_builddir)/win32/vs9/YourProject.headers # if headers need to be installed +# +# --or, if Visual Studio 2013 or later is required-- +# dist-hook: \ # (or add to it if it is already there, this does -not- call other vs items in the process) +# $(top_builddir)/win32/vs12/YourProject.vcxproj \ +# $(top_builddir)/win32/vs12/YourProject.vs12.headers # if headers need to be installed + +# Private functions + +# Author: Fan, Chun-wei +# Common autotools file for constructing the g-ir-scanner and +# g-ir-compiler command lines for Visual Studio builds. + +# This is copied from $(srcroot)/win32 from the gobject-introspection +# project, which may be included in projects that support both +# Visual Studio builds and introspection. + +# * Input variables: +# +# MSVC_INTROSPECT_GIRS - List of .gir's that should be built +# in the NMake Makefiles +# +# * Simple tutorial +# +# Add this to Makefile.am where your library/program is built: +# (Either YourLib_1_0_gir_MSVC_LIBS or YourLib_1_0_gir_MSVC_PROGRAM +# is required unless --headers-only is specified in +# YourLib_1_0_gir__MSVC_SCANNERFLAGS) +# +# include +# MSVC_INTROSPECT_GIRS = YourLib-1.0.gir +# YourLib_1_0_gir_NAMESPACE = YourLib # This is optional +# YourLib_1_0_gir_VERSION = 1.0 # This is optional +# YourLib_1_0_gir_MSVC_LIBS = yourlib-1.0 +# YourLib_1_0_gir_MSVC_FILES = $(libyourlib_1_0_SOURCES) +# YourLib_1_0_gir_MSVC_PROGRAM = YourProgram +# YourLib_1_0_gir_MSVC_PACKAGES = (Dependent .pc files) +# YourLib_1_0_gir_MSVC_INCLUDE_GIRS = (Dependent external .gir's) +# YourLib_1_0_gir_MSVC_EXPORT_PACKAGES = (Packages exported by this .gir) +# YourLib_1_0_gir_MSVC_C_INCLUDES = (List of public C headers which need to be included by +# consumers at compile time to make use of the API) + +# Private functions + + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +@BUILD_LIBSOUP_GNOME_TRUE@am__append_1 = libsoup-gnome-2.4.la +@HAVE_INTROSPECTION_TRUE@am__append_2 = Soup-2.4.gir +@ENABLE_VAPIGEN_TRUE@@HAVE_INTROSPECTION_TRUE@am__append_3 = libsoup-2.4.vapi +@HAVE_INTROSPECTION_TRUE@am__append_4 = Soup-2.4.metadata Soup-2.4-custom.vala libsoup-2.4.deps +@BUILD_LIBSOUP_GNOME_TRUE@@HAVE_INTROSPECTION_TRUE@am__append_5 = SoupGNOME-2.4.gir +@HAVE_INTROSPECTION_TRUE@am__append_6 = $(gir_DATA) $(typelib_DATA) $(BUILT_SOURCES) +@BUILD_LIBSOUP_GNOME_TRUE@@HAVE_INTROSPECTION_TRUE@am__append_7 = SoupGNOME-2.4.gir +subdir = libsoup +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_code_coverage.m4 \ + $(top_srcdir)/m4/glibtests.m4 $(top_srcdir)/m4/gtk-doc.m4 \ + $(top_srcdir)/m4/intltool.m4 $(top_srcdir)/m4/introspection.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/vapigen.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am \ + $(am__libsoupgnomeinclude_HEADERS_DIST) \ + $(libsoupinclude_HEADERS) $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = soup-version.h +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(girdir)" \ + "$(DESTDIR)$(typelibdir)" "$(DESTDIR)$(vapidir)" \ + "$(DESTDIR)$(libsoupgnomeincludedir)" \ + "$(DESTDIR)$(libsoupincludedir)" \ + "$(DESTDIR)$(libsoupincludedir)" +LTLIBRARIES = $(lib_LTLIBRARIES) +am__DEPENDENCIES_1 = +libsoup_2_4_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +am_libsoup_2_4_la_OBJECTS = libsoup_2_4_la-soup-address.lo \ + libsoup_2_4_la-soup-auth.lo libsoup_2_4_la-soup-auth-basic.lo \ + libsoup_2_4_la-soup-auth-digest.lo \ + libsoup_2_4_la-soup-auth-ntlm.lo \ + libsoup_2_4_la-soup-auth-negotiate.lo \ + libsoup_2_4_la-soup-auth-domain.lo \ + libsoup_2_4_la-soup-auth-domain-basic.lo \ + libsoup_2_4_la-soup-auth-domain-digest.lo \ + libsoup_2_4_la-soup-auth-manager.lo \ + libsoup_2_4_la-soup-body-input-stream.lo \ + libsoup_2_4_la-soup-body-output-stream.lo \ + libsoup_2_4_la-soup-cache.lo \ + libsoup_2_4_la-soup-cache-client-input-stream.lo \ + libsoup_2_4_la-soup-cache-input-stream.lo \ + libsoup_2_4_la-soup-client-input-stream.lo \ + libsoup_2_4_la-soup-connection.lo \ + libsoup_2_4_la-soup-connection-auth.lo \ + libsoup_2_4_la-soup-content-decoder.lo \ + libsoup_2_4_la-soup-content-processor.lo \ + libsoup_2_4_la-soup-content-sniffer.lo \ + libsoup_2_4_la-soup-content-sniffer-stream.lo \ + libsoup_2_4_la-soup-converter-wrapper.lo \ + libsoup_2_4_la-soup-cookie.lo \ + libsoup_2_4_la-soup-cookie-jar.lo \ + libsoup_2_4_la-soup-cookie-jar-db.lo \ + libsoup_2_4_la-soup-cookie-jar-text.lo \ + libsoup_2_4_la-soup-date.lo \ + libsoup_2_4_la-soup-directory-input-stream.lo \ + libsoup_2_4_la-soup-enum-types.lo \ + libsoup_2_4_la-soup-filter-input-stream.lo \ + libsoup_2_4_la-soup-form.lo libsoup_2_4_la-soup-headers.lo \ + libsoup_2_4_la-soup-init.lo libsoup_2_4_la-soup-io-stream.lo \ + libsoup_2_4_la-soup-logger.lo libsoup_2_4_la-soup-message.lo \ + libsoup_2_4_la-soup-message-body.lo \ + libsoup_2_4_la-soup-message-client-io.lo \ + libsoup_2_4_la-soup-message-headers.lo \ + libsoup_2_4_la-soup-message-io.lo \ + libsoup_2_4_la-soup-message-queue.lo \ + libsoup_2_4_la-soup-message-server-io.lo \ + libsoup_2_4_la-soup-method.lo libsoup_2_4_la-soup-misc.lo \ + libsoup_2_4_la-soup-multipart.lo \ + libsoup_2_4_la-soup-multipart-input-stream.lo \ + libsoup_2_4_la-soup-password-manager.lo \ + libsoup_2_4_la-soup-path-map.lo \ + libsoup_2_4_la-soup-proxy-resolver.lo \ + libsoup_2_4_la-soup-proxy-resolver-default.lo \ + libsoup_2_4_la-soup-proxy-resolver-wrapper.lo \ + libsoup_2_4_la-soup-proxy-uri-resolver.lo \ + libsoup_2_4_la-soup-request.lo \ + libsoup_2_4_la-soup-request-data.lo \ + libsoup_2_4_la-soup-request-file.lo \ + libsoup_2_4_la-soup-request-http.lo \ + libsoup_2_4_la-soup-requester.lo libsoup_2_4_la-soup-server.lo \ + libsoup_2_4_la-soup-session.lo \ + libsoup_2_4_la-soup-session-async.lo \ + libsoup_2_4_la-soup-session-feature.lo \ + libsoup_2_4_la-soup-session-sync.lo \ + libsoup_2_4_la-soup-socket.lo \ + libsoup_2_4_la-soup-socket-properties.lo \ + libsoup_2_4_la-soup-status.lo libsoup_2_4_la-soup-tld.lo \ + libsoup_2_4_la-soup-uri.lo libsoup_2_4_la-soup-value-utils.lo \ + libsoup_2_4_la-soup-version.lo \ + libsoup_2_4_la-soup-websocket.lo \ + libsoup_2_4_la-soup-websocket-connection.lo \ + libsoup_2_4_la-soup-xmlrpc.lo \ + libsoup_2_4_la-soup-xmlrpc-old.lo +libsoup_2_4_la_OBJECTS = $(am_libsoup_2_4_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libsoup_2_4_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(libsoup_2_4_la_CFLAGS) $(CFLAGS) $(libsoup_2_4_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +@BUILD_LIBSOUP_GNOME_TRUE@libsoup_gnome_2_4_la_DEPENDENCIES = \ +@BUILD_LIBSOUP_GNOME_TRUE@ libsoup-2.4.la $(am__DEPENDENCIES_1) +am__libsoup_gnome_2_4_la_SOURCES_DIST = soup-cookie-jar-sqlite.c \ + soup-gnome-features.c soup-proxy-resolver-gnome.h \ + soup-proxy-resolver-gnome.c soup-password-manager-gnome.h \ + soup-password-manager-gnome.c +@BUILD_LIBSOUP_GNOME_TRUE@am_libsoup_gnome_2_4_la_OBJECTS = libsoup_gnome_2_4_la-soup-cookie-jar-sqlite.lo \ +@BUILD_LIBSOUP_GNOME_TRUE@ libsoup_gnome_2_4_la-soup-gnome-features.lo \ +@BUILD_LIBSOUP_GNOME_TRUE@ libsoup_gnome_2_4_la-soup-proxy-resolver-gnome.lo \ +@BUILD_LIBSOUP_GNOME_TRUE@ libsoup_gnome_2_4_la-soup-password-manager-gnome.lo +libsoup_gnome_2_4_la_OBJECTS = $(am_libsoup_gnome_2_4_la_OBJECTS) +libsoup_gnome_2_4_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(libsoup_gnome_2_4_la_CFLAGS) $(CFLAGS) \ + $(libsoup_gnome_2_4_la_LDFLAGS) $(LDFLAGS) -o $@ +@BUILD_LIBSOUP_GNOME_TRUE@am_libsoup_gnome_2_4_la_rpath = -rpath \ +@BUILD_LIBSOUP_GNOME_TRUE@ $(libdir) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libsoup_2_4_la_SOURCES) $(libsoup_gnome_2_4_la_SOURCES) +DIST_SOURCES = $(libsoup_2_4_la_SOURCES) \ + $(am__libsoup_gnome_2_4_la_SOURCES_DIST) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +DATA = $(gir_DATA) $(typelib_DATA) $(vapi_DATA) +am__libsoupgnomeinclude_HEADERS_DIST = soup-cookie-jar-sqlite.h \ + soup-gnome.h soup-gnome-features.h +HEADERS = $(libsoupgnomeinclude_HEADERS) $(libsoupinclude_HEADERS) \ + $(nodist_libsoupinclude_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/soup-version.h.in \ + $(top_srcdir)/build-aux/depcomp \ + $(top_srcdir)/win32/Makefile.msvc-introspection \ + $(top_srcdir)/win32/Makefile.msvcproj +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALL_LINGUAS = @ALL_LINGUAS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +APACHE_HTTPD = @APACHE_HTTPD@ +APACHE_MODULE_DIR = @APACHE_MODULE_DIR@ +APACHE_PHP_MODULE_DIR = @APACHE_PHP_MODULE_DIR@ +APACHE_SSL_MODULE_DIR = @APACHE_SSL_MODULE_DIR@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CODE_COVERAGE_CFLAGS = @CODE_COVERAGE_CFLAGS@ +CODE_COVERAGE_CPPFLAGS = @CODE_COVERAGE_CPPFLAGS@ +CODE_COVERAGE_CXXFLAGS = @CODE_COVERAGE_CXXFLAGS@ +CODE_COVERAGE_ENABLED = @CODE_COVERAGE_ENABLED@ +CODE_COVERAGE_LDFLAGS = @CODE_COVERAGE_LDFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CURL = @CURL@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GCOV = @GCOV@ +GENHTML = @GENHTML@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_COMPILE_RESOURCES = @GLIB_COMPILE_RESOURCES@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MAKEFILE = @GLIB_MAKEFILE@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GMSGFMT = @GMSGFMT@ +GOBJECT_QUERY = @GOBJECT_QUERY@ +GREP = @GREP@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +HAVE_GNOME = @HAVE_GNOME@ +HTML_DIR = @HTML_DIR@ +IF_HAVE_MOD_UNIXD = @IF_HAVE_MOD_UNIXD@ +IF_HAVE_PHP = @IF_HAVE_PHP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ +INTLTOOL_MERGE = @INTLTOOL_MERGE@ +INTLTOOL_PERL = @INTLTOOL_PERL@ +INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ +INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@ +INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@ +INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@ +INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LCOV = @LCOV@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PHP = @PHP@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOUP_AGE = @SOUP_AGE@ +SOUP_API_VERSION = @SOUP_API_VERSION@ +SOUP_CURRENT = @SOUP_CURRENT@ +SOUP_DEBUG_FLAGS = @SOUP_DEBUG_FLAGS@ +SOUP_HIDDEN_VISIBILITY_CFLAGS = @SOUP_HIDDEN_VISIBILITY_CFLAGS@ +SOUP_MAJOR_VERSION = @SOUP_MAJOR_VERSION@ +SOUP_MICRO_VERSION = @SOUP_MICRO_VERSION@ +SOUP_MINOR_VERSION = @SOUP_MINOR_VERSION@ +SOUP_REVISION = @SOUP_REVISION@ +SQLITE_CFLAGS = @SQLITE_CFLAGS@ +SQLITE_LIBS = @SQLITE_LIBS@ +STRIP = @STRIP@ +USE_NLS = @USE_NLS@ +VALAC = @VALAC@ +VAPIDIR = @VAPIDIR@ +VAPIGEN = @VAPIGEN@ +VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@ +VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@ +VERSION = @VERSION@ +XGETTEXT = @XGETTEXT@ +XML_CFLAGS = @XML_CFLAGS@ +XML_LIBS = @XML_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +installed_test_metadir = @installed_test_metadir@ +installed_testdir = @installed_testdir@ +intltool__v_merge_options_ = @intltool__v_merge_options_@ +intltool__v_merge_options_0 = @intltool__v_merge_options_0@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +ntlm_auth = @ntlm_auth@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ + +# TLD rules +EXTRA_DIST = tld-parser.py $(am__append_4) +CLEANFILES = $(am__append_3) $(am__append_6) +@OS_WIN32_TRUE@LIBWS2_32 = -lws2_32 +SOUP_COMMON_CPPFLAGS = \ + -DG_LOG_DOMAIN=\"libsoup\" \ + -DLIBSOUP_COMPILATION + +AM_CPPFLAGS = \ + $(SOUP_COMMON_CPPFLAGS) \ + -DLOCALEDIR=\"$(localedir)\" \ + -I$(top_srcdir) \ + -I$(top_builddir) \ + $(SOUP_DEBUG_FLAGS) \ + $(GLIB_CFLAGS) \ + $(XML_CFLAGS) \ + $(SQLITE_CFLAGS) \ + $(CODE_COVERAGE_CFLAGS) \ + $(KRB5_CFLAGS) + +libsoupincludedir = $(includedir)/libsoup-2.4/libsoup +soup_headers = \ + soup.h \ + soup-address.h \ + soup-auth.h \ + soup-auth-domain.h \ + soup-auth-domain-basic.h \ + soup-auth-domain-digest.h \ + soup-auth-manager.h \ + soup-autocleanups.h \ + soup-cache.h \ + soup-content-decoder.h \ + soup-content-sniffer.h \ + soup-cookie.h \ + soup-cookie-jar.h \ + soup-cookie-jar-db.h \ + soup-cookie-jar-text.h \ + soup-date.h \ + soup-form.h \ + soup-headers.h \ + soup-logger.h \ + soup-message.h \ + soup-message-body.h \ + soup-message-headers.h \ + soup-method.h \ + soup-misc.h \ + soup-multipart.h \ + soup-multipart-input-stream.h \ + soup-password-manager.h \ + soup-portability.h \ + soup-proxy-resolver.h \ + soup-proxy-resolver-default.h \ + soup-proxy-uri-resolver.h \ + soup-request.h \ + soup-request-data.h \ + soup-request-file.h \ + soup-request-http.h \ + soup-requester.h \ + soup-server.h \ + soup-session.h \ + soup-session-async.h \ + soup-session-feature.h \ + soup-session-sync.h \ + soup-socket.h \ + soup-status.h \ + soup-tld.h \ + soup-types.h \ + soup-uri.h \ + soup-value-utils.h \ + soup-websocket.h \ + soup-websocket-connection.h \ + soup-xmlrpc.h \ + soup-xmlrpc-old.h + +libsoupinclude_HEADERS = \ + $(soup_headers) \ + soup-enum-types.h + +nodist_libsoupinclude_HEADERS = \ + soup-version.h + +lib_LTLIBRARIES = libsoup-2.4.la $(am__append_1) +libsoup_2_4_la_CFLAGS = $(AM_CFLAGS) $(SOUP_HIDDEN_VISIBILITY_CFLAGS) +libsoup_2_4_la_LDFLAGS = \ + -version-info $(SOUP_CURRENT):$(SOUP_REVISION):$(SOUP_AGE) \ + -no-undefined \ + -export-dynamic \ + $(CODE_COVERAGE_LDFLAGS) + +libsoup_2_4_la_LIBADD = \ + $(GLIB_LIBS) \ + $(LIBWS2_32) \ + $(XML_LIBS) \ + $(SQLITE_LIBS) \ + $(KRB5_LIBS) + +libsoup_2_4_la_SOURCES = \ + gconstructor.h \ + soup-address.c \ + soup-auth.c \ + soup-auth-basic.h \ + soup-auth-basic.c \ + soup-auth-digest.h \ + soup-auth-digest.c \ + soup-auth-ntlm.h \ + soup-auth-ntlm.c \ + soup-auth-negotiate.h \ + soup-auth-negotiate.c \ + soup-auth-domain.c \ + soup-auth-domain-basic.c \ + soup-auth-domain-digest.c \ + soup-auth-manager.c \ + soup-body-input-stream.h \ + soup-body-input-stream.c \ + soup-body-output-stream.h \ + soup-body-output-stream.c \ + soup-cache.c \ + soup-cache-client-input-stream.h\ + soup-cache-client-input-stream.c\ + soup-cache-input-stream.h \ + soup-cache-input-stream.c \ + soup-cache-private.h \ + soup-client-input-stream.h \ + soup-client-input-stream.c \ + soup-connection.h \ + soup-connection.c \ + soup-connection-auth.h \ + soup-connection-auth.c \ + soup-content-decoder.c \ + soup-content-processor.h \ + soup-content-processor.c \ + soup-content-sniffer.c \ + soup-content-sniffer-stream.h \ + soup-content-sniffer-stream.c \ + soup-converter-wrapper.h \ + soup-converter-wrapper.c \ + soup-cookie.c \ + soup-cookie-jar.c \ + soup-cookie-jar-db.c \ + soup-cookie-jar-text.c \ + soup-date.c \ + soup-directory-input-stream.h \ + soup-directory-input-stream.c \ + soup-enum-types.h \ + soup-enum-types.c \ + soup-filter-input-stream.c \ + soup-filter-input-stream.h \ + soup-form.c \ + soup-headers.c \ + soup-init.c \ + soup-io-stream.h \ + soup-io-stream.c \ + soup-logger.c \ + soup-message.c \ + soup-message-body.c \ + soup-message-client-io.c \ + soup-message-headers.c \ + soup-message-io.c \ + soup-message-private.h \ + soup-message-queue.h \ + soup-message-queue.c \ + soup-message-server-io.c \ + soup-method.c \ + soup-misc.c \ + soup-misc-private.h \ + soup-multipart.c \ + soup-multipart-input-stream.c \ + soup-password-manager.c \ + soup-path-map.h \ + soup-path-map.c \ + soup-proxy-resolver.c \ + soup-proxy-resolver-default.c \ + soup-proxy-resolver-wrapper.h \ + soup-proxy-resolver-wrapper.c \ + soup-proxy-uri-resolver.c \ + soup-request.c \ + soup-request-data.c \ + soup-request-file.c \ + soup-request-http.c \ + soup-requester.c \ + soup-server.c \ + soup-session.c \ + soup-session-async.c \ + soup-session-feature.c \ + soup-session-private.h \ + soup-session-sync.c \ + soup-socket.c \ + soup-socket-private.h \ + soup-socket-properties.c \ + soup-status.c \ + soup-tld.c \ + soup-tld-private.h \ + soup-uri.c \ + soup-value-utils.c \ + soup-version.c \ + soup-websocket.c \ + soup-websocket-connection.c \ + soup-xmlrpc.c \ + soup-xmlrpc-old.c + +TLD_DATA_FILE = $(top_srcdir)/data/effective_tld_names.dat +@BUILD_LIBSOUP_GNOME_TRUE@libsoupgnomeincludedir = $(includedir)/libsoup-gnome-2.4/libsoup +@BUILD_LIBSOUP_GNOME_TRUE@libsoupgnomeinclude_HEADERS = \ +@BUILD_LIBSOUP_GNOME_TRUE@ soup-cookie-jar-sqlite.h\ +@BUILD_LIBSOUP_GNOME_TRUE@ soup-gnome.h \ +@BUILD_LIBSOUP_GNOME_TRUE@ soup-gnome-features.h + +@BUILD_LIBSOUP_GNOME_TRUE@libsoup_gnome_2_4_la_CFLAGS = $(AM_CFLAGS) $(SOUP_HIDDEN_VISIBILITY_CFLAGS) +@BUILD_LIBSOUP_GNOME_TRUE@libsoup_gnome_2_4_la_LDFLAGS = \ +@BUILD_LIBSOUP_GNOME_TRUE@ -version-info $(SOUP_CURRENT):$(SOUP_REVISION):$(SOUP_AGE) \ +@BUILD_LIBSOUP_GNOME_TRUE@ -no-undefined \ +@BUILD_LIBSOUP_GNOME_TRUE@ -export-dynamic + +@BUILD_LIBSOUP_GNOME_TRUE@libsoup_gnome_2_4_la_LIBADD = \ +@BUILD_LIBSOUP_GNOME_TRUE@ libsoup-2.4.la \ +@BUILD_LIBSOUP_GNOME_TRUE@ $(GLIB_LIBS) + +@BUILD_LIBSOUP_GNOME_TRUE@libsoup_gnome_2_4_la_SOURCES = \ +@BUILD_LIBSOUP_GNOME_TRUE@ soup-cookie-jar-sqlite.c \ +@BUILD_LIBSOUP_GNOME_TRUE@ soup-gnome-features.c \ +@BUILD_LIBSOUP_GNOME_TRUE@ soup-proxy-resolver-gnome.h \ +@BUILD_LIBSOUP_GNOME_TRUE@ soup-proxy-resolver-gnome.c \ +@BUILD_LIBSOUP_GNOME_TRUE@ soup-password-manager-gnome.h \ +@BUILD_LIBSOUP_GNOME_TRUE@ soup-password-manager-gnome.c + +GLIB_GENERATED = soup-enum-types.c soup-enum-types.h +BUILT_SOURCES = \ + $(GLIB_GENERATED) \ + tld_data.inc + +soup_enum_types_sources = $(libsoupinclude_HEADERS) $(libsoupgnomeinclude_HEADERS) +soup_enum_types_MKENUMS_C_FLAGS = --fhead "\#define LIBSOUP_USE_UNSTABLE_REQUEST_API" +soup_enum_types_MKENUMS_H_FLAGS = --fhead "\#include \n\#define GLIB_MKENUMS_EXTERN _SOUP_EXTERN\n" +INTROSPECTION_GIRS = $(am__append_2) $(am__append_5) +INTROSPECTION_SCANNER_ARGS = --add-include-path=. +INTROSPECTION_COMPILER_ARGS = --includedir=. +@HAVE_INTROSPECTION_TRUE@SOUP_UNSTABLE_REQUEST_CFLAG = -DLIBSOUP_USE_UNSTABLE_REQUEST_API + +# Core library +@HAVE_INTROSPECTION_TRUE@gi_soup_files = \ +@HAVE_INTROSPECTION_TRUE@ $(filter-out soup.h soup-enum-types.% soup-proxy-resolver.h,\ +@HAVE_INTROSPECTION_TRUE@ $(soup_headers) $(filter-out %.h, $(libsoup_2_4_la_SOURCES))) + +@HAVE_INTROSPECTION_TRUE@gi_built_soup_files = soup-enum-types.h soup-version.h +@HAVE_INTROSPECTION_TRUE@Soup_2_4_gir_INCLUDES = Gio-2.0 +@HAVE_INTROSPECTION_TRUE@Soup_2_4_gir_CFLAGS = $(AM_CPPFLAGS) $(SOUP_UNSTABLE_REQUEST_CFLAG) +@HAVE_INTROSPECTION_TRUE@Soup_2_4_gir_LIBS = libsoup-2.4.la +@HAVE_INTROSPECTION_TRUE@Soup_2_4_gir_EXPORT_PACKAGES = libsoup-2.4 +@HAVE_INTROSPECTION_TRUE@Soup_2_4_gir_SCANNERFLAGS = --c-include "libsoup/soup.h" +@HAVE_INTROSPECTION_TRUE@Soup_2_4_gir_FILES = \ +@HAVE_INTROSPECTION_TRUE@ $(addprefix $(srcdir)/, $(gi_soup_files)) \ +@HAVE_INTROSPECTION_TRUE@ $(foreach f,$(gi_built_soup_files), \ +@HAVE_INTROSPECTION_TRUE@ $(if $(shell test -f $(addprefix $(srcdir)/,$(f)) && echo yes), \ +@HAVE_INTROSPECTION_TRUE@ $(addprefix $(srcdir)/,$(f)), \ +@HAVE_INTROSPECTION_TRUE@ $(f))) + +@ENABLE_VAPIGEN_TRUE@@HAVE_INTROSPECTION_TRUE@vapidir = $(VAPIDIR) +@ENABLE_VAPIGEN_TRUE@@HAVE_INTROSPECTION_TRUE@vapi_DATA = libsoup-2.4.vapi libsoup-2.4.deps +@BUILD_LIBSOUP_GNOME_TRUE@@HAVE_INTROSPECTION_TRUE@SOUPGNOME_GIR_SCANNER_BASE_FLAGS = \ +@BUILD_LIBSOUP_GNOME_TRUE@@HAVE_INTROSPECTION_TRUE@ --identifier-prefix=Soup \ +@BUILD_LIBSOUP_GNOME_TRUE@@HAVE_INTROSPECTION_TRUE@ --symbol-prefix=soup + + +# GNOME extensions +@BUILD_LIBSOUP_GNOME_TRUE@@HAVE_INTROSPECTION_TRUE@gi_soup_gnome_files = $(filter-out soup-gnome.h,\ +@BUILD_LIBSOUP_GNOME_TRUE@@HAVE_INTROSPECTION_TRUE@ $(libsoupgnomeinclude_HEADERS) \ +@BUILD_LIBSOUP_GNOME_TRUE@@HAVE_INTROSPECTION_TRUE@ $(filter-out %.h, $(libsoup_gnome_2_4_la_SOURCES))) + +@BUILD_LIBSOUP_GNOME_TRUE@@HAVE_INTROSPECTION_TRUE@SoupGNOME_2_4_gir_SCANNERFLAGS = \ +@BUILD_LIBSOUP_GNOME_TRUE@@HAVE_INTROSPECTION_TRUE@ $(SOUPGNOME_GIR_SCANNER_BASE_FLAGS) \ +@BUILD_LIBSOUP_GNOME_TRUE@@HAVE_INTROSPECTION_TRUE@ --c-include "libsoup/soup-gnome.h" \ +@BUILD_LIBSOUP_GNOME_TRUE@@HAVE_INTROSPECTION_TRUE@ --include-uninstalled=$(builddir)/Soup-2.4.gir + +@BUILD_LIBSOUP_GNOME_TRUE@@HAVE_INTROSPECTION_TRUE@SoupGNOME_2_4_gir_CFLAGS = $(AM_CPPFLAGS) +@BUILD_LIBSOUP_GNOME_TRUE@@HAVE_INTROSPECTION_TRUE@SoupGNOME_2_4_gir_LIBS = libsoup-gnome-2.4.la libsoup-2.4.la +@BUILD_LIBSOUP_GNOME_TRUE@@HAVE_INTROSPECTION_TRUE@SoupGNOME_2_4_gir_FILES = $(addprefix $(srcdir)/,$(gi_soup_gnome_files)) +@BUILD_LIBSOUP_GNOME_TRUE@@HAVE_INTROSPECTION_TRUE@SoupGNOME_2_4_gir_EXPORT_PACKAGES = libsoup-gnome-2.4 +@HAVE_INTROSPECTION_TRUE@girdir = $(datadir)/gir-1.0 +@HAVE_INTROSPECTION_TRUE@gir_DATA = $(INTROSPECTION_GIRS) +@HAVE_INTROSPECTION_TRUE@typelibdir = $(libdir)/girepository-1.0 +@HAVE_INTROSPECTION_TRUE@typelib_DATA = $(INTROSPECTION_GIRS:.gir=.typelib) + +# ------ MSVC Project File Generation ------ +MSVCPROJS = soup soup-gnome +soup_FILES = $(libsoup_2_4_la_SOURCES) +soup_EXCLUDES = dummy +soup_HEADERS_DIR = $(libsoupincludedir) +soup_HEADERS_INST = $(libsoupinclude_HEADERS) $(nodist_libsoupinclude_HEADERS) +soup_HEADERS_EXCLUDES = dummy +soup_gnome_FILES = $(libsoup_gnome_2_4_la_SOURCES) +soup_gnome_EXCLUDES = dummy +soup_gnome_HEADERS_DIR = $(libsoupgnomeincludedir) +soup_gnome_HEADERS_INST = $(libsoupgnomeinclude_HEADERS) +soup_gnome_HEADERS_EXCLUDES = dummy +_proj_name = $(subst /,_,$(subst -,_,$(subst .,_,$(1)))) +_proj_path_raw := $(subst $(abs_top_srcdir),,$(abs_srcdir)) +_proj_path = $(subst /,\\,$(_proj_path_raw)) +_proj_subdir_int = $(subst \\\\,\\,\\$(_proj_path)\\) +_proj_subdir = $(subst \\.\\,\\,$(_proj_subdir_int)) +_proj_files_raw = $(subst /,\\,$($(_proj_name)_FILES)) +_proj_files = $(subst $(srcdir)\\,,$(subst $(builddir)\\,,$(subst $(top_builddir)\\$(_proj_path)\\,\\,$(_proj_files_raw)))) +_proj_filters = $($(_proj_name)_EXCLUDES) +_proj_headers_raw = $(subst /,\\,$($(_proj_name)_HEADERS_INST)) +_proj_headers = $(subst $(srcdir)\\,,$(subst $(builddir)\\,,$(subst $(top_builddir)\\$(_proj_path)\\,\\,$(_proj_headers_raw)))) +_proj_headers_excludes = $($(_proj_name)_HEADERS_EXCLUDES) +_headers_dest_posix = $(subst $(includedir),,$($(_proj_name)_HEADERS_DIR)) +_headers_destdir = $(subst /,\\,$(_headers_dest_posix)) + +# Introspection Items for MSVC +@HAVE_INTROSPECTION_TRUE@MSVC_INTROSPECT_GIRS = Soup-2.4.gir \ +@HAVE_INTROSPECTION_TRUE@ $(am__append_7) +@HAVE_INTROSPECTION_TRUE@BASE_MSVC_GIR_CFLAGS = \ +@HAVE_INTROSPECTION_TRUE@ $(SOUP_COMMON_CPPFLAGS) \ +@HAVE_INTROSPECTION_TRUE@ -I.. + +@HAVE_INTROSPECTION_FALSE@INTROSPECTION_INTERMEDIATE_ITEMS = +@HAVE_INTROSPECTION_TRUE@INTROSPECTION_INTERMEDIATE_ITEMS = \ +@HAVE_INTROSPECTION_TRUE@ $(top_builddir)/win32/Soup-2.4.gir.msvc.introspect \ +@HAVE_INTROSPECTION_TRUE@ $(top_builddir)/win32/Soup_2_4_gir_list \ +@HAVE_INTROSPECTION_TRUE@ $(top_builddir)/win32/SoupGNOME-2.4.gir.msvc.introspect \ +@HAVE_INTROSPECTION_TRUE@ $(top_builddir)/win32/SoupGNOME_2_4_gir_list + + +# libsoup +@HAVE_INTROSPECTION_TRUE@Soup_2_4_gir_MSVC_FILES = $(gi_soup_files) $(gi_built_soup_files) +@HAVE_INTROSPECTION_TRUE@Soup_2_4_gir_MSVC_EXPORT_PACKAGES = $(Soup_2_4_gir_EXPORT_PACKAGES) +@HAVE_INTROSPECTION_TRUE@Soup_2_4_gir_MSVC_INCLUDE_GIRS = $(Soup_2_4_gir_INCLUDES) +@HAVE_INTROSPECTION_TRUE@Soup_2_4_gir_MSVC_LIBS = soup-2.4 +@HAVE_INTROSPECTION_TRUE@Soup_2_4_gir_MSVC_CFLAGS = $(BASE_MSVC_GIR_CFLAGS) $(SOUP_UNSTABLE_REQUEST_CFLAG) +@HAVE_INTROSPECTION_TRUE@Soup_2_4_gir_MSVC_SCANNERFLAGS = --c-include \"libsoup/soup.h\" + +# libsoup-gnome +@BUILD_LIBSOUP_GNOME_TRUE@@HAVE_INTROSPECTION_TRUE@SoupGNOME_2_4_gir_MSVC_FILES = $(gi_soup_gnome_files) +@BUILD_LIBSOUP_GNOME_TRUE@@HAVE_INTROSPECTION_TRUE@SoupGNOME_2_4_gir_MSVC_GIR_DEPS = Soup-2.4.gir +@BUILD_LIBSOUP_GNOME_TRUE@@HAVE_INTROSPECTION_TRUE@SoupGNOME_2_4_gir_MSVC_EXPORT_PACKAGES = $(SoupGNOME_2_4_gir_EXPORT_PACKAGES) +@BUILD_LIBSOUP_GNOME_TRUE@@HAVE_INTROSPECTION_TRUE@SoupGNOME_2_4_gir_MSVC_LIBS = soup-gnome-2.4 soup-2.4 +@BUILD_LIBSOUP_GNOME_TRUE@@HAVE_INTROSPECTION_TRUE@SoupGNOME_2_4_gir_MSVC_CFLAGS = $(BASE_MSVC_GIR_CFLAGS) +@BUILD_LIBSOUP_GNOME_TRUE@@HAVE_INTROSPECTION_TRUE@SoupGNOME_2_4_gir_MSVC_SCANNERFLAGS = i \ +@BUILD_LIBSOUP_GNOME_TRUE@@HAVE_INTROSPECTION_TRUE@ $(SOUPGNOME_GIR_SCANNER_BASE_FLAGS) \ +@BUILD_LIBSOUP_GNOME_TRUE@@HAVE_INTROSPECTION_TRUE@ --c-include \"libsoup/soup-gnome.h\" \ +@BUILD_LIBSOUP_GNOME_TRUE@@HAVE_INTROSPECTION_TRUE@ --include-uninstalled=./Soup-2.4.gir + +@HAVE_INTROSPECTION_TRUE@_gir_name = $(subst /,_,$(subst -,_,$(subst .,_,$(1)))) + +# Namespace and Version is either fetched from the gir filename +# or the _NAMESPACE/_VERSION variable combo +@HAVE_INTROSPECTION_TRUE@_gir_namespace_msvc = $(or $($(_gir_name)_NAMESPACE),$(firstword $(subst -, ,$(notdir $(1))))) +@HAVE_INTROSPECTION_TRUE@_gir_version_msvc = $(or $($(_gir_name)_VERSION),$(lastword $(subst -, ,$(1:.gir=)))) +@HAVE_INTROSPECTION_TRUE@_typelib_basename_msvc = $(_gir_namespace_msvc)'-'$(_gir_version_msvc) + +# _PROGRAM is an optional variable which needs its own --program argument +@HAVE_INTROSPECTION_TRUE@_gir_program_msvc = $(if $($(_gir_name)_MSVC_PROGRAM),--program=$($(_gir_name)_MSVC_PROGRAM)) + +# Deduce the sub-folder from $(srcroot) where the sources reside in +@HAVE_INTROSPECTION_TRUE@_gir_source_path_raw_msvc := $(subst $(abs_top_srcdir),,$(abs_srcdir)) +@HAVE_INTROSPECTION_TRUE@_gir_source_path_msvc = $(subst /,\\,$(_gir_source_path_raw_msvc)) +@HAVE_INTROSPECTION_TRUE@_gir_source_subdir_int_msvc = $(subst \\\\,\\,\\$(_gir_source_path_msvc)\\) +@HAVE_INTROSPECTION_TRUE@_gir_source_subdir_msvc = $(subst \\.\\,\\,$(_gir_source_subdir_int_msvc)) +@HAVE_INTROSPECTION_TRUE@_gir_files_raw_msvc = $(subst /,\\,$($(_gir_name)_MSVC_FILES)) +@HAVE_INTROSPECTION_TRUE@_gir_files_msvc = $(subst $(srcdir)\\,,$(subst $(builddir)\\,,$(subst $(top_builddir)\\$(_gir_source_path_msvc)\\,\\,$(_gir_files_raw_msvc)))) + +# Create a list of items for: +# - Libraries +# - Packages +# - GIRs to include +# - packages to export +@HAVE_INTROSPECTION_TRUE@_gir_libraries_msvc = $(foreach lib,$($(_gir_name)_MSVC_LIBS),--library=$(lib)) +@HAVE_INTROSPECTION_TRUE@_gir_packages_msvc = $(foreach pkg,$($(_gir_name)_MSVC_PACKAGES),--pkg=$(pkg)) +@HAVE_INTROSPECTION_TRUE@_gir_includes_msvc = $(foreach include,$($(_gir_name)_MSVC_INCLUDE_GIRS),--include=$(include)) +@HAVE_INTROSPECTION_TRUE@_gir_export_packages_msvc = $(foreach pkg,$($(_gir_name)_MSVC_EXPORT_PACKAGES),--pkg-export=$(pkg)) +@HAVE_INTROSPECTION_TRUE@_gir_c_includes_msvc = $(foreach include,$($(_gir_name)_MSVC_C_INCLUDES),--c-include=$(include)) +all: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/win32/Makefile.msvcproj $(top_srcdir)/win32/Makefile.msvc-introspection $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign libsoup/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign libsoup/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; +$(top_srcdir)/win32/Makefile.msvcproj $(top_srcdir)/win32/Makefile.msvc-introspection $(am__empty): + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +soup-version.h: $(top_builddir)/config.status $(srcdir)/soup-version.h.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ + +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ + } + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ + done + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + @list='$(lib_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libsoup-2.4.la: $(libsoup_2_4_la_OBJECTS) $(libsoup_2_4_la_DEPENDENCIES) $(EXTRA_libsoup_2_4_la_DEPENDENCIES) + $(AM_V_CCLD)$(libsoup_2_4_la_LINK) -rpath $(libdir) $(libsoup_2_4_la_OBJECTS) $(libsoup_2_4_la_LIBADD) $(LIBS) + +libsoup-gnome-2.4.la: $(libsoup_gnome_2_4_la_OBJECTS) $(libsoup_gnome_2_4_la_DEPENDENCIES) $(EXTRA_libsoup_gnome_2_4_la_DEPENDENCIES) + $(AM_V_CCLD)$(libsoup_gnome_2_4_la_LINK) $(am_libsoup_gnome_2_4_la_rpath) $(libsoup_gnome_2_4_la_OBJECTS) $(libsoup_gnome_2_4_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-address.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-auth-basic.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-auth-digest.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-auth-domain-basic.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-auth-domain-digest.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-auth-domain.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-auth-manager.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-auth-negotiate.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-auth-ntlm.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-auth.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-body-input-stream.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-body-output-stream.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-cache-client-input-stream.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-cache-input-stream.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-cache.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-client-input-stream.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-connection-auth.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-connection.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-content-decoder.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-content-processor.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-content-sniffer-stream.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-content-sniffer.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-converter-wrapper.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-cookie-jar-db.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-cookie-jar-text.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-cookie-jar.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-cookie.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-date.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-directory-input-stream.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-enum-types.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-filter-input-stream.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-form.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-headers.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-init.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-io-stream.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-logger.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-message-body.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-message-client-io.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-message-headers.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-message-io.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-message-queue.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-message-server-io.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-message.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-method.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-misc.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-multipart-input-stream.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-multipart.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-password-manager.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-path-map.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-proxy-resolver-default.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-proxy-resolver-wrapper.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-proxy-resolver.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-proxy-uri-resolver.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-request-data.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-request-file.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-request-http.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-request.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-requester.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-server.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-session-async.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-session-feature.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-session-sync.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-session.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-socket-properties.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-socket.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-status.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-tld.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-uri.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-value-utils.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-version.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-websocket-connection.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-websocket.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-xmlrpc-old.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_2_4_la-soup-xmlrpc.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_gnome_2_4_la-soup-cookie-jar-sqlite.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_gnome_2_4_la-soup-gnome-features.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_gnome_2_4_la-soup-password-manager-gnome.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoup_gnome_2_4_la-soup-proxy-resolver-gnome.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +libsoup_2_4_la-soup-address.lo: soup-address.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-address.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-address.Tpo -c -o libsoup_2_4_la-soup-address.lo `test -f 'soup-address.c' || echo '$(srcdir)/'`soup-address.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-address.Tpo $(DEPDIR)/libsoup_2_4_la-soup-address.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-address.c' object='libsoup_2_4_la-soup-address.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-address.lo `test -f 'soup-address.c' || echo '$(srcdir)/'`soup-address.c + +libsoup_2_4_la-soup-auth.lo: soup-auth.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-auth.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-auth.Tpo -c -o libsoup_2_4_la-soup-auth.lo `test -f 'soup-auth.c' || echo '$(srcdir)/'`soup-auth.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-auth.Tpo $(DEPDIR)/libsoup_2_4_la-soup-auth.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-auth.c' object='libsoup_2_4_la-soup-auth.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-auth.lo `test -f 'soup-auth.c' || echo '$(srcdir)/'`soup-auth.c + +libsoup_2_4_la-soup-auth-basic.lo: soup-auth-basic.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-auth-basic.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-auth-basic.Tpo -c -o libsoup_2_4_la-soup-auth-basic.lo `test -f 'soup-auth-basic.c' || echo '$(srcdir)/'`soup-auth-basic.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-auth-basic.Tpo $(DEPDIR)/libsoup_2_4_la-soup-auth-basic.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-auth-basic.c' object='libsoup_2_4_la-soup-auth-basic.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-auth-basic.lo `test -f 'soup-auth-basic.c' || echo '$(srcdir)/'`soup-auth-basic.c + +libsoup_2_4_la-soup-auth-digest.lo: soup-auth-digest.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-auth-digest.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-auth-digest.Tpo -c -o libsoup_2_4_la-soup-auth-digest.lo `test -f 'soup-auth-digest.c' || echo '$(srcdir)/'`soup-auth-digest.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-auth-digest.Tpo $(DEPDIR)/libsoup_2_4_la-soup-auth-digest.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-auth-digest.c' object='libsoup_2_4_la-soup-auth-digest.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-auth-digest.lo `test -f 'soup-auth-digest.c' || echo '$(srcdir)/'`soup-auth-digest.c + +libsoup_2_4_la-soup-auth-ntlm.lo: soup-auth-ntlm.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-auth-ntlm.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-auth-ntlm.Tpo -c -o libsoup_2_4_la-soup-auth-ntlm.lo `test -f 'soup-auth-ntlm.c' || echo '$(srcdir)/'`soup-auth-ntlm.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-auth-ntlm.Tpo $(DEPDIR)/libsoup_2_4_la-soup-auth-ntlm.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-auth-ntlm.c' object='libsoup_2_4_la-soup-auth-ntlm.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-auth-ntlm.lo `test -f 'soup-auth-ntlm.c' || echo '$(srcdir)/'`soup-auth-ntlm.c + +libsoup_2_4_la-soup-auth-negotiate.lo: soup-auth-negotiate.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-auth-negotiate.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-auth-negotiate.Tpo -c -o libsoup_2_4_la-soup-auth-negotiate.lo `test -f 'soup-auth-negotiate.c' || echo '$(srcdir)/'`soup-auth-negotiate.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-auth-negotiate.Tpo $(DEPDIR)/libsoup_2_4_la-soup-auth-negotiate.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-auth-negotiate.c' object='libsoup_2_4_la-soup-auth-negotiate.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-auth-negotiate.lo `test -f 'soup-auth-negotiate.c' || echo '$(srcdir)/'`soup-auth-negotiate.c + +libsoup_2_4_la-soup-auth-domain.lo: soup-auth-domain.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-auth-domain.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-auth-domain.Tpo -c -o libsoup_2_4_la-soup-auth-domain.lo `test -f 'soup-auth-domain.c' || echo '$(srcdir)/'`soup-auth-domain.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-auth-domain.Tpo $(DEPDIR)/libsoup_2_4_la-soup-auth-domain.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-auth-domain.c' object='libsoup_2_4_la-soup-auth-domain.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-auth-domain.lo `test -f 'soup-auth-domain.c' || echo '$(srcdir)/'`soup-auth-domain.c + +libsoup_2_4_la-soup-auth-domain-basic.lo: soup-auth-domain-basic.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-auth-domain-basic.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-auth-domain-basic.Tpo -c -o libsoup_2_4_la-soup-auth-domain-basic.lo `test -f 'soup-auth-domain-basic.c' || echo '$(srcdir)/'`soup-auth-domain-basic.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-auth-domain-basic.Tpo $(DEPDIR)/libsoup_2_4_la-soup-auth-domain-basic.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-auth-domain-basic.c' object='libsoup_2_4_la-soup-auth-domain-basic.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-auth-domain-basic.lo `test -f 'soup-auth-domain-basic.c' || echo '$(srcdir)/'`soup-auth-domain-basic.c + +libsoup_2_4_la-soup-auth-domain-digest.lo: soup-auth-domain-digest.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-auth-domain-digest.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-auth-domain-digest.Tpo -c -o libsoup_2_4_la-soup-auth-domain-digest.lo `test -f 'soup-auth-domain-digest.c' || echo '$(srcdir)/'`soup-auth-domain-digest.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-auth-domain-digest.Tpo $(DEPDIR)/libsoup_2_4_la-soup-auth-domain-digest.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-auth-domain-digest.c' object='libsoup_2_4_la-soup-auth-domain-digest.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-auth-domain-digest.lo `test -f 'soup-auth-domain-digest.c' || echo '$(srcdir)/'`soup-auth-domain-digest.c + +libsoup_2_4_la-soup-auth-manager.lo: soup-auth-manager.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-auth-manager.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-auth-manager.Tpo -c -o libsoup_2_4_la-soup-auth-manager.lo `test -f 'soup-auth-manager.c' || echo '$(srcdir)/'`soup-auth-manager.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-auth-manager.Tpo $(DEPDIR)/libsoup_2_4_la-soup-auth-manager.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-auth-manager.c' object='libsoup_2_4_la-soup-auth-manager.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-auth-manager.lo `test -f 'soup-auth-manager.c' || echo '$(srcdir)/'`soup-auth-manager.c + +libsoup_2_4_la-soup-body-input-stream.lo: soup-body-input-stream.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-body-input-stream.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-body-input-stream.Tpo -c -o libsoup_2_4_la-soup-body-input-stream.lo `test -f 'soup-body-input-stream.c' || echo '$(srcdir)/'`soup-body-input-stream.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-body-input-stream.Tpo $(DEPDIR)/libsoup_2_4_la-soup-body-input-stream.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-body-input-stream.c' object='libsoup_2_4_la-soup-body-input-stream.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-body-input-stream.lo `test -f 'soup-body-input-stream.c' || echo '$(srcdir)/'`soup-body-input-stream.c + +libsoup_2_4_la-soup-body-output-stream.lo: soup-body-output-stream.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-body-output-stream.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-body-output-stream.Tpo -c -o libsoup_2_4_la-soup-body-output-stream.lo `test -f 'soup-body-output-stream.c' || echo '$(srcdir)/'`soup-body-output-stream.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-body-output-stream.Tpo $(DEPDIR)/libsoup_2_4_la-soup-body-output-stream.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-body-output-stream.c' object='libsoup_2_4_la-soup-body-output-stream.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-body-output-stream.lo `test -f 'soup-body-output-stream.c' || echo '$(srcdir)/'`soup-body-output-stream.c + +libsoup_2_4_la-soup-cache.lo: soup-cache.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-cache.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-cache.Tpo -c -o libsoup_2_4_la-soup-cache.lo `test -f 'soup-cache.c' || echo '$(srcdir)/'`soup-cache.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-cache.Tpo $(DEPDIR)/libsoup_2_4_la-soup-cache.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-cache.c' object='libsoup_2_4_la-soup-cache.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-cache.lo `test -f 'soup-cache.c' || echo '$(srcdir)/'`soup-cache.c + +libsoup_2_4_la-soup-cache-client-input-stream.lo: soup-cache-client-input-stream.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-cache-client-input-stream.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-cache-client-input-stream.Tpo -c -o libsoup_2_4_la-soup-cache-client-input-stream.lo `test -f 'soup-cache-client-input-stream.c' || echo '$(srcdir)/'`soup-cache-client-input-stream.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-cache-client-input-stream.Tpo $(DEPDIR)/libsoup_2_4_la-soup-cache-client-input-stream.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-cache-client-input-stream.c' object='libsoup_2_4_la-soup-cache-client-input-stream.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-cache-client-input-stream.lo `test -f 'soup-cache-client-input-stream.c' || echo '$(srcdir)/'`soup-cache-client-input-stream.c + +libsoup_2_4_la-soup-cache-input-stream.lo: soup-cache-input-stream.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-cache-input-stream.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-cache-input-stream.Tpo -c -o libsoup_2_4_la-soup-cache-input-stream.lo `test -f 'soup-cache-input-stream.c' || echo '$(srcdir)/'`soup-cache-input-stream.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-cache-input-stream.Tpo $(DEPDIR)/libsoup_2_4_la-soup-cache-input-stream.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-cache-input-stream.c' object='libsoup_2_4_la-soup-cache-input-stream.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-cache-input-stream.lo `test -f 'soup-cache-input-stream.c' || echo '$(srcdir)/'`soup-cache-input-stream.c + +libsoup_2_4_la-soup-client-input-stream.lo: soup-client-input-stream.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-client-input-stream.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-client-input-stream.Tpo -c -o libsoup_2_4_la-soup-client-input-stream.lo `test -f 'soup-client-input-stream.c' || echo '$(srcdir)/'`soup-client-input-stream.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-client-input-stream.Tpo $(DEPDIR)/libsoup_2_4_la-soup-client-input-stream.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-client-input-stream.c' object='libsoup_2_4_la-soup-client-input-stream.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-client-input-stream.lo `test -f 'soup-client-input-stream.c' || echo '$(srcdir)/'`soup-client-input-stream.c + +libsoup_2_4_la-soup-connection.lo: soup-connection.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-connection.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-connection.Tpo -c -o libsoup_2_4_la-soup-connection.lo `test -f 'soup-connection.c' || echo '$(srcdir)/'`soup-connection.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-connection.Tpo $(DEPDIR)/libsoup_2_4_la-soup-connection.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-connection.c' object='libsoup_2_4_la-soup-connection.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-connection.lo `test -f 'soup-connection.c' || echo '$(srcdir)/'`soup-connection.c + +libsoup_2_4_la-soup-connection-auth.lo: soup-connection-auth.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-connection-auth.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-connection-auth.Tpo -c -o libsoup_2_4_la-soup-connection-auth.lo `test -f 'soup-connection-auth.c' || echo '$(srcdir)/'`soup-connection-auth.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-connection-auth.Tpo $(DEPDIR)/libsoup_2_4_la-soup-connection-auth.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-connection-auth.c' object='libsoup_2_4_la-soup-connection-auth.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-connection-auth.lo `test -f 'soup-connection-auth.c' || echo '$(srcdir)/'`soup-connection-auth.c + +libsoup_2_4_la-soup-content-decoder.lo: soup-content-decoder.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-content-decoder.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-content-decoder.Tpo -c -o libsoup_2_4_la-soup-content-decoder.lo `test -f 'soup-content-decoder.c' || echo '$(srcdir)/'`soup-content-decoder.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-content-decoder.Tpo $(DEPDIR)/libsoup_2_4_la-soup-content-decoder.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-content-decoder.c' object='libsoup_2_4_la-soup-content-decoder.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-content-decoder.lo `test -f 'soup-content-decoder.c' || echo '$(srcdir)/'`soup-content-decoder.c + +libsoup_2_4_la-soup-content-processor.lo: soup-content-processor.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-content-processor.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-content-processor.Tpo -c -o libsoup_2_4_la-soup-content-processor.lo `test -f 'soup-content-processor.c' || echo '$(srcdir)/'`soup-content-processor.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-content-processor.Tpo $(DEPDIR)/libsoup_2_4_la-soup-content-processor.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-content-processor.c' object='libsoup_2_4_la-soup-content-processor.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-content-processor.lo `test -f 'soup-content-processor.c' || echo '$(srcdir)/'`soup-content-processor.c + +libsoup_2_4_la-soup-content-sniffer.lo: soup-content-sniffer.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-content-sniffer.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-content-sniffer.Tpo -c -o libsoup_2_4_la-soup-content-sniffer.lo `test -f 'soup-content-sniffer.c' || echo '$(srcdir)/'`soup-content-sniffer.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-content-sniffer.Tpo $(DEPDIR)/libsoup_2_4_la-soup-content-sniffer.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-content-sniffer.c' object='libsoup_2_4_la-soup-content-sniffer.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-content-sniffer.lo `test -f 'soup-content-sniffer.c' || echo '$(srcdir)/'`soup-content-sniffer.c + +libsoup_2_4_la-soup-content-sniffer-stream.lo: soup-content-sniffer-stream.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-content-sniffer-stream.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-content-sniffer-stream.Tpo -c -o libsoup_2_4_la-soup-content-sniffer-stream.lo `test -f 'soup-content-sniffer-stream.c' || echo '$(srcdir)/'`soup-content-sniffer-stream.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-content-sniffer-stream.Tpo $(DEPDIR)/libsoup_2_4_la-soup-content-sniffer-stream.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-content-sniffer-stream.c' object='libsoup_2_4_la-soup-content-sniffer-stream.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-content-sniffer-stream.lo `test -f 'soup-content-sniffer-stream.c' || echo '$(srcdir)/'`soup-content-sniffer-stream.c + +libsoup_2_4_la-soup-converter-wrapper.lo: soup-converter-wrapper.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-converter-wrapper.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-converter-wrapper.Tpo -c -o libsoup_2_4_la-soup-converter-wrapper.lo `test -f 'soup-converter-wrapper.c' || echo '$(srcdir)/'`soup-converter-wrapper.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-converter-wrapper.Tpo $(DEPDIR)/libsoup_2_4_la-soup-converter-wrapper.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-converter-wrapper.c' object='libsoup_2_4_la-soup-converter-wrapper.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-converter-wrapper.lo `test -f 'soup-converter-wrapper.c' || echo '$(srcdir)/'`soup-converter-wrapper.c + +libsoup_2_4_la-soup-cookie.lo: soup-cookie.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-cookie.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-cookie.Tpo -c -o libsoup_2_4_la-soup-cookie.lo `test -f 'soup-cookie.c' || echo '$(srcdir)/'`soup-cookie.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-cookie.Tpo $(DEPDIR)/libsoup_2_4_la-soup-cookie.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-cookie.c' object='libsoup_2_4_la-soup-cookie.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-cookie.lo `test -f 'soup-cookie.c' || echo '$(srcdir)/'`soup-cookie.c + +libsoup_2_4_la-soup-cookie-jar.lo: soup-cookie-jar.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-cookie-jar.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-cookie-jar.Tpo -c -o libsoup_2_4_la-soup-cookie-jar.lo `test -f 'soup-cookie-jar.c' || echo '$(srcdir)/'`soup-cookie-jar.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-cookie-jar.Tpo $(DEPDIR)/libsoup_2_4_la-soup-cookie-jar.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-cookie-jar.c' object='libsoup_2_4_la-soup-cookie-jar.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-cookie-jar.lo `test -f 'soup-cookie-jar.c' || echo '$(srcdir)/'`soup-cookie-jar.c + +libsoup_2_4_la-soup-cookie-jar-db.lo: soup-cookie-jar-db.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-cookie-jar-db.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-cookie-jar-db.Tpo -c -o libsoup_2_4_la-soup-cookie-jar-db.lo `test -f 'soup-cookie-jar-db.c' || echo '$(srcdir)/'`soup-cookie-jar-db.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-cookie-jar-db.Tpo $(DEPDIR)/libsoup_2_4_la-soup-cookie-jar-db.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-cookie-jar-db.c' object='libsoup_2_4_la-soup-cookie-jar-db.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-cookie-jar-db.lo `test -f 'soup-cookie-jar-db.c' || echo '$(srcdir)/'`soup-cookie-jar-db.c + +libsoup_2_4_la-soup-cookie-jar-text.lo: soup-cookie-jar-text.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-cookie-jar-text.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-cookie-jar-text.Tpo -c -o libsoup_2_4_la-soup-cookie-jar-text.lo `test -f 'soup-cookie-jar-text.c' || echo '$(srcdir)/'`soup-cookie-jar-text.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-cookie-jar-text.Tpo $(DEPDIR)/libsoup_2_4_la-soup-cookie-jar-text.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-cookie-jar-text.c' object='libsoup_2_4_la-soup-cookie-jar-text.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-cookie-jar-text.lo `test -f 'soup-cookie-jar-text.c' || echo '$(srcdir)/'`soup-cookie-jar-text.c + +libsoup_2_4_la-soup-date.lo: soup-date.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-date.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-date.Tpo -c -o libsoup_2_4_la-soup-date.lo `test -f 'soup-date.c' || echo '$(srcdir)/'`soup-date.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-date.Tpo $(DEPDIR)/libsoup_2_4_la-soup-date.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-date.c' object='libsoup_2_4_la-soup-date.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-date.lo `test -f 'soup-date.c' || echo '$(srcdir)/'`soup-date.c + +libsoup_2_4_la-soup-directory-input-stream.lo: soup-directory-input-stream.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-directory-input-stream.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-directory-input-stream.Tpo -c -o libsoup_2_4_la-soup-directory-input-stream.lo `test -f 'soup-directory-input-stream.c' || echo '$(srcdir)/'`soup-directory-input-stream.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-directory-input-stream.Tpo $(DEPDIR)/libsoup_2_4_la-soup-directory-input-stream.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-directory-input-stream.c' object='libsoup_2_4_la-soup-directory-input-stream.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-directory-input-stream.lo `test -f 'soup-directory-input-stream.c' || echo '$(srcdir)/'`soup-directory-input-stream.c + +libsoup_2_4_la-soup-enum-types.lo: soup-enum-types.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-enum-types.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-enum-types.Tpo -c -o libsoup_2_4_la-soup-enum-types.lo `test -f 'soup-enum-types.c' || echo '$(srcdir)/'`soup-enum-types.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-enum-types.Tpo $(DEPDIR)/libsoup_2_4_la-soup-enum-types.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-enum-types.c' object='libsoup_2_4_la-soup-enum-types.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-enum-types.lo `test -f 'soup-enum-types.c' || echo '$(srcdir)/'`soup-enum-types.c + +libsoup_2_4_la-soup-filter-input-stream.lo: soup-filter-input-stream.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-filter-input-stream.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-filter-input-stream.Tpo -c -o libsoup_2_4_la-soup-filter-input-stream.lo `test -f 'soup-filter-input-stream.c' || echo '$(srcdir)/'`soup-filter-input-stream.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-filter-input-stream.Tpo $(DEPDIR)/libsoup_2_4_la-soup-filter-input-stream.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-filter-input-stream.c' object='libsoup_2_4_la-soup-filter-input-stream.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-filter-input-stream.lo `test -f 'soup-filter-input-stream.c' || echo '$(srcdir)/'`soup-filter-input-stream.c + +libsoup_2_4_la-soup-form.lo: soup-form.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-form.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-form.Tpo -c -o libsoup_2_4_la-soup-form.lo `test -f 'soup-form.c' || echo '$(srcdir)/'`soup-form.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-form.Tpo $(DEPDIR)/libsoup_2_4_la-soup-form.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-form.c' object='libsoup_2_4_la-soup-form.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-form.lo `test -f 'soup-form.c' || echo '$(srcdir)/'`soup-form.c + +libsoup_2_4_la-soup-headers.lo: soup-headers.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-headers.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-headers.Tpo -c -o libsoup_2_4_la-soup-headers.lo `test -f 'soup-headers.c' || echo '$(srcdir)/'`soup-headers.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-headers.Tpo $(DEPDIR)/libsoup_2_4_la-soup-headers.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-headers.c' object='libsoup_2_4_la-soup-headers.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-headers.lo `test -f 'soup-headers.c' || echo '$(srcdir)/'`soup-headers.c + +libsoup_2_4_la-soup-init.lo: soup-init.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-init.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-init.Tpo -c -o libsoup_2_4_la-soup-init.lo `test -f 'soup-init.c' || echo '$(srcdir)/'`soup-init.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-init.Tpo $(DEPDIR)/libsoup_2_4_la-soup-init.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-init.c' object='libsoup_2_4_la-soup-init.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-init.lo `test -f 'soup-init.c' || echo '$(srcdir)/'`soup-init.c + +libsoup_2_4_la-soup-io-stream.lo: soup-io-stream.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-io-stream.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-io-stream.Tpo -c -o libsoup_2_4_la-soup-io-stream.lo `test -f 'soup-io-stream.c' || echo '$(srcdir)/'`soup-io-stream.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-io-stream.Tpo $(DEPDIR)/libsoup_2_4_la-soup-io-stream.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-io-stream.c' object='libsoup_2_4_la-soup-io-stream.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-io-stream.lo `test -f 'soup-io-stream.c' || echo '$(srcdir)/'`soup-io-stream.c + +libsoup_2_4_la-soup-logger.lo: soup-logger.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-logger.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-logger.Tpo -c -o libsoup_2_4_la-soup-logger.lo `test -f 'soup-logger.c' || echo '$(srcdir)/'`soup-logger.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-logger.Tpo $(DEPDIR)/libsoup_2_4_la-soup-logger.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-logger.c' object='libsoup_2_4_la-soup-logger.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-logger.lo `test -f 'soup-logger.c' || echo '$(srcdir)/'`soup-logger.c + +libsoup_2_4_la-soup-message.lo: soup-message.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-message.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-message.Tpo -c -o libsoup_2_4_la-soup-message.lo `test -f 'soup-message.c' || echo '$(srcdir)/'`soup-message.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-message.Tpo $(DEPDIR)/libsoup_2_4_la-soup-message.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-message.c' object='libsoup_2_4_la-soup-message.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-message.lo `test -f 'soup-message.c' || echo '$(srcdir)/'`soup-message.c + +libsoup_2_4_la-soup-message-body.lo: soup-message-body.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-message-body.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-message-body.Tpo -c -o libsoup_2_4_la-soup-message-body.lo `test -f 'soup-message-body.c' || echo '$(srcdir)/'`soup-message-body.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-message-body.Tpo $(DEPDIR)/libsoup_2_4_la-soup-message-body.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-message-body.c' object='libsoup_2_4_la-soup-message-body.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-message-body.lo `test -f 'soup-message-body.c' || echo '$(srcdir)/'`soup-message-body.c + +libsoup_2_4_la-soup-message-client-io.lo: soup-message-client-io.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-message-client-io.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-message-client-io.Tpo -c -o libsoup_2_4_la-soup-message-client-io.lo `test -f 'soup-message-client-io.c' || echo '$(srcdir)/'`soup-message-client-io.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-message-client-io.Tpo $(DEPDIR)/libsoup_2_4_la-soup-message-client-io.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-message-client-io.c' object='libsoup_2_4_la-soup-message-client-io.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-message-client-io.lo `test -f 'soup-message-client-io.c' || echo '$(srcdir)/'`soup-message-client-io.c + +libsoup_2_4_la-soup-message-headers.lo: soup-message-headers.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-message-headers.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-message-headers.Tpo -c -o libsoup_2_4_la-soup-message-headers.lo `test -f 'soup-message-headers.c' || echo '$(srcdir)/'`soup-message-headers.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-message-headers.Tpo $(DEPDIR)/libsoup_2_4_la-soup-message-headers.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-message-headers.c' object='libsoup_2_4_la-soup-message-headers.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-message-headers.lo `test -f 'soup-message-headers.c' || echo '$(srcdir)/'`soup-message-headers.c + +libsoup_2_4_la-soup-message-io.lo: soup-message-io.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-message-io.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-message-io.Tpo -c -o libsoup_2_4_la-soup-message-io.lo `test -f 'soup-message-io.c' || echo '$(srcdir)/'`soup-message-io.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-message-io.Tpo $(DEPDIR)/libsoup_2_4_la-soup-message-io.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-message-io.c' object='libsoup_2_4_la-soup-message-io.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-message-io.lo `test -f 'soup-message-io.c' || echo '$(srcdir)/'`soup-message-io.c + +libsoup_2_4_la-soup-message-queue.lo: soup-message-queue.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-message-queue.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-message-queue.Tpo -c -o libsoup_2_4_la-soup-message-queue.lo `test -f 'soup-message-queue.c' || echo '$(srcdir)/'`soup-message-queue.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-message-queue.Tpo $(DEPDIR)/libsoup_2_4_la-soup-message-queue.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-message-queue.c' object='libsoup_2_4_la-soup-message-queue.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-message-queue.lo `test -f 'soup-message-queue.c' || echo '$(srcdir)/'`soup-message-queue.c + +libsoup_2_4_la-soup-message-server-io.lo: soup-message-server-io.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-message-server-io.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-message-server-io.Tpo -c -o libsoup_2_4_la-soup-message-server-io.lo `test -f 'soup-message-server-io.c' || echo '$(srcdir)/'`soup-message-server-io.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-message-server-io.Tpo $(DEPDIR)/libsoup_2_4_la-soup-message-server-io.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-message-server-io.c' object='libsoup_2_4_la-soup-message-server-io.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-message-server-io.lo `test -f 'soup-message-server-io.c' || echo '$(srcdir)/'`soup-message-server-io.c + +libsoup_2_4_la-soup-method.lo: soup-method.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-method.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-method.Tpo -c -o libsoup_2_4_la-soup-method.lo `test -f 'soup-method.c' || echo '$(srcdir)/'`soup-method.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-method.Tpo $(DEPDIR)/libsoup_2_4_la-soup-method.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-method.c' object='libsoup_2_4_la-soup-method.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-method.lo `test -f 'soup-method.c' || echo '$(srcdir)/'`soup-method.c + +libsoup_2_4_la-soup-misc.lo: soup-misc.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-misc.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-misc.Tpo -c -o libsoup_2_4_la-soup-misc.lo `test -f 'soup-misc.c' || echo '$(srcdir)/'`soup-misc.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-misc.Tpo $(DEPDIR)/libsoup_2_4_la-soup-misc.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-misc.c' object='libsoup_2_4_la-soup-misc.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-misc.lo `test -f 'soup-misc.c' || echo '$(srcdir)/'`soup-misc.c + +libsoup_2_4_la-soup-multipart.lo: soup-multipart.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-multipart.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-multipart.Tpo -c -o libsoup_2_4_la-soup-multipart.lo `test -f 'soup-multipart.c' || echo '$(srcdir)/'`soup-multipart.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-multipart.Tpo $(DEPDIR)/libsoup_2_4_la-soup-multipart.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-multipart.c' object='libsoup_2_4_la-soup-multipart.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-multipart.lo `test -f 'soup-multipart.c' || echo '$(srcdir)/'`soup-multipart.c + +libsoup_2_4_la-soup-multipart-input-stream.lo: soup-multipart-input-stream.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-multipart-input-stream.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-multipart-input-stream.Tpo -c -o libsoup_2_4_la-soup-multipart-input-stream.lo `test -f 'soup-multipart-input-stream.c' || echo '$(srcdir)/'`soup-multipart-input-stream.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-multipart-input-stream.Tpo $(DEPDIR)/libsoup_2_4_la-soup-multipart-input-stream.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-multipart-input-stream.c' object='libsoup_2_4_la-soup-multipart-input-stream.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-multipart-input-stream.lo `test -f 'soup-multipart-input-stream.c' || echo '$(srcdir)/'`soup-multipart-input-stream.c + +libsoup_2_4_la-soup-password-manager.lo: soup-password-manager.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-password-manager.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-password-manager.Tpo -c -o libsoup_2_4_la-soup-password-manager.lo `test -f 'soup-password-manager.c' || echo '$(srcdir)/'`soup-password-manager.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-password-manager.Tpo $(DEPDIR)/libsoup_2_4_la-soup-password-manager.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-password-manager.c' object='libsoup_2_4_la-soup-password-manager.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-password-manager.lo `test -f 'soup-password-manager.c' || echo '$(srcdir)/'`soup-password-manager.c + +libsoup_2_4_la-soup-path-map.lo: soup-path-map.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-path-map.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-path-map.Tpo -c -o libsoup_2_4_la-soup-path-map.lo `test -f 'soup-path-map.c' || echo '$(srcdir)/'`soup-path-map.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-path-map.Tpo $(DEPDIR)/libsoup_2_4_la-soup-path-map.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-path-map.c' object='libsoup_2_4_la-soup-path-map.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-path-map.lo `test -f 'soup-path-map.c' || echo '$(srcdir)/'`soup-path-map.c + +libsoup_2_4_la-soup-proxy-resolver.lo: soup-proxy-resolver.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-proxy-resolver.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-proxy-resolver.Tpo -c -o libsoup_2_4_la-soup-proxy-resolver.lo `test -f 'soup-proxy-resolver.c' || echo '$(srcdir)/'`soup-proxy-resolver.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-proxy-resolver.Tpo $(DEPDIR)/libsoup_2_4_la-soup-proxy-resolver.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-proxy-resolver.c' object='libsoup_2_4_la-soup-proxy-resolver.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-proxy-resolver.lo `test -f 'soup-proxy-resolver.c' || echo '$(srcdir)/'`soup-proxy-resolver.c + +libsoup_2_4_la-soup-proxy-resolver-default.lo: soup-proxy-resolver-default.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-proxy-resolver-default.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-proxy-resolver-default.Tpo -c -o libsoup_2_4_la-soup-proxy-resolver-default.lo `test -f 'soup-proxy-resolver-default.c' || echo '$(srcdir)/'`soup-proxy-resolver-default.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-proxy-resolver-default.Tpo $(DEPDIR)/libsoup_2_4_la-soup-proxy-resolver-default.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-proxy-resolver-default.c' object='libsoup_2_4_la-soup-proxy-resolver-default.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-proxy-resolver-default.lo `test -f 'soup-proxy-resolver-default.c' || echo '$(srcdir)/'`soup-proxy-resolver-default.c + +libsoup_2_4_la-soup-proxy-resolver-wrapper.lo: soup-proxy-resolver-wrapper.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-proxy-resolver-wrapper.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-proxy-resolver-wrapper.Tpo -c -o libsoup_2_4_la-soup-proxy-resolver-wrapper.lo `test -f 'soup-proxy-resolver-wrapper.c' || echo '$(srcdir)/'`soup-proxy-resolver-wrapper.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-proxy-resolver-wrapper.Tpo $(DEPDIR)/libsoup_2_4_la-soup-proxy-resolver-wrapper.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-proxy-resolver-wrapper.c' object='libsoup_2_4_la-soup-proxy-resolver-wrapper.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-proxy-resolver-wrapper.lo `test -f 'soup-proxy-resolver-wrapper.c' || echo '$(srcdir)/'`soup-proxy-resolver-wrapper.c + +libsoup_2_4_la-soup-proxy-uri-resolver.lo: soup-proxy-uri-resolver.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-proxy-uri-resolver.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-proxy-uri-resolver.Tpo -c -o libsoup_2_4_la-soup-proxy-uri-resolver.lo `test -f 'soup-proxy-uri-resolver.c' || echo '$(srcdir)/'`soup-proxy-uri-resolver.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-proxy-uri-resolver.Tpo $(DEPDIR)/libsoup_2_4_la-soup-proxy-uri-resolver.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-proxy-uri-resolver.c' object='libsoup_2_4_la-soup-proxy-uri-resolver.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-proxy-uri-resolver.lo `test -f 'soup-proxy-uri-resolver.c' || echo '$(srcdir)/'`soup-proxy-uri-resolver.c + +libsoup_2_4_la-soup-request.lo: soup-request.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-request.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-request.Tpo -c -o libsoup_2_4_la-soup-request.lo `test -f 'soup-request.c' || echo '$(srcdir)/'`soup-request.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-request.Tpo $(DEPDIR)/libsoup_2_4_la-soup-request.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-request.c' object='libsoup_2_4_la-soup-request.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-request.lo `test -f 'soup-request.c' || echo '$(srcdir)/'`soup-request.c + +libsoup_2_4_la-soup-request-data.lo: soup-request-data.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-request-data.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-request-data.Tpo -c -o libsoup_2_4_la-soup-request-data.lo `test -f 'soup-request-data.c' || echo '$(srcdir)/'`soup-request-data.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-request-data.Tpo $(DEPDIR)/libsoup_2_4_la-soup-request-data.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-request-data.c' object='libsoup_2_4_la-soup-request-data.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-request-data.lo `test -f 'soup-request-data.c' || echo '$(srcdir)/'`soup-request-data.c + +libsoup_2_4_la-soup-request-file.lo: soup-request-file.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-request-file.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-request-file.Tpo -c -o libsoup_2_4_la-soup-request-file.lo `test -f 'soup-request-file.c' || echo '$(srcdir)/'`soup-request-file.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-request-file.Tpo $(DEPDIR)/libsoup_2_4_la-soup-request-file.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-request-file.c' object='libsoup_2_4_la-soup-request-file.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-request-file.lo `test -f 'soup-request-file.c' || echo '$(srcdir)/'`soup-request-file.c + +libsoup_2_4_la-soup-request-http.lo: soup-request-http.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-request-http.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-request-http.Tpo -c -o libsoup_2_4_la-soup-request-http.lo `test -f 'soup-request-http.c' || echo '$(srcdir)/'`soup-request-http.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-request-http.Tpo $(DEPDIR)/libsoup_2_4_la-soup-request-http.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-request-http.c' object='libsoup_2_4_la-soup-request-http.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-request-http.lo `test -f 'soup-request-http.c' || echo '$(srcdir)/'`soup-request-http.c + +libsoup_2_4_la-soup-requester.lo: soup-requester.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-requester.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-requester.Tpo -c -o libsoup_2_4_la-soup-requester.lo `test -f 'soup-requester.c' || echo '$(srcdir)/'`soup-requester.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-requester.Tpo $(DEPDIR)/libsoup_2_4_la-soup-requester.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-requester.c' object='libsoup_2_4_la-soup-requester.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-requester.lo `test -f 'soup-requester.c' || echo '$(srcdir)/'`soup-requester.c + +libsoup_2_4_la-soup-server.lo: soup-server.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-server.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-server.Tpo -c -o libsoup_2_4_la-soup-server.lo `test -f 'soup-server.c' || echo '$(srcdir)/'`soup-server.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-server.Tpo $(DEPDIR)/libsoup_2_4_la-soup-server.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-server.c' object='libsoup_2_4_la-soup-server.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-server.lo `test -f 'soup-server.c' || echo '$(srcdir)/'`soup-server.c + +libsoup_2_4_la-soup-session.lo: soup-session.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-session.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-session.Tpo -c -o libsoup_2_4_la-soup-session.lo `test -f 'soup-session.c' || echo '$(srcdir)/'`soup-session.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-session.Tpo $(DEPDIR)/libsoup_2_4_la-soup-session.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-session.c' object='libsoup_2_4_la-soup-session.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-session.lo `test -f 'soup-session.c' || echo '$(srcdir)/'`soup-session.c + +libsoup_2_4_la-soup-session-async.lo: soup-session-async.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-session-async.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-session-async.Tpo -c -o libsoup_2_4_la-soup-session-async.lo `test -f 'soup-session-async.c' || echo '$(srcdir)/'`soup-session-async.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-session-async.Tpo $(DEPDIR)/libsoup_2_4_la-soup-session-async.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-session-async.c' object='libsoup_2_4_la-soup-session-async.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-session-async.lo `test -f 'soup-session-async.c' || echo '$(srcdir)/'`soup-session-async.c + +libsoup_2_4_la-soup-session-feature.lo: soup-session-feature.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-session-feature.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-session-feature.Tpo -c -o libsoup_2_4_la-soup-session-feature.lo `test -f 'soup-session-feature.c' || echo '$(srcdir)/'`soup-session-feature.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-session-feature.Tpo $(DEPDIR)/libsoup_2_4_la-soup-session-feature.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-session-feature.c' object='libsoup_2_4_la-soup-session-feature.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-session-feature.lo `test -f 'soup-session-feature.c' || echo '$(srcdir)/'`soup-session-feature.c + +libsoup_2_4_la-soup-session-sync.lo: soup-session-sync.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-session-sync.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-session-sync.Tpo -c -o libsoup_2_4_la-soup-session-sync.lo `test -f 'soup-session-sync.c' || echo '$(srcdir)/'`soup-session-sync.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-session-sync.Tpo $(DEPDIR)/libsoup_2_4_la-soup-session-sync.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-session-sync.c' object='libsoup_2_4_la-soup-session-sync.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-session-sync.lo `test -f 'soup-session-sync.c' || echo '$(srcdir)/'`soup-session-sync.c + +libsoup_2_4_la-soup-socket.lo: soup-socket.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-socket.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-socket.Tpo -c -o libsoup_2_4_la-soup-socket.lo `test -f 'soup-socket.c' || echo '$(srcdir)/'`soup-socket.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-socket.Tpo $(DEPDIR)/libsoup_2_4_la-soup-socket.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-socket.c' object='libsoup_2_4_la-soup-socket.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-socket.lo `test -f 'soup-socket.c' || echo '$(srcdir)/'`soup-socket.c + +libsoup_2_4_la-soup-socket-properties.lo: soup-socket-properties.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-socket-properties.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-socket-properties.Tpo -c -o libsoup_2_4_la-soup-socket-properties.lo `test -f 'soup-socket-properties.c' || echo '$(srcdir)/'`soup-socket-properties.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-socket-properties.Tpo $(DEPDIR)/libsoup_2_4_la-soup-socket-properties.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-socket-properties.c' object='libsoup_2_4_la-soup-socket-properties.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-socket-properties.lo `test -f 'soup-socket-properties.c' || echo '$(srcdir)/'`soup-socket-properties.c + +libsoup_2_4_la-soup-status.lo: soup-status.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-status.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-status.Tpo -c -o libsoup_2_4_la-soup-status.lo `test -f 'soup-status.c' || echo '$(srcdir)/'`soup-status.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-status.Tpo $(DEPDIR)/libsoup_2_4_la-soup-status.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-status.c' object='libsoup_2_4_la-soup-status.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-status.lo `test -f 'soup-status.c' || echo '$(srcdir)/'`soup-status.c + +libsoup_2_4_la-soup-tld.lo: soup-tld.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-tld.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-tld.Tpo -c -o libsoup_2_4_la-soup-tld.lo `test -f 'soup-tld.c' || echo '$(srcdir)/'`soup-tld.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-tld.Tpo $(DEPDIR)/libsoup_2_4_la-soup-tld.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-tld.c' object='libsoup_2_4_la-soup-tld.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-tld.lo `test -f 'soup-tld.c' || echo '$(srcdir)/'`soup-tld.c + +libsoup_2_4_la-soup-uri.lo: soup-uri.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-uri.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-uri.Tpo -c -o libsoup_2_4_la-soup-uri.lo `test -f 'soup-uri.c' || echo '$(srcdir)/'`soup-uri.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-uri.Tpo $(DEPDIR)/libsoup_2_4_la-soup-uri.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-uri.c' object='libsoup_2_4_la-soup-uri.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-uri.lo `test -f 'soup-uri.c' || echo '$(srcdir)/'`soup-uri.c + +libsoup_2_4_la-soup-value-utils.lo: soup-value-utils.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-value-utils.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-value-utils.Tpo -c -o libsoup_2_4_la-soup-value-utils.lo `test -f 'soup-value-utils.c' || echo '$(srcdir)/'`soup-value-utils.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-value-utils.Tpo $(DEPDIR)/libsoup_2_4_la-soup-value-utils.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-value-utils.c' object='libsoup_2_4_la-soup-value-utils.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-value-utils.lo `test -f 'soup-value-utils.c' || echo '$(srcdir)/'`soup-value-utils.c + +libsoup_2_4_la-soup-version.lo: soup-version.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-version.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-version.Tpo -c -o libsoup_2_4_la-soup-version.lo `test -f 'soup-version.c' || echo '$(srcdir)/'`soup-version.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-version.Tpo $(DEPDIR)/libsoup_2_4_la-soup-version.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-version.c' object='libsoup_2_4_la-soup-version.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-version.lo `test -f 'soup-version.c' || echo '$(srcdir)/'`soup-version.c + +libsoup_2_4_la-soup-websocket.lo: soup-websocket.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-websocket.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-websocket.Tpo -c -o libsoup_2_4_la-soup-websocket.lo `test -f 'soup-websocket.c' || echo '$(srcdir)/'`soup-websocket.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-websocket.Tpo $(DEPDIR)/libsoup_2_4_la-soup-websocket.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-websocket.c' object='libsoup_2_4_la-soup-websocket.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-websocket.lo `test -f 'soup-websocket.c' || echo '$(srcdir)/'`soup-websocket.c + +libsoup_2_4_la-soup-websocket-connection.lo: soup-websocket-connection.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-websocket-connection.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-websocket-connection.Tpo -c -o libsoup_2_4_la-soup-websocket-connection.lo `test -f 'soup-websocket-connection.c' || echo '$(srcdir)/'`soup-websocket-connection.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-websocket-connection.Tpo $(DEPDIR)/libsoup_2_4_la-soup-websocket-connection.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-websocket-connection.c' object='libsoup_2_4_la-soup-websocket-connection.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-websocket-connection.lo `test -f 'soup-websocket-connection.c' || echo '$(srcdir)/'`soup-websocket-connection.c + +libsoup_2_4_la-soup-xmlrpc.lo: soup-xmlrpc.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-xmlrpc.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-xmlrpc.Tpo -c -o libsoup_2_4_la-soup-xmlrpc.lo `test -f 'soup-xmlrpc.c' || echo '$(srcdir)/'`soup-xmlrpc.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-xmlrpc.Tpo $(DEPDIR)/libsoup_2_4_la-soup-xmlrpc.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-xmlrpc.c' object='libsoup_2_4_la-soup-xmlrpc.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-xmlrpc.lo `test -f 'soup-xmlrpc.c' || echo '$(srcdir)/'`soup-xmlrpc.c + +libsoup_2_4_la-soup-xmlrpc-old.lo: soup-xmlrpc-old.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_2_4_la-soup-xmlrpc-old.lo -MD -MP -MF $(DEPDIR)/libsoup_2_4_la-soup-xmlrpc-old.Tpo -c -o libsoup_2_4_la-soup-xmlrpc-old.lo `test -f 'soup-xmlrpc-old.c' || echo '$(srcdir)/'`soup-xmlrpc-old.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_2_4_la-soup-xmlrpc-old.Tpo $(DEPDIR)/libsoup_2_4_la-soup-xmlrpc-old.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-xmlrpc-old.c' object='libsoup_2_4_la-soup-xmlrpc-old.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_2_4_la-soup-xmlrpc-old.lo `test -f 'soup-xmlrpc-old.c' || echo '$(srcdir)/'`soup-xmlrpc-old.c + +libsoup_gnome_2_4_la-soup-cookie-jar-sqlite.lo: soup-cookie-jar-sqlite.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_gnome_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_gnome_2_4_la-soup-cookie-jar-sqlite.lo -MD -MP -MF $(DEPDIR)/libsoup_gnome_2_4_la-soup-cookie-jar-sqlite.Tpo -c -o libsoup_gnome_2_4_la-soup-cookie-jar-sqlite.lo `test -f 'soup-cookie-jar-sqlite.c' || echo '$(srcdir)/'`soup-cookie-jar-sqlite.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_gnome_2_4_la-soup-cookie-jar-sqlite.Tpo $(DEPDIR)/libsoup_gnome_2_4_la-soup-cookie-jar-sqlite.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-cookie-jar-sqlite.c' object='libsoup_gnome_2_4_la-soup-cookie-jar-sqlite.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_gnome_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_gnome_2_4_la-soup-cookie-jar-sqlite.lo `test -f 'soup-cookie-jar-sqlite.c' || echo '$(srcdir)/'`soup-cookie-jar-sqlite.c + +libsoup_gnome_2_4_la-soup-gnome-features.lo: soup-gnome-features.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_gnome_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_gnome_2_4_la-soup-gnome-features.lo -MD -MP -MF $(DEPDIR)/libsoup_gnome_2_4_la-soup-gnome-features.Tpo -c -o libsoup_gnome_2_4_la-soup-gnome-features.lo `test -f 'soup-gnome-features.c' || echo '$(srcdir)/'`soup-gnome-features.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_gnome_2_4_la-soup-gnome-features.Tpo $(DEPDIR)/libsoup_gnome_2_4_la-soup-gnome-features.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-gnome-features.c' object='libsoup_gnome_2_4_la-soup-gnome-features.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_gnome_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_gnome_2_4_la-soup-gnome-features.lo `test -f 'soup-gnome-features.c' || echo '$(srcdir)/'`soup-gnome-features.c + +libsoup_gnome_2_4_la-soup-proxy-resolver-gnome.lo: soup-proxy-resolver-gnome.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_gnome_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_gnome_2_4_la-soup-proxy-resolver-gnome.lo -MD -MP -MF $(DEPDIR)/libsoup_gnome_2_4_la-soup-proxy-resolver-gnome.Tpo -c -o libsoup_gnome_2_4_la-soup-proxy-resolver-gnome.lo `test -f 'soup-proxy-resolver-gnome.c' || echo '$(srcdir)/'`soup-proxy-resolver-gnome.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_gnome_2_4_la-soup-proxy-resolver-gnome.Tpo $(DEPDIR)/libsoup_gnome_2_4_la-soup-proxy-resolver-gnome.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-proxy-resolver-gnome.c' object='libsoup_gnome_2_4_la-soup-proxy-resolver-gnome.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_gnome_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_gnome_2_4_la-soup-proxy-resolver-gnome.lo `test -f 'soup-proxy-resolver-gnome.c' || echo '$(srcdir)/'`soup-proxy-resolver-gnome.c + +libsoup_gnome_2_4_la-soup-password-manager-gnome.lo: soup-password-manager-gnome.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_gnome_2_4_la_CFLAGS) $(CFLAGS) -MT libsoup_gnome_2_4_la-soup-password-manager-gnome.lo -MD -MP -MF $(DEPDIR)/libsoup_gnome_2_4_la-soup-password-manager-gnome.Tpo -c -o libsoup_gnome_2_4_la-soup-password-manager-gnome.lo `test -f 'soup-password-manager-gnome.c' || echo '$(srcdir)/'`soup-password-manager-gnome.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoup_gnome_2_4_la-soup-password-manager-gnome.Tpo $(DEPDIR)/libsoup_gnome_2_4_la-soup-password-manager-gnome.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soup-password-manager-gnome.c' object='libsoup_gnome_2_4_la-soup-password-manager-gnome.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoup_gnome_2_4_la_CFLAGS) $(CFLAGS) -c -o libsoup_gnome_2_4_la-soup-password-manager-gnome.lo `test -f 'soup-password-manager-gnome.c' || echo '$(srcdir)/'`soup-password-manager-gnome.c + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-girDATA: $(gir_DATA) + @$(NORMAL_INSTALL) + @list='$(gir_DATA)'; test -n "$(girdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(girdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(girdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(girdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(girdir)" || exit $$?; \ + done + +uninstall-girDATA: + @$(NORMAL_UNINSTALL) + @list='$(gir_DATA)'; test -n "$(girdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(girdir)'; $(am__uninstall_files_from_dir) +install-typelibDATA: $(typelib_DATA) + @$(NORMAL_INSTALL) + @list='$(typelib_DATA)'; test -n "$(typelibdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(typelibdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(typelibdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(typelibdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(typelibdir)" || exit $$?; \ + done + +uninstall-typelibDATA: + @$(NORMAL_UNINSTALL) + @list='$(typelib_DATA)'; test -n "$(typelibdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(typelibdir)'; $(am__uninstall_files_from_dir) +install-vapiDATA: $(vapi_DATA) + @$(NORMAL_INSTALL) + @list='$(vapi_DATA)'; test -n "$(vapidir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(vapidir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(vapidir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(vapidir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(vapidir)" || exit $$?; \ + done + +uninstall-vapiDATA: + @$(NORMAL_UNINSTALL) + @list='$(vapi_DATA)'; test -n "$(vapidir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(vapidir)'; $(am__uninstall_files_from_dir) +install-libsoupgnomeincludeHEADERS: $(libsoupgnomeinclude_HEADERS) + @$(NORMAL_INSTALL) + @list='$(libsoupgnomeinclude_HEADERS)'; test -n "$(libsoupgnomeincludedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(libsoupgnomeincludedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libsoupgnomeincludedir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libsoupgnomeincludedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(libsoupgnomeincludedir)" || exit $$?; \ + done + +uninstall-libsoupgnomeincludeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(libsoupgnomeinclude_HEADERS)'; test -n "$(libsoupgnomeincludedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(libsoupgnomeincludedir)'; $(am__uninstall_files_from_dir) +install-libsoupincludeHEADERS: $(libsoupinclude_HEADERS) + @$(NORMAL_INSTALL) + @list='$(libsoupinclude_HEADERS)'; test -n "$(libsoupincludedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(libsoupincludedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libsoupincludedir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libsoupincludedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(libsoupincludedir)" || exit $$?; \ + done + +uninstall-libsoupincludeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(libsoupinclude_HEADERS)'; test -n "$(libsoupincludedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(libsoupincludedir)'; $(am__uninstall_files_from_dir) +install-nodist_libsoupincludeHEADERS: $(nodist_libsoupinclude_HEADERS) + @$(NORMAL_INSTALL) + @list='$(nodist_libsoupinclude_HEADERS)'; test -n "$(libsoupincludedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(libsoupincludedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libsoupincludedir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libsoupincludedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(libsoupincludedir)" || exit $$?; \ + done + +uninstall-nodist_libsoupincludeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(nodist_libsoupinclude_HEADERS)'; test -n "$(libsoupincludedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(libsoupincludedir)'; $(am__uninstall_files_from_dir) + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$(top_distdir)" distdir="$(distdir)" \ + dist-hook +check-am: all-am +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-am +all-am: Makefile $(LTLIBRARIES) $(DATA) $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(girdir)" "$(DESTDIR)$(typelibdir)" "$(DESTDIR)$(vapidir)" "$(DESTDIR)$(libsoupgnomeincludedir)" "$(DESTDIR)$(libsoupincludedir)" "$(DESTDIR)$(libsoupincludedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +clean: clean-am + +clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-girDATA install-libsoupgnomeincludeHEADERS \ + install-libsoupincludeHEADERS \ + install-nodist_libsoupincludeHEADERS install-typelibDATA \ + install-vapiDATA + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-libLTLIBRARIES + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-girDATA uninstall-libLTLIBRARIES \ + uninstall-libsoupgnomeincludeHEADERS \ + uninstall-libsoupincludeHEADERS \ + uninstall-nodist_libsoupincludeHEADERS uninstall-typelibDATA \ + uninstall-vapiDATA + +.MAKE: all check install install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libLTLIBRARIES clean-libtool cscopelist-am ctags \ + ctags-am dist-hook distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-girDATA install-html \ + install-html-am install-info install-info-am \ + install-libLTLIBRARIES install-libsoupgnomeincludeHEADERS \ + install-libsoupincludeHEADERS install-man \ + install-nodist_libsoupincludeHEADERS install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + install-typelibDATA install-vapiDATA installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am uninstall-girDATA \ + uninstall-libLTLIBRARIES uninstall-libsoupgnomeincludeHEADERS \ + uninstall-libsoupincludeHEADERS \ + uninstall-nodist_libsoupincludeHEADERS uninstall-typelibDATA \ + uninstall-vapiDATA + +.PRECIOUS: Makefile + + +include $(GLIB_MAKEFILE) + +tld_data.inc: tld-parser.py $(TLD_DATA_FILE) + $(srcdir)/tld-parser.py $(TLD_DATA_FILE) tld_data.inc + +# +# Introspection support +# +include $(INTROSPECTION_MAKEFILE) + +@HAVE_INTROSPECTION_TRUE@Soup-2.4.gir: libsoup-2.4.la + +@ENABLE_VAPIGEN_TRUE@@HAVE_INTROSPECTION_TRUE@libsoup-2.4.vapi: Soup-2.4.gir Soup-2.4.metadata Soup-2.4-custom.vala +@ENABLE_VAPIGEN_TRUE@@HAVE_INTROSPECTION_TRUE@ $(VAPIGEN) --metadatadir=$(top_srcdir)/libsoup --pkg gio-2.0 --library=libsoup-2.4 $^ +@BUILD_LIBSOUP_GNOME_TRUE@@HAVE_INTROSPECTION_TRUE@SoupGNOME-2.4.gir: libsoup-gnome-2.4.la Soup-2.4.gir + +# +# Creates Visual Studio 2008/2010 projects from items passed in from autotools files +# $(1) - Base Name of the MSVC project files (outputs) +# + +define msvcproj-builder + +$(top_builddir)/win32/vs10/$(1).vcxproj: $(top_builddir)/win32/vs9/$(1).vcproj +$(top_builddir)/win32/vs10/$(1).vcxproj.filters: $(top_builddir)/win32/vs9/$(1).vcproj +$(1).sourcefiles: $(top_builddir)/win32/vs9/$(1).vcproj +$(1).vs10.sourcefiles: $(top_builddir)/win32/vs9/$(1).vcproj +$(1).vs10.sourcefiles.filters: $(top_builddir)/win32/vs9/$(1).vcproj + +$(top_builddir)/win32/vs9/$(1).vcproj: Makefile + -$(RM) $(top_builddir)/win32/vs9/$(1).vcproj + -$(RM) $(top_builddir)/win32/vs10/$(1).vcxproj + -$(RM) $(top_builddir)/win32/vs10/$(1).vcxproj.filters + -$(RM) $(top_builddir)/win32/vs11/$(1).vcxproj + -$(RM) $(top_builddir)/win32/vs11/$(1).vcxproj.filters + -$(RM) $(top_builddir)/win32/vs12/$(1).vcxproj + -$(RM) $(top_builddir)/win32/vs12/$(1).vcxproj.filters + -$(RM) $(top_builddir)/win32/vs14/$(1).vcxproj + -$(RM) $(top_builddir)/win32/vs14/$(1).vcxproj.filters + + for F in $(_proj_files); do \ + case $$$$F in \ + $(_proj_filters)) \ + ;; \ + *.c|*.cpp|*.cc|*.cxx) \ + echo ' ' >>$(1).sourcefiles && \ + echo ' ' >>$(1).vs10.sourcefiles && \ + echo ' Source Files' >>$(1).vs10.sourcefiles.filters \ + ;; \ + esac; \ + done + + $(CPP) -P - <$(top_srcdir)/win32/vs9/$(1).vcprojin >$(top_builddir)/win32/vs9/$(1).vcproj + $(CPP) -P - <$(top_srcdir)/win32/vs10/$(1).vcxprojin >$(top_builddir)/win32/vs10/$(1).vcxproj + $(CPP) -P - <$(top_srcdir)/win32/vs10/$(1).vcxproj.filtersin >$(top_builddir)/win32/vs10/$(1).vcxproj.filters + $(RM) $(1).sourcefiles + $(RM) $(1).vs10.sourcefiles + $(RM) $(1).vs10.sourcefiles.filters + +$(top_builddir)/win32/vs10/$(1).vs10.headers: $(top_builddir)/win32/vs9/$(1).headers + +$(top_builddir)/win32/vs9/$(1).headers: Makefile + -$(RM) $(top_builddir)/win32/vs9/$(1).headers + -$(RM) $(top_builddir)/win32/vs10/$(1).vs10.headers + + for F in $(_proj_headers); do \ + case $$$$F in \ + $(_proj_headers_excludes)) \ + ;; \ + *.h|*.hpp|*.hh|*.hxx) \ + echo 'copy ..\..'$(_proj_subdir)$$$$F' $$$$(CopyDir)\include'$(_headers_destdir)'\'$$$$F' ' >>$(top_builddir)/win32/vs9/$(1).headers && \ + echo 'copy ..\..'$(_proj_subdir)$$$$F' $$$$(CopyDir)\include'$(_headers_destdir)'\'$$$$F >>$(top_builddir)/win32/vs10/$(1).vs10.headers \ + ;; \ + esac; \ + done + +$(top_builddir)/win32/vs12/$(1).vcxproj.filters: $(top_builddir)/win32/vs12/$(1).vcxproj + +$(top_builddir)/win32/vs12/$(1).vcxproj: Makefile + -$(RM) $(top_builddir)/win32/vs14/$(1).vcxproj + -$(RM) $(top_builddir)/win32/vs14/$(1).vcxproj.filters + + for F in $(_proj_files); do \ + case $$$$F in \ + $(_proj_filters)) \ + ;; \ + *.c|*.cpp|*.cc|*.cxx) \ + echo ' ' >>$(1).vs12.sourcefiles && \ + echo ' Source Files' >>$(1).vs12.sourcefiles.filters \ + ;; \ + esac; \ + done + + $(CPP) -P - <$(top_srcdir)/win32/vs12/$(1).vcxprojin >$(top_builddir)/win32/vs12/$(1).vcxproj + $(CPP) -P - <$(top_srcdir)/win32/vs12/$(1).vcxproj.filtersin >$(top_builddir)/win32/vs12/$(1).vcxproj.filters + $(RM) $(1).vs12.sourcefiles + $(RM) $(1).vs12.sourcefiles.filters + +$(top_builddir)/win32/vs12/$(1).vs12.headers: Makefile + -$(RM) $(top_builddir)/win32/vs12/$(1).vs12.headers + + for F in $(_proj_headers); do \ + case $$$$F in \ + $(_proj_headers_excludes)) \ + ;; \ + *.h|*.hpp|*.hh|*.hxx) \ + echo 'copy ..\..'$(_proj_subdir)$$$$F' $$$$(CopyDir)\include'$(_headers_destdir)'\'$$$$F >>$(top_builddir)/win32/vs12/$(1).vs12.headers \ + ;; \ + esac; \ + done + +endef + +$(foreach proj,$(MSVCPROJS),$(eval $(call msvcproj-builder,$(proj)))) + +# +# Create NMake Makefile Sections for Building Introspection files +# from autotools files +# $(1) - File Name of the .gir that is to be generated +# + +@HAVE_INTROSPECTION_TRUE@define gir-nmake-builder + +# Basic sanity check, to make sure required variables are set +@HAVE_INTROSPECTION_TRUE@$(if $($(_gir_name)_MSVC_FILES),,$(error Need to define $(_gir_name)_MSVC_FILES)) +@HAVE_INTROSPECTION_TRUE@$(if $(or $(findstring --header-only,$($(_gir_name)_MSVC_SCANNERFLAGS)), +@HAVE_INTROSPECTION_TRUE@ $($(_gir_name)_MSVC_LIBS), +@HAVE_INTROSPECTION_TRUE@ $($(_gir_name)_MSVC_PROGRAM)),, +@HAVE_INTROSPECTION_TRUE@ $(error Need to define $(_gir_name)_MSVC_LIBS or $(_gir_name)_MSVC_PROGRAM)) + +@HAVE_INTROSPECTION_TRUE@$(top_builddir)/win32/$(_gir_name)_list: +@HAVE_INTROSPECTION_TRUE@ for F in $(_gir_files_msvc); do \ +@HAVE_INTROSPECTION_TRUE@ case $$$$F in \ +@HAVE_INTROSPECTION_TRUE@ *.c|*.cpp|*.cc|*.cxx|*.h|*.hpp|*.hh|*.hxx) \ +@HAVE_INTROSPECTION_TRUE@ echo '..'$(_gir_source_subdir_msvc)$$$$F >>$(top_builddir)/win32/$(_gir_name)_list \ +@HAVE_INTROSPECTION_TRUE@ ;; \ +@HAVE_INTROSPECTION_TRUE@ esac; \ +@HAVE_INTROSPECTION_TRUE@ done + +@HAVE_INTROSPECTION_TRUE@$(top_builddir)/win32/$(1).msvc.introspect: +@HAVE_INTROSPECTION_TRUE@ -$(RM) $(top_builddir)/win32/$(1).msvc.introspect + +# Assemble the Command to Run g-ir-scanner +@HAVE_INTROSPECTION_TRUE@ echo $(1)': '$(_gir_name)'_list '$($(_gir_name)_MSVC_GIR_DEPS)>>$(top_builddir)/win32/$(1).msvc.introspect +@HAVE_INTROSPECTION_TRUE@ echo ' @-echo Generating $$$$@...'>>$(top_builddir)/win32/$(1).msvc.introspect +@HAVE_INTROSPECTION_TRUE@ echo ' $$$$(PYTHON) $$$$(G_IR_SCANNER) \'>>$(top_builddir)/win32/$(1).msvc.introspect +@HAVE_INTROSPECTION_TRUE@ echo ' --verbose -no-libtool \'>>$(top_builddir)/win32/$(1).msvc.introspect +@HAVE_INTROSPECTION_TRUE@ echo ' --namespace='$(_gir_namespace_msvc)' \'>>$(top_builddir)/win32/$(1).msvc.introspect +@HAVE_INTROSPECTION_TRUE@ echo ' --nsversion='$(_gir_version_msvc)' \'>>$(top_builddir)/win32/$(1).msvc.introspect +@HAVE_INTROSPECTION_TRUE@ echo ' '$(_gir_packages_msvc)' \'>>$(top_builddir)/win32/$(1).msvc.introspect +@HAVE_INTROSPECTION_TRUE@ echo ' '$(_gir_libraries_msvc)' \'>>$(top_builddir)/win32/$(1).msvc.introspect +@HAVE_INTROSPECTION_TRUE@ echo ' '$(_gir_program_msvc)' \'>>$(top_builddir)/win32/$(1).msvc.introspect +@HAVE_INTROSPECTION_TRUE@ echo ' --add-include-path=$$$$(G_IR_INCLUDEDIR) \'>>$(top_builddir)/win32/$(1).msvc.introspect +@HAVE_INTROSPECTION_TRUE@ echo ' '$(_gir_includes_msvc)' \'>>$(top_builddir)/win32/$(1).msvc.introspect +@HAVE_INTROSPECTION_TRUE@ echo ' '$(_gir_export_packages_msvc)' \'>>$(top_builddir)/win32/$(1).msvc.introspect +@HAVE_INTROSPECTION_TRUE@ echo ' '$(_gir_c_includes_msvc)' \'>>$(top_builddir)/win32/$(1).msvc.introspect +@HAVE_INTROSPECTION_TRUE@ echo ' --cflags-begin \'>>$(top_builddir)/win32/$(1).msvc.introspect +@HAVE_INTROSPECTION_TRUE@ echo ' '$($(_gir_name)_MSVC_CFLAGS)' \'>>$(top_builddir)/win32/$(1).msvc.introspect +@HAVE_INTROSPECTION_TRUE@ echo ' --cflags-end \'>>$(top_builddir)/win32/$(1).msvc.introspect +@HAVE_INTROSPECTION_TRUE@ echo ' '$($(_gir_name)_MSVC_SCANNERFLAGS)' \'>>$(top_builddir)/win32/$(1).msvc.introspect +@HAVE_INTROSPECTION_TRUE@ echo ' --filelist='$(_gir_name)'_list \'>>$(top_builddir)/win32/$(1).msvc.introspect +@HAVE_INTROSPECTION_TRUE@ echo ' -o $$$$@'>>$(top_builddir)/win32/$(1).msvc.introspect +@HAVE_INTROSPECTION_TRUE@ echo '' >>$(top_builddir)/win32/$(1).msvc.introspect + +# Finally Assemble the Command to Compile the generated .gir +@HAVE_INTROSPECTION_TRUE@ echo '$(_typelib_basename_msvc).typelib: '$(_typelib_basename_msvc)'.gir'>>$(top_builddir)/win32/$(1).msvc.introspect +@HAVE_INTROSPECTION_TRUE@ echo ' @-echo Compiling $$$$@...'>>$(top_builddir)/win32/$(1).msvc.introspect +@HAVE_INTROSPECTION_TRUE@ echo ' $$$$(G_IR_COMPILER) \'>>$(top_builddir)/win32/$(1).msvc.introspect +@HAVE_INTROSPECTION_TRUE@ echo ' --includedir=. --debug --verbose \'>>$(top_builddir)/win32/$(1).msvc.introspect +@HAVE_INTROSPECTION_TRUE@ echo ' '$(1)' \'>>$(top_builddir)/win32/$(1).msvc.introspect +@HAVE_INTROSPECTION_TRUE@ echo ' -o $$$$@'>>$(top_builddir)/win32/$(1).msvc.introspect +@HAVE_INTROSPECTION_TRUE@ echo '' >>$(top_builddir)/win32/$(1).msvc.introspect +@HAVE_INTROSPECTION_TRUE@endef + +@HAVE_INTROSPECTION_TRUE@$(foreach gir,$(MSVC_INTROSPECT_GIRS),$(eval $(call gir-nmake-builder,$(gir)))) + +dist-hook: \ + $(top_builddir)/win32/vs9/soup.vcproj \ + $(top_builddir)/win32/vs9/soup.headers \ + $(top_builddir)/win32/vs9/soup-gnome.vcproj \ + $(top_builddir)/win32/vs9/soup-gnome.headers \ + $(INTROSPECTION_INTERMEDIATE_ITEMS) + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/libsoup/Soup-2.4-custom.vala b/libsoup/Soup-2.4-custom.vala new file mode 100644 index 0000000..95c2ad9 --- /dev/null +++ b/libsoup/Soup-2.4-custom.vala @@ -0,0 +1,168 @@ +namespace Soup { + [CCode (type_id = "soup_auth_domain_basic_get_type ()", cheader_filename = "libsoup/soup.h")] + public class AuthDomainBasic : Soup.AuthDomain { + public static void set_auth_callback (Soup.AuthDomain domain, owned Soup.AuthDomainBasicAuthCallback callback); + } + + [CCode (type_id = "soup_auth_domain_digest_get_type ()", cheader_filename = "libsoup/soup.h")] + public class AuthDomainDigest : Soup.AuthDomain { + public static void set_auth_callback (Soup.AuthDomain domain, owned Soup.AuthDomainDigestAuthCallback callback); + } + + [Compact] + [CCode (copy_function = "g_boxed_copy", free_function = "g_boxed_free", type_id = "soup_buffer_get_type ()", cheader_filename = "libsoup/soup.h")] + public class Buffer { + [CCode (has_construct_function = false)] + public Buffer.subbuffer (Soup.Buffer parent, size_t offset, size_t length); + } + + [Version (replacement = "Soup.ProxyURIResolver")] + [CCode (cheader_filename = "libsoup/soup.h", type_cname = "SoupProxyResolverInterface", type_id = "soup_proxy_resolver_get_type ()")] + public interface ProxyResolver : Soup.SessionFeature, GLib.Object { + public abstract void get_proxy_async (Soup.Message msg, GLib.MainContext async_context, GLib.Cancellable? cancellable, Soup.ProxyResolverCallback callback); + public abstract uint get_proxy_sync (Soup.Message msg, GLib.Cancellable? cancellable, out unowned Soup.Address addr); + } + + public errordomain SSLError { + HANDSHAKE_NEEDS_READ, + HANDSHAKE_NEEDS_WRITE, + CERTIFICATE, + HANDSHAKE_FAILED; + public static GLib.Quark quark (); + } + + [Compact] + [CCode (copy_function = "g_boxed_copy", free_function = "g_boxed_free", type_id = "soup_uri_get_type ()", cheader_filename = "libsoup/soup.h")] + public class URI { + [CCode (has_construct_function = false)] + public URI.with_base (Soup.URI @base, string uri_string); + } + + [Version (deprecated_since = "vala-0.12", replacement = "XMLRPC.build_fault")] + [PrintfFormat] + public static unowned string xmlrpc_build_fault (int fault_code, string fault_format, ...); + [Version (deprecated_since = "vala-0.12", replacement = "XMLRPC.build_method_call")] + public static unowned string xmlrpc_build_method_call (string method_name, GLib.Value[] @params); + [Version (deprecated_since = "vala-0.12", replacement = "XMLRPC.build_method_response")] + public static unowned string xmlrpc_build_method_response (GLib.Value value); + [Version (deprecated_since = "vala-0.12", replacement = "XMLRPC.error_quark")] + public static GLib.Quark xmlrpc_error_quark (); + [Version (deprecated_since = "vala-0.12", replacement = "XMLRPC.extract_method_call")] + [CCode (sentinel = "G_TYPE_INVALID")] + public static bool xmlrpc_extract_method_call (string method_call, int length, out unowned string method_name, ...); + [Version (deprecated_since = "vala-0.12", replacement = "XMLRPC.extract_method_response")] + [CCode (sentinel = "G_TYPE_INVALID")] + public static bool xmlrpc_extract_method_response (string method_response, int length, ...) throws GLib.Error; + [Version (deprecated_since = "vala-0.12", replacement = "XMLRPC.fault_quark")] + public static GLib.Quark xmlrpc_fault_quark (); + [Version (deprecated_since = "vala-0.12", replacement = "XMLRPC.parse_method_call")] + public static bool xmlrpc_parse_method_call (string method_call, int length, out unowned string method_name, out unowned GLib.ValueArray @params); + [Version (deprecated_since = "vala-0.12", replacement = "XMLRPC.parse_method_response")] + public static bool xmlrpc_parse_method_response (string method_response, int length, GLib.Value value) throws GLib.Error; + [Version (deprecated_since = "vala-0.12", replacement = "XMLRPC.request_new")] + [CCode (sentinel = "G_TYPE_INVALID")] + public static unowned Soup.Message xmlrpc_request_new (string uri, string method_name, ...); + [Version (deprecated_since = "vala-0.12", replacement = "XMLRPC.set_fault")] + [PrintfFormat] + public static void xmlrpc_set_fault (Soup.Message msg, int fault_code, string fault_format, ...); + [Version (deprecated_since = "vala-0.12", replacement = "XMLRPC.set_response")] + [CCode (sentinel = "G_TYPE_INVALID")] + public static void xmlrpc_set_response (Soup.Message msg, ...); + + [Version (deprecated_since = "vala-0.12", replacement = "Form.decode")] + public static GLib.HashTable form_decode (string encoded_form); + [Version (deprecated_since = "vala-0.12", replacement = "Form.decode_multipart")] + public static GLib.HashTable form_decode_multipart (Soup.Message msg, string file_control_name, out string filename, out string content_type, out Soup.Buffer file); + [Version (deprecated_since = "vala-0.12", replacement = "Form.encode")] + public static string form_encode (...); + [Version (deprecated_since = "vala-0.12", replacement = "Form.encode_datalist")] + public static string form_encode_datalist (void* form_data_set); + [Version (deprecated_since = "vala-0.12", replacement = "Form.encode_hash")] + public static string form_encode_hash (GLib.HashTable form_data_set); + [Version (deprecated_since = "vala-0.12")] + public static string form_encode_valist (string first_field, void* args); + [Version (deprecated_since = "vala-0.12", replacement = "Form.request_new")] + public static Soup.Message form_request_new (string method, string uri, ...); + [Version (deprecated_since = "vala-0.12", replacement = "Form.request_new_from_datalist")] + public static Soup.Message form_request_new_from_datalist (string method, string uri, void* form_data_set); + [Version (deprecated_since = "vala-0.12", replacement = "Form.request_new_from_hash")] + public static Soup.Message form_request_new_from_hash (string method, string uri, GLib.HashTable form_data_set); + [Version (deprecated_since = "vala-0.12", replacement = "Form.request_new_from_multipart")] + public static Soup.Message form_request_new_from_multipart (string uri, Soup.Multipart multipart); + [Version (deprecated_since = "vala-0.14", replacement = "SSLError.quark")] + public static GLib.Quark ssl_error_quark (); + + [Version (deprecated_since = "vala-0.22", replacement = "Status.get_phrase")] + public static unowned string status_get_phrase (uint status_code); + [Version (deprecated_since = "vala-0.22", replacement = "Status.proxify")] + public static uint status_proxify (uint status_code); + [Version (deprecated_since = "vala-0.22", replacement = "Status")] + [CCode (cheader_filename = "libsoup/soup.h", cprefix = "SOUP_STATUS_", type_id = "soup_known_status_code_get_type ()")] + public enum KnownStatusCode { + NONE, + CANCELLED, + CANT_RESOLVE, + CANT_RESOLVE_PROXY, + CANT_CONNECT, + CANT_CONNECT_PROXY, + SSL_FAILED, + IO_ERROR, + MALFORMED, + TRY_AGAIN, + TOO_MANY_REDIRECTS, + TLS_FAILED, + CONTINUE, + SWITCHING_PROTOCOLS, + PROCESSING, + OK, + CREATED, + ACCEPTED, + NON_AUTHORITATIVE, + NO_CONTENT, + RESET_CONTENT, + PARTIAL_CONTENT, + MULTI_STATUS, + MULTIPLE_CHOICES, + MOVED_PERMANENTLY, + FOUND, + MOVED_TEMPORARILY, + SEE_OTHER, + NOT_MODIFIED, + USE_PROXY, + NOT_APPEARING_IN_THIS_PROTOCOL, + TEMPORARY_REDIRECT, + BAD_REQUEST, + UNAUTHORIZED, + PAYMENT_REQUIRED, + FORBIDDEN, + NOT_FOUND, + METHOD_NOT_ALLOWED, + NOT_ACCEPTABLE, + PROXY_AUTHENTICATION_REQUIRED, + PROXY_UNAUTHORIZED, + REQUEST_TIMEOUT, + CONFLICT, + GONE, + LENGTH_REQUIRED, + PRECONDITION_FAILED, + REQUEST_ENTITY_TOO_LARGE, + REQUEST_URI_TOO_LONG, + UNSUPPORTED_MEDIA_TYPE, + REQUESTED_RANGE_NOT_SATISFIABLE, + INVALID_RANGE, + EXPECTATION_FAILED, + UNPROCESSABLE_ENTITY, + LOCKED, + FAILED_DEPENDENCY, + INTERNAL_SERVER_ERROR, + NOT_IMPLEMENTED, + BAD_GATEWAY, + SERVICE_UNAVAILABLE, + GATEWAY_TIMEOUT, + HTTP_VERSION_NOT_SUPPORTED, + INSUFFICIENT_STORAGE, + NOT_EXTENDED + } + + public delegate void ProxyResolverCallback (Soup.ProxyResolver p1, Soup.Message p2, uint p3, Soup.Address p4); +} diff --git a/libsoup/Soup-2.4.metadata b/libsoup/Soup-2.4.metadata new file mode 100644 index 0000000..43b6d04 --- /dev/null +++ b/libsoup/Soup-2.4.metadata @@ -0,0 +1,99 @@ +// Vala-specific +AuthDomain + .add_path#property skip + .remove_path#property skip +form_* parent="Soup.Form" name="form_(.+)" +form_encode_datalist.form_data_set type_arguments="string" +form_request_new_from_datalist.form_data_set type_arguments="string" +xmlrpc_* parent="Soup.XMLRPC" name="xmlrpc_(.+)" +XMLRPCFault errordomain parent="Soup.XMLRPC" name="Fault" +XMLRPCError parent="Soup.XMLRPC" name="Error" +xmlrpc_set_response.type skip +HTTPVersion.http_* name="http_(.+)" + +// Backwards compatibility +KnownStatusCode skip +Requester deprecated_since="2.42" replacement="Session" +Requester + .request* skip=false unowned=false + +// Report upstream +Soup cheader_filename="libsoup/soup.h" +add_* skip=false type="unowned GLib.TimeoutSource" +AuthDomain + .accepts#method skip + .challenge#virtual_method vfunc_name="challenge" + .basic_set_auth_callback skip + .digest_set_auth_callback skip +AuthDomainBasic.new skip=false +AuthDomainDigest.new skip=false +Buffer.new.data type="uint8[]" array_length_idx=2 +Buffer.new_with_owner.data type="uint8[]" array_length_idx=1 +Buffer.new_subbuffer skip +Buffer.new_with_owner.owner_dnotify nullable +CookieJar.all_cookies type_arguments="Cookie" +ContentSniffer.sniff.params type_arguments="string,string" nullable out unowned=false +form_* skip=false +header_parse_list type_arguments="string" +header_parse_quality_list type_arguments="string" + .unacceptable out type_arguments="string" +Message + .add_header_handler skip=false + .add_status_code_handler skip=false + .request_*#property skip + .response_*#property skip + .set_request.req_body type="uint8[]" array_length_idx=3 +MessageHeaders + .get_ranges.ranges out type="Soup.Range[]" array_length_idx=2 +Server + .new skip=false + .async_context type="GLib.MainContext" +Session + .async_context type="GLib.MainContext" + .get_features type_arguments="weak Soup.SessionFeature" + .send_async.cancellable#parameter default=null +Session*.new_with_options skip=false +Socket + .async_context type="GLib.MainContext" + .new skip=false + .read.buffer type="uint8[]" array_length_idx=1 + .read_until.buffer type="uint8[]" array_length_idx=1 + .read_until.nread out + .write.buffer type="uint8[]" array_length_idx=1 +URI + .new_with_base skip + .set_query_from_fields skip=false +uri_encode.escape_extra nullable +// uri_host_*.* type="Soup.URI" +ProxyURIResolverCallback.user_data skip +xmlrpc_* skip=false +// xmlrpc_build_method_call.params array array_length_idx=2 +xmlrpc_extract_method_response throws="Soup.XMLRPC.Fault" + .error skip + .type skip +value_* skip=false +ProxyURIResolver + .get_proxy_uri_async skip=false + .get_proxy_uri_async.callback owned scope="async" + .get_proxy_uri_async.async_context nullable + .get_proxy_uri_sync.proxy_uri out unowned=false + +// Not enough GIR information +Buffer.data type="uint8[]" array_length_field="length" +MessageBody.data type="uint8[]" array_length_field="length" +xmlrpc_parse_method_response throws="Soup.XMLRPC.Fault" +Date + .new_from_time_t.when type="time_t" + .to_time_t type="time_t" +xmlrpc_extract_method_call sentinel="G_TYPE_INVALID" +xmlrpc_extract_method_response sentinel="G_TYPE_INVALID" +xmlrpc_request_new sentinel="G_TYPE_INVALID" +xmlrpc_set_fault printf_format +xmlrpc_set_response sentinel="G_TYPE_INVALID" +xmlrpc_build_fault printf_format + +// Simplify memory management +Buffer + .new deprecated_since="2.32" replacement="Buffer.take" +MessageBody + .append deprecated_since="2.32" replacement="MessageBody.append_take" diff --git a/libsoup/gconstructor.h b/libsoup/gconstructor.h new file mode 100644 index 0000000..dccb031 --- /dev/null +++ b/libsoup/gconstructor.h @@ -0,0 +1,120 @@ +/* + If G_HAS_CONSTRUCTORS is true then the compiler support *both* constructors and + destructors, in a sane way, including e.g. on library unload. If not you're on + your own. + + Some compilers need #pragma to handle this, which does not work with macros, + so the way you need to use this is (for constructors): + + #ifdef G_DEFINE_CONSTRUCTOR_NEEDS_PRAGMA + #pragma G_DEFINE_CONSTRUCTOR_PRAGMA_ARGS(my_constructor) + #endif + G_DEFINE_CONSTRUCTOR(my_constructor) + static void my_constructor(void) { + ... + } + +*/ + +#ifndef __GTK_DOC_IGNORE__ + +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7) + +#define G_HAS_CONSTRUCTORS 1 + +#define G_DEFINE_CONSTRUCTOR(_func) static void __attribute__((constructor)) _func (void); +#define G_DEFINE_DESTRUCTOR(_func) static void __attribute__((destructor)) _func (void); + +#elif defined (_MSC_VER) && (_MSC_VER >= 1500) +/* Visual studio 2008 and later has _Pragma */ + +#define G_HAS_CONSTRUCTORS 1 + +/* We do some weird things to avoid the constructors being optimized + * away on VS2015 if WholeProgramOptimization is enabled. First we + * make a reference to the array from the wrapper to make sure its + * references. Then we use a pragma to make sure the wrapper function + * symbol is always included at the link stage. Also, the symbols + * need to be extern (but not dllexport), even though they are not + * really used from another object file. + */ + +/* We need to account for differences between the mangling of symbols + * for Win32 (x86) and x64 programs, as symbols on Win32 are prefixed + * with an underscore but symbols on x64 are not. + */ +#ifdef _WIN64 +#define G_MSVC_SYMBOL_PREFIX "" +#else +#define G_MSVC_SYMBOL_PREFIX "_" +#endif + +#define G_DEFINE_CONSTRUCTOR(_func) G_MSVC_CTOR (_func, G_MSVC_SYMBOL_PREFIX) +#define G_DEFINE_DESTRUCTOR(_func) G_MSVC_DTOR (_func, G_MSVC_SYMBOL_PREFIX) + +#define G_MSVC_CTOR(_func,_sym_prefix) \ + static void _func(void); \ + extern int (* _array ## _func)(void); \ + int _func ## _wrapper(void) { _func(); g_slist_find (NULL, _array ## _func); return 0; } \ + __pragma(comment(linker,"/include:" _sym_prefix # _func "_wrapper")) \ + __pragma(section(".CRT$XCU",read)) \ + __declspec(allocate(".CRT$XCU")) int (* _array ## _func)(void) = _func ## _wrapper; + +#define G_MSVC_DTOR(_func,_sym_prefix) \ + static void _func(void); \ + extern int (* _array ## _func)(void); \ + int _func ## _constructor(void) { atexit (_func); g_slist_find (NULL, _array ## _func); return 0; } \ + __pragma(comment(linker,"/include:" _sym_prefix # _func "_constructor")) \ + __pragma(section(".CRT$XCU",read)) \ + __declspec(allocate(".CRT$XCU")) int (* _array ## _func)(void) = _func ## _constructor; + +#elif defined (_MSC_VER) + +#define G_HAS_CONSTRUCTORS 1 + +/* Pre Visual studio 2008 must use #pragma section */ +#define G_DEFINE_CONSTRUCTOR_NEEDS_PRAGMA 1 +#define G_DEFINE_DESTRUCTOR_NEEDS_PRAGMA 1 + +#define G_DEFINE_CONSTRUCTOR_PRAGMA_ARGS(_func) \ + section(".CRT$XCU",read) +#define G_DEFINE_CONSTRUCTOR(_func) \ + static void _func(void); \ + static int _func ## _wrapper(void) { _func(); return 0; } \ + __declspec(allocate(".CRT$XCU")) static int (*p)(void) = _func ## _wrapper; + +#define G_DEFINE_DESTRUCTOR_PRAGMA_ARGS(_func) \ + section(".CRT$XCU",read) +#define G_DEFINE_DESTRUCTOR(_func) \ + static void _func(void); \ + static int _func ## _constructor(void) { atexit (_func); return 0; } \ + __declspec(allocate(".CRT$XCU")) static int (* _array ## _func)(void) = _func ## _constructor; + +#elif defined(__SUNPRO_C) + +/* This is not tested, but i believe it should work, based on: + * http://opensource.apple.com/source/OpenSSL098/OpenSSL098-35/src/fips/fips_premain.c + */ + +#define G_HAS_CONSTRUCTORS 1 + +#define G_DEFINE_CONSTRUCTOR_NEEDS_PRAGMA 1 +#define G_DEFINE_DESTRUCTOR_NEEDS_PRAGMA 1 + +#define G_DEFINE_CONSTRUCTOR_PRAGMA_ARGS(_func) \ + init(_func) +#define G_DEFINE_CONSTRUCTOR(_func) \ + static void _func(void); + +#define G_DEFINE_DESTRUCTOR_PRAGMA_ARGS(_func) \ + fini(_func) +#define G_DEFINE_DESTRUCTOR(_func) \ + static void _func(void); + +#else + +/* constructors not supported for this compiler */ + +#endif + +#endif /* __GTK_DOC_IGNORE__ */ diff --git a/libsoup/libsoup-2.4.deps b/libsoup/libsoup-2.4.deps new file mode 100644 index 0000000..cd10dfd --- /dev/null +++ b/libsoup/libsoup-2.4.deps @@ -0,0 +1 @@ +gio-2.0 diff --git a/libsoup/soup-address.c b/libsoup/soup-address.c new file mode 100644 index 0000000..53d3b61 --- /dev/null +++ b/libsoup/soup-address.c @@ -0,0 +1,1291 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-address.c: Internet address handing + * + * Copyright (C) 2010 Red Hat, Inc. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include + +#include "soup-address.h" +#include "soup.h" +#include "soup-misc-private.h" + +/** + * SECTION:soup-address + * @short_description: DNS support + * + * #SoupAddress represents the address of a TCP connection endpoint: + * both the IP address and the port. (It is somewhat like an + * object-oriented version of struct sockaddr.) + * + * Although #SoupAddress is still used in some libsoup API's, it + * should not be used in new code; use GLib's #GNetworkAddress or + * #GSocketAddress instead. + **/ + +enum { + PROP_0, + + PROP_NAME, + PROP_FAMILY, + PROP_PORT, + PROP_PROTOCOL, + PROP_PHYSICAL, + PROP_SOCKADDR, + + LAST_PROP +}; + +typedef struct { + struct sockaddr_storage *sockaddr; + int n_addrs, offset; + + char *name, *physical; + guint port; + const char *protocol; + + GMutex lock; +} SoupAddressPrivate; + +/* sockaddr generic macros */ +#define SOUP_SIN(priv) ((struct sockaddr_in *)priv->sockaddr) +#define SOUP_SIN6(priv) ((struct sockaddr_in6 *)priv->sockaddr) + +/* sockaddr family macros */ +#define SOUP_ADDRESS_GET_FAMILY(priv) (priv->sockaddr->ss_family) +#define SOUP_ADDRESS_SET_FAMILY(priv, family) \ + (priv->sockaddr->ss_family = family) +#define SOUP_ADDRESS_FAMILY_IS_VALID(family) \ + (family == AF_INET || family == AF_INET6) +#define SOUP_ADDRESS_FAMILY_SOCKADDR_SIZE(family) \ + (family == AF_INET ? sizeof (struct sockaddr_in) : \ + sizeof (struct sockaddr_in6)) +#define SOUP_ADDRESS_FAMILY_DATA_SIZE(family) \ + (family == AF_INET ? sizeof (struct in_addr) : \ + sizeof (struct in6_addr)) + +/* sockaddr port macros */ +#define SOUP_ADDRESS_PORT_IS_VALID(port) (((gint) port) >= 0 && port <= 65535) +#define SOUP_ADDRESS_GET_PORT(priv) \ + (priv->sockaddr->ss_family == AF_INET ? \ + SOUP_SIN(priv)->sin_port : \ + SOUP_SIN6(priv)->sin6_port) +#define SOUP_ADDRESS_SET_PORT(priv, port) \ + G_STMT_START { \ + if (priv->sockaddr->ss_family == AF_INET) \ + SOUP_SIN(priv)->sin_port = port; \ + else \ + SOUP_SIN6(priv)->sin6_port = port; \ + } G_STMT_END + +/* sockaddr data macros */ +#define SOUP_ADDRESS_GET_DATA(priv) \ + (priv->sockaddr->ss_family == AF_INET ? \ + (gpointer)&SOUP_SIN(priv)->sin_addr : \ + (gpointer)&SOUP_SIN6(priv)->sin6_addr) +#define SOUP_ADDRESS_SET_DATA(priv, data, length) \ + memcpy (SOUP_ADDRESS_GET_DATA (priv), data, length) + + +static void soup_address_connectable_iface_init (GSocketConnectableIface *connectable_iface); + +G_DEFINE_TYPE_WITH_CODE (SoupAddress, soup_address, G_TYPE_OBJECT, + G_ADD_PRIVATE (SoupAddress) + G_IMPLEMENT_INTERFACE (G_TYPE_SOCKET_CONNECTABLE, + soup_address_connectable_iface_init)) + +static void +soup_address_init (SoupAddress *addr) +{ + SoupAddressPrivate *priv = soup_address_get_instance_private (addr); + + g_mutex_init (&priv->lock); +} + +static void +soup_address_finalize (GObject *object) +{ + SoupAddress *addr = SOUP_ADDRESS (object); + SoupAddressPrivate *priv = soup_address_get_instance_private (addr); + + g_free (priv->sockaddr); + g_free (priv->name); + g_free (priv->physical); + + g_mutex_clear (&priv->lock); + + G_OBJECT_CLASS (soup_address_parent_class)->finalize (object); +} + +static GObject * +soup_address_constructor (GType type, + guint n_construct_properties, + GObjectConstructParam *construct_properties) +{ + GObject *addr; + SoupAddressPrivate *priv; + + addr = G_OBJECT_CLASS (soup_address_parent_class)->constructor ( + type, n_construct_properties, construct_properties); + if (!addr) + return NULL; + priv = soup_address_get_instance_private (SOUP_ADDRESS (addr)); + + if (!priv->name && !priv->sockaddr) { + g_object_unref (addr); + return NULL; + } + + return addr; +} + +static void +soup_address_set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + SoupAddressPrivate *priv = soup_address_get_instance_private (SOUP_ADDRESS (object)); + SoupAddressFamily family; + struct sockaddr *sa; + int len, port; + + /* This is a mess because the properties are mostly orthogonal, + * but g_object_constructor wants to set a default value for each + * of them. + */ + + switch (prop_id) { + case PROP_NAME: + priv->name = g_value_dup_string (value); + break; + + case PROP_FAMILY: + family = g_value_get_enum (value); + if (family == SOUP_ADDRESS_FAMILY_INVALID) + return; + g_return_if_fail (SOUP_ADDRESS_FAMILY_IS_VALID (family)); + g_return_if_fail (priv->sockaddr == NULL); + + priv->sockaddr = g_malloc0 (SOUP_ADDRESS_FAMILY_SOCKADDR_SIZE (family)); + SOUP_ADDRESS_SET_FAMILY (priv, family); + SOUP_ADDRESS_SET_PORT (priv, htons (priv->port)); + priv->n_addrs = 1; + break; + + case PROP_PORT: + port = g_value_get_int (value); + if (port == -1) + return; + g_return_if_fail (SOUP_ADDRESS_PORT_IS_VALID (port)); + + priv->port = port; + if (priv->sockaddr) + SOUP_ADDRESS_SET_PORT (priv, htons (port)); + break; + + case PROP_PROTOCOL: + priv->protocol = g_intern_string (g_value_get_string (value)); + break; + + case PROP_SOCKADDR: + sa = g_value_get_pointer (value); + if (!sa) + return; + g_return_if_fail (priv->sockaddr == NULL); + + len = SOUP_ADDRESS_FAMILY_SOCKADDR_SIZE (sa->sa_family); + priv->sockaddr = g_memdup (sa, len); + priv->n_addrs = 1; + priv->port = ntohs (SOUP_ADDRESS_GET_PORT (priv)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +soup_address_get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + SoupAddressPrivate *priv = soup_address_get_instance_private (SOUP_ADDRESS (object)); + + switch (prop_id) { + case PROP_NAME: + g_value_set_string (value, priv->name); + break; + case PROP_FAMILY: + if (priv->sockaddr) + g_value_set_enum (value, SOUP_ADDRESS_GET_FAMILY (priv)); + else + g_value_set_enum (value, 0); + break; + case PROP_PORT: + g_value_set_int (value, priv->port); + break; + case PROP_PHYSICAL: + g_value_set_string (value, soup_address_get_physical (SOUP_ADDRESS (object))); + break; + case PROP_PROTOCOL: + g_value_set_string (value, priv->protocol); + break; + case PROP_SOCKADDR: + g_value_set_pointer (value, priv->sockaddr); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +soup_address_class_init (SoupAddressClass *address_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (address_class); + + /* virtual method override */ + object_class->constructor = soup_address_constructor; + object_class->finalize = soup_address_finalize; + object_class->set_property = soup_address_set_property; + object_class->get_property = soup_address_get_property; + + /* properties */ + /** + * SOUP_ADDRESS_NAME: + * + * Alias for the #SoupAddress:name property. (The hostname for + * this address.) + **/ + g_object_class_install_property ( + object_class, PROP_NAME, + g_param_spec_string (SOUP_ADDRESS_NAME, + "Name", + "Hostname for this address", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + /** + * SOUP_ADDRESS_FAMILY: + * + * Alias for the #SoupAddress:family property. (The + * #SoupAddressFamily for this address.) + **/ + g_object_class_install_property ( + object_class, PROP_FAMILY, + g_param_spec_enum (SOUP_ADDRESS_FAMILY, + "Family", + "Address family for this address", + SOUP_TYPE_ADDRESS_FAMILY, + SOUP_ADDRESS_FAMILY_INVALID, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + /** + * SOUP_ADDRESS_PORT: + * + * An alias for the #SoupAddress:port property. (The port for + * this address.) + **/ + g_object_class_install_property ( + object_class, PROP_PORT, + g_param_spec_int (SOUP_ADDRESS_PORT, + "Port", + "Port for this address", + -1, 65535, -1, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + /** + * SOUP_ADDRESS_PROTOCOL: + * + * Alias for the #SoupAddress:protocol property. (The URI scheme + * used with this address.) + **/ + g_object_class_install_property ( + object_class, PROP_PROTOCOL, + g_param_spec_string (SOUP_ADDRESS_PROTOCOL, + "Protocol", + "URI scheme for this address", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + /** + * SOUP_ADDRESS_PHYSICAL: + * + * An alias for the #SoupAddress:physical property. (The + * stringified IP address for this address.) + **/ + g_object_class_install_property ( + object_class, PROP_PHYSICAL, + g_param_spec_string (SOUP_ADDRESS_PHYSICAL, + "Physical address", + "IP address for this address", + NULL, + G_PARAM_READABLE)); + /** + * SOUP_ADDRESS_SOCKADDR: + * + * An alias for the #SoupAddress:sockaddr property. (A pointer + * to the struct sockaddr for this address.) + **/ + g_object_class_install_property ( + object_class, PROP_SOCKADDR, + g_param_spec_pointer (SOUP_ADDRESS_SOCKADDR, + "sockaddr", + "struct sockaddr for this address", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); +} + +/** + * soup_address_new: + * @name: a hostname or physical address + * @port: a port number + * + * Creates a #SoupAddress from @name and @port. The #SoupAddress's IP + * address may not be available right away; the caller can call + * soup_address_resolve_async() or soup_address_resolve_sync() to + * force a DNS resolution. + * + * Return value: a #SoupAddress + **/ +SoupAddress * +soup_address_new (const char *name, guint port) +{ + g_return_val_if_fail (name != NULL, NULL); + g_return_val_if_fail (SOUP_ADDRESS_PORT_IS_VALID (port), NULL); + + return g_object_new (SOUP_TYPE_ADDRESS, + SOUP_ADDRESS_NAME, name, + SOUP_ADDRESS_PORT, port, + NULL); +} + +/** + * soup_address_new_from_sockaddr: + * @sa: a pointer to a sockaddr + * @len: size of @sa + * + * Returns a #SoupAddress equivalent to @sa (or %NULL if @sa's + * address family isn't supported) + * + * Return value: (nullable): the new #SoupAddress + **/ +SoupAddress * +soup_address_new_from_sockaddr (struct sockaddr *sa, int len) +{ + g_return_val_if_fail (sa != NULL, NULL); + g_return_val_if_fail (SOUP_ADDRESS_FAMILY_IS_VALID (sa->sa_family), NULL); + g_return_val_if_fail (len == SOUP_ADDRESS_FAMILY_SOCKADDR_SIZE (sa->sa_family), NULL); + + return g_object_new (SOUP_TYPE_ADDRESS, + SOUP_ADDRESS_SOCKADDR, sa, + NULL); +} + +SoupAddress * +soup_address_new_from_gsockaddr (GSocketAddress *addr) +{ + struct sockaddr_storage sa; + + g_socket_address_to_native (addr, &sa, sizeof (sa), NULL); + return g_object_new (SOUP_TYPE_ADDRESS, + SOUP_ADDRESS_SOCKADDR, &sa, + NULL); +} + +/** + * SoupAddressFamily: + * @SOUP_ADDRESS_FAMILY_INVALID: an invalid %SoupAddress + * @SOUP_ADDRESS_FAMILY_IPV4: an IPv4 address + * @SOUP_ADDRESS_FAMILY_IPV6: an IPv6 address + * + * The supported address families. + **/ + +/** + * SOUP_ADDRESS_ANY_PORT: + * + * This can be passed to any #SoupAddress method that expects a port, + * to indicate that you don't care what port is used. + **/ + +/** + * soup_address_new_any: + * @family: the address family + * @port: the port number (usually %SOUP_ADDRESS_ANY_PORT) + * + * Returns a #SoupAddress corresponding to the "any" address + * for @family (or %NULL if @family isn't supported), suitable for + * using as a listening #SoupSocket. + * + * Return value: (nullable): the new #SoupAddress + **/ +SoupAddress * +soup_address_new_any (SoupAddressFamily family, guint port) +{ + g_return_val_if_fail (SOUP_ADDRESS_FAMILY_IS_VALID (family), NULL); + g_return_val_if_fail (SOUP_ADDRESS_PORT_IS_VALID (port), NULL); + + return g_object_new (SOUP_TYPE_ADDRESS, + SOUP_ADDRESS_FAMILY, family, + SOUP_ADDRESS_PORT, port, + NULL); +} + +/** + * soup_address_get_name: + * @addr: a #SoupAddress + * + * Returns the hostname associated with @addr. + * + * This method is not thread-safe; if you call it while @addr is being + * resolved in another thread, it may return garbage. You can use + * soup_address_is_resolved() to safely test whether or not an address + * is resolved before fetching its name or address. + * + * Return value: (nullable): the hostname, or %NULL if it is not known. + **/ +const char * +soup_address_get_name (SoupAddress *addr) +{ + SoupAddressPrivate *priv; + + g_return_val_if_fail (SOUP_IS_ADDRESS (addr), NULL); + priv = soup_address_get_instance_private (addr); + + return priv->name; +} + +/** + * soup_address_get_sockaddr: + * @addr: a #SoupAddress + * @len: return location for sockaddr length + * + * Returns the sockaddr associated with @addr, with its length in + * *@len. If the sockaddr is not yet known, returns %NULL. + * + * This method is not thread-safe; if you call it while @addr is being + * resolved in another thread, it may return garbage. You can use + * soup_address_is_resolved() to safely test whether or not an address + * is resolved before fetching its name or address. + * + * Return value: (nullable) (transfer none): the sockaddr, or %NULL + **/ +struct sockaddr * +soup_address_get_sockaddr (SoupAddress *addr, int *len) +{ + SoupAddressPrivate *priv; + + g_return_val_if_fail (SOUP_IS_ADDRESS (addr), NULL); + priv = soup_address_get_instance_private (addr); + + if (priv->sockaddr && len) + *len = SOUP_ADDRESS_FAMILY_SOCKADDR_SIZE (SOUP_ADDRESS_GET_FAMILY (priv)); + return (struct sockaddr *)priv->sockaddr; +} + +/** + * soup_address_get_gsockaddr: + * @addr: a #SoupAddress + * + * Creates a new #GSocketAddress corresponding to @addr (which is assumed + * to only have one socket address associated with it). + * + * Return value: (transfer full): a new #GSocketAddress + * + * Since: 2.32 + */ +GSocketAddress * +soup_address_get_gsockaddr (SoupAddress *addr) +{ + SoupAddressPrivate *priv = soup_address_get_instance_private (addr); + + return g_socket_address_new_from_native (priv->sockaddr, + SOUP_ADDRESS_FAMILY_SOCKADDR_SIZE (SOUP_ADDRESS_GET_FAMILY (priv))); +} + +static GInetAddress * +soup_address_make_inet_address (SoupAddress *addr) +{ + SoupAddressPrivate *priv = soup_address_get_instance_private (addr); + GSocketAddress *gsa; + GInetAddress *gia; + + gsa = g_socket_address_new_from_native (priv->sockaddr, + SOUP_ADDRESS_FAMILY_SOCKADDR_SIZE (SOUP_ADDRESS_GET_FAMILY (priv))); + gia = g_inet_socket_address_get_address ((GInetSocketAddress *)gsa); + g_object_ref (gia); + g_object_unref (gsa); + return gia; +} + +/** + * soup_address_get_physical: + * @addr: a #SoupAddress + * + * Returns the physical address associated with @addr as a string. + * (Eg, "127.0.0.1"). If the address is not yet known, returns %NULL. + * + * This method is not thread-safe; if you call it while @addr is being + * resolved in another thread, it may return garbage. You can use + * soup_address_is_resolved() to safely test whether or not an address + * is resolved before fetching its name or address. + * + * Return value: (nullable): the physical address, or %NULL + **/ +const char * +soup_address_get_physical (SoupAddress *addr) +{ + SoupAddressPrivate *priv; + + g_return_val_if_fail (SOUP_IS_ADDRESS (addr), NULL); + priv = soup_address_get_instance_private (addr); + + if (!priv->sockaddr) + return NULL; + + if (!priv->physical) { + GInetAddress *gia; + + gia = soup_address_make_inet_address (addr); + priv->physical = g_inet_address_to_string (gia); + g_object_unref (gia); + } + + return priv->physical; +} + +/** + * soup_address_get_port: + * @addr: a #SoupAddress + * + * Returns the port associated with @addr. + * + * Return value: the port + **/ +guint +soup_address_get_port (SoupAddress *addr) +{ + SoupAddressPrivate *priv; + + g_return_val_if_fail (SOUP_IS_ADDRESS (addr), 0); + priv = soup_address_get_instance_private (addr); + + return priv->port; +} + + +/* Tries to resolve priv->name as an IP address, possibly including an + * IPv6 scope id. + */ +static void +maybe_resolve_ip (SoupAddress *addr) +{ + SoupAddressPrivate *priv = soup_address_get_instance_private (addr); + const char *pct, *ip; + char *tmp = NULL; + GSocketConnectable *gaddr; + GSocketAddressEnumerator *sa_enum; + GSocketAddress *saddr; + + if (priv->sockaddr || !priv->name) + return; + + pct = strchr (priv->name, '%'); + if (pct) + ip = tmp = g_strndup (priv->name, pct - priv->name); + else + ip = priv->name; + + if (!g_hostname_is_ip_address (ip)) { + g_free (tmp); + return; + } + g_free (tmp); + + gaddr = g_network_address_new (priv->name, priv->port); + if (!gaddr) + return; + + sa_enum = g_socket_connectable_enumerate (gaddr); + saddr = g_socket_address_enumerator_next (sa_enum, NULL, NULL); + if (saddr) { + priv->n_addrs = 1; + priv->sockaddr = g_new (struct sockaddr_storage, 1); + if (!g_socket_address_to_native (saddr, priv->sockaddr, + sizeof (struct sockaddr_storage), + NULL)) { + /* can't happen: We know the address format is supported + * and the buffer is large enough + */ + g_warn_if_reached (); + } + g_object_unref (saddr); + } + + g_object_unref (sa_enum); + g_object_unref (gaddr); +} + + +static guint +update_addrs (SoupAddress *addr, GList *addrs, GError *error) +{ + SoupAddressPrivate *priv = soup_address_get_instance_private (addr); + GInetAddress *gia; + GSocketAddress *gsa; + int i; + + if (error) { + if (error->domain == G_IO_ERROR && + error->code == G_IO_ERROR_CANCELLED) + return SOUP_STATUS_CANCELLED; + else + return SOUP_STATUS_CANT_RESOLVE; + } else if (!addrs) + return SOUP_STATUS_CANT_RESOLVE; + else if (priv->sockaddr) + return SOUP_STATUS_OK; + + priv->n_addrs = g_list_length (addrs); + priv->sockaddr = g_new (struct sockaddr_storage, priv->n_addrs); + for (i = 0; addrs; addrs = addrs->next, i++) { + gia = addrs->data; + gsa = g_inet_socket_address_new (gia, priv->port); + + if (!g_socket_address_to_native (gsa, &priv->sockaddr[i], + sizeof (struct sockaddr_storage), + NULL)) { + /* can't happen: We know the address format is supported + * and the buffer is large enough + */ + g_warn_if_reached (); + } + g_object_unref (gsa); + } + + return SOUP_STATUS_OK; +} + +static guint +update_name (SoupAddress *addr, const char *name, GError *error) +{ + SoupAddressPrivate *priv = soup_address_get_instance_private (addr); + + if (error) { + if (error->domain == G_IO_ERROR && + error->code == G_IO_ERROR_CANCELLED) + return SOUP_STATUS_CANCELLED; + else + return SOUP_STATUS_CANT_RESOLVE; + } else if (!name) + return SOUP_STATUS_CANT_RESOLVE; + else if (priv->name) + return SOUP_STATUS_OK; + + priv->name = g_strdup (name); + return SOUP_STATUS_OK; +} + +typedef struct { + SoupAddress *addr; + SoupAddressCallback callback; + gpointer callback_data; +} SoupAddressResolveAsyncData; + +static void +complete_resolve_async (SoupAddressResolveAsyncData *res_data, guint status) +{ + GSource *current_source; + GMainContext *current_context; + + if (res_data->callback) { + /* Awful hack; to make soup_socket_connect_async() + * with an non-default async_context work correctly, + * we need to ensure that the non-default context + * (which we're now running in) is the thread-default + * when the callbacks are run... + */ + current_source = g_main_current_source (); + if (current_source && !g_source_is_destroyed (current_source)) + current_context = g_source_get_context (current_source); + else + current_context = NULL; + g_main_context_push_thread_default (current_context); + + res_data->callback (res_data->addr, status, + res_data->callback_data); + + g_main_context_pop_thread_default (current_context); + } + + g_object_unref (res_data->addr); + g_slice_free (SoupAddressResolveAsyncData, res_data); +} + +static void +lookup_resolved (GObject *source, GAsyncResult *result, gpointer user_data) +{ + GResolver *resolver = G_RESOLVER (source); + SoupAddressResolveAsyncData *res_data = user_data; + SoupAddress *addr = res_data->addr; + SoupAddressPrivate *priv = soup_address_get_instance_private (addr); + GError *error = NULL; + guint status; + + if (!priv->sockaddr) { + GList *addrs; + + addrs = g_resolver_lookup_by_name_finish (resolver, result, + &error); + status = update_addrs (addr, addrs, error); + g_resolver_free_addresses (addrs); + } else if (!priv->name) { + char *name; + + name = g_resolver_lookup_by_address_finish (resolver, result, + &error); + status = update_name (addr, name, error); + g_free (name); + } else + status = SOUP_STATUS_OK; + + /* For the enumerator impl, below */ + g_object_ref (addr); + g_object_set_data (G_OBJECT (addr), "async-resolved-error", error); + + complete_resolve_async (res_data, status); + + g_object_set_data (G_OBJECT (addr), "async-resolved-error", NULL); + g_object_unref (addr); + if (error) + g_error_free (error); +} + +static gboolean +idle_complete_resolve (gpointer res_data) +{ + complete_resolve_async (res_data, SOUP_STATUS_OK); + return FALSE; +} + +/** + * SoupAddressCallback: + * @addr: the #SoupAddress that was resolved + * @status: %SOUP_STATUS_OK, %SOUP_STATUS_CANT_RESOLVE, or + * %SOUP_STATUS_CANCELLED + * @user_data: the user data that was passed to + * soup_address_resolve_async() + * + * The callback function passed to soup_address_resolve_async(). + **/ + +/** + * soup_address_resolve_async: + * @addr: a #SoupAddress + * @async_context: (allow-none): the #GMainContext to call @callback from + * @cancellable: a #GCancellable object, or %NULL + * @callback: (scope async): callback to call with the result + * @user_data: data for @callback + * + * Asynchronously resolves the missing half of @addr (its IP address + * if it was created with soup_address_new(), or its hostname if it + * was created with soup_address_new_from_sockaddr() or + * soup_address_new_any().) + * + * If @cancellable is non-%NULL, it can be used to cancel the + * resolution. @callback will still be invoked in this case, with a + * status of %SOUP_STATUS_CANCELLED. + * + * It is safe to call this more than once on a given address, from the + * same thread, with the same @async_context (and doing so will not + * result in redundant DNS queries being made). But it is not safe to + * call from multiple threads, or with different @async_contexts, or + * mixed with calls to soup_address_resolve_sync(). + **/ +void +soup_address_resolve_async (SoupAddress *addr, GMainContext *async_context, + GCancellable *cancellable, + SoupAddressCallback callback, gpointer user_data) +{ + SoupAddressPrivate *priv; + SoupAddressResolveAsyncData *res_data; + GResolver *resolver; + + g_return_if_fail (SOUP_IS_ADDRESS (addr)); + priv = soup_address_get_instance_private (addr); + g_return_if_fail (priv->name || priv->sockaddr); + + /* We don't need to do locking here because the async case is + * not intended to be thread-safe. + */ + + if (priv->name && !priv->sockaddr) + maybe_resolve_ip (addr); + if (priv->name && priv->sockaddr && !callback) + return; + + res_data = g_slice_new0 (SoupAddressResolveAsyncData); + res_data->addr = g_object_ref (addr); + res_data->callback = callback; + res_data->callback_data = user_data; + + if (async_context) + g_main_context_push_thread_default (async_context); + + if (priv->name && priv->sockaddr) + soup_add_completion (async_context, idle_complete_resolve, res_data); + else { + resolver = g_resolver_get_default (); + + if (priv->name) { + g_resolver_lookup_by_name_async (resolver, priv->name, + cancellable, + lookup_resolved, res_data); + } else { + GInetAddress *gia; + + gia = soup_address_make_inet_address (addr); + g_resolver_lookup_by_address_async (resolver, gia, + cancellable, + lookup_resolved, res_data); + g_object_unref (gia); + } + + g_object_unref (resolver); + } + + if (async_context) + g_main_context_pop_thread_default (async_context); +} + +static guint +resolve_sync_internal (SoupAddress *addr, GCancellable *cancellable, GError **error) +{ + SoupAddressPrivate *priv = soup_address_get_instance_private (addr); + GResolver *resolver; + guint status; + GError *my_err = NULL; + + resolver = g_resolver_get_default (); + + /* We could optimize this to avoid multiple lookups the same + * way _resolve_async does, but we don't currently. So, first + * lock the mutex to ensure we have a consistent view of + * priv->sockaddr and priv->name, unlock it around the + * blocking op, and then re-lock it to modify @addr. + */ + g_mutex_lock (&priv->lock); + + if (priv->name && !priv->sockaddr) + maybe_resolve_ip (addr); + + if (!priv->sockaddr) { + GList *addrs; + + g_mutex_unlock (&priv->lock); + addrs = g_resolver_lookup_by_name (resolver, priv->name, + cancellable, &my_err); + g_mutex_lock (&priv->lock); + + status = update_addrs (addr, addrs, my_err); + g_resolver_free_addresses (addrs); + } else if (!priv->name) { + GInetAddress *gia; + char *name; + + g_mutex_unlock (&priv->lock); + gia = soup_address_make_inet_address (addr); + name = g_resolver_lookup_by_address (resolver, gia, + cancellable, &my_err); + g_object_unref (gia); + g_mutex_lock (&priv->lock); + + status = update_name (addr, name, my_err); + g_free (name); + } else + status = SOUP_STATUS_OK; + + g_mutex_unlock (&priv->lock); + + if (my_err) + g_propagate_error (error, my_err); + g_object_unref (resolver); + + return status; +} + +/** + * soup_address_resolve_sync: + * @addr: a #SoupAddress + * @cancellable: a #GCancellable object, or %NULL + * + * Synchronously resolves the missing half of @addr, as with + * soup_address_resolve_async(). + * + * If @cancellable is non-%NULL, it can be used to cancel the + * resolution. soup_address_resolve_sync() will then return a status + * of %SOUP_STATUS_CANCELLED. + * + * It is safe to call this more than once, even from different + * threads, but it is not safe to mix calls to + * soup_address_resolve_sync() with calls to + * soup_address_resolve_async() on the same address. + * + * Return value: %SOUP_STATUS_OK, %SOUP_STATUS_CANT_RESOLVE, or + * %SOUP_STATUS_CANCELLED. + **/ +guint +soup_address_resolve_sync (SoupAddress *addr, GCancellable *cancellable) +{ + SoupAddressPrivate *priv; + + g_return_val_if_fail (SOUP_IS_ADDRESS (addr), SOUP_STATUS_MALFORMED); + priv = soup_address_get_instance_private (addr); + g_return_val_if_fail (priv->name || priv->sockaddr, SOUP_STATUS_MALFORMED); + + return resolve_sync_internal (addr, cancellable, NULL); +} + +/** + * soup_address_is_resolved: + * @addr: a #SoupAddress + * + * Tests if @addr has already been resolved. Unlike the other + * #SoupAddress "get" methods, this is safe to call when @addr might + * be being resolved in another thread. + * + * Return value: %TRUE if @addr has been resolved. + **/ +gboolean +soup_address_is_resolved (SoupAddress *addr) +{ + SoupAddressPrivate *priv; + gboolean resolved; + + g_return_val_if_fail (SOUP_IS_ADDRESS (addr), FALSE); + priv = soup_address_get_instance_private (addr); + + g_mutex_lock (&priv->lock); + resolved = priv->sockaddr && priv->name; + g_mutex_unlock (&priv->lock); + + return resolved; +} + +/** + * soup_address_hash_by_name: + * @addr: (type Soup.Address): a #SoupAddress + * + * A hash function (for #GHashTable) that corresponds to + * soup_address_equal_by_name(), qv + * + * Return value: the named-based hash value for @addr. + * + * Since: 2.26 + **/ +guint +soup_address_hash_by_name (gconstpointer addr) +{ + SoupAddressPrivate *priv = soup_address_get_instance_private (SOUP_ADDRESS (addr)); + + g_return_val_if_fail (priv->name != NULL, 0); + return g_str_hash (priv->name); +} + +/** + * soup_address_equal_by_name: + * @addr1: (type Soup.Address): a #SoupAddress with a resolved name + * @addr2: (type Soup.Address): another #SoupAddress with a resolved + * name + * + * Tests if @addr1 and @addr2 have the same "name". This method can be + * used with soup_address_hash_by_name() to create a #GHashTable that + * hashes on address "names". + * + * Comparing by name normally means comparing the addresses by their + * hostnames. But if the address was originally created using an IP + * address literal, then it will be compared by that instead. + * + * In particular, if "www.example.com" has the IP address 10.0.0.1, + * and @addr1 was created with the name "www.example.com" and @addr2 + * was created with the name "10.0.0.1", then they will compare as + * unequal for purposes of soup_address_equal_by_name(). + * + * This would be used to distinguish hosts in situations where + * different virtual hosts on the same IP address should be considered + * different. Eg, for purposes of HTTP authentication or cookies, two + * hosts with the same IP address but different names are considered + * to be different hosts. + * + * See also soup_address_equal_by_ip(), which compares by IP address + * rather than by name. + * + * Return value: whether or not @addr1 and @addr2 have the same name + * + * Since: 2.26 + **/ +gboolean +soup_address_equal_by_name (gconstpointer addr1, gconstpointer addr2) +{ + SoupAddressPrivate *priv1 = soup_address_get_instance_private (SOUP_ADDRESS (addr1)); + SoupAddressPrivate *priv2 = soup_address_get_instance_private (SOUP_ADDRESS (addr2)); + + g_return_val_if_fail (priv1->name != NULL, FALSE); + g_return_val_if_fail (priv2->name != NULL, FALSE); + return !g_ascii_strcasecmp (priv1->name, priv2->name); +} + +/** + * soup_address_hash_by_ip: + * @addr: (type Soup.Address): a #SoupAddress + * + * A hash function (for #GHashTable) that corresponds to + * soup_address_equal_by_ip(), qv + * + * Return value: the IP-based hash value for @addr. + * + * Since: 2.26 + **/ +guint +soup_address_hash_by_ip (gconstpointer addr) +{ + SoupAddressPrivate *priv = soup_address_get_instance_private (SOUP_ADDRESS (addr)); + guint hash; + + g_return_val_if_fail (priv->sockaddr != NULL, 0); + + memcpy (&hash, SOUP_ADDRESS_GET_DATA (priv), + MIN (sizeof (hash), SOUP_ADDRESS_FAMILY_DATA_SIZE (priv->sockaddr->ss_family))); + return hash; +} + +/** + * soup_address_equal_by_ip: + * @addr1: (type Soup.Address): a #SoupAddress with a resolved IP + * address + * @addr2: (type Soup.Address): another #SoupAddress with a resolved + * IP address + * + * Tests if @addr1 and @addr2 have the same IP address. This method + * can be used with soup_address_hash_by_ip() to create a + * #GHashTable that hashes on IP address. + * + * This would be used to distinguish hosts in situations where + * different virtual hosts on the same IP address should be considered + * the same. Eg, if "www.example.com" and "www.example.net" have the + * same IP address, then a single connection can be used to talk + * to either of them. + * + * See also soup_address_equal_by_name(), which compares by name + * rather than by IP address. + * + * Return value: whether or not @addr1 and @addr2 have the same IP + * address. + * + * Since: 2.26 + **/ +gboolean +soup_address_equal_by_ip (gconstpointer addr1, gconstpointer addr2) +{ + SoupAddressPrivate *priv1 = soup_address_get_instance_private (SOUP_ADDRESS (addr1)); + SoupAddressPrivate *priv2 = soup_address_get_instance_private (SOUP_ADDRESS (addr2)); + int size; + + g_return_val_if_fail (priv1->sockaddr != NULL, FALSE); + g_return_val_if_fail (priv2->sockaddr != NULL, FALSE); + + size = SOUP_ADDRESS_FAMILY_SOCKADDR_SIZE (priv1->sockaddr->ss_family); + return (priv1->sockaddr->ss_family == + priv2->sockaddr->ss_family && + !memcmp (priv1->sockaddr, priv2->sockaddr, size)); +} + + +#define SOUP_TYPE_ADDRESS_ADDRESS_ENUMERATOR (_soup_address_address_enumerator_get_type ()) +#define SOUP_ADDRESS_ADDRESS_ENUMERATOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SOUP_TYPE_ADDRESS_ADDRESS_ENUMERATOR, SoupAddressAddressEnumerator)) + +typedef struct { + GSocketAddressEnumerator parent_instance; + + SoupAddress *addr; + int orig_offset; + int n; +} SoupAddressAddressEnumerator; + +typedef struct { + GSocketAddressEnumeratorClass parent_class; + +} SoupAddressAddressEnumeratorClass; + +GType _soup_address_address_enumerator_get_type (void); +G_DEFINE_TYPE (SoupAddressAddressEnumerator, _soup_address_address_enumerator, G_TYPE_SOCKET_ADDRESS_ENUMERATOR) + +static void +soup_address_address_enumerator_finalize (GObject *object) +{ + SoupAddressAddressEnumerator *addr_enum = + SOUP_ADDRESS_ADDRESS_ENUMERATOR (object); + + g_object_unref (addr_enum->addr); + + G_OBJECT_CLASS (_soup_address_address_enumerator_parent_class)->finalize (object); +} + +static GSocketAddress * +next_address (SoupAddressAddressEnumerator *addr_enum) +{ + SoupAddressPrivate *priv = soup_address_get_instance_private (addr_enum->addr); + struct sockaddr_storage *ss; + int next_addr; + + /* If there are two addresses but the first one is unusable + * (eg, it's IPv6 and we can only do IPv4), then we don't want to + * try the bad one every time. So we use priv->offset to remember + * the offset of the first usable address (ie, the first address + * that we weren't called again after returning). + */ + next_addr = (addr_enum->orig_offset + addr_enum->n) % priv->n_addrs; + priv->offset = next_addr; + + if (addr_enum->n >= priv->n_addrs) + return NULL; + addr_enum->n++; + + ss = &priv->sockaddr[next_addr]; + return g_socket_address_new_from_native (ss, SOUP_ADDRESS_FAMILY_SOCKADDR_SIZE (ss->ss_family)); +} + +static GSocketAddress * +soup_address_address_enumerator_next (GSocketAddressEnumerator *enumerator, + GCancellable *cancellable, + GError **error) +{ + SoupAddressAddressEnumerator *addr_enum = + SOUP_ADDRESS_ADDRESS_ENUMERATOR (enumerator); + SoupAddressPrivate *priv = soup_address_get_instance_private (addr_enum->addr); + + if (!priv->sockaddr) { + if (resolve_sync_internal (addr_enum->addr, cancellable, error) != SOUP_STATUS_OK) + return NULL; + } + + return next_address (addr_enum); +} + +static void +got_addresses (SoupAddress *addr, guint status, gpointer user_data) +{ + GTask *task = user_data; + GError *error; + + error = g_object_get_data (G_OBJECT (addr), "async-resolved-error"); + if (error) + g_task_return_error (task, g_error_copy (error)); + else { + GSocketAddress *socket_addr; + + socket_addr = next_address (g_task_get_source_object (task)); + g_task_return_pointer (task, socket_addr, g_object_unref); + } + g_object_unref (task); +} + +static void +soup_address_address_enumerator_next_async (GSocketAddressEnumerator *enumerator, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + SoupAddressAddressEnumerator *addr_enum = + SOUP_ADDRESS_ADDRESS_ENUMERATOR (enumerator); + SoupAddressPrivate *priv = soup_address_get_instance_private (addr_enum->addr); + GTask *task; + + task = g_task_new (enumerator, cancellable, callback, user_data); + if (!priv->sockaddr) { + soup_address_resolve_async (addr_enum->addr, + g_main_context_get_thread_default (), + cancellable, got_addresses, task); + } else { + g_task_return_pointer (task, next_address (addr_enum), g_object_unref); + g_object_unref (task); + } +} + +static GSocketAddress * +soup_address_address_enumerator_next_finish (GSocketAddressEnumerator *enumerator, + GAsyncResult *result, + GError **error) +{ + return g_task_propagate_pointer (G_TASK (result), error); +} + +static void +_soup_address_address_enumerator_init (SoupAddressAddressEnumerator *enumerator) +{ +} + +static void +_soup_address_address_enumerator_class_init (SoupAddressAddressEnumeratorClass *addrenum_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (addrenum_class); + GSocketAddressEnumeratorClass *enumerator_class = + G_SOCKET_ADDRESS_ENUMERATOR_CLASS (addrenum_class); + + enumerator_class->next = soup_address_address_enumerator_next; + enumerator_class->next_async = soup_address_address_enumerator_next_async; + enumerator_class->next_finish = soup_address_address_enumerator_next_finish; + object_class->finalize = soup_address_address_enumerator_finalize; +} + +static GSocketAddressEnumerator * +soup_address_connectable_enumerate (GSocketConnectable *connectable) +{ + SoupAddressAddressEnumerator *addr_enum; + SoupAddressPrivate *priv; + + addr_enum = g_object_new (SOUP_TYPE_ADDRESS_ADDRESS_ENUMERATOR, NULL); + addr_enum->addr = g_object_ref (SOUP_ADDRESS (connectable)); + + priv = soup_address_get_instance_private (addr_enum->addr); + addr_enum->orig_offset = priv->offset; + + return (GSocketAddressEnumerator *)addr_enum; +} + +static GSocketAddressEnumerator * +soup_address_connectable_proxy_enumerate (GSocketConnectable *connectable) +{ + SoupAddress *addr = SOUP_ADDRESS (connectable); + SoupAddressPrivate *priv = soup_address_get_instance_private (addr); + GSocketAddressEnumerator *proxy_enum; + SoupURI *uri; + char *uri_string; + + /* We cheerily assume "http" here because you shouldn't be + * using SoupAddress any more if you're not doing HTTP anyway. + */ + uri = soup_uri_new (NULL); + soup_uri_set_scheme (uri, priv->protocol ? priv->protocol : "http"); + soup_uri_set_host (uri, priv->name ? priv->name : soup_address_get_physical (addr)); + soup_uri_set_port (uri, priv->port); + soup_uri_set_path (uri, ""); + uri_string = soup_uri_to_string_internal (uri, FALSE, FALSE, TRUE); + + proxy_enum = g_object_new (G_TYPE_PROXY_ADDRESS_ENUMERATOR, + "connectable", connectable, + "uri", uri_string, + NULL); + g_free (uri_string); + soup_uri_free (uri); + + return proxy_enum; +} + +static void +soup_address_connectable_iface_init (GSocketConnectableIface *connectable_iface) +{ + connectable_iface->enumerate = soup_address_connectable_enumerate; + connectable_iface->proxy_enumerate = soup_address_connectable_proxy_enumerate; +} diff --git a/libsoup/soup-address.h b/libsoup/soup-address.h new file mode 100644 index 0000000..af178de --- /dev/null +++ b/libsoup/soup-address.h @@ -0,0 +1,110 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2000-2003, Ximian, Inc. + */ + +#ifndef SOUP_ADDRESS_H +#define SOUP_ADDRESS_H + +#include + +#include + +G_BEGIN_DECLS + +#define SOUP_TYPE_ADDRESS (soup_address_get_type ()) +#define SOUP_ADDRESS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SOUP_TYPE_ADDRESS, SoupAddress)) +#define SOUP_ADDRESS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_ADDRESS, SoupAddressClass)) +#define SOUP_IS_ADDRESS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SOUP_TYPE_ADDRESS)) +#define SOUP_IS_ADDRESS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), SOUP_TYPE_ADDRESS)) +#define SOUP_ADDRESS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_ADDRESS, SoupAddressClass)) + +struct _SoupAddress { + GObject parent; + +}; + +typedef struct { + GObjectClass parent_class; + + /* Padding for future expansion */ + void (*_libsoup_reserved1) (void); + void (*_libsoup_reserved2) (void); + void (*_libsoup_reserved3) (void); + void (*_libsoup_reserved4) (void); +} SoupAddressClass; + +#define SOUP_ADDRESS_NAME "name" +#define SOUP_ADDRESS_FAMILY "family" +#define SOUP_ADDRESS_PORT "port" +#define SOUP_ADDRESS_PROTOCOL "protocol" +#define SOUP_ADDRESS_PHYSICAL "physical" +#define SOUP_ADDRESS_SOCKADDR "sockaddr" + +typedef enum { + SOUP_ADDRESS_FAMILY_INVALID = -1, + + SOUP_ADDRESS_FAMILY_IPV4 = G_SOCKET_FAMILY_IPV4, + SOUP_ADDRESS_FAMILY_IPV6 = G_SOCKET_FAMILY_IPV6 +} SoupAddressFamily; + +#define SOUP_ADDRESS_ANY_PORT 0 + +struct sockaddr; + +typedef void (*SoupAddressCallback) (SoupAddress *addr, + guint status, + gpointer user_data); + +SOUP_AVAILABLE_IN_2_4 +GType soup_address_get_type (void); + +SOUP_AVAILABLE_IN_2_4 +SoupAddress *soup_address_new (const char *name, + guint port); +SOUP_AVAILABLE_IN_2_4 +SoupAddress *soup_address_new_from_sockaddr (struct sockaddr *sa, + int len); +SOUP_AVAILABLE_IN_2_4 +SoupAddress *soup_address_new_any (SoupAddressFamily family, + guint port); + +SOUP_AVAILABLE_IN_2_4 +void soup_address_resolve_async (SoupAddress *addr, + GMainContext *async_context, + GCancellable *cancellable, + SoupAddressCallback callback, + gpointer user_data); +SOUP_AVAILABLE_IN_2_4 +guint soup_address_resolve_sync (SoupAddress *addr, + GCancellable *cancellable); + +SOUP_AVAILABLE_IN_2_4 +const char *soup_address_get_name (SoupAddress *addr); +SOUP_AVAILABLE_IN_2_4 +const char *soup_address_get_physical (SoupAddress *addr); +SOUP_AVAILABLE_IN_2_4 +guint soup_address_get_port (SoupAddress *addr); +SOUP_AVAILABLE_IN_2_4 +struct sockaddr *soup_address_get_sockaddr (SoupAddress *addr, + int *len); +SOUP_AVAILABLE_IN_2_32 +GSocketAddress *soup_address_get_gsockaddr (SoupAddress *addr); +SOUP_AVAILABLE_IN_2_4 +gboolean soup_address_is_resolved (SoupAddress *addr); + +SOUP_AVAILABLE_IN_2_26 +guint soup_address_hash_by_name (gconstpointer addr); +SOUP_AVAILABLE_IN_2_26 +gboolean soup_address_equal_by_name (gconstpointer addr1, + gconstpointer addr2); +SOUP_AVAILABLE_IN_2_26 +guint soup_address_hash_by_ip (gconstpointer addr); +SOUP_AVAILABLE_IN_2_26 +gboolean soup_address_equal_by_ip (gconstpointer addr1, + gconstpointer addr2); + + +G_END_DECLS + +#endif /* SOUP_ADDRESS_H */ diff --git a/libsoup/soup-auth-basic.c b/libsoup/soup-auth-basic.c new file mode 100644 index 0000000..5f1e718 --- /dev/null +++ b/libsoup/soup-auth-basic.c @@ -0,0 +1,145 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-auth-basic.c: HTTP Basic Authentication + * + * Copyright (C) 2001-2003, Ximian, Inc. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "soup-auth-basic.h" +#include "soup.h" + +typedef struct { + char *token; +} SoupAuthBasicPrivate; + +/** + * SOUP_TYPE_AUTH_BASIC: + * + * A #GType corresponding to HTTP "Basic" authentication. + * #SoupSessions support this by default; if you want to disable + * support for it, call soup_session_remove_feature_by_type(), + * passing %SOUP_TYPE_AUTH_BASIC. + * + * Since: 2.34 + */ + +G_DEFINE_TYPE_WITH_PRIVATE (SoupAuthBasic, soup_auth_basic, SOUP_TYPE_AUTH) + +static void +soup_auth_basic_init (SoupAuthBasic *basic) +{ +} + +static void +soup_auth_basic_finalize (GObject *object) +{ + SoupAuthBasicPrivate *priv = soup_auth_basic_get_instance_private (SOUP_AUTH_BASIC (object)); + + g_free (priv->token); + + G_OBJECT_CLASS (soup_auth_basic_parent_class)->finalize (object); +} + +static gboolean +soup_auth_basic_update (SoupAuth *auth, SoupMessage *msg, + GHashTable *auth_params) +{ + SoupAuthBasicPrivate *priv = soup_auth_basic_get_instance_private (SOUP_AUTH_BASIC (auth)); + + /* If we're updating a pre-existing auth, the + * username/password must be bad now, so forget it. + * Other than that, there's nothing to do here. + */ + if (priv->token) { + memset (priv->token, 0, strlen (priv->token)); + g_free (priv->token); + priv->token = NULL; + } + + return TRUE; +} + +static GSList * +soup_auth_basic_get_protection_space (SoupAuth *auth, SoupURI *source_uri) +{ + char *space, *p; + + space = g_strdup (source_uri->path); + + /* Strip filename component */ + p = strrchr (space, '/'); + if (p == space && p[1]) + p[1] = '\0'; + else if (p && p[1]) + *p = '\0'; + + return g_slist_prepend (NULL, space); +} + +static void +soup_auth_basic_authenticate (SoupAuth *auth, const char *username, + const char *password) +{ + SoupAuthBasicPrivate *priv = soup_auth_basic_get_instance_private (SOUP_AUTH_BASIC (auth)); + char *user_pass, *user_pass_latin1; + int len; + + user_pass = g_strdup_printf ("%s:%s", username, password); + user_pass_latin1 = g_convert (user_pass, -1, "ISO-8859-1", "UTF-8", + NULL, NULL, NULL); + if (user_pass_latin1) { + memset (user_pass, 0, strlen (user_pass)); + g_free (user_pass); + user_pass = user_pass_latin1; + } + len = strlen (user_pass); + + if (priv->token) { + memset (priv->token, 0, strlen (priv->token)); + g_free (priv->token); + } + priv->token = g_base64_encode ((guchar *)user_pass, len); + + memset (user_pass, 0, len); + g_free (user_pass); +} + +static gboolean +soup_auth_basic_is_authenticated (SoupAuth *auth) +{ + SoupAuthBasicPrivate *priv = soup_auth_basic_get_instance_private (SOUP_AUTH_BASIC (auth)); + + return priv->token != NULL; +} + +static char * +soup_auth_basic_get_authorization (SoupAuth *auth, SoupMessage *msg) +{ + SoupAuthBasicPrivate *priv = soup_auth_basic_get_instance_private (SOUP_AUTH_BASIC (auth)); + + return g_strdup_printf ("Basic %s", priv->token); +} + +static void +soup_auth_basic_class_init (SoupAuthBasicClass *auth_basic_class) +{ + SoupAuthClass *auth_class = SOUP_AUTH_CLASS (auth_basic_class); + GObjectClass *object_class = G_OBJECT_CLASS (auth_basic_class); + + auth_class->scheme_name = "Basic"; + auth_class->strength = 1; + + auth_class->update = soup_auth_basic_update; + auth_class->get_protection_space = soup_auth_basic_get_protection_space; + auth_class->authenticate = soup_auth_basic_authenticate; + auth_class->is_authenticated = soup_auth_basic_is_authenticated; + auth_class->get_authorization = soup_auth_basic_get_authorization; + + object_class->finalize = soup_auth_basic_finalize; +} diff --git a/libsoup/soup-auth-basic.h b/libsoup/soup-auth-basic.h new file mode 100644 index 0000000..639bf03 --- /dev/null +++ b/libsoup/soup-auth-basic.h @@ -0,0 +1,27 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2000-2003, Ximian, Inc. + */ + +#ifndef SOUP_AUTH_BASIC_H +#define SOUP_AUTH_BASIC_H 1 + +#include "soup-auth.h" + +#define SOUP_AUTH_BASIC(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), SOUP_TYPE_AUTH_BASIC, SoupAuthBasic)) +#define SOUP_AUTH_BASIC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_AUTH_BASIC, SoupAuthBasicClass)) +#define SOUP_IS_AUTH_BASIC(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), SOUP_TYPE_AUTH_BASIC)) +#define SOUP_IS_AUTH_BASIC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SOUP_TYPE_AUTH_BASIC)) +#define SOUP_AUTH_BASIC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_AUTH_BASIC, SoupAuthBasicClass)) + +typedef struct { + SoupAuth parent; + +} SoupAuthBasic; + +typedef struct { + SoupAuthClass parent_class; + +} SoupAuthBasicClass; + +#endif /*SOUP_AUTH_BASIC_H*/ diff --git a/libsoup/soup-auth-digest.c b/libsoup/soup-auth-digest.c new file mode 100644 index 0000000..eda2a93 --- /dev/null +++ b/libsoup/soup-auth-digest.c @@ -0,0 +1,490 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-auth-digest.c: HTTP Digest Authentication + * + * Copyright (C) 2001-2003, Ximian, Inc. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "soup-auth-digest.h" +#include "soup.h" +#include "soup-message-private.h" + +#ifdef G_OS_WIN32 +#include +#endif + +typedef struct { + char *user; + char hex_urp[33]; + char hex_a1[33]; + + /* These are provided by the server */ + char *nonce; + char *opaque; + SoupAuthDigestQop qop_options; + SoupAuthDigestAlgorithm algorithm; + char *domain; + + /* These are generated by the client */ + char *cnonce; + int nc; + SoupAuthDigestQop qop; +} SoupAuthDigestPrivate; + +static void recompute_hex_a1 (SoupAuthDigestPrivate *priv); + +/** + * SOUP_TYPE_AUTH_DIGEST: + * + * A #GType corresponding to HTTP "Digest" authentication. + * #SoupSessions support this by default; if you want to disable + * support for it, call soup_session_remove_feature_by_type(), + * passing %SOUP_TYPE_AUTH_DIGEST. + * + * Since: 2.34 + */ + +G_DEFINE_TYPE_WITH_PRIVATE (SoupAuthDigest, soup_auth_digest, SOUP_TYPE_AUTH) + +static void +soup_auth_digest_init (SoupAuthDigest *digest) +{ +} + +static void +soup_auth_digest_finalize (GObject *object) +{ + SoupAuthDigestPrivate *priv = soup_auth_digest_get_instance_private (SOUP_AUTH_DIGEST (object)); + + g_free (priv->user); + g_free (priv->nonce); + g_free (priv->domain); + g_free (priv->cnonce); + + memset (priv->hex_urp, 0, sizeof (priv->hex_urp)); + memset (priv->hex_a1, 0, sizeof (priv->hex_a1)); + + G_OBJECT_CLASS (soup_auth_digest_parent_class)->finalize (object); +} + +SoupAuthDigestAlgorithm +soup_auth_digest_parse_algorithm (const char *algorithm) +{ + if (!algorithm || !g_ascii_strcasecmp (algorithm, "MD5")) + return SOUP_AUTH_DIGEST_ALGORITHM_MD5; + else if (!g_ascii_strcasecmp (algorithm, "MD5-sess")) + return SOUP_AUTH_DIGEST_ALGORITHM_MD5_SESS; + else + return -1; +} + +char * +soup_auth_digest_get_algorithm (SoupAuthDigestAlgorithm algorithm) +{ + if (algorithm == SOUP_AUTH_DIGEST_ALGORITHM_MD5) + return g_strdup ("MD5"); + else if (algorithm == SOUP_AUTH_DIGEST_ALGORITHM_MD5_SESS) + return g_strdup ("MD5-sess"); + else + return NULL; +} + +SoupAuthDigestQop +soup_auth_digest_parse_qop (const char *qop) +{ + GSList *qop_values, *iter; + SoupAuthDigestQop out = 0; + + g_return_val_if_fail (qop != NULL, 0); + + qop_values = soup_header_parse_list (qop); + for (iter = qop_values; iter; iter = iter->next) { + if (!g_ascii_strcasecmp (iter->data, "auth")) + out |= SOUP_AUTH_DIGEST_QOP_AUTH; + else if (!g_ascii_strcasecmp (iter->data, "auth-int")) + out |= SOUP_AUTH_DIGEST_QOP_AUTH_INT; + } + soup_header_free_list (qop_values); + + return out; +} + +char * +soup_auth_digest_get_qop (SoupAuthDigestQop qop) +{ + GString *out; + + out = g_string_new (NULL); + if (qop & SOUP_AUTH_DIGEST_QOP_AUTH) + g_string_append (out, "auth"); + if (qop & SOUP_AUTH_DIGEST_QOP_AUTH_INT) { + if (qop & SOUP_AUTH_DIGEST_QOP_AUTH) + g_string_append (out, ","); + g_string_append (out, "auth-int"); + } + + return g_string_free (out, FALSE); +} + +static gboolean +soup_auth_digest_update (SoupAuth *auth, SoupMessage *msg, + GHashTable *auth_params) +{ + SoupAuthDigest *auth_digest = SOUP_AUTH_DIGEST (auth); + SoupAuthDigestPrivate *priv = soup_auth_digest_get_instance_private (auth_digest); + const char *stale, *qop; + guint qop_options; + gboolean ok = TRUE; + + g_free (priv->domain); + g_free (priv->nonce); + g_free (priv->opaque); + + priv->nc = 1; + + priv->domain = g_strdup (g_hash_table_lookup (auth_params, "domain")); + priv->nonce = g_strdup (g_hash_table_lookup (auth_params, "nonce")); + priv->opaque = g_strdup (g_hash_table_lookup (auth_params, "opaque")); + + qop = g_hash_table_lookup (auth_params, "qop"); + if (qop) { + qop_options = soup_auth_digest_parse_qop (qop); + /* We only support auth */ + if (!(qop_options & SOUP_AUTH_DIGEST_QOP_AUTH)) + ok = FALSE; + priv->qop = SOUP_AUTH_DIGEST_QOP_AUTH; + } else + priv->qop = 0; + + priv->algorithm = soup_auth_digest_parse_algorithm (g_hash_table_lookup (auth_params, "algorithm")); + if (priv->algorithm == -1) + ok = FALSE; + + stale = g_hash_table_lookup (auth_params, "stale"); + if (stale && !g_ascii_strcasecmp (stale, "TRUE") && *priv->hex_urp) + recompute_hex_a1 (priv); + else { + g_free (priv->user); + priv->user = NULL; + g_free (priv->cnonce); + priv->cnonce = NULL; + memset (priv->hex_urp, 0, sizeof (priv->hex_urp)); + memset (priv->hex_a1, 0, sizeof (priv->hex_a1)); + } + + return ok; +} + +static GSList * +soup_auth_digest_get_protection_space (SoupAuth *auth, SoupURI *source_uri) +{ + SoupAuthDigest *auth_digest = SOUP_AUTH_DIGEST (auth); + SoupAuthDigestPrivate *priv = soup_auth_digest_get_instance_private (auth_digest); + GSList *space = NULL; + SoupURI *uri; + char **dvec, *d, *dir, *slash; + int dix; + + if (!priv->domain || !*priv->domain) { + /* If no domain directive, the protection space is the + * whole server. + */ + return g_slist_prepend (NULL, g_strdup ("")); + } + + dvec = g_strsplit (priv->domain, " ", 0); + for (dix = 0; dvec[dix] != NULL; dix++) { + d = dvec[dix]; + if (*d == '/') + dir = g_strdup (d); + else { + uri = soup_uri_new (d); + if (uri && uri->scheme == source_uri->scheme && + uri->port == source_uri->port && + !strcmp (uri->host, source_uri->host)) + dir = g_strdup (uri->path); + else + dir = NULL; + if (uri) + soup_uri_free (uri); + } + + if (dir) { + slash = strrchr (dir, '/'); + if (slash && !slash[1]) + *slash = '\0'; + + space = g_slist_prepend (space, dir); + } + } + g_strfreev (dvec); + + return space; +} + +void +soup_auth_digest_compute_hex_urp (const char *username, + const char *realm, + const char *password, + char hex_urp[33]) +{ + GChecksum *checksum; + + checksum = g_checksum_new (G_CHECKSUM_MD5); + g_checksum_update (checksum, (guchar *)username, strlen (username)); + g_checksum_update (checksum, (guchar *)":", 1); + g_checksum_update (checksum, (guchar *)realm, strlen (realm)); + g_checksum_update (checksum, (guchar *)":", 1); + g_checksum_update (checksum, (guchar *)password, strlen (password)); + strncpy (hex_urp, g_checksum_get_string (checksum), 33); + g_checksum_free (checksum); +} + +void +soup_auth_digest_compute_hex_a1 (const char *hex_urp, + SoupAuthDigestAlgorithm algorithm, + const char *nonce, + const char *cnonce, + char hex_a1[33]) +{ + if (algorithm == SOUP_AUTH_DIGEST_ALGORITHM_MD5) { + /* In MD5, A1 is just user:realm:password, so hex_A1 + * is just hex_urp. + */ + /* You'd think you could say "sizeof (hex_a1)" here, + * but you'd be wrong. + */ + memcpy (hex_a1, hex_urp, 33); + } else { + GChecksum *checksum; + + /* In MD5-sess, A1 is hex_urp:nonce:cnonce */ + + checksum = g_checksum_new (G_CHECKSUM_MD5); + g_checksum_update (checksum, (guchar *)hex_urp, strlen (hex_urp)); + g_checksum_update (checksum, (guchar *)":", 1); + g_checksum_update (checksum, (guchar *)nonce, strlen (nonce)); + g_checksum_update (checksum, (guchar *)":", 1); + g_checksum_update (checksum, (guchar *)cnonce, strlen (cnonce)); + strncpy (hex_a1, g_checksum_get_string (checksum), 33); + g_checksum_free (checksum); + } +} + +static void +recompute_hex_a1 (SoupAuthDigestPrivate *priv) +{ + soup_auth_digest_compute_hex_a1 (priv->hex_urp, + priv->algorithm, + priv->nonce, + priv->cnonce, + priv->hex_a1); +} + +static void +soup_auth_digest_authenticate (SoupAuth *auth, const char *username, + const char *password) +{ + SoupAuthDigest *auth_digest = SOUP_AUTH_DIGEST (auth); + SoupAuthDigestPrivate *priv = soup_auth_digest_get_instance_private (auth_digest); + char *bgen; + + g_clear_pointer (&priv->cnonce, g_free); + g_clear_pointer (&priv->user, g_free); + + /* Create client nonce */ + bgen = g_strdup_printf ("%p:%lu:%lu", + auth, + (unsigned long) getpid (), + (unsigned long) time (0)); + priv->cnonce = g_base64_encode ((guchar *)bgen, strlen (bgen)); + g_free (bgen); + + priv->user = g_strdup (username); + + /* compute "URP" (user:realm:password) */ + soup_auth_digest_compute_hex_urp (username, auth->realm, + password ? password : "", + priv->hex_urp); + + /* And compute A1 from that */ + recompute_hex_a1 (priv); +} + +static gboolean +soup_auth_digest_is_authenticated (SoupAuth *auth) +{ + SoupAuthDigestPrivate *priv = soup_auth_digest_get_instance_private (SOUP_AUTH_DIGEST (auth)); + + return priv->cnonce != NULL; +} + +void +soup_auth_digest_compute_response (const char *method, + const char *uri, + const char *hex_a1, + SoupAuthDigestQop qop, + const char *nonce, + const char *cnonce, + int nc, + char response[33]) +{ + char hex_a2[33]; + GChecksum *checksum; + + /* compute A2 */ + checksum = g_checksum_new (G_CHECKSUM_MD5); + g_checksum_update (checksum, (guchar *)method, strlen (method)); + g_checksum_update (checksum, (guchar *)":", 1); + g_checksum_update (checksum, (guchar *)uri, strlen (uri)); + strncpy (hex_a2, g_checksum_get_string (checksum), 33); + g_checksum_free (checksum); + + /* compute KD */ + checksum = g_checksum_new (G_CHECKSUM_MD5); + g_checksum_update (checksum, (guchar *)hex_a1, strlen (hex_a1)); + g_checksum_update (checksum, (guchar *)":", 1); + g_checksum_update (checksum, (guchar *)nonce, strlen (nonce)); + g_checksum_update (checksum, (guchar *)":", 1); + + if (qop) { + char tmp[9]; + + g_snprintf (tmp, 9, "%.8x", nc); + g_checksum_update (checksum, (guchar *)tmp, strlen (tmp)); + g_checksum_update (checksum, (guchar *)":", 1); + g_checksum_update (checksum, (guchar *)cnonce, strlen (cnonce)); + g_checksum_update (checksum, (guchar *)":", 1); + + if (!(qop & SOUP_AUTH_DIGEST_QOP_AUTH)) + g_warn_if_reached (); + g_checksum_update (checksum, (guchar *)"auth", strlen ("auth")); + g_checksum_update (checksum, (guchar *)":", 1); + } + + g_checksum_update (checksum, (guchar *)hex_a2, 32); + strncpy (response, g_checksum_get_string (checksum), 33); + g_checksum_free (checksum); +} + +static void +authentication_info_cb (SoupMessage *msg, gpointer data) +{ + SoupAuth *auth = data; + SoupAuthDigest *auth_digest = SOUP_AUTH_DIGEST (auth); + SoupAuthDigestPrivate *priv = soup_auth_digest_get_instance_private (auth_digest); + const char *header; + GHashTable *auth_params; + char *nextnonce; + + if (auth != soup_message_get_auth (msg)) + return; + + header = soup_message_headers_get_one (msg->response_headers, + soup_auth_is_for_proxy (auth) ? + "Proxy-Authentication-Info" : + "Authentication-Info"); + g_return_if_fail (header != NULL); + + auth_params = soup_header_parse_param_list (header); + if (!auth_params) + return; + + nextnonce = g_strdup (g_hash_table_lookup (auth_params, "nextnonce")); + if (nextnonce) { + g_free (priv->nonce); + priv->nonce = nextnonce; + } + + soup_header_free_param_list (auth_params); +} + +static char * +soup_auth_digest_get_authorization (SoupAuth *auth, SoupMessage *msg) +{ + SoupAuthDigest *auth_digest = SOUP_AUTH_DIGEST (auth); + SoupAuthDigestPrivate *priv = soup_auth_digest_get_instance_private (auth_digest); + char response[33], *token; + char *url, *algorithm; + GString *out; + SoupURI *uri; + + uri = soup_message_get_uri (msg); + g_return_val_if_fail (uri != NULL, NULL); + url = soup_uri_to_string (uri, TRUE); + + soup_auth_digest_compute_response (msg->method, url, priv->hex_a1, + priv->qop, priv->nonce, + priv->cnonce, priv->nc, + response); + + out = g_string_new ("Digest "); + + soup_header_g_string_append_param_quoted (out, "username", priv->user); + g_string_append (out, ", "); + soup_header_g_string_append_param_quoted (out, "realm", auth->realm); + g_string_append (out, ", "); + soup_header_g_string_append_param_quoted (out, "nonce", priv->nonce); + g_string_append (out, ", "); + soup_header_g_string_append_param_quoted (out, "uri", url); + g_string_append (out, ", "); + algorithm = soup_auth_digest_get_algorithm (priv->algorithm); + g_string_append_printf (out, "algorithm=%s", algorithm); + g_free (algorithm); + g_string_append (out, ", "); + soup_header_g_string_append_param_quoted (out, "response", response); + + if (priv->opaque) { + g_string_append (out, ", "); + soup_header_g_string_append_param_quoted (out, "opaque", priv->opaque); + } + + if (priv->qop) { + char *qop = soup_auth_digest_get_qop (priv->qop); + + g_string_append (out, ", "); + soup_header_g_string_append_param_quoted (out, "cnonce", priv->cnonce); + g_string_append_printf (out, ", nc=%.8x, qop=%s", + priv->nc, qop); + g_free (qop); + } + + g_free (url); + + priv->nc++; + + token = g_string_free (out, FALSE); + + soup_message_add_header_handler (msg, + "got_headers", + soup_auth_is_for_proxy (auth) ? + "Proxy-Authentication-Info" : + "Authentication-Info", + G_CALLBACK (authentication_info_cb), + auth); + return token; +} + +static void +soup_auth_digest_class_init (SoupAuthDigestClass *auth_digest_class) +{ + SoupAuthClass *auth_class = SOUP_AUTH_CLASS (auth_digest_class); + GObjectClass *object_class = G_OBJECT_CLASS (auth_digest_class); + + auth_class->scheme_name = "Digest"; + auth_class->strength = 5; + + auth_class->get_protection_space = soup_auth_digest_get_protection_space; + auth_class->update = soup_auth_digest_update; + auth_class->authenticate = soup_auth_digest_authenticate; + auth_class->is_authenticated = soup_auth_digest_is_authenticated; + auth_class->get_authorization = soup_auth_digest_get_authorization; + + object_class->finalize = soup_auth_digest_finalize; +} diff --git a/libsoup/soup-auth-digest.h b/libsoup/soup-auth-digest.h new file mode 100644 index 0000000..0165f74 --- /dev/null +++ b/libsoup/soup-auth-digest.h @@ -0,0 +1,64 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2000-2003, Ximian, Inc. + */ + +#ifndef SOUP_AUTH_DIGEST_H +#define SOUP_AUTH_DIGEST_H 1 + +#include "soup-auth.h" + +#define SOUP_AUTH_DIGEST(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), SOUP_TYPE_AUTH_DIGEST, SoupAuthDigest)) +#define SOUP_AUTH_DIGEST_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_AUTH_DIGEST, SoupAuthDigestClass)) +#define SOUP_IS_AUTH_DIGEST(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), SOUP_TYPE_AUTH_DIGEST)) +#define SOUP_IS_AUTH_DIGEST_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SOUP_TYPE_AUTH_DIGEST)) +#define SOUP_AUTH_DIGEST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_AUTH_DIGEST, SoupAuthDigestClass)) + +typedef struct { + SoupAuth parent; + +} SoupAuthDigest; + +typedef struct { + SoupAuthClass parent_class; + +} SoupAuthDigestClass; + +/* Utility routines (also used by SoupAuthDomainDigest) */ + +typedef enum { + SOUP_AUTH_DIGEST_ALGORITHM_NONE, + SOUP_AUTH_DIGEST_ALGORITHM_MD5, + SOUP_AUTH_DIGEST_ALGORITHM_MD5_SESS +} SoupAuthDigestAlgorithm; + +typedef enum { + SOUP_AUTH_DIGEST_QOP_AUTH = 1 << 0, + SOUP_AUTH_DIGEST_QOP_AUTH_INT = 1 << 1 +} SoupAuthDigestQop; + +SoupAuthDigestAlgorithm soup_auth_digest_parse_algorithm (const char *algorithm); +char *soup_auth_digest_get_algorithm (SoupAuthDigestAlgorithm algorithm); + +SoupAuthDigestQop soup_auth_digest_parse_qop (const char *qop); +char *soup_auth_digest_get_qop (SoupAuthDigestQop qop); + +void soup_auth_digest_compute_hex_urp (const char *username, + const char *realm, + const char *password, + char hex_urp[33]); +void soup_auth_digest_compute_hex_a1 (const char *hex_urp, + SoupAuthDigestAlgorithm algorithm, + const char *nonce, + const char *cnonce, + char hex_a1[33]); +void soup_auth_digest_compute_response (const char *method, + const char *uri, + const char *hex_a1, + SoupAuthDigestQop qop, + const char *nonce, + const char *cnonce, + int nc, + char response[33]); + +#endif /*SOUP_AUTH_DIGEST_H*/ diff --git a/libsoup/soup-auth-domain-basic.c b/libsoup/soup-auth-domain-basic.c new file mode 100644 index 0000000..aef2f68 --- /dev/null +++ b/libsoup/soup-auth-domain-basic.c @@ -0,0 +1,332 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-auth-domain-basic.c: HTTP Basic Authentication (server-side) + * + * Copyright (C) 2007 Novell, Inc. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "soup-auth-domain-basic.h" +#include "soup.h" + +/** + * SECTION:soup-auth-domain-basic + * @short_description: Server-side "Basic" authentication + * + * #SoupAuthDomainBasic handles the server side of HTTP "Basic" (ie, + * cleartext password) authentication. + **/ + +enum { + PROP_0, + + PROP_AUTH_CALLBACK, + PROP_AUTH_DATA, + + LAST_PROP +}; + +typedef struct { + SoupAuthDomainBasicAuthCallback auth_callback; + gpointer auth_data; + GDestroyNotify auth_dnotify; +} SoupAuthDomainBasicPrivate; + +G_DEFINE_TYPE_WITH_PRIVATE (SoupAuthDomainBasic, soup_auth_domain_basic, SOUP_TYPE_AUTH_DOMAIN) + +static void +soup_auth_domain_basic_init (SoupAuthDomainBasic *basic) +{ +} + +static void +soup_auth_domain_basic_finalize (GObject *object) +{ + SoupAuthDomainBasicPrivate *priv = + soup_auth_domain_basic_get_instance_private (SOUP_AUTH_DOMAIN_BASIC (object)); + + if (priv->auth_dnotify) + priv->auth_dnotify (priv->auth_data); + + G_OBJECT_CLASS (soup_auth_domain_basic_parent_class)->finalize (object); +} + +static void +soup_auth_domain_basic_set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + SoupAuthDomainBasicPrivate *priv = + soup_auth_domain_basic_get_instance_private (SOUP_AUTH_DOMAIN_BASIC (object)); + + switch (prop_id) { + case PROP_AUTH_CALLBACK: + priv->auth_callback = g_value_get_pointer (value); + break; + case PROP_AUTH_DATA: + if (priv->auth_dnotify) { + priv->auth_dnotify (priv->auth_data); + priv->auth_dnotify = NULL; + } + priv->auth_data = g_value_get_pointer (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +soup_auth_domain_basic_get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + SoupAuthDomainBasicPrivate *priv = + soup_auth_domain_basic_get_instance_private (SOUP_AUTH_DOMAIN_BASIC (object)); + + switch (prop_id) { + case PROP_AUTH_CALLBACK: + g_value_set_pointer (value, priv->auth_callback); + break; + case PROP_AUTH_DATA: + g_value_set_pointer (value, priv->auth_data); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/** + * soup_auth_domain_basic_new: + * @optname1: name of first option, or %NULL + * @...: option name/value pairs + * + * Creates a #SoupAuthDomainBasic. You must set the + * %SOUP_AUTH_DOMAIN_REALM parameter, to indicate the realm name to be + * returned with the authentication challenge to the client. Other + * parameters are optional. + * + * Return value: the new #SoupAuthDomain + **/ +SoupAuthDomain * +soup_auth_domain_basic_new (const char *optname1, ...) +{ + SoupAuthDomain *domain; + va_list ap; + + va_start (ap, optname1); + domain = (SoupAuthDomain *)g_object_new_valist (SOUP_TYPE_AUTH_DOMAIN_BASIC, + optname1, ap); + va_end (ap); + + g_return_val_if_fail (soup_auth_domain_get_realm (domain) != NULL, NULL); + + return domain; +} + +/** + * SoupAuthDomainBasicAuthCallback: + * @domain: the domain + * @msg: the message being authenticated + * @username: the username provided by the client + * @password: the password provided by the client + * @user_data: the data passed to soup_auth_domain_basic_set_auth_callback() + * + * Callback used by #SoupAuthDomainBasic for authentication purposes. + * The application should verify that @username and @password and valid + * and return %TRUE or %FALSE. + * + * If you are maintaining your own password database (rather than + * using the password to authenticate against some other system like + * PAM or a remote server), you should make sure you know what you are + * doing. In particular, don't store cleartext passwords, or + * easily-computed hashes of cleartext passwords, even if you don't + * care that much about the security of your server, because users + * will frequently use the same password for multiple sites, and so + * compromising any site with a cleartext (or easily-cracked) password + * database may give attackers access to other more-interesting sites + * as well. + * + * Return value: %TRUE if @username and @password are valid + **/ + +/** + * soup_auth_domain_basic_set_auth_callback: + * @domain: the domain + * @callback: the callback + * @user_data: data to pass to @auth_callback + * @dnotify: destroy notifier to free @user_data when @domain + * is destroyed + * + * Sets the callback that @domain will use to authenticate incoming + * requests. For each request containing authorization, @domain will + * invoke the callback, and then either accept or reject the request + * based on @callback's return value. + * + * You can also set the auth callback by setting the + * %SOUP_AUTH_DOMAIN_BASIC_AUTH_CALLBACK and + * %SOUP_AUTH_DOMAIN_BASIC_AUTH_DATA properties, which can also be + * used to set the callback at construct time. + **/ +void +soup_auth_domain_basic_set_auth_callback (SoupAuthDomain *domain, + SoupAuthDomainBasicAuthCallback callback, + gpointer user_data, + GDestroyNotify dnotify) +{ + SoupAuthDomainBasicPrivate *priv = + soup_auth_domain_basic_get_instance_private (SOUP_AUTH_DOMAIN_BASIC (domain)); + + if (priv->auth_dnotify) + priv->auth_dnotify (priv->auth_data); + + priv->auth_callback = callback; + priv->auth_data = user_data; + priv->auth_dnotify = dnotify; + + g_object_notify (G_OBJECT (domain), SOUP_AUTH_DOMAIN_BASIC_AUTH_CALLBACK); + g_object_notify (G_OBJECT (domain), SOUP_AUTH_DOMAIN_BASIC_AUTH_DATA); +} + +static void +pw_free (char *pw) +{ + memset (pw, 0, strlen (pw)); + g_free (pw); +} + +static gboolean +parse_basic (SoupMessage *msg, const char *header, + char **username, char **password) +{ + char *decoded, *colon; + gsize len, plen; + + if (!header || (strncmp (header, "Basic ", 6) != 0)) + return FALSE; + + decoded = (char *)g_base64_decode (header + 6, &len); + if (!decoded) + return FALSE; + + colon = memchr (decoded, ':', len); + if (!colon) { + pw_free (decoded); + return FALSE; + } + *colon = '\0'; + plen = len - (colon - decoded) - 1; + + *password = g_strndup (colon + 1, plen); + memset (colon + 1, 0, plen); + *username = decoded; + return TRUE; +} + +static char * +soup_auth_domain_basic_accepts (SoupAuthDomain *domain, SoupMessage *msg, + const char *header) +{ + SoupAuthDomainBasicPrivate *priv = + soup_auth_domain_basic_get_instance_private (SOUP_AUTH_DOMAIN_BASIC (domain)); + char *username, *password; + gboolean ok = FALSE; + + if (!parse_basic (msg, header, &username, &password)) + return NULL; + + if (priv->auth_callback) { + ok = priv->auth_callback (domain, msg, username, password, + priv->auth_data); + } else { + ok = soup_auth_domain_try_generic_auth_callback ( + domain, msg, username); + } + + pw_free (password); + + if (ok) + return username; + else { + g_free (username); + return NULL; + } +} + +static char * +soup_auth_domain_basic_challenge (SoupAuthDomain *domain, SoupMessage *msg) +{ + GString *challenge; + + challenge = g_string_new ("Basic "); + soup_header_g_string_append_param (challenge, "realm", soup_auth_domain_get_realm (domain)); + return g_string_free (challenge, FALSE); +} + +static gboolean +soup_auth_domain_basic_check_password (SoupAuthDomain *domain, + SoupMessage *msg, + const char *username, + const char *password) +{ + const char *header; + char *msg_username, *msg_password; + gboolean ok; + + header = soup_message_headers_get_one (msg->request_headers, + "Authorization"); + if (!parse_basic (msg, header, &msg_username, &msg_password)) + return FALSE; + + ok = (!strcmp (username, msg_username) && + !strcmp (password, msg_password)); + g_free (msg_username); + pw_free (msg_password); + + return ok; +} + +static void +soup_auth_domain_basic_class_init (SoupAuthDomainBasicClass *basic_class) +{ + SoupAuthDomainClass *auth_domain_class = + SOUP_AUTH_DOMAIN_CLASS (basic_class); + GObjectClass *object_class = G_OBJECT_CLASS (basic_class); + + auth_domain_class->accepts = soup_auth_domain_basic_accepts; + auth_domain_class->challenge = soup_auth_domain_basic_challenge; + auth_domain_class->check_password = soup_auth_domain_basic_check_password; + + object_class->finalize = soup_auth_domain_basic_finalize; + object_class->set_property = soup_auth_domain_basic_set_property; + object_class->get_property = soup_auth_domain_basic_get_property; + + /** + * SOUP_AUTH_DOMAIN_BASIC_AUTH_CALLBACK: + * + * Alias for the #SoupAuthDomainBasic:auth-callback property. + * (The #SoupAuthDomainBasicAuthCallback.) + **/ + g_object_class_install_property ( + object_class, PROP_AUTH_CALLBACK, + g_param_spec_pointer (SOUP_AUTH_DOMAIN_BASIC_AUTH_CALLBACK, + "Authentication callback", + "Password-checking callback", + G_PARAM_READWRITE)); + /** + * SOUP_AUTH_DOMAIN_BASIC_AUTH_DATA: + * + * Alias for the #SoupAuthDomainBasic:auth-data property. + * (The data to pass to the #SoupAuthDomainBasicAuthCallback.) + **/ + g_object_class_install_property ( + object_class, PROP_AUTH_DATA, + g_param_spec_pointer (SOUP_AUTH_DOMAIN_BASIC_AUTH_DATA, + "Authentication callback data", + "Data to pass to authentication callback", + G_PARAM_READWRITE)); +} diff --git a/libsoup/soup-auth-domain-basic.h b/libsoup/soup-auth-domain-basic.h new file mode 100644 index 0000000..f1caeb2 --- /dev/null +++ b/libsoup/soup-auth-domain-basic.h @@ -0,0 +1,59 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2007 Novell, Inc. + */ + +#ifndef SOUP_AUTH_DOMAIN_BASIC_H +#define SOUP_AUTH_DOMAIN_BASIC_H 1 + +#include + +G_BEGIN_DECLS + +#define SOUP_TYPE_AUTH_DOMAIN_BASIC (soup_auth_domain_basic_get_type ()) +#define SOUP_AUTH_DOMAIN_BASIC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SOUP_TYPE_AUTH_DOMAIN_BASIC, SoupAuthDomainBasic)) +#define SOUP_AUTH_DOMAIN_BASIC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_AUTH_DOMAIN_BASIC, SoupAuthDomainBasicClass)) +#define SOUP_IS_AUTH_DOMAIN_BASIC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SOUP_TYPE_AUTH_DOMAIN_BASIC)) +#define SOUP_IS_AUTH_DOMAIN_BASIC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), SOUP_TYPE_AUTH_DOMAIN_BASIC)) +#define SOUP_AUTH_DOMAIN_BASIC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_AUTH_DOMAIN_BASIC, SoupAuthDomainBasicClass)) + +typedef struct { + SoupAuthDomain parent; + +} SoupAuthDomainBasic; + +typedef struct { + SoupAuthDomainClass parent_class; + + /* Padding for future expansion */ + void (*_libsoup_reserved1) (void); + void (*_libsoup_reserved2) (void); + void (*_libsoup_reserved3) (void); + void (*_libsoup_reserved4) (void); +} SoupAuthDomainBasicClass; + +#define SOUP_AUTH_DOMAIN_BASIC_AUTH_CALLBACK "auth-callback" +#define SOUP_AUTH_DOMAIN_BASIC_AUTH_DATA "auth-data" + +SOUP_AVAILABLE_IN_2_4 +GType soup_auth_domain_basic_get_type (void); + +SOUP_AVAILABLE_IN_2_4 +SoupAuthDomain *soup_auth_domain_basic_new (const char *optname1, + ...) G_GNUC_NULL_TERMINATED; + +typedef gboolean (*SoupAuthDomainBasicAuthCallback) (SoupAuthDomain *domain, + SoupMessage *msg, + const char *username, + const char *password, + gpointer user_data); + +SOUP_AVAILABLE_IN_2_4 +void soup_auth_domain_basic_set_auth_callback (SoupAuthDomain *domain, + SoupAuthDomainBasicAuthCallback callback, + gpointer user_data, + GDestroyNotify dnotify); + +G_END_DECLS + +#endif /* SOUP_AUTH_DOMAIN_BASIC_H */ diff --git a/libsoup/soup-auth-domain-digest.c b/libsoup/soup-auth-domain-digest.c new file mode 100644 index 0000000..8bdb561 --- /dev/null +++ b/libsoup/soup-auth-domain-digest.c @@ -0,0 +1,438 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-auth-domain-digest.c: HTTP Digest Authentication (server-side) + * + * Copyright (C) 2007 Novell, Inc. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include "soup-auth-domain-digest.h" +#include "soup.h" +#include "soup-auth-digest.h" + +/** + * SECTION:soup-auth-domain-digest + * @short_description: Server-side "Digest" authentication + * + * #SoupAuthDomainDigest handles the server side of HTTP "Digest" + * authentication. + **/ + +enum { + PROP_0, + + PROP_AUTH_CALLBACK, + PROP_AUTH_DATA, + + LAST_PROP +}; + +typedef struct { + SoupAuthDomainDigestAuthCallback auth_callback; + gpointer auth_data; + GDestroyNotify auth_dnotify; + +} SoupAuthDomainDigestPrivate; + +G_DEFINE_TYPE_WITH_PRIVATE (SoupAuthDomainDigest, soup_auth_domain_digest, SOUP_TYPE_AUTH_DOMAIN) + +static void +soup_auth_domain_digest_init (SoupAuthDomainDigest *digest) +{ +} + +static void +soup_auth_domain_digest_finalize (GObject *object) +{ + SoupAuthDomainDigestPrivate *priv = + soup_auth_domain_digest_get_instance_private (SOUP_AUTH_DOMAIN_DIGEST (object)); + + if (priv->auth_dnotify) + priv->auth_dnotify (priv->auth_data); + + G_OBJECT_CLASS (soup_auth_domain_digest_parent_class)->finalize (object); +} + +static void +soup_auth_domain_digest_set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + SoupAuthDomainDigestPrivate *priv = + soup_auth_domain_digest_get_instance_private (SOUP_AUTH_DOMAIN_DIGEST (object)); + + switch (prop_id) { + case PROP_AUTH_CALLBACK: + priv->auth_callback = g_value_get_pointer (value); + break; + case PROP_AUTH_DATA: + if (priv->auth_dnotify) { + priv->auth_dnotify (priv->auth_data); + priv->auth_dnotify = NULL; + } + priv->auth_data = g_value_get_pointer (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +soup_auth_domain_digest_get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + SoupAuthDomainDigestPrivate *priv = + soup_auth_domain_digest_get_instance_private (SOUP_AUTH_DOMAIN_DIGEST (object)); + + switch (prop_id) { + case PROP_AUTH_CALLBACK: + g_value_set_pointer (value, priv->auth_callback); + break; + case PROP_AUTH_DATA: + g_value_set_pointer (value, priv->auth_data); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/** + * soup_auth_domain_digest_new: + * @optname1: name of first option, or %NULL + * @...: option name/value pairs + * + * Creates a #SoupAuthDomainDigest. You must set the + * %SOUP_AUTH_DOMAIN_REALM parameter, to indicate the realm name to be + * returned with the authentication challenge to the client. Other + * parameters are optional. + * + * Return value: the new #SoupAuthDomain + **/ +SoupAuthDomain * +soup_auth_domain_digest_new (const char *optname1, ...) +{ + SoupAuthDomain *domain; + va_list ap; + + va_start (ap, optname1); + domain = (SoupAuthDomain *)g_object_new_valist (SOUP_TYPE_AUTH_DOMAIN_DIGEST, + optname1, ap); + va_end (ap); + + g_return_val_if_fail (soup_auth_domain_get_realm (domain) != NULL, NULL); + + return domain; +} + +/** + * SoupAuthDomainDigestAuthCallback: + * @domain: the domain + * @msg: the message being authenticated + * @username: the username provided by the client + * @user_data: the data passed to soup_auth_domain_digest_set_auth_callback() + * + * Callback used by #SoupAuthDomainDigest for authentication purposes. + * The application should look up @username in its password database, + * and return the corresponding encoded password (see + * soup_auth_domain_digest_encode_password()). + * + * Return value: (nullable): the encoded password, or %NULL if + * @username is not a valid user. @domain will free the password when + * it is done with it. + **/ + +/** + * soup_auth_domain_digest_set_auth_callback: + * @domain: the domain + * @callback: the callback + * @user_data: data to pass to @auth_callback + * @dnotify: destroy notifier to free @user_data when @domain + * is destroyed + * + * Sets the callback that @domain will use to authenticate incoming + * requests. For each request containing authorization, @domain will + * invoke the callback, and then either accept or reject the request + * based on @callback's return value. + * + * You can also set the auth callback by setting the + * %SOUP_AUTH_DOMAIN_DIGEST_AUTH_CALLBACK and + * %SOUP_AUTH_DOMAIN_DIGEST_AUTH_DATA properties, which can also be + * used to set the callback at construct time. + **/ +void +soup_auth_domain_digest_set_auth_callback (SoupAuthDomain *domain, + SoupAuthDomainDigestAuthCallback callback, + gpointer user_data, + GDestroyNotify dnotify) +{ + SoupAuthDomainDigestPrivate *priv = + soup_auth_domain_digest_get_instance_private (SOUP_AUTH_DOMAIN_DIGEST (domain)); + + if (priv->auth_dnotify) + priv->auth_dnotify (priv->auth_data); + + priv->auth_callback = callback; + priv->auth_data = user_data; + priv->auth_dnotify = dnotify; + + g_object_notify (G_OBJECT (domain), SOUP_AUTH_DOMAIN_DIGEST_AUTH_CALLBACK); + g_object_notify (G_OBJECT (domain), SOUP_AUTH_DOMAIN_DIGEST_AUTH_DATA); +} + +static gboolean +check_hex_urp (SoupAuthDomain *domain, SoupMessage *msg, + GHashTable *params, const char *username, + const char *hex_urp) +{ + const char *uri, *qop, *realm, *msg_username; + const char *nonce, *nc, *cnonce, *response; + char hex_a1[33], computed_response[33]; + int nonce_count; + SoupURI *dig_uri, *req_uri; + + msg_username = g_hash_table_lookup (params, "username"); + if (!msg_username || strcmp (msg_username, username) != 0) + return FALSE; + + /* Check uri */ + uri = g_hash_table_lookup (params, "uri"); + if (!uri) + return FALSE; + + req_uri = soup_message_get_uri (msg); + dig_uri = soup_uri_new (uri); + if (dig_uri) { + if (!soup_uri_equal (dig_uri, req_uri)) { + soup_uri_free (dig_uri); + return FALSE; + } + soup_uri_free (dig_uri); + } else { + char *req_path; + char *dig_path; + + req_path = soup_uri_to_string (req_uri, TRUE); + dig_path = soup_uri_decode (uri); + + if (strcmp (dig_path, req_path) != 0) { + g_free (req_path); + g_free (dig_path); + return FALSE; + } + g_free (req_path); + g_free (dig_path); + } + + /* Check qop; we only support "auth" for now */ + qop = g_hash_table_lookup (params, "qop"); + if (!qop || strcmp (qop, "auth") != 0) + return FALSE; + + /* Check realm */ + realm = g_hash_table_lookup (params, "realm"); + if (!realm || strcmp (realm, soup_auth_domain_get_realm (domain)) != 0) + return FALSE; + + nonce = g_hash_table_lookup (params, "nonce"); + if (!nonce) + return FALSE; + nc = g_hash_table_lookup (params, "nc"); + if (!nc) + return FALSE; + nonce_count = strtoul (nc, NULL, 16); + if (nonce_count <= 0) + return FALSE; + cnonce = g_hash_table_lookup (params, "cnonce"); + if (!cnonce) + return FALSE; + response = g_hash_table_lookup (params, "response"); + if (!response) + return FALSE; + + soup_auth_digest_compute_hex_a1 (hex_urp, + SOUP_AUTH_DIGEST_ALGORITHM_MD5, + nonce, cnonce, hex_a1); + soup_auth_digest_compute_response (msg->method, uri, + hex_a1, + SOUP_AUTH_DIGEST_QOP_AUTH, + nonce, cnonce, nonce_count, + computed_response); + return strcmp (response, computed_response) == 0; +} + +static char * +soup_auth_domain_digest_accepts (SoupAuthDomain *domain, SoupMessage *msg, + const char *header) +{ + SoupAuthDomainDigestPrivate *priv = + soup_auth_domain_digest_get_instance_private (SOUP_AUTH_DOMAIN_DIGEST (domain)); + GHashTable *params; + const char *username; + gboolean accept = FALSE; + char *ret_user; + + if (strncmp (header, "Digest ", 7) != 0) + return NULL; + + params = soup_header_parse_param_list (header + 7); + if (!params) + return NULL; + + username = g_hash_table_lookup (params, "username"); + if (!username) { + soup_header_free_param_list (params); + return NULL; + } + + if (priv->auth_callback) { + char *hex_urp; + + hex_urp = priv->auth_callback (domain, msg, username, + priv->auth_data); + if (hex_urp) { + accept = check_hex_urp (domain, msg, params, + username, hex_urp); + g_free (hex_urp); + } else + accept = FALSE; + } else { + accept = soup_auth_domain_try_generic_auth_callback ( + domain, msg, username); + } + + ret_user = accept ? g_strdup (username) : NULL; + soup_header_free_param_list (params); + return ret_user; +} + +static char * +soup_auth_domain_digest_challenge (SoupAuthDomain *domain, SoupMessage *msg) +{ + GString *str; + + str = g_string_new ("Digest "); + soup_header_g_string_append_param_quoted (str, "realm", soup_auth_domain_get_realm (domain)); + g_string_append_printf (str, ", nonce=\"%lu%lu\"", + (unsigned long) msg, + (unsigned long) time (0)); + g_string_append_printf (str, ", qop=\"auth\""); + g_string_append_printf (str, ", algorithm=MD5"); + + return g_string_free (str, FALSE); +} + +/** + * soup_auth_domain_digest_encode_password: + * @username: a username + * @realm: an auth realm name + * @password: the password for @username in @realm + * + * Encodes the username/realm/password triplet for Digest + * authentication. (That is, it returns a stringified MD5 hash of + * @username, @realm, and @password concatenated together). This is + * the form that is needed as the return value of + * #SoupAuthDomainDigest's auth handler. + * + * For security reasons, you should store the encoded hash, rather + * than storing the cleartext password itself and calling this method + * only when you need to verify it. This way, if your server is + * compromised, the attackers will not gain access to cleartext + * passwords which might also be usable at other sites. (Note also + * that the encoded password returned by this method is identical to + * the encoded password stored in an Apache .htdigest file.) + * + * Return value: the encoded password + **/ +char * +soup_auth_domain_digest_encode_password (const char *username, + const char *realm, + const char *password) +{ + char hex_urp[33]; + + soup_auth_digest_compute_hex_urp (username, realm, password, hex_urp); + return g_strdup (hex_urp); +} + +static gboolean +soup_auth_domain_digest_check_password (SoupAuthDomain *domain, + SoupMessage *msg, + const char *username, + const char *password) +{ + const char *header; + GHashTable *params; + const char *msg_username; + char hex_urp[33]; + gboolean accept; + + header = soup_message_headers_get_one (msg->request_headers, + "Authorization"); + if (!header || (strncmp (header, "Digest ", 7) != 0)) + return FALSE; + + params = soup_header_parse_param_list (header + 7); + if (!params) + return FALSE; + + msg_username = g_hash_table_lookup (params, "username"); + if (!msg_username || strcmp (msg_username, username) != 0) { + soup_header_free_param_list (params); + return FALSE; + } + + soup_auth_digest_compute_hex_urp (username, + soup_auth_domain_get_realm (domain), + password, hex_urp); + accept = check_hex_urp (domain, msg, params, username, hex_urp); + soup_header_free_param_list (params); + return accept; +} + +static void +soup_auth_domain_digest_class_init (SoupAuthDomainDigestClass *digest_class) +{ + SoupAuthDomainClass *auth_domain_class = + SOUP_AUTH_DOMAIN_CLASS (digest_class); + GObjectClass *object_class = G_OBJECT_CLASS (digest_class); + + auth_domain_class->accepts = soup_auth_domain_digest_accepts; + auth_domain_class->challenge = soup_auth_domain_digest_challenge; + auth_domain_class->check_password = soup_auth_domain_digest_check_password; + + object_class->finalize = soup_auth_domain_digest_finalize; + object_class->set_property = soup_auth_domain_digest_set_property; + object_class->get_property = soup_auth_domain_digest_get_property; + + /** + * SOUP_AUTH_DOMAIN_DIGEST_AUTH_CALLBACK: + * + * Alias for the #SoupAuthDomainDigest:auth-callback property. + * (The #SoupAuthDomainDigestAuthCallback.) + **/ + g_object_class_install_property ( + object_class, PROP_AUTH_CALLBACK, + g_param_spec_pointer (SOUP_AUTH_DOMAIN_DIGEST_AUTH_CALLBACK, + "Authentication callback", + "Password-finding callback", + G_PARAM_READWRITE)); + /** + * SOUP_AUTH_DOMAIN_DIGEST_AUTH_DATA: + * + * Alias for the #SoupAuthDomainDigest:auth-callback property. + * (The #SoupAuthDomainDigestAuthCallback.) + **/ + g_object_class_install_property ( + object_class, PROP_AUTH_DATA, + g_param_spec_pointer (SOUP_AUTH_DOMAIN_DIGEST_AUTH_DATA, + "Authentication callback data", + "Data to pass to authentication callback", + G_PARAM_READWRITE)); +} diff --git a/libsoup/soup-auth-domain-digest.h b/libsoup/soup-auth-domain-digest.h new file mode 100644 index 0000000..8940a18 --- /dev/null +++ b/libsoup/soup-auth-domain-digest.h @@ -0,0 +1,63 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2007 Novell, Inc. + */ + +#ifndef SOUP_AUTH_DOMAIN_DIGEST_H +#define SOUP_AUTH_DOMAIN_DIGEST_H 1 + +#include + +G_BEGIN_DECLS + +#define SOUP_TYPE_AUTH_DOMAIN_DIGEST (soup_auth_domain_digest_get_type ()) +#define SOUP_AUTH_DOMAIN_DIGEST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SOUP_TYPE_AUTH_DOMAIN_DIGEST, SoupAuthDomainDigest)) +#define SOUP_AUTH_DOMAIN_DIGEST_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_AUTH_DOMAIN_DIGEST, SoupAuthDomainDigestClass)) +#define SOUP_IS_AUTH_DOMAIN_DIGEST(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SOUP_TYPE_AUTH_DOMAIN_DIGEST)) +#define SOUP_IS_AUTH_DOMAIN_DIGEST_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), SOUP_TYPE_AUTH_DOMAIN_DIGEST)) +#define SOUP_AUTH_DOMAIN_DIGEST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_AUTH_DOMAIN_DIGEST, SoupAuthDomainDigestClass)) + +typedef struct { + SoupAuthDomain parent; + +} SoupAuthDomainDigest; + +typedef struct { + SoupAuthDomainClass parent_class; + + /* Padding for future expansion */ + void (*_libsoup_reserved1) (void); + void (*_libsoup_reserved2) (void); + void (*_libsoup_reserved3) (void); + void (*_libsoup_reserved4) (void); +} SoupAuthDomainDigestClass; + +#define SOUP_AUTH_DOMAIN_DIGEST_AUTH_CALLBACK "auth-callback" +#define SOUP_AUTH_DOMAIN_DIGEST_AUTH_DATA "auth-data" + +SOUP_AVAILABLE_IN_2_4 +GType soup_auth_domain_digest_get_type (void); + +SOUP_AVAILABLE_IN_2_4 +SoupAuthDomain *soup_auth_domain_digest_new (const char *optname1, + ...) G_GNUC_NULL_TERMINATED; + +typedef char * (*SoupAuthDomainDigestAuthCallback) (SoupAuthDomain *domain, + SoupMessage *msg, + const char *username, + gpointer user_data); + +SOUP_AVAILABLE_IN_2_4 +void soup_auth_domain_digest_set_auth_callback (SoupAuthDomain *domain, + SoupAuthDomainDigestAuthCallback callback, + gpointer user_data, + GDestroyNotify dnotify); + +SOUP_AVAILABLE_IN_2_4 +char *soup_auth_domain_digest_encode_password (const char *username, + const char *realm, + const char *password); + +G_END_DECLS + +#endif /* SOUP_AUTH_DOMAIN_DIGEST_H */ diff --git a/libsoup/soup-auth-domain.c b/libsoup/soup-auth-domain.c new file mode 100644 index 0000000..06c9e64 --- /dev/null +++ b/libsoup/soup-auth-domain.c @@ -0,0 +1,617 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-auth-domain.c: HTTP Authentication Domain (server-side) + * + * Copyright (C) 2007 Novell, Inc. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "soup-auth-domain.h" +#include "soup.h" +#include "soup-path-map.h" + +/** + * SECTION:soup-auth-domain + * @short_description: Server-side authentication + * @see_also: #SoupServer + * + * A #SoupAuthDomain manages authentication for all or part of a + * #SoupServer. To make a server require authentication, first create + * an appropriate subclass of #SoupAuthDomain, and then add it to the + * server with soup_server_add_auth_domain(). + * + * In order for an auth domain to have any effect, you must add one or + * more paths to it (via soup_auth_domain_add_path() or the + * %SOUP_AUTH_DOMAIN_ADD_PATH property). To require authentication for + * all ordinary requests, add the path "/". (Note that this does not + * include the special "*" URI (eg, "OPTIONS *"), which must be added + * as a separate path if you want to cover it.) + * + * If you need greater control over which requests should and + * shouldn't be authenticated, add paths covering everything you + * might want authenticated, and then use a + * filter (soup_auth_domain_set_filter()) to bypass authentication for + * those requests that don't need it. + **/ + +enum { + PROP_0, + + PROP_REALM, + PROP_PROXY, + PROP_ADD_PATH, + PROP_REMOVE_PATH, + PROP_FILTER, + PROP_FILTER_DATA, + PROP_GENERIC_AUTH_CALLBACK, + PROP_GENERIC_AUTH_DATA, + + LAST_PROP +}; + +typedef struct { + char *realm; + gboolean proxy; + SoupPathMap *paths; + + SoupAuthDomainFilter filter; + gpointer filter_data; + GDestroyNotify filter_dnotify; + + SoupAuthDomainGenericAuthCallback auth_callback; + gpointer auth_data; + GDestroyNotify auth_dnotify; + +} SoupAuthDomainPrivate; + +G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (SoupAuthDomain, soup_auth_domain, G_TYPE_OBJECT) + +static void +soup_auth_domain_init (SoupAuthDomain *domain) +{ + SoupAuthDomainPrivate *priv = soup_auth_domain_get_instance_private (domain); + + priv->paths = soup_path_map_new (NULL); +} + +static void +soup_auth_domain_finalize (GObject *object) +{ + SoupAuthDomainPrivate *priv = soup_auth_domain_get_instance_private (SOUP_AUTH_DOMAIN (object)); + + g_free (priv->realm); + soup_path_map_free (priv->paths); + + if (priv->filter_dnotify) + priv->filter_dnotify (priv->filter_data); + if (priv->auth_dnotify) + priv->auth_dnotify (priv->auth_data); + + G_OBJECT_CLASS (soup_auth_domain_parent_class)->finalize (object); +} + +static void +soup_auth_domain_set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + SoupAuthDomain *auth_domain = SOUP_AUTH_DOMAIN (object); + SoupAuthDomainPrivate *priv = soup_auth_domain_get_instance_private (auth_domain); + + switch (prop_id) { + case PROP_REALM: + g_free (priv->realm); + priv->realm = g_value_dup_string (value); + break; + case PROP_PROXY: + priv->proxy = g_value_get_boolean (value); + break; + case PROP_ADD_PATH: + soup_auth_domain_add_path (auth_domain, + g_value_get_string (value)); + break; + case PROP_REMOVE_PATH: + soup_auth_domain_remove_path (auth_domain, + g_value_get_string (value)); + break; + case PROP_FILTER: + priv->filter = g_value_get_pointer (value); + break; + case PROP_FILTER_DATA: + if (priv->filter_dnotify) { + priv->filter_dnotify (priv->filter_data); + priv->filter_dnotify = NULL; + } + priv->filter_data = g_value_get_pointer (value); + break; + case PROP_GENERIC_AUTH_CALLBACK: + priv->auth_callback = g_value_get_pointer (value); + break; + case PROP_GENERIC_AUTH_DATA: + if (priv->auth_dnotify) { + priv->auth_dnotify (priv->auth_data); + priv->auth_dnotify = NULL; + } + priv->auth_data = g_value_get_pointer (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +soup_auth_domain_get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + SoupAuthDomainPrivate *priv = soup_auth_domain_get_instance_private (SOUP_AUTH_DOMAIN (object)); + + switch (prop_id) { + case PROP_REALM: + g_value_set_string (value, priv->realm); + break; + case PROP_PROXY: + g_value_set_boolean (value, priv->proxy); + break; + case PROP_FILTER: + g_value_set_pointer (value, priv->filter); + break; + case PROP_FILTER_DATA: + g_value_set_pointer (value, priv->filter_data); + break; + case PROP_GENERIC_AUTH_CALLBACK: + g_value_set_pointer (value, priv->auth_callback); + break; + case PROP_GENERIC_AUTH_DATA: + g_value_set_pointer (value, priv->auth_data); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +soup_auth_domain_class_init (SoupAuthDomainClass *auth_domain_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (auth_domain_class); + + object_class->finalize = soup_auth_domain_finalize; + object_class->set_property = soup_auth_domain_set_property; + object_class->get_property = soup_auth_domain_get_property; + + /** + * SOUP_AUTH_DOMAIN_REALM: + * + * Alias for the #SoupAuthDomain:realm property. (The realm of + * this auth domain.) + **/ + g_object_class_install_property ( + object_class, PROP_REALM, + g_param_spec_string (SOUP_AUTH_DOMAIN_REALM, + "Realm", + "The realm of this auth domain", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + /** + * SOUP_AUTH_DOMAIN_PROXY: + * + * Alias for the #SoupAuthDomain:proxy property. (Whether or + * not this is a proxy auth domain.) + **/ + g_object_class_install_property ( + object_class, PROP_PROXY, + g_param_spec_boolean (SOUP_AUTH_DOMAIN_PROXY, + "Proxy", + "Whether or not this is a proxy auth domain", + FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + /** + * SOUP_AUTH_DOMAIN_ADD_PATH: + * + * Alias for the #SoupAuthDomain:add-path property. (Shortcut + * for calling soup_auth_domain_add_path().) + **/ + g_object_class_install_property ( + object_class, PROP_ADD_PATH, + g_param_spec_string (SOUP_AUTH_DOMAIN_ADD_PATH, + "Add a path", + "Add a path covered by this auth domain", + NULL, + G_PARAM_WRITABLE)); + /** + * SOUP_AUTH_DOMAIN_REMOVE_PATH: + * + * Alias for the #SoupAuthDomain:remove-path property. + * (Shortcut for calling soup_auth_domain_remove_path().) + **/ + g_object_class_install_property ( + object_class, PROP_REMOVE_PATH, + g_param_spec_string (SOUP_AUTH_DOMAIN_REMOVE_PATH, + "Remove a path", + "Remove a path covered by this auth domain", + NULL, + G_PARAM_WRITABLE)); + /** + * SOUP_AUTH_DOMAIN_FILTER: + * + * Alias for the #SoupAuthDomain:filter property. (The + * #SoupAuthDomainFilter for the domain.) + **/ + g_object_class_install_property ( + object_class, PROP_FILTER, + g_param_spec_pointer (SOUP_AUTH_DOMAIN_FILTER, + "Filter", + "A filter for deciding whether or not to require authentication", + G_PARAM_READWRITE)); + /** + * SOUP_AUTH_DOMAIN_FILTER_DATA: + * + * Alias for the #SoupAuthDomain:filter-data property. (Data + * to pass to the #SoupAuthDomainFilter.) + **/ + g_object_class_install_property ( + object_class, PROP_FILTER_DATA, + g_param_spec_pointer (SOUP_AUTH_DOMAIN_FILTER_DATA, + "Filter data", + "Data to pass to filter", + G_PARAM_READWRITE)); + /** + * SOUP_AUTH_DOMAIN_GENERIC_AUTH_CALLBACK: + * + * Alias for the #SoupAuthDomain:generic-auth-callback property. + * (The #SoupAuthDomainGenericAuthCallback.) + **/ + g_object_class_install_property ( + object_class, PROP_GENERIC_AUTH_CALLBACK, + g_param_spec_pointer (SOUP_AUTH_DOMAIN_GENERIC_AUTH_CALLBACK, + "Generic authentication callback", + "An authentication callback that can be used with any SoupAuthDomain subclass", + G_PARAM_READWRITE)); + /** + * SOUP_AUTH_DOMAIN_GENERIC_AUTH_DATA: + * + * Alias for the #SoupAuthDomain:generic-auth-data property. + * (The data to pass to the #SoupAuthDomainGenericAuthCallback.) + **/ + g_object_class_install_property ( + object_class, PROP_GENERIC_AUTH_DATA, + g_param_spec_pointer (SOUP_AUTH_DOMAIN_GENERIC_AUTH_DATA, + "Authentication callback data", + "Data to pass to auth callback", + G_PARAM_READWRITE)); +} + +/** + * soup_auth_domain_add_path: + * @domain: a #SoupAuthDomain + * @path: the path to add to @domain + * + * Adds @path to @domain, such that requests under @path on @domain's + * server will require authentication (unless overridden by + * soup_auth_domain_remove_path() or soup_auth_domain_set_filter()). + * + * You can also add paths by setting the %SOUP_AUTH_DOMAIN_ADD_PATH + * property, which can also be used to add one or more paths at + * construct time. + **/ +void +soup_auth_domain_add_path (SoupAuthDomain *domain, const char *path) +{ + SoupAuthDomainPrivate *priv = soup_auth_domain_get_instance_private (domain); + + /* "" should not match "*" */ + if (!*path) + path = "/"; + + soup_path_map_add (priv->paths, path, GINT_TO_POINTER (TRUE)); +} + +/** + * soup_auth_domain_remove_path: + * @domain: a #SoupAuthDomain + * @path: the path to remove from @domain + * + * Removes @path from @domain, such that requests under @path on + * @domain's server will NOT require authentication. + * + * This is not simply an undo-er for soup_auth_domain_add_path(); it + * can be used to "carve out" a subtree that does not require + * authentication inside a hierarchy that does. Note also that unlike + * with soup_auth_domain_add_path(), this cannot be overridden by + * adding a filter, as filters can only bypass authentication that + * would otherwise be required, not require it where it would + * otherwise be unnecessary. + * + * You can also remove paths by setting the + * %SOUP_AUTH_DOMAIN_REMOVE_PATH property, which can also be used to + * remove one or more paths at construct time. + **/ +void +soup_auth_domain_remove_path (SoupAuthDomain *domain, const char *path) +{ + SoupAuthDomainPrivate *priv = soup_auth_domain_get_instance_private (domain); + + /* "" should not match "*" */ + if (!*path) + path = "/"; + + soup_path_map_add (priv->paths, path, GINT_TO_POINTER (FALSE)); +} + +/** + * SoupAuthDomainFilter: + * @domain: a #SoupAuthDomain + * @msg: a #SoupMessage + * @user_data: the data passed to soup_auth_domain_set_filter() + * + * The prototype for a #SoupAuthDomain filter; see + * soup_auth_domain_set_filter() for details. + * + * Return value: %TRUE if @msg requires authentication, %FALSE if not. + **/ + +/** + * soup_auth_domain_set_filter: + * @domain: a #SoupAuthDomain + * @filter: the auth filter for @domain + * @filter_data: data to pass to @filter + * @dnotify: destroy notifier to free @filter_data when @domain + * is destroyed + * + * Adds @filter as an authentication filter to @domain. The filter + * gets a chance to bypass authentication for certain requests that + * would otherwise require it. Eg, it might check the message's path + * in some way that is too complicated to do via the other methods, or + * it might check the message's method, and allow GETs but not PUTs. + * + * The filter function returns %TRUE if the request should still + * require authentication, or %FALSE if authentication is unnecessary + * for this request. + * + * To help prevent security holes, your filter should return %TRUE by + * default, and only return %FALSE under specifically-tested + * circumstances, rather than the other way around. Eg, in the example + * above, where you want to authenticate PUTs but not GETs, you should + * check if the method is GET and return %FALSE in that case, and then + * return %TRUE for all other methods (rather than returning %TRUE for + * PUT and %FALSE for all other methods). This way if it turned out + * (now or later) that some paths supported additional methods besides + * GET and PUT, those methods would default to being NOT allowed for + * unauthenticated users. + * + * You can also set the filter by setting the %SOUP_AUTH_DOMAIN_FILTER + * and %SOUP_AUTH_DOMAIN_FILTER_DATA properties, which can also be + * used to set the filter at construct time. + **/ +void +soup_auth_domain_set_filter (SoupAuthDomain *domain, + SoupAuthDomainFilter filter, + gpointer filter_data, + GDestroyNotify dnotify) +{ + SoupAuthDomainPrivate *priv = soup_auth_domain_get_instance_private (domain); + + if (priv->filter_dnotify) + priv->filter_dnotify (priv->filter_data); + + priv->filter = filter; + priv->filter_data = filter_data; + priv->filter_dnotify = dnotify; + + g_object_notify (G_OBJECT (domain), SOUP_AUTH_DOMAIN_FILTER); + g_object_notify (G_OBJECT (domain), SOUP_AUTH_DOMAIN_FILTER_DATA); +} + +/** + * soup_auth_domain_get_realm: + * @domain: a #SoupAuthDomain + * + * Gets the realm name associated with @domain + * + * Return value: @domain's realm + **/ +const char * +soup_auth_domain_get_realm (SoupAuthDomain *domain) +{ + SoupAuthDomainPrivate *priv = soup_auth_domain_get_instance_private (domain); + + return priv->realm; +} + +/** + * SoupAuthDomainGenericAuthCallback: + * @domain: a #SoupAuthDomain + * @msg: the #SoupMessage being authenticated + * @username: the username from @msg + * @user_data: the data passed to + * soup_auth_domain_set_generic_auth_callback() + * + * The prototype for a #SoupAuthDomain generic authentication callback. + * + * The callback should look up the user's password, call + * soup_auth_domain_check_password(), and use the return value from + * that method as its own return value. + * + * In general, for security reasons, it is preferable to use the + * auth-domain-specific auth callbacks (eg, + * #SoupAuthDomainBasicAuthCallback and + * #SoupAuthDomainDigestAuthCallback), because they don't require + * keeping a cleartext password database. Most users will use the same + * password for many different sites, meaning if any site with a + * cleartext password database is compromised, accounts on other + * servers might be compromised as well. For many of the cases where + * #SoupServer is used, this is not really relevant, but it may still + * be worth considering. + * + * Return value: %TRUE if @msg is authenticated, %FALSE if not. + **/ + +/** + * soup_auth_domain_set_generic_auth_callback: + * @domain: a #SoupAuthDomain + * @auth_callback: the auth callback + * @auth_data: data to pass to @auth_callback + * @dnotify: destroy notifier to free @auth_data when @domain + * is destroyed + * + * Sets @auth_callback as an authentication-handling callback for + * @domain. Whenever a request comes in to @domain which cannot be + * authenticated via a domain-specific auth callback (eg, + * #SoupAuthDomainDigestAuthCallback), the generic auth callback + * will be invoked. See #SoupAuthDomainGenericAuthCallback for information + * on what the callback should do. + **/ +void +soup_auth_domain_set_generic_auth_callback (SoupAuthDomain *domain, + SoupAuthDomainGenericAuthCallback auth_callback, + gpointer auth_data, + GDestroyNotify dnotify) +{ + SoupAuthDomainPrivate *priv = soup_auth_domain_get_instance_private (domain); + + if (priv->auth_dnotify) + priv->auth_dnotify (priv->auth_data); + + priv->auth_callback = auth_callback; + priv->auth_data = auth_data; + priv->auth_dnotify = dnotify; + + g_object_notify (G_OBJECT (domain), SOUP_AUTH_DOMAIN_GENERIC_AUTH_CALLBACK); + g_object_notify (G_OBJECT (domain), SOUP_AUTH_DOMAIN_GENERIC_AUTH_DATA); +} + +gboolean +soup_auth_domain_try_generic_auth_callback (SoupAuthDomain *domain, + SoupMessage *msg, + const char *username) +{ + SoupAuthDomainPrivate *priv = soup_auth_domain_get_instance_private (domain); + + if (priv->auth_callback) + return priv->auth_callback (domain, msg, username, priv->auth_data); + else + return FALSE; +} + +/** + * soup_auth_domain_check_password: + * @domain: a #SoupAuthDomain + * @msg: a #SoupMessage + * @username: a username + * @password: a password + * + * Checks if @msg authenticates to @domain via @username and + * @password. This would normally be called from a + * #SoupAuthDomainGenericAuthCallback. + * + * Return value: whether or not the message is authenticated + **/ +gboolean +soup_auth_domain_check_password (SoupAuthDomain *domain, + SoupMessage *msg, + const char *username, + const char *password) +{ + return SOUP_AUTH_DOMAIN_GET_CLASS (domain)->check_password (domain, msg, + username, + password); +} + +/** + * soup_auth_domain_covers: + * @domain: a #SoupAuthDomain + * @msg: a #SoupMessage + * + * Checks if @domain requires @msg to be authenticated (according to + * its paths and filter function). This does not actually look at + * whether @msg is authenticated, merely whether + * or not it needs to be. + * + * This is used by #SoupServer internally and is probably of no use to + * anyone else. + * + * Return value: %TRUE if @domain requires @msg to be authenticated + **/ +gboolean +soup_auth_domain_covers (SoupAuthDomain *domain, SoupMessage *msg) +{ + SoupAuthDomainPrivate *priv = soup_auth_domain_get_instance_private (domain); + const char *path; + + if (!priv->proxy) { + path = soup_message_get_uri (msg)->path; + if (!soup_path_map_lookup (priv->paths, path)) + return FALSE; + } + + if (priv->filter && !priv->filter (domain, msg, priv->filter_data)) + return FALSE; + else + return TRUE; +} + +/** + * soup_auth_domain_accepts: + * @domain: a #SoupAuthDomain + * @msg: a #SoupMessage + * + * Checks if @msg contains appropriate authorization for @domain to + * accept it. Mirroring soup_auth_domain_covers(), this does not check + * whether or not @domain cares if @msg is + * authorized. + * + * This is used by #SoupServer internally and is probably of no use to + * anyone else. + * + * Return value: (nullable): the username that @msg has authenticated + * as, if in fact it has authenticated. %NULL otherwise. + **/ +char * +soup_auth_domain_accepts (SoupAuthDomain *domain, SoupMessage *msg) +{ + SoupAuthDomainPrivate *priv = soup_auth_domain_get_instance_private (domain); + const char *header; + + header = soup_message_headers_get_one (msg->request_headers, + priv->proxy ? + "Proxy-Authorization" : + "Authorization"); + if (!header) + return NULL; + return SOUP_AUTH_DOMAIN_GET_CLASS (domain)->accepts (domain, msg, header); +} + +/** + * soup_auth_domain_challenge: + * @domain: a #SoupAuthDomain + * @msg: a #SoupMessage + * + * Adds a "WWW-Authenticate" or "Proxy-Authenticate" header to @msg, + * requesting that the client authenticate, and sets @msg's status + * accordingly. + * + * This is used by #SoupServer internally and is probably of no use to + * anyone else. + **/ +void +soup_auth_domain_challenge (SoupAuthDomain *domain, SoupMessage *msg) +{ + SoupAuthDomainPrivate *priv = soup_auth_domain_get_instance_private (domain); + char *challenge; + + challenge = SOUP_AUTH_DOMAIN_GET_CLASS (domain)->challenge (domain, msg); + soup_message_set_status (msg, priv->proxy ? + SOUP_STATUS_PROXY_UNAUTHORIZED : + SOUP_STATUS_UNAUTHORIZED); + soup_message_headers_append (msg->response_headers, + priv->proxy ? + "Proxy-Authenticate" : + "WWW-Authenticate", + challenge); + g_free (challenge); +} diff --git a/libsoup/soup-auth-domain.h b/libsoup/soup-auth-domain.h new file mode 100644 index 0000000..2bec096 --- /dev/null +++ b/libsoup/soup-auth-domain.h @@ -0,0 +1,110 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2007 Novell, Inc. + */ + +#ifndef SOUP_AUTH_DOMAIN_H +#define SOUP_AUTH_DOMAIN_H 1 + +#include + +G_BEGIN_DECLS + +#define SOUP_TYPE_AUTH_DOMAIN (soup_auth_domain_get_type ()) +#define SOUP_AUTH_DOMAIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SOUP_TYPE_AUTH_DOMAIN, SoupAuthDomain)) +#define SOUP_AUTH_DOMAIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_AUTH_DOMAIN, SoupAuthDomainClass)) +#define SOUP_IS_AUTH_DOMAIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SOUP_TYPE_AUTH_DOMAIN)) +#define SOUP_IS_AUTH_DOMAIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), SOUP_TYPE_AUTH_DOMAIN)) +#define SOUP_AUTH_DOMAIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_AUTH_DOMAIN, SoupAuthDomainClass)) + +struct _SoupAuthDomain { + GObject parent; + +}; + +typedef struct { + GObjectClass parent_class; + + char * (*accepts) (SoupAuthDomain *domain, + SoupMessage *msg, + const char *header); + char * (*challenge) (SoupAuthDomain *domain, + SoupMessage *msg); + gboolean (*check_password) (SoupAuthDomain *domain, + SoupMessage *msg, + const char *username, + const char *password); + + /* Padding for future expansion */ + void (*_libsoup_reserved2) (void); + void (*_libsoup_reserved3) (void); + void (*_libsoup_reserved4) (void); +} SoupAuthDomainClass; + +#define SOUP_AUTH_DOMAIN_REALM "realm" +#define SOUP_AUTH_DOMAIN_PROXY "proxy" +#define SOUP_AUTH_DOMAIN_ADD_PATH "add-path" +#define SOUP_AUTH_DOMAIN_REMOVE_PATH "remove-path" +#define SOUP_AUTH_DOMAIN_FILTER "filter" +#define SOUP_AUTH_DOMAIN_FILTER_DATA "filter-data" +#define SOUP_AUTH_DOMAIN_GENERIC_AUTH_CALLBACK "generic-auth-callback" +#define SOUP_AUTH_DOMAIN_GENERIC_AUTH_DATA "generic-auth-data" + +typedef gboolean (*SoupAuthDomainFilter) (SoupAuthDomain *domain, + SoupMessage *msg, + gpointer user_data); + +typedef gboolean (*SoupAuthDomainGenericAuthCallback) (SoupAuthDomain *domain, + SoupMessage *msg, + const char *username, + gpointer user_data); + +SOUP_AVAILABLE_IN_2_4 +GType soup_auth_domain_get_type (void); + +SOUP_AVAILABLE_IN_2_4 +void soup_auth_domain_add_path (SoupAuthDomain *domain, + const char *path); +SOUP_AVAILABLE_IN_2_4 +void soup_auth_domain_remove_path (SoupAuthDomain *domain, + const char *path); + +SOUP_AVAILABLE_IN_2_4 +void soup_auth_domain_set_filter (SoupAuthDomain *domain, + SoupAuthDomainFilter filter, + gpointer filter_data, + GDestroyNotify dnotify); + +SOUP_AVAILABLE_IN_2_4 +const char *soup_auth_domain_get_realm (SoupAuthDomain *domain); + +SOUP_AVAILABLE_IN_2_4 +void soup_auth_domain_set_generic_auth_callback (SoupAuthDomain *domain, + SoupAuthDomainGenericAuthCallback auth_callback, + gpointer auth_data, + GDestroyNotify dnotify); +SOUP_AVAILABLE_IN_2_4 +gboolean soup_auth_domain_check_password (SoupAuthDomain *domain, + SoupMessage *msg, + const char *username, + const char *password); + +SOUP_AVAILABLE_IN_2_4 +gboolean soup_auth_domain_covers (SoupAuthDomain *domain, + SoupMessage *msg); +SOUP_AVAILABLE_IN_2_4 +char *soup_auth_domain_accepts (SoupAuthDomain *domain, + SoupMessage *msg); +SOUP_AVAILABLE_IN_2_4 +void soup_auth_domain_challenge (SoupAuthDomain *domain, + SoupMessage *msg); + +/* protected */ +SOUP_AVAILABLE_IN_2_4 +gboolean soup_auth_domain_try_generic_auth_callback (SoupAuthDomain *domain, + SoupMessage *msg, + const char *username); + +G_END_DECLS + +#endif /* SOUP_AUTH_DOMAIN_H */ diff --git a/libsoup/soup-auth-manager.c b/libsoup/soup-auth-manager.c new file mode 100644 index 0000000..62fe9c4 --- /dev/null +++ b/libsoup/soup-auth-manager.c @@ -0,0 +1,854 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-auth-manager.c: SoupAuth manager for SoupSession + * + * Copyright (C) 2007 Red Hat, Inc. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "soup-auth-manager.h" +#include "soup.h" +#include "soup-connection-auth.h" +#include "soup-message-private.h" +#include "soup-message-queue.h" +#include "soup-path-map.h" +#include "soup-session-private.h" + +/** + * SECTION:soup-auth-manager + * @short_description: HTTP client-side authentication handler + * @see_also: #SoupSession, #SoupAuth + * + * #SoupAuthManager is the #SoupSessionFeature that handles HTTP + * authentication for a #SoupSession. + * + * A #SoupAuthManager is added to the session by default, and normally + * you don't need to worry about it at all. However, if you want to + * disable HTTP authentication, you can remove the feature from the + * session with soup_session_remove_feature_by_type(), or disable it on + * individual requests with soup_message_disable_feature(). + * + * Since: 2.42 + **/ + +/** + * SOUP_TYPE_AUTH_MANAGER: + * + * The #GType of #SoupAuthManager; you can use this with + * soup_session_remove_feature_by_type() or + * soup_message_disable_feature(). + * + * (Although this type has only been publicly visible since libsoup + * 2.42, it has always existed in the background, and you can use + * g_type_from_name ("SoupAuthManager") + * to get its #GType in earlier releases.) + * + * Since: 2.42 + */ +static void soup_auth_manager_session_feature_init (SoupSessionFeatureInterface *feature_interface, gpointer interface_data); +static SoupSessionFeatureInterface *soup_session_feature_default_interface; + +enum { + AUTHENTICATE, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + + +struct SoupAuthManagerPrivate { + SoupSession *session; + GPtrArray *auth_types; + gboolean auto_ntlm; + + GMutex lock; + SoupAuth *proxy_auth; + GHashTable *auth_hosts; +}; + +typedef struct { + SoupURI *uri; + SoupPathMap *auth_realms; /* path -> scheme:realm */ + GHashTable *auths; /* scheme:realm -> SoupAuth */ +} SoupAuthHost; + +G_DEFINE_TYPE_WITH_CODE (SoupAuthManager, soup_auth_manager, G_TYPE_OBJECT, + G_ADD_PRIVATE (SoupAuthManager) + G_IMPLEMENT_INTERFACE (SOUP_TYPE_SESSION_FEATURE, + soup_auth_manager_session_feature_init)) + +static void soup_auth_host_free (SoupAuthHost *host); +static SoupAuth *record_auth_for_uri (SoupAuthManagerPrivate *priv, + SoupURI *uri, SoupAuth *auth, + gboolean prior_auth_failed); + +static void +soup_auth_manager_init (SoupAuthManager *manager) +{ + SoupAuthManagerPrivate *priv; + + priv = manager->priv = soup_auth_manager_get_instance_private (manager); + + priv->auth_types = g_ptr_array_new_with_free_func ((GDestroyNotify)g_type_class_unref); + priv->auth_hosts = g_hash_table_new_full (soup_uri_host_hash, + soup_uri_host_equal, + NULL, + (GDestroyNotify)soup_auth_host_free); + g_mutex_init (&priv->lock); +} + +static void +soup_auth_manager_finalize (GObject *object) +{ + SoupAuthManagerPrivate *priv = SOUP_AUTH_MANAGER (object)->priv; + + g_ptr_array_free (priv->auth_types, TRUE); + + g_hash_table_destroy (priv->auth_hosts); + + g_clear_object (&priv->proxy_auth); + + g_mutex_clear (&priv->lock); + + G_OBJECT_CLASS (soup_auth_manager_parent_class)->finalize (object); +} + +static void +soup_auth_manager_class_init (SoupAuthManagerClass *auth_manager_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (auth_manager_class); + + object_class->finalize = soup_auth_manager_finalize; + + /** + * SoupAuthManager::authenticate: + * @manager: the #SoupAuthManager + * @msg: the #SoupMessage being sent + * @auth: the #SoupAuth to authenticate + * @retrying: %TRUE if this is the second (or later) attempt + * + * Emitted when the manager requires the application to + * provide authentication credentials. + * + * #SoupSession connects to this signal and emits its own + * #SoupSession::authenticate signal when it is emitted, so + * you shouldn't need to use this signal directly. + */ + signals[AUTHENTICATE] = + g_signal_new ("authenticate", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (SoupAuthManagerClass, authenticate), + NULL, NULL, + NULL, + G_TYPE_NONE, 3, + SOUP_TYPE_MESSAGE, + SOUP_TYPE_AUTH, + G_TYPE_BOOLEAN); + +} + +static int +auth_type_compare_func (gconstpointer a, gconstpointer b) +{ + SoupAuthClass **auth1 = (SoupAuthClass **)a; + SoupAuthClass **auth2 = (SoupAuthClass **)b; + + return (*auth1)->strength - (*auth2)->strength; +} + +static gboolean +soup_auth_manager_add_feature (SoupSessionFeature *feature, GType type) +{ + SoupAuthManagerPrivate *priv = SOUP_AUTH_MANAGER (feature)->priv; + SoupAuthClass *auth_class; + + if (!g_type_is_a (type, SOUP_TYPE_AUTH)) + return FALSE; + + auth_class = g_type_class_ref (type); + g_ptr_array_add (priv->auth_types, auth_class); + g_ptr_array_sort (priv->auth_types, auth_type_compare_func); + + /* Plain SoupSession does not get the backward-compat + * auto-NTLM behavior; SoupSession subclasses do. + */ + if (type == SOUP_TYPE_AUTH_NTLM && + G_TYPE_FROM_INSTANCE (priv->session) != SOUP_TYPE_SESSION) + priv->auto_ntlm = TRUE; + + return TRUE; +} + +static gboolean +soup_auth_manager_remove_feature (SoupSessionFeature *feature, GType type) +{ + SoupAuthManagerPrivate *priv = SOUP_AUTH_MANAGER (feature)->priv; + SoupAuthClass *auth_class; + guint i; + + if (!g_type_is_a (type, SOUP_TYPE_AUTH)) + return FALSE; + + auth_class = g_type_class_peek (type); + + for (i = 0; i < priv->auth_types->len; i++) { + if (priv->auth_types->pdata[i] == (gpointer)auth_class) { + if (type == SOUP_TYPE_AUTH_NTLM) + priv->auto_ntlm = FALSE; + + g_ptr_array_remove_index (priv->auth_types, i); + return TRUE; + } + } + + return FALSE; +} + +static gboolean +soup_auth_manager_has_feature (SoupSessionFeature *feature, GType type) +{ + SoupAuthManagerPrivate *priv = SOUP_AUTH_MANAGER (feature)->priv; + SoupAuthClass *auth_class; + guint i; + + if (!g_type_is_a (type, SOUP_TYPE_AUTH)) + return FALSE; + + auth_class = g_type_class_peek (type); + for (i = 0; i < priv->auth_types->len; i++) { + if (priv->auth_types->pdata[i] == (gpointer)auth_class) + return TRUE; + } + return FALSE; +} + +static void +soup_auth_manager_attach (SoupSessionFeature *feature, SoupSession *session) +{ + SoupAuthManagerPrivate *priv = SOUP_AUTH_MANAGER (feature)->priv; + + /* FIXME: should support multiple sessions */ + priv->session = session; + + soup_session_feature_default_interface->attach (feature, session); +} + +static inline const char * +auth_header_for_message (SoupMessage *msg) +{ + if (msg->status_code == SOUP_STATUS_PROXY_UNAUTHORIZED) { + return soup_message_headers_get_list (msg->response_headers, + "Proxy-Authenticate"); + } else { + return soup_message_headers_get_list (msg->response_headers, + "WWW-Authenticate"); + } +} + +static GSList * +next_challenge_start (GSList *items) +{ + /* The relevant grammar (from httpbis): + * + * WWW-Authenticate = 1#challenge + * Proxy-Authenticate = 1#challenge + * challenge = auth-scheme [ 1*SP ( b64token / #auth-param ) ] + * auth-scheme = token + * auth-param = token BWS "=" BWS ( token / quoted-string ) + * b64token = 1*( ALPHA / DIGIT / + * "-" / "." / "_" / "~" / "+" / "/" ) *"=" + * + * The fact that quoted-strings can contain commas, equals + * signs, and auth scheme names makes it tricky to "cheat" on + * the parsing. So soup_auth_manager_extract_challenge() will + * have used soup_header_parse_list() to split the header into + * items. Given the grammar above, the possible items are: + * + * auth-scheme + * auth-scheme 1*SP b64token + * auth-scheme 1*SP auth-param + * auth-param + * + * where the first three represent the start of a new challenge and + * the last one does not. + */ + + for (; items; items = items->next) { + const char *item = items->data; + const char *sp = strpbrk (item, "\t\r\n "); + const char *eq = strchr (item, '='); + + if (!eq) { + /* No "=", so it can't be an auth-param */ + return items; + } + if (!sp || sp > eq) { + /* No space, or first space appears after the "=", + * so it must be an auth-param. + */ + continue; + } + while (g_ascii_isspace (*++sp)) + ; + if (sp == eq) { + /* First "=" appears immediately after the first + * space, so this must be an auth-param with + * space around the "=". + */ + continue; + } + + /* "auth-scheme auth-param" or "auth-scheme b64token" */ + return items; + } + + return NULL; +} + +static char * +soup_auth_manager_extract_challenge (const char *challenges, const char *scheme) +{ + GSList *items, *i, *next; + int schemelen = strlen (scheme); + char *item; + GString *challenge; + + items = soup_header_parse_list (challenges); + + /* First item will start with the scheme name, followed by + * either nothing, or else a space and then the first + * auth-param. + */ + for (i = items; i; i = next_challenge_start (i->next)) { + item = i->data; + if (!g_ascii_strncasecmp (item, scheme, schemelen) && + (!item[schemelen] || g_ascii_isspace (item[schemelen]))) + break; + } + if (!i) { + soup_header_free_list (items); + return NULL; + } + + next = next_challenge_start (i->next); + challenge = g_string_new (item); + for (i = i->next; i != next; i = i->next) { + item = i->data; + g_string_append (challenge, ", "); + g_string_append (challenge, item); + } + + soup_header_free_list (items); + return g_string_free (challenge, FALSE); +} + +static SoupAuth * +create_auth (SoupAuthManagerPrivate *priv, SoupMessage *msg) +{ + const char *header; + SoupAuthClass *auth_class; + char *challenge = NULL; + SoupAuth *auth = NULL; + int i; + + header = auth_header_for_message (msg); + if (!header) + return NULL; + + for (i = priv->auth_types->len - 1; i >= 0; i--) { + auth_class = priv->auth_types->pdata[i]; + challenge = soup_auth_manager_extract_challenge (header, auth_class->scheme_name); + if (!challenge) + continue; + auth = soup_auth_new (G_TYPE_FROM_CLASS (auth_class), msg, challenge); + g_free (challenge); + if (auth) + break; + } + + return auth; +} + +static gboolean +check_auth (SoupMessage *msg, SoupAuth *auth) +{ + const char *header, *scheme; + char *challenge = NULL; + gboolean ok = TRUE; + + scheme = soup_auth_get_scheme_name (auth); + + header = auth_header_for_message (msg); + if (header) + challenge = soup_auth_manager_extract_challenge (header, scheme); + if (!challenge) { + ok = FALSE; + challenge = g_strdup (scheme); + } + + if (!soup_auth_update (auth, msg, challenge)) + ok = FALSE; + g_free (challenge); + return ok; +} + +static SoupAuthHost * +get_auth_host_for_uri (SoupAuthManagerPrivate *priv, SoupURI *uri) +{ + SoupAuthHost *host; + + host = g_hash_table_lookup (priv->auth_hosts, uri); + if (host) + return host; + + host = g_slice_new0 (SoupAuthHost); + host->uri = soup_uri_copy_host (uri); + g_hash_table_insert (priv->auth_hosts, host->uri, host); + + return host; +} + +static void +soup_auth_host_free (SoupAuthHost *host) +{ + g_clear_pointer (&host->auth_realms, soup_path_map_free); + g_clear_pointer (&host->auths, g_hash_table_destroy); + + soup_uri_free (host->uri); + g_slice_free (SoupAuthHost, host); +} + +static gboolean +make_auto_ntlm_auth (SoupAuthManagerPrivate *priv, SoupAuthHost *host) +{ + SoupAuth *auth; + + if (!priv->auto_ntlm) + return FALSE; + + auth = g_object_new (SOUP_TYPE_AUTH_NTLM, + SOUP_AUTH_HOST, host->uri->host, + NULL); + record_auth_for_uri (priv, host->uri, auth, FALSE); + g_object_unref (auth); + return TRUE; +} + +static void +update_authorization_header (SoupMessage *msg, SoupAuth *auth, gboolean is_proxy) +{ + const char *authorization_header = is_proxy ? "Proxy-Authorization" : "Authorization"; + char *token; + + if (soup_message_get_auth (msg)) + soup_message_headers_remove (msg->request_headers, authorization_header); + + if (!auth) + return; + + token = soup_auth_get_authorization (auth, msg); + if (!token) + return; + + soup_message_headers_replace (msg->request_headers, authorization_header, token); + g_free (token); +} + +static SoupAuth * +lookup_auth (SoupAuthManagerPrivate *priv, SoupMessage *msg) +{ + SoupAuthHost *host; + const char *path, *realm; + SoupAuth *auth; + + /* If the message already has a ready auth, use that instead */ + auth = soup_message_get_auth (msg); + if (auth && soup_auth_is_ready (auth, msg)) + return auth; + + if (soup_message_get_flags (msg) & SOUP_MESSAGE_DO_NOT_USE_AUTH_CACHE) + return NULL; + + host = get_auth_host_for_uri (priv, soup_message_get_uri (msg)); + if (!host->auth_realms && !make_auto_ntlm_auth (priv, host)) + return NULL; + + path = soup_message_get_uri (msg)->path; + if (!path) + path = "/"; + realm = soup_path_map_lookup (host->auth_realms, path); + if (realm) + return g_hash_table_lookup (host->auths, realm); + + return NULL; +} + +static SoupAuth * +lookup_proxy_auth (SoupAuthManagerPrivate *priv, SoupMessage *msg) +{ + SoupAuth *auth; + + /* If the message already has a ready auth, use that instead */ + auth = soup_message_get_proxy_auth (msg); + if (auth && soup_auth_is_ready (auth, msg)) + return auth; + + if (soup_message_get_flags (msg) & SOUP_MESSAGE_DO_NOT_USE_AUTH_CACHE) + return NULL; + + return priv->proxy_auth; +} + +static void +authenticate_auth (SoupAuthManager *manager, SoupAuth *auth, + SoupMessage *msg, gboolean prior_auth_failed, + gboolean proxy, gboolean can_interact) +{ + SoupAuthManagerPrivate *priv = manager->priv; + SoupURI *uri; + + if (!soup_auth_can_authenticate (auth)) + return; + + if (proxy) { + SoupMessageQueue *queue; + SoupMessageQueueItem *item; + + queue = soup_session_get_queue (priv->session); + item = soup_message_queue_lookup (queue, msg); + if (!item) + return; + + /* When loaded from the disk cache, the connection is NULL. */ + uri = item->conn ? soup_connection_get_proxy_uri (item->conn) : NULL; + soup_message_queue_item_unref (item); + if (!uri) + return; + } else + uri = soup_message_get_uri (msg); + + /* If a password is specified explicitly in the URI, use it + * even if the auth had previously already been authenticated. + */ + if (uri->password && uri->user) { + soup_auth_authenticate (auth, uri->user, uri->password); + soup_uri_set_password (uri, NULL); + soup_uri_set_user (uri, NULL); + } else if (!soup_auth_is_authenticated (auth) && can_interact) { + g_signal_emit (manager, signals[AUTHENTICATE], 0, + msg, auth, prior_auth_failed); + } +} + +static SoupAuth * +record_auth_for_uri (SoupAuthManagerPrivate *priv, SoupURI *uri, + SoupAuth *auth, gboolean prior_auth_failed) +{ + SoupAuthHost *host; + SoupAuth *old_auth; + const char *path; + char *auth_info, *old_auth_info; + GSList *pspace, *p; + + host = get_auth_host_for_uri (priv, uri); + auth_info = soup_auth_get_info (auth); + + if (!host->auth_realms) { + host->auth_realms = soup_path_map_new (g_free); + host->auths = g_hash_table_new_full (g_str_hash, g_str_equal, + g_free, g_object_unref); + } + + /* Record where this auth realm is used. */ + pspace = soup_auth_get_protection_space (auth, uri); + for (p = pspace; p; p = p->next) { + path = p->data; + old_auth_info = soup_path_map_lookup (host->auth_realms, path); + if (old_auth_info) { + if (!strcmp (old_auth_info, auth_info)) + continue; + soup_path_map_remove (host->auth_realms, path); + } + + soup_path_map_add (host->auth_realms, path, + g_strdup (auth_info)); + } + soup_auth_free_protection_space (auth, pspace); + + /* Now, make sure the auth is recorded. (If there's a + * pre-existing good auth, we keep that rather than the new one, + * since the old one might already be authenticated.) + */ + old_auth = g_hash_table_lookup (host->auths, auth_info); + if (old_auth && (old_auth != auth || !prior_auth_failed)) { + g_free (auth_info); + return old_auth; + } else { + g_hash_table_insert (host->auths, auth_info, + g_object_ref (auth)); + return auth; + } +} + +static void +auth_got_headers (SoupMessage *msg, gpointer manager) +{ + SoupAuthManagerPrivate *priv = SOUP_AUTH_MANAGER (manager)->priv; + SoupAuth *auth, *prior_auth; + gboolean prior_auth_failed = FALSE; + + g_mutex_lock (&priv->lock); + + /* See if we used auth last time */ + prior_auth = soup_message_get_auth (msg); + if (prior_auth && check_auth (msg, prior_auth)) { + auth = g_object_ref (prior_auth); + if (!soup_auth_is_ready (auth, msg)) + prior_auth_failed = TRUE; + } else { + auth = create_auth (priv, msg); + if (!auth) { + g_mutex_unlock (&priv->lock); + return; + } + } + + if (!(soup_message_get_flags (msg) & SOUP_MESSAGE_DO_NOT_USE_AUTH_CACHE)) { + SoupAuth *new_auth; + + new_auth = record_auth_for_uri (priv, soup_message_get_uri (msg), + auth, prior_auth_failed); + g_object_unref (auth); + auth = g_object_ref (new_auth); + } + + /* If we need to authenticate, try to do it. */ + authenticate_auth (manager, auth, msg, + prior_auth_failed, FALSE, TRUE); + soup_message_set_auth (msg, auth); + g_object_unref (auth); + g_mutex_unlock (&priv->lock); +} + +static void +auth_got_body (SoupMessage *msg, gpointer manager) +{ + SoupAuthManagerPrivate *priv = SOUP_AUTH_MANAGER (manager)->priv; + SoupAuth *auth; + + g_mutex_lock (&priv->lock); + auth = lookup_auth (priv, msg); + if (auth && soup_auth_is_ready (auth, msg)) { + if (SOUP_IS_CONNECTION_AUTH (auth)) { + SoupMessageFlags flags; + + flags = soup_message_get_flags (msg); + soup_message_set_flags (msg, flags & ~SOUP_MESSAGE_NEW_CONNECTION); + } + + /* When not using cached credentials, update the Authorization header + * right before requeuing the message. + */ + if (soup_message_get_flags (msg) & SOUP_MESSAGE_DO_NOT_USE_AUTH_CACHE) + update_authorization_header (msg, auth, FALSE); + + soup_session_requeue_message (priv->session, msg); + } + g_mutex_unlock (&priv->lock); +} + +static void +proxy_auth_got_headers (SoupMessage *msg, gpointer manager) +{ + SoupAuthManagerPrivate *priv = SOUP_AUTH_MANAGER (manager)->priv; + SoupAuth *auth = NULL, *prior_auth; + gboolean prior_auth_failed = FALSE; + + g_mutex_lock (&priv->lock); + + /* See if we used auth last time */ + prior_auth = soup_message_get_proxy_auth (msg); + if (prior_auth && check_auth (msg, prior_auth)) { + if (!soup_auth_is_ready (prior_auth, msg)) + prior_auth_failed = TRUE; + } + + if (!(soup_message_get_flags (msg) & SOUP_MESSAGE_DO_NOT_USE_AUTH_CACHE)) + auth = priv->proxy_auth ? g_object_ref (priv->proxy_auth) : NULL; + + if (!auth) { + auth = create_auth (priv, msg); + if (!auth) { + g_mutex_unlock (&priv->lock); + return; + } + if (!(soup_message_get_flags (msg) & SOUP_MESSAGE_DO_NOT_USE_AUTH_CACHE)) + priv->proxy_auth = g_object_ref (auth); + } + + /* If we need to authenticate, try to do it. */ + authenticate_auth (manager, auth, msg, + prior_auth_failed, TRUE, TRUE); + soup_message_set_proxy_auth (msg, auth); + g_object_unref (auth); + g_mutex_unlock (&priv->lock); +} + +static void +proxy_auth_got_body (SoupMessage *msg, gpointer manager) +{ + SoupAuthManagerPrivate *priv = SOUP_AUTH_MANAGER (manager)->priv; + SoupAuth *auth; + + g_mutex_lock (&priv->lock); + + auth = lookup_proxy_auth (priv, msg); + if (auth && soup_auth_is_ready (auth, msg)) { + /* When not using cached credentials, update the Authorization header + * right before requeuing the message. + */ + if (soup_message_get_flags (msg) & SOUP_MESSAGE_DO_NOT_USE_AUTH_CACHE) + update_authorization_header (msg, auth, TRUE); + soup_session_requeue_message (priv->session, msg); + } + + g_mutex_unlock (&priv->lock); +} + +static void +auth_msg_starting (SoupMessage *msg, gpointer manager) +{ + SoupAuthManagerPrivate *priv = SOUP_AUTH_MANAGER (manager)->priv; + SoupAuth *auth; + + if (soup_message_get_flags (msg) & SOUP_MESSAGE_DO_NOT_USE_AUTH_CACHE) + return; + + g_mutex_lock (&priv->lock); + + if (msg->method != SOUP_METHOD_CONNECT) { + auth = lookup_auth (priv, msg); + if (auth) { + authenticate_auth (manager, auth, msg, FALSE, FALSE, FALSE); + if (!soup_auth_is_ready (auth, msg)) + auth = NULL; + } + soup_message_set_auth (msg, auth); + update_authorization_header (msg, auth, FALSE); + } + + auth = lookup_proxy_auth (priv, msg); + if (auth) { + authenticate_auth (manager, auth, msg, FALSE, TRUE, FALSE); + if (!soup_auth_is_ready (auth, msg)) + auth = NULL; + } + soup_message_set_proxy_auth (msg, auth); + update_authorization_header (msg, auth, TRUE); + + g_mutex_unlock (&priv->lock); +} + +static void +soup_auth_manager_request_queued (SoupSessionFeature *manager, + SoupSession *session, + SoupMessage *msg) +{ + g_signal_connect (msg, "starting", + G_CALLBACK (auth_msg_starting), manager); + + soup_message_add_status_code_handler ( + msg, "got_headers", SOUP_STATUS_UNAUTHORIZED, + G_CALLBACK (auth_got_headers), manager); + soup_message_add_status_code_handler ( + msg, "got_body", SOUP_STATUS_UNAUTHORIZED, + G_CALLBACK (auth_got_body), manager); + + soup_message_add_status_code_handler ( + msg, "got_headers", SOUP_STATUS_PROXY_UNAUTHORIZED, + G_CALLBACK (proxy_auth_got_headers), manager); + soup_message_add_status_code_handler ( + msg, "got_body", SOUP_STATUS_PROXY_UNAUTHORIZED, + G_CALLBACK (proxy_auth_got_body), manager); +} + +static void +soup_auth_manager_request_unqueued (SoupSessionFeature *manager, + SoupSession *session, + SoupMessage *msg) +{ + g_signal_handlers_disconnect_matched (msg, G_SIGNAL_MATCH_DATA, + 0, 0, NULL, NULL, manager); +} + +/** + * soup_auth_manager_use_auth: + * @manager: a #SoupAuthManager + * @uri: the #SoupURI under which @auth is to be used + * @auth: the #SoupAuth to use + * + * Records that @auth is to be used under @uri, as though a + * WWW-Authenticate header had been received at that URI. This can be + * used to "preload" @manager's auth cache, to avoid an extra HTTP + * round trip in the case where you know ahead of time that a 401 + * response will be returned. + * + * This is only useful for authentication types where the initial + * Authorization header does not depend on any additional information + * from the server. (Eg, Basic or NTLM, but not Digest.) + * + * Since: 2.42 + */ +void +soup_auth_manager_use_auth (SoupAuthManager *manager, + SoupURI *uri, + SoupAuth *auth) +{ + SoupAuthManagerPrivate *priv = manager->priv; + + g_mutex_lock (&priv->lock); + record_auth_for_uri (priv, uri, auth, FALSE); + g_mutex_unlock (&priv->lock); +} + +/** + * soup_auth_manager_clear_cached_credentials: + * @manager: a #SoupAuthManager + * + * Clear all credentials cached by @manager + * + * Since: 2.58 + */ +void +soup_auth_manager_clear_cached_credentials (SoupAuthManager *manager) +{ + SoupAuthManagerPrivate *priv; + + g_return_if_fail (SOUP_IS_AUTH_MANAGER (manager)); + + priv = manager->priv; + g_mutex_lock (&priv->lock); + g_hash_table_remove_all (priv->auth_hosts); + g_mutex_unlock (&priv->lock); +} + +static void +soup_auth_manager_session_feature_init (SoupSessionFeatureInterface *feature_interface, + gpointer interface_data) +{ + soup_session_feature_default_interface = + g_type_default_interface_peek (SOUP_TYPE_SESSION_FEATURE); + + feature_interface->attach = soup_auth_manager_attach; + feature_interface->request_queued = soup_auth_manager_request_queued; + feature_interface->request_unqueued = soup_auth_manager_request_unqueued; + feature_interface->add_feature = soup_auth_manager_add_feature; + feature_interface->remove_feature = soup_auth_manager_remove_feature; + feature_interface->has_feature = soup_auth_manager_has_feature; +} diff --git a/libsoup/soup-auth-manager.h b/libsoup/soup-auth-manager.h new file mode 100644 index 0000000..c935d99 --- /dev/null +++ b/libsoup/soup-auth-manager.h @@ -0,0 +1,49 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2007 Red Hat, Inc. + */ + +#ifndef SOUP_AUTH_MANAGER_H +#define SOUP_AUTH_MANAGER_H 1 + +#include "soup-types.h" +#include "soup-auth.h" + +G_BEGIN_DECLS + +#define SOUP_TYPE_AUTH_MANAGER (soup_auth_manager_get_type ()) +#define SOUP_AUTH_MANAGER(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), SOUP_TYPE_AUTH_MANAGER, SoupAuthManager)) +#define SOUP_AUTH_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_AUTH_MANAGER, SoupAuthManagerClass)) +#define SOUP_IS_AUTH_MANAGER(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), SOUP_TYPE_AUTH_MANAGER)) +#define SOUP_IS_AUTH_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SOUP_TYPE_AUTH_MANAGER)) +#define SOUP_AUTH_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_AUTH_MANAGER, SoupAuthManagerClass)) + +typedef struct SoupAuthManagerPrivate SoupAuthManagerPrivate; + +typedef struct { + GObject parent; + + SoupAuthManagerPrivate *priv; +} SoupAuthManager; + +typedef struct { + GObjectClass parent_class; + + void (*authenticate) (SoupAuthManager *manager, SoupMessage *msg, + SoupAuth *auth, gboolean retrying); +} SoupAuthManagerClass; + +SOUP_AVAILABLE_IN_2_4 +GType soup_auth_manager_get_type (void); + +SOUP_AVAILABLE_IN_2_4 +void soup_auth_manager_use_auth (SoupAuthManager *manager, + SoupURI *uri, + SoupAuth *auth); + +SOUP_AVAILABLE_IN_2_58 +void soup_auth_manager_clear_cached_credentials (SoupAuthManager *manager); + +G_END_DECLS + +#endif /* SOUP_AUTH_MANAGER_H */ diff --git a/libsoup/soup-auth-negotiate.c b/libsoup/soup-auth-negotiate.c new file mode 100644 index 0000000..1fdf142 --- /dev/null +++ b/libsoup/soup-auth-negotiate.c @@ -0,0 +1,622 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-auth-negotiate.c: HTTP Negotiate Authentication helper + * + * Copyright (C) 2009,2013 Guido Guenther + * Copyright (C) 2016 Red Hat, Inc. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#ifdef LIBSOUP_HAVE_GSSAPI +#include +#endif /* LIBSOUP_HAVE_GSSAPI */ + +#include "soup-auth-negotiate.h" +#include "soup-headers.h" +#include "soup-message.h" +#include "soup-message-private.h" +#include "soup-misc-private.h" +#include "soup-uri.h" + +/** + * soup_auth_negotiate_supported: + * + * Indicates whether libsoup was built with GSSAPI support. If this is + * %FALSE, %SOUP_TYPE_AUTH_NEGOTIATE will still be defined and can + * still be added to a #SoupSession, but libsoup will never attempt to + * actually use this auth type. + * + * Since: 2.54 + */ +gboolean +soup_auth_negotiate_supported (void) +{ +#ifdef LIBSOUP_HAVE_GSSAPI + return TRUE; +#else + return FALSE; +#endif +} + +#define AUTH_GSS_ERROR -1 +#define AUTH_GSS_COMPLETE 1 +#define AUTH_GSS_CONTINUE 0 + +typedef enum { + SOUP_NEGOTIATE_NEW, + SOUP_NEGOTIATE_RECEIVED_CHALLENGE, /* received initial negotiate header */ + SOUP_NEGOTIATE_SENT_RESPONSE, /* sent response to server */ + SOUP_NEGOTIATE_FAILED +} SoupNegotiateState; + +typedef struct { + gboolean initialized; + gchar *response_header; + +#ifdef LIBSOUP_HAVE_GSSAPI + gss_ctx_id_t context; + gss_name_t server_name; +#endif + + SoupNegotiateState state; +} SoupNegotiateConnectionState; + +typedef struct { + gboolean is_authenticated; +} SoupAuthNegotiatePrivate; + +/** + * SOUP_TYPE_AUTH_NEGOTIATE: + * + * A #GType corresponding to HTTP-based GSS-Negotiate authentication. + * #SoupSessions do not support this type by default; if you want to + * enable support for it, call soup_session_add_feature_by_type(), + * passing %SOUP_TYPE_AUTH_NEGOTIATE. + * + * This auth type will only work if libsoup was compiled with GSSAPI + * support; you can check soup_auth_negotiate_supported() to see if it + * was. + * + * Since: 2.54 + */ +G_DEFINE_TYPE_WITH_PRIVATE (SoupAuthNegotiate, soup_auth_negotiate, SOUP_TYPE_CONNECTION_AUTH) + +#ifdef LIBSOUP_HAVE_GSSAPI +static gboolean check_auth_trusted_uri (SoupConnectionAuth *auth, + SoupMessage *msg); +static gboolean soup_gss_build_response (SoupNegotiateConnectionState *conn, + SoupAuth *auth, GError **err); +static void soup_gss_client_cleanup (SoupNegotiateConnectionState *conn); +static gboolean soup_gss_client_init (SoupNegotiateConnectionState *conn, + const char *host, GError **err); +static int soup_gss_client_step (SoupNegotiateConnectionState *conn, + const char *host, GError **err); + +static GSList *trusted_uris; +static GSList *blacklisted_uris; + +static void parse_uris_from_env_variable (const gchar *env_variable, GSList **list); + +static void check_server_response (SoupMessage *msg, gpointer auth); + +static const char spnego_OID[] = "\x2b\x06\x01\x05\x05\x02"; +static const gss_OID_desc gss_mech_spnego = { sizeof (spnego_OID) - 1, (void *) &spnego_OID }; + +static gpointer +soup_auth_negotiate_create_connection_state (SoupConnectionAuth *auth) +{ + SoupNegotiateConnectionState *conn; + + conn = g_slice_new0 (SoupNegotiateConnectionState); + conn->state = SOUP_NEGOTIATE_NEW; + + return conn; +} + +static void +free_connection_state_data (SoupNegotiateConnectionState *conn) +{ + soup_gss_client_cleanup (conn); + g_free (conn->response_header); +} + +static void +soup_auth_negotiate_free_connection_state (SoupConnectionAuth *auth, + gpointer state) +{ + SoupNegotiateConnectionState *conn = state; + + free_connection_state_data (conn); + + g_slice_free (SoupNegotiateConnectionState, conn); +} + +static GSList * +soup_auth_negotiate_get_protection_space (SoupAuth *auth, SoupURI *source_uri) +{ + char *space, *p; + + space = g_strdup (source_uri->path); + + /* Strip filename component */ + p = strrchr (space, '/'); + if (p && p == space && p[1]) + p[1] = '\0'; + else if (p && p[1]) + *p = '\0'; + + return g_slist_prepend (NULL, space); +} + +static void +soup_auth_negotiate_authenticate (SoupAuth *auth, const char *username, + const char *password) +{ + SoupAuthNegotiate *negotiate = SOUP_AUTH_NEGOTIATE (auth); + SoupAuthNegotiatePrivate *priv = soup_auth_negotiate_get_instance_private (negotiate); + + /* It is not possible to authenticate with username and password. */ + priv->is_authenticated = FALSE; +} + +static gboolean +soup_auth_negotiate_is_authenticated (SoupAuth *auth) +{ + SoupAuthNegotiate *negotiate = SOUP_AUTH_NEGOTIATE (auth); + SoupAuthNegotiatePrivate *priv = soup_auth_negotiate_get_instance_private (negotiate); + + /* We are authenticated just in case we received the GSS_S_COMPLETE. */ + return priv->is_authenticated; +} + +static gboolean +soup_auth_negotiate_can_authenticate (SoupAuth *auth) +{ + return FALSE; +} + +static char * +soup_auth_negotiate_get_connection_authorization (SoupConnectionAuth *auth, + SoupMessage *msg, + gpointer state) +{ + SoupNegotiateConnectionState *conn = state; + char *header = NULL; + + if (conn->state == SOUP_NEGOTIATE_NEW) { + GError *err = NULL; + + if (!check_auth_trusted_uri (auth, msg)) { + conn->state = SOUP_NEGOTIATE_FAILED; + return NULL; + } + + if (!soup_gss_build_response (conn, SOUP_AUTH (auth), &err)) { + /* FIXME: report further upward via + * soup_message_get_error_message */ + if (conn->initialized) + g_warning ("gssapi step failed: %s", err->message); + else + g_warning ("gssapi init failed: %s", err->message); + conn->state = SOUP_NEGOTIATE_FAILED; + g_clear_error (&err); + + return NULL; + } + } + + if (conn->response_header) { + header = conn->response_header; + conn->response_header = NULL; + conn->state = SOUP_NEGOTIATE_SENT_RESPONSE; + } + + return header; +} + +static gboolean +soup_auth_negotiate_is_connection_ready (SoupConnectionAuth *auth, + SoupMessage *msg, + gpointer state) +{ + SoupNegotiateConnectionState *conn = state; + + return conn->state != SOUP_NEGOTIATE_FAILED; +} +#endif /* LIBSOUP_HAVE_GSSAPI */ + +static gboolean +soup_auth_negotiate_update_connection (SoupConnectionAuth *auth, SoupMessage *msg, + const char *header, gpointer state) +{ +#ifdef LIBSOUP_HAVE_GSSAPI + gboolean success = TRUE; + SoupNegotiateConnectionState *conn = state; + GError *err = NULL; + + if (!check_auth_trusted_uri (auth, msg)) { + conn->state = SOUP_NEGOTIATE_FAILED; + goto out; + } + + /* Found negotiate header with no token, start negotiate */ + if (strcmp (header, "Negotiate") == 0) { + /* If we were already negotiating and we get a 401 + * with no token, start again. */ + if (conn->state == SOUP_NEGOTIATE_SENT_RESPONSE) { + free_connection_state_data (conn); + conn->initialized = FALSE; + } + + conn->state = SOUP_NEGOTIATE_RECEIVED_CHALLENGE; + if (soup_gss_build_response (conn, SOUP_AUTH (auth), &err)) { + /* Connect the signal only once per message */ + if (!g_object_get_data (G_OBJECT (msg), "negotiate-got-headers-connected")) { + /* Wait for the 2xx response to verify server response */ + g_signal_connect_data (msg, + "got_headers", + G_CALLBACK (check_server_response), + g_object_ref (auth), + (GClosureNotify) g_object_unref, + 0); + /* Mark that the signal was connected */ + g_object_set_data (G_OBJECT (msg), + "negotiate-got-headers-connected", + GINT_TO_POINTER (1)); + } + goto out; + } else { + /* FIXME: report further upward via + * soup_message_get_error_message */ + if (conn->initialized) + g_warning ("gssapi step failed: %s", err->message); + else + g_warning ("gssapi init failed: %s", err->message); + success = FALSE; + } + } else if (!strncmp (header, "Negotiate ", 10)) { + if (soup_gss_client_step (conn, header + 10, &err) == AUTH_GSS_CONTINUE) { + conn->state = SOUP_NEGOTIATE_RECEIVED_CHALLENGE; + goto out; + } + } + + conn->state = SOUP_NEGOTIATE_FAILED; + out: + g_clear_error (&err); + return success; +#else + return FALSE; +#endif /* LIBSOUP_HAVE_GSSAPI */ +} + +static void +soup_auth_negotiate_init (SoupAuthNegotiate *negotiate) +{ + g_object_set (G_OBJECT (negotiate), SOUP_AUTH_REALM, "", NULL); +} + +static void +soup_auth_negotiate_class_init (SoupAuthNegotiateClass *auth_negotiate_class) +{ + SoupAuthClass *auth_class = SOUP_AUTH_CLASS (auth_negotiate_class); + SoupConnectionAuthClass *conn_auth_class = + SOUP_CONNECTION_AUTH_CLASS (auth_negotiate_class); + + auth_class->scheme_name = "Negotiate"; + auth_class->strength = 0; + + conn_auth_class->update_connection = soup_auth_negotiate_update_connection; +#ifdef LIBSOUP_HAVE_GSSAPI + auth_class->strength = 7; + + conn_auth_class->create_connection_state = soup_auth_negotiate_create_connection_state; + conn_auth_class->free_connection_state = soup_auth_negotiate_free_connection_state; + conn_auth_class->get_connection_authorization = soup_auth_negotiate_get_connection_authorization; + conn_auth_class->is_connection_ready = soup_auth_negotiate_is_connection_ready; + + auth_class->get_protection_space = soup_auth_negotiate_get_protection_space; + auth_class->authenticate = soup_auth_negotiate_authenticate; + auth_class->is_authenticated = soup_auth_negotiate_is_authenticated; + auth_class->can_authenticate = soup_auth_negotiate_can_authenticate; + + parse_uris_from_env_variable ("SOUP_GSSAPI_TRUSTED_URIS", &trusted_uris); + parse_uris_from_env_variable ("SOUP_GSSAPI_BLACKLISTED_URIS", &blacklisted_uris); +#endif /* LIBSOUP_HAVE_GSSAPI */ +} + +#ifdef LIBSOUP_HAVE_GSSAPI +static void +check_server_response (SoupMessage *msg, gpointer auth) +{ + gint ret; + const char *auth_headers; + GError *err = NULL; + SoupAuthNegotiate *negotiate = auth; + SoupAuthNegotiatePrivate *priv = soup_auth_negotiate_get_instance_private (negotiate); + SoupNegotiateConnectionState *conn; + + conn = soup_connection_auth_get_connection_state_for_message (SOUP_CONNECTION_AUTH (auth), msg); + if (!conn) + return; + + if (auth != soup_message_get_auth (msg)) + return; + + if (msg->status_code == SOUP_STATUS_UNAUTHORIZED) + return; + + /* FIXME: need to check for proxy-auth too */ + auth_headers = soup_message_headers_get_one (msg->response_headers, + "WWW-Authenticate"); + if (!auth_headers || g_ascii_strncasecmp (auth_headers, "Negotiate ", 10) != 0) { + g_warning ("Failed to parse auth header"); + conn->state = SOUP_NEGOTIATE_FAILED; + goto out; + } + + ret = soup_gss_client_step (conn, auth_headers + 10, &err); + + switch (ret) { + case AUTH_GSS_COMPLETE: + priv->is_authenticated = TRUE; + break; + case AUTH_GSS_CONTINUE: + conn->state = SOUP_NEGOTIATE_RECEIVED_CHALLENGE; + break; + case AUTH_GSS_ERROR: + if (err) + g_warning ("%s", err->message); + /* Unfortunately, so many programs (curl, Firefox, ..) ignore + * the return token that is included in the response, so it is + * possible that there are servers that send back broken stuff. + * Try to behave in the right way (pass the token to + * gss_init_sec_context()), show a warning, but don't fail + * if the server returned 200. */ + if (msg->status_code == SOUP_STATUS_OK) + priv->is_authenticated = TRUE; + else + conn->state = SOUP_NEGOTIATE_FAILED; + break; + default: + conn->state = SOUP_NEGOTIATE_FAILED; + } + out: + g_clear_error (&err); +} + +/* Check if scheme://host:port from message matches the given URI. */ +static gint +match_base_uri (SoupURI *list_uri, SoupURI *msg_uri) +{ + if (msg_uri->scheme != list_uri->scheme) + return 1; + + if (list_uri->port && (msg_uri->port != list_uri->port)) + return 1; + + if (list_uri->host) + return !soup_host_matches_host (msg_uri->host, list_uri->host); + + return 0; +} + +/* Parses a comma separated list of URIS from the environment. */ +static void +parse_uris_from_env_variable (const gchar *env_variable, GSList **list) +{ + gchar **uris = NULL; + const gchar *env; + gint i; + guint length; + + /* Initialize the list */ + *list = NULL; + + if (!(env = g_getenv (env_variable))) + return; + + if (!(uris = g_strsplit (env, ",", -1))) + return; + + length = g_strv_length (uris); + for (i = 0; i < length; i++) { + SoupURI *uri; + + /* If the supplied URI is valid, append it to the list */ + if ((uri = soup_uri_new (uris[i]))) + *list = g_slist_prepend (*list, uri); + } + + g_strfreev (uris); +} + +static gboolean +check_auth_trusted_uri (SoupConnectionAuth *auth, SoupMessage *msg) +{ + SoupURI *msg_uri; + GSList *matched = NULL; + + g_return_val_if_fail (auth != NULL, FALSE); + g_return_val_if_fail (msg != NULL, FALSE); + + msg_uri = soup_message_get_uri (msg); + + /* First check if the URI is not on blacklist */ + if (blacklisted_uris && + g_slist_find_custom (blacklisted_uris, msg_uri, (GCompareFunc) match_base_uri)) + return FALSE; + + /* If no trusted URIs are set, we allow all HTTPS URIs */ + if (!trusted_uris) + return soup_uri_is_https (msg_uri, NULL); + + matched = g_slist_find_custom (trusted_uris, + msg_uri, + (GCompareFunc) match_base_uri); + + return matched ? TRUE : FALSE; +} + +static gboolean +soup_gss_build_response (SoupNegotiateConnectionState *conn, SoupAuth *auth, GError **err) +{ + if (!conn->initialized) + if (!soup_gss_client_init (conn, soup_auth_get_host (auth), err)) + return FALSE; + + if (soup_gss_client_step (conn, "", err) != AUTH_GSS_CONTINUE) + return FALSE; + + return TRUE; +} + +static void +soup_gss_error (OM_uint32 err_maj, OM_uint32 err_min, GError **err) +{ + OM_uint32 maj_stat, min_stat, msg_ctx = 0; + gss_buffer_desc status; + gchar *buf_maj = NULL, *buf_min = NULL; + + do { + maj_stat = gss_display_status (&min_stat, + err_maj, + GSS_C_GSS_CODE, + (gss_OID) &gss_mech_spnego, + &msg_ctx, + &status); + if (GSS_ERROR (maj_stat)) + break; + + buf_maj = g_strdup ((gchar *) status.value); + gss_release_buffer (&min_stat, &status); + + maj_stat = gss_display_status (&min_stat, + err_min, + GSS_C_MECH_CODE, + GSS_C_NULL_OID, + &msg_ctx, + &status); + if (!GSS_ERROR (maj_stat)) { + buf_min = g_strdup ((gchar *) status.value); + gss_release_buffer (&min_stat, &status); + } + + if (err && *err == NULL) { + g_set_error (err, + SOUP_HTTP_ERROR, + SOUP_STATUS_UNAUTHORIZED, + "%s: %s", + buf_maj, + buf_min ? buf_min : ""); + } + g_free (buf_maj); + g_free (buf_min); + buf_min = buf_maj = NULL; + } while (!GSS_ERROR (maj_stat) && msg_ctx != 0); +} + +static gboolean +soup_gss_client_init (SoupNegotiateConnectionState *conn, const gchar *host, GError **err) +{ + OM_uint32 maj_stat, min_stat; + gchar *service = NULL; + gss_buffer_desc token = GSS_C_EMPTY_BUFFER; + gboolean ret = FALSE; + gchar *h; + + conn->server_name = GSS_C_NO_NAME; + conn->context = GSS_C_NO_CONTEXT; + + h = g_ascii_strdown (host, -1); + service = g_strconcat ("HTTP@", h, NULL); + token.length = strlen (service); + token.value = (gchar *) service; + + maj_stat = gss_import_name (&min_stat, + &token, + (gss_OID) GSS_C_NT_HOSTBASED_SERVICE, + &conn->server_name); + + if (GSS_ERROR (maj_stat)) { + soup_gss_error (maj_stat, min_stat, err); + ret = FALSE; + goto out; + } + + conn->initialized = TRUE; + ret = TRUE; +out: + g_free (h); + g_free (service); + return ret; +} + +static gint +soup_gss_client_step (SoupNegotiateConnectionState *conn, const gchar *challenge, GError **err) +{ + OM_uint32 maj_stat, min_stat; + gss_buffer_desc in = GSS_C_EMPTY_BUFFER; + gss_buffer_desc out = GSS_C_EMPTY_BUFFER; + gint ret = AUTH_GSS_CONTINUE; + + g_clear_pointer (&conn->response_header, g_free); + + if (challenge && *challenge) { + size_t len; + in.value = g_base64_decode (challenge, &len); + in.length = len; + } + + maj_stat = gss_init_sec_context (&min_stat, + GSS_C_NO_CREDENTIAL, + &conn->context, + conn->server_name, + (gss_OID) &gss_mech_spnego, + GSS_C_MUTUAL_FLAG, + GSS_C_INDEFINITE, + GSS_C_NO_CHANNEL_BINDINGS, + &in, + NULL, + &out, + NULL, + NULL); + + if ((maj_stat != GSS_S_COMPLETE) && (maj_stat != GSS_S_CONTINUE_NEEDED)) { + soup_gss_error (maj_stat, min_stat, err); + ret = AUTH_GSS_ERROR; + goto out; + } + + ret = (maj_stat == GSS_S_COMPLETE) ? AUTH_GSS_COMPLETE : AUTH_GSS_CONTINUE; + if (out.length) { + gchar *response = g_base64_encode ((const guchar *) out.value, out.length); + conn->response_header = g_strconcat ("Negotiate ", response, NULL); + g_free (response); + maj_stat = gss_release_buffer (&min_stat, &out); + } + +out: + if (out.value) + gss_release_buffer (&min_stat, &out); + if (in.value) + g_free (in.value); + return ret; +} + +static void +soup_gss_client_cleanup (SoupNegotiateConnectionState *conn) +{ + OM_uint32 maj_stat, min_stat; + + gss_release_name (&min_stat, &conn->server_name); + maj_stat = gss_delete_sec_context (&min_stat, &conn->context, GSS_C_NO_BUFFER); + if (maj_stat != GSS_S_COMPLETE) + maj_stat = gss_delete_sec_context (&min_stat, &conn->context, GSS_C_NO_BUFFER); +} +#endif /* LIBSOUP_HAVE_GSSAPI */ diff --git a/libsoup/soup-auth-negotiate.h b/libsoup/soup-auth-negotiate.h new file mode 100644 index 0000000..e976644 --- /dev/null +++ b/libsoup/soup-auth-negotiate.h @@ -0,0 +1,28 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2010 Guido Guenther + * Copyright (C) 2016 Red Hat, Inc. + */ + +#ifndef SOUP_AUTH_NEGOTIATE_H +#define SOUP_AUTH_NEGOTIATE_H 1 + +#include "soup-connection-auth.h" + +#define SOUP_AUTH_NEGOTIATE(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), SOUP_TYPE_AUTH_NEGOTIATE, SoupAuthNegotiate)) +#define SOUP_AUTH_NEGOTIATE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_AUTH_NEGOTIATE, SoupAuthNegotiateClass)) +#define SOUP_IS_AUTH_NEGOTIATE(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), SOUP_TYPE_AUTH_NEGOTIATE)) +#define SOUP_IS_AUTH_NEGOTIATE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SOUP_TYPE_AUTH_NEGOTIATE)) +#define SOUP_AUTH_NEGOTIATE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_AUTH_NEGOTIATE, SoupAuthNegotiateClass)) + +typedef struct { + SoupConnectionAuth parent; + +} SoupAuthNegotiate; + +typedef struct { + SoupConnectionAuthClass parent_class; + +} SoupAuthNegotiateClass; + +#endif /* SOUP_AUTH_NEGOTIATE_H */ diff --git a/libsoup/soup-auth-ntlm.c b/libsoup/soup-auth-ntlm.c new file mode 100644 index 0000000..19a551e --- /dev/null +++ b/libsoup/soup-auth-ntlm.c @@ -0,0 +1,1333 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-auth-ntlm.c: HTTP NTLM Authentication helper + * + * Copyright (C) 2007 Red Hat, Inc. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#include "soup-auth-ntlm.h" +#include "soup.h" +#include "soup-message-private.h" + +static void soup_ntlm_lanmanager_hash (const char *password, + guchar hash[21]); +static void soup_ntlm_nt_hash (const char *password, + guchar hash[21]); +static char *soup_ntlm_request (void); +static gboolean soup_ntlm_parse_challenge (const char *challenge, + char **nonce, + char **default_domain, + gboolean *ntlmv2_session); +static char *soup_ntlm_response (const char *nonce, + const char *user, + guchar nt_hash[21], + guchar lm_hash[21], + const char *host, + const char *domain, + gboolean ntlmv2_session); + +typedef enum { + SOUP_NTLM_NEW, + SOUP_NTLM_SSO_FAILED, + SOUP_NTLM_SENT_REQUEST, + SOUP_NTLM_RECEIVED_CHALLENGE, + SOUP_NTLM_SENT_RESPONSE, + SOUP_NTLM_FAILED +} SoupNTLMState; + +typedef struct { + SoupNTLMState state; + char *nonce; + char *response_header; + gboolean ntlmv2_session; +} SoupNTLMConnectionState; + +typedef enum { + SOUP_NTLM_PASSWORD_NONE, + SOUP_NTLM_PASSWORD_PROVIDED, + SOUP_NTLM_PASSWORD_ACCEPTED, + SOUP_NTLM_PASSWORD_REJECTED +} SoupNTLMPasswordState; + +typedef struct { + char *username, *domain; + guchar nt_hash[21], lm_hash[21]; + SoupNTLMPasswordState password_state; + +#ifdef USE_NTLM_AUTH + /* Use Samba's 'winbind' daemon to support NTLM single-sign-on, + * by delegating the NTLM challenge/response protocal to a helper + * in ntlm_auth. + * http://devel.squid-cache.org/ntlm/squid_helper_protocol.html + * http://www.samba.org/samba/docs/man/manpages-3/winbindd.8.html + * http://www.samba.org/samba/docs/man/manpages-3/ntlm_auth.1.html + */ + gboolean sso_available; + int fd_in; + int fd_out; +#endif +} SoupAuthNTLMPrivate; + +#ifdef USE_NTLM_AUTH +static gboolean ntlm_auth_available, ntlm_auth_debug; +static void sso_ntlm_close (SoupAuthNTLMPrivate *priv); +#endif + +/** + * SOUP_TYPE_AUTH_NTLM: + * + * A #GType corresponding to HTTP-based NTLM authentication. + * #SoupSessions do not support this type by default; if you want to + * enable support for it, call soup_session_add_feature_by_type(), + * passing %SOUP_TYPE_AUTH_NTLM. + * + * Since: 2.34 + */ + +G_DEFINE_TYPE_WITH_PRIVATE (SoupAuthNTLM, soup_auth_ntlm, SOUP_TYPE_CONNECTION_AUTH) + +static void +soup_auth_ntlm_init (SoupAuthNTLM *ntlm) +{ +#ifdef USE_NTLM_AUTH + SoupAuthNTLMPrivate *priv = soup_auth_ntlm_get_instance_private (ntlm); + const char *username = NULL, *slash; + + priv->sso_available = TRUE; + priv->fd_in = -1; + priv->fd_out = -1; + + username = getenv ("NTLMUSER"); + if (!username) + username = g_get_user_name (); + + slash = strpbrk (username, "\\/"); + if (slash) { + priv->username = g_strdup (slash + 1); + priv->domain = g_strndup (username, slash - username); + } else { + priv->username = g_strdup (username); + priv->domain = NULL; + } +#endif +} + +static void +soup_auth_ntlm_finalize (GObject *object) +{ + SoupAuthNTLMPrivate *priv = soup_auth_ntlm_get_instance_private (SOUP_AUTH_NTLM (object)); + + g_free (priv->username); + g_free (priv->domain); + + memset (priv->nt_hash, 0, sizeof (priv->nt_hash)); + memset (priv->lm_hash, 0, sizeof (priv->lm_hash)); + +#ifdef USE_NTLM_AUTH + sso_ntlm_close (priv); +#endif + + G_OBJECT_CLASS (soup_auth_ntlm_parent_class)->finalize (object); +} + +#ifdef USE_NTLM_AUTH +static void +sso_ntlm_close (SoupAuthNTLMPrivate *priv) +{ + if (priv->fd_in != -1) { + close (priv->fd_in); + priv->fd_in = -1; + } + + if (priv->fd_out != -1) { + close (priv->fd_out); + priv->fd_out = -1; + } +} + +static gboolean +sso_ntlm_initiate (SoupAuthNTLMPrivate *priv) +{ + char *argv[9]; + gboolean ret; + + if (!priv->sso_available) + return FALSE; + + if (!ntlm_auth_available && !ntlm_auth_debug) { + priv->sso_available = FALSE; + return FALSE; + } + + /* Return if ntlm_auth execution process exist already */ + if (priv->fd_in != -1 && priv->fd_out != -1) + return TRUE; + else { + /* Clean all sso data before re-initiate */ + sso_ntlm_close (priv); + } + + if (ntlm_auth_debug) { + argv[0] = (char *) g_getenv ("SOUP_NTLM_AUTH_DEBUG"); + if (!*argv[0]) { + priv->sso_available = FALSE; + return FALSE; + } + } else + argv[0] = NTLM_AUTH; + argv[1] = "--helper-protocol"; + argv[2] = "ntlmssp-client-1"; + argv[3] = "--use-cached-creds"; + argv[4] = "--username"; + argv[5] = priv->username; + argv[6] = priv->domain ? "--domain" : NULL; + argv[7] = priv->domain; + argv[8] = NULL; + + ret = g_spawn_async_with_pipes (NULL, argv, NULL, + G_SPAWN_STDERR_TO_DEV_NULL, + NULL, NULL, + NULL, &priv->fd_in, &priv->fd_out, + NULL, NULL); + if (!ret) + priv->sso_available = FALSE; + return ret; +} + +static char * +sso_ntlm_response (SoupAuthNTLMPrivate *priv, const char *input, SoupNTLMState conn_state) +{ + ssize_t size; + char buf[1024]; + char *tmpbuf = buf; + size_t len_in = strlen (input), len_out = sizeof (buf); + + while (len_in > 0) { + int written = write (priv->fd_in, input, len_in); + if (written == -1) { + if (errno == EINTR) + continue; + /* write failed if other errors happen */ + return NULL; + } + input += written; + len_in -= written; + } + /* Read one line */ + while (len_out > 0) { + size = read (priv->fd_out, tmpbuf, len_out); + if (size == -1) { + if (errno == EINTR) + continue; + return NULL; + } else if (size == 0) + return NULL; + else if (tmpbuf[size - 1] == '\n') { + tmpbuf[size - 1] = '\0'; + goto wrfinish; + } + tmpbuf += size; + len_out -= size; + } + return NULL; + +wrfinish: + if (g_ascii_strcasecmp (buf, "PW") == 0) { + /* Samba/winbind installed but not configured */ + return g_strdup ("PW"); + } + if (conn_state == SOUP_NTLM_NEW && + g_ascii_strncasecmp (buf, "YR ", 3) != 0) { + /* invalid response for type 1 message */ + return NULL; + } + if (conn_state == SOUP_NTLM_RECEIVED_CHALLENGE && + g_ascii_strncasecmp (buf, "KK ", 3) != 0 && + g_ascii_strncasecmp (buf, "AF ", 3) != 0) { + /* invalid response for type 3 message */ + return NULL; + } + + return g_strdup_printf ("NTLM %.*s", (int)(size - 4), buf + 3); +} +#endif /* USE_NTLM_AUTH */ + +static gpointer +soup_auth_ntlm_create_connection_state (SoupConnectionAuth *auth) +{ + SoupNTLMConnectionState *conn; + + conn = g_slice_new0 (SoupNTLMConnectionState); + conn->state = SOUP_NTLM_NEW; + + return conn; +} + +static void +soup_auth_ntlm_free_connection_state (SoupConnectionAuth *auth, + gpointer state) +{ + SoupNTLMConnectionState *conn = state; + + g_free (conn->nonce); + g_free (conn->response_header); + g_slice_free (SoupNTLMConnectionState, conn); +} + +static gboolean +soup_auth_ntlm_update_connection (SoupConnectionAuth *auth, SoupMessage *msg, + const char *auth_header, gpointer state) +{ + SoupAuthNTLM *auth_ntlm = SOUP_AUTH_NTLM (auth); + SoupAuthNTLMPrivate *priv = soup_auth_ntlm_get_instance_private (auth_ntlm); + SoupNTLMConnectionState *conn = state; + gboolean success = TRUE; + + /* Note that we only return FALSE if some sort of parsing error + * occurs. Otherwise, the SoupAuth is still reusable (though it may + * no longer be _ready or _authenticated). + */ + + if (!g_str_has_prefix (auth_header, "NTLM")) + return FALSE; + + if (conn->state > SOUP_NTLM_SENT_REQUEST) { + if (priv->password_state == SOUP_NTLM_PASSWORD_ACCEPTED) { + /* We know our password is correct, so a 401 + * means "permission denied". The code can't deal + * with re-authenticating correctly, so make sure + * we don't try. + */ + conn->state = SOUP_NTLM_FAILED; + if (soup_message_is_keepalive (msg)) { + soup_message_headers_append (msg->response_headers, + "Connection", "close"); + } + return TRUE; + } + +#ifdef USE_NTLM_AUTH + if (priv->sso_available) { + conn->state = SOUP_NTLM_SSO_FAILED; + priv->password_state = SOUP_NTLM_PASSWORD_NONE; + } else { +#endif + conn->state = SOUP_NTLM_FAILED; + priv->password_state = SOUP_NTLM_PASSWORD_REJECTED; +#ifdef USE_NTLM_AUTH + } +#endif + return TRUE; + } + + if (conn->state == SOUP_NTLM_NEW && !auth_header[4]) + return TRUE; + + if (!auth_header[4] || !auth_header[5]) { + conn->state = SOUP_NTLM_FAILED; + return FALSE; + } + + if (!soup_ntlm_parse_challenge (auth_header + 5, &conn->nonce, + priv->domain ? NULL : &priv->domain, + &conn->ntlmv2_session)) { + conn->state = SOUP_NTLM_FAILED; + return FALSE; + } + +#ifdef USE_NTLM_AUTH + if (priv->sso_available && conn->state == SOUP_NTLM_SENT_REQUEST) { + char *input, *response; + + /* Re-Initiate ntlm_auth process in case it was closed/killed abnormally */ + if (!sso_ntlm_initiate (priv)) { + conn->state = SOUP_NTLM_SSO_FAILED; + success = FALSE; + goto out; + } + + input = g_strdup_printf ("TT %s\n", auth_header + 5); + response = sso_ntlm_response (priv, input, conn->state); + sso_ntlm_close (priv); + g_free (input); + + if (!response) { + conn->state = SOUP_NTLM_SSO_FAILED; + success = FALSE; + } else if (!g_ascii_strcasecmp (response, "PW")) { + conn->state = SOUP_NTLM_SSO_FAILED; + priv->sso_available = FALSE; + g_free (response); + } else { + conn->response_header = response; + if (priv->password_state != SOUP_NTLM_PASSWORD_ACCEPTED) + priv->password_state = SOUP_NTLM_PASSWORD_PROVIDED; + } + } + out: +#endif + + if (conn->state == SOUP_NTLM_SENT_REQUEST) + conn->state = SOUP_NTLM_RECEIVED_CHALLENGE; + + g_object_set (G_OBJECT (auth), + SOUP_AUTH_REALM, priv->domain, + SOUP_AUTH_HOST, soup_message_get_uri (msg)->host, + NULL); + return success; +} + +static GSList * +soup_auth_ntlm_get_protection_space (SoupAuth *auth, SoupURI *source_uri) +{ + char *space, *p; + + space = g_strdup (source_uri->path); + + /* Strip filename component */ + p = strrchr (space, '/'); + if (p && p != space && p[1]) + *p = '\0'; + + return g_slist_prepend (NULL, space); +} + +static void +soup_auth_ntlm_authenticate (SoupAuth *auth, const char *username, + const char *password) +{ + SoupAuthNTLM *auth_ntlm = SOUP_AUTH_NTLM (auth); + SoupAuthNTLMPrivate *priv = soup_auth_ntlm_get_instance_private (auth_ntlm); + const char *slash; + + g_return_if_fail (username != NULL); + g_return_if_fail (password != NULL); + + if (priv->username) + g_free (priv->username); + if (priv->domain) + g_free (priv->domain); + + slash = strpbrk (username, "\\/"); + if (slash) { + priv->domain = g_strndup (username, slash - username); + priv->username = g_strdup (slash + 1); + } else { + priv->domain = g_strdup (""); + priv->username = g_strdup (username); + } + + soup_ntlm_nt_hash (password, priv->nt_hash); + soup_ntlm_lanmanager_hash (password, priv->lm_hash); + + priv->password_state = SOUP_NTLM_PASSWORD_PROVIDED; +} + +static gboolean +soup_auth_ntlm_is_authenticated (SoupAuth *auth) +{ + SoupAuthNTLM *auth_ntlm = SOUP_AUTH_NTLM (auth); + SoupAuthNTLMPrivate *priv = soup_auth_ntlm_get_instance_private (auth_ntlm); + + return (priv->password_state != SOUP_NTLM_PASSWORD_NONE && + priv->password_state != SOUP_NTLM_PASSWORD_REJECTED); +} + +static gboolean +soup_auth_ntlm_is_connection_ready (SoupConnectionAuth *auth, + SoupMessage *msg, + gpointer state) +{ + SoupAuthNTLM *auth_ntlm = SOUP_AUTH_NTLM (auth); + SoupAuthNTLMPrivate *priv = soup_auth_ntlm_get_instance_private (auth_ntlm); + SoupNTLMConnectionState *conn = state; + + if (priv->password_state == SOUP_NTLM_PASSWORD_REJECTED) + return FALSE; + + if (priv->password_state == SOUP_NTLM_PASSWORD_PROVIDED) + return TRUE; + + return conn->state != SOUP_NTLM_FAILED; +} + +static void +got_final_auth_result (SoupMessage *msg, gpointer data) +{ + SoupAuth *auth = data; + SoupAuthNTLMPrivate *priv = soup_auth_ntlm_get_instance_private (SOUP_AUTH_NTLM (auth)); + + g_signal_handlers_disconnect_by_func (msg, G_CALLBACK (got_final_auth_result), auth); + + if (auth != soup_message_get_auth (msg)) + return; + + if (msg->status_code != SOUP_STATUS_UNAUTHORIZED) + priv->password_state = SOUP_NTLM_PASSWORD_ACCEPTED; +} + +static char * +soup_auth_ntlm_get_connection_authorization (SoupConnectionAuth *auth, + SoupMessage *msg, + gpointer state) +{ + SoupAuthNTLM *auth_ntlm = SOUP_AUTH_NTLM (auth); + SoupAuthNTLMPrivate *priv = soup_auth_ntlm_get_instance_private (auth_ntlm); + SoupNTLMConnectionState *conn = state; + char *header = NULL; + + switch (conn->state) { + case SOUP_NTLM_NEW: +#ifdef USE_NTLM_AUTH + if (sso_ntlm_initiate (priv)) { + header = sso_ntlm_response (priv, "YR\n", conn->state); + if (header) { + if (g_ascii_strcasecmp (header, "PW") != 0) { + conn->state = SOUP_NTLM_SENT_REQUEST; + break; + } else { + g_free (header); + header = NULL; + priv->sso_available = FALSE; + } + } else { + g_debug ("NTLM single-sign-on using %s failed", NTLM_AUTH); + } + } + /* If NTLM single-sign-on fails, go back to original + * request handling process. + */ +#endif + header = soup_ntlm_request (); + conn->state = SOUP_NTLM_SENT_REQUEST; + break; + case SOUP_NTLM_RECEIVED_CHALLENGE: + if (conn->response_header) { + header = conn->response_header; + conn->response_header = NULL; + } else { + header = soup_ntlm_response (conn->nonce, + priv->username, + priv->nt_hash, + priv->lm_hash, + NULL, + priv->domain, + conn->ntlmv2_session); + } + g_clear_pointer (&conn->nonce, g_free); + conn->state = SOUP_NTLM_SENT_RESPONSE; + + if (priv->password_state != SOUP_NTLM_PASSWORD_ACCEPTED) { + /* We need to know if this worked */ + g_signal_connect (msg, "got-headers", + G_CALLBACK (got_final_auth_result), + auth); + } + break; +#ifdef USE_NTLM_AUTH + case SOUP_NTLM_SSO_FAILED: + /* Restart request without SSO */ + g_debug ("NTLM single-sign-on by using %s failed", NTLM_AUTH); + priv->sso_available = FALSE; + header = soup_ntlm_request (); + conn->state = SOUP_NTLM_SENT_REQUEST; + break; +#endif + default: + break; + } + + return header; +} + +static void +soup_auth_ntlm_class_init (SoupAuthNTLMClass *auth_ntlm_class) +{ + SoupAuthClass *auth_class = SOUP_AUTH_CLASS (auth_ntlm_class); + SoupConnectionAuthClass *connauth_class = SOUP_CONNECTION_AUTH_CLASS (auth_ntlm_class); + GObjectClass *object_class = G_OBJECT_CLASS (auth_ntlm_class); + + auth_class->scheme_name = "NTLM"; + auth_class->strength = 3; + + auth_class->get_protection_space = soup_auth_ntlm_get_protection_space; + auth_class->authenticate = soup_auth_ntlm_authenticate; + auth_class->is_authenticated = soup_auth_ntlm_is_authenticated; + + connauth_class->create_connection_state = soup_auth_ntlm_create_connection_state; + connauth_class->free_connection_state = soup_auth_ntlm_free_connection_state; + connauth_class->update_connection = soup_auth_ntlm_update_connection; + connauth_class->get_connection_authorization = soup_auth_ntlm_get_connection_authorization; + connauth_class->is_connection_ready = soup_auth_ntlm_is_connection_ready; + + object_class->finalize = soup_auth_ntlm_finalize; + +#ifdef USE_NTLM_AUTH + ntlm_auth_available = g_file_test (NTLM_AUTH, G_FILE_TEST_IS_EXECUTABLE); + ntlm_auth_debug = (g_getenv ("SOUP_NTLM_AUTH_DEBUG") != NULL); +#endif +} + +static void md4sum (const unsigned char *in, + int nbytes, + unsigned char digest[16]); + +typedef guint32 DES_KS[16][2]; /* Single-key DES key schedule */ + +static void deskey (DES_KS, unsigned char *, int); + +static void des (DES_KS, unsigned char *); + +static void setup_schedule (const guchar *key_56, DES_KS ks); + +static void calc_response (const guchar *key, + const guchar *plaintext, + guchar *results); + +#define LM_PASSWORD_MAGIC "\x4B\x47\x53\x21\x40\x23\x24\x25" \ + "\x4B\x47\x53\x21\x40\x23\x24\x25" \ + "\x00\x00\x00\x00\x00" + +static void +soup_ntlm_lanmanager_hash (const char *password, guchar hash[21]) +{ + guchar lm_password [15]; + DES_KS ks; + int i; + + for (i = 0; i < 14 && password [i]; i++) + lm_password [i] = g_ascii_toupper ((unsigned char) password [i]); + + for (; i < 15; i++) + lm_password [i] = '\0'; + + memcpy (hash, LM_PASSWORD_MAGIC, 21); + + setup_schedule (lm_password, ks); + des (ks, hash); + + setup_schedule (lm_password + 7, ks); + des (ks, hash + 8); +} + +static void +soup_ntlm_nt_hash (const char *password, guchar hash[21]) +{ + unsigned char *buf, *p; + + p = buf = g_malloc (strlen (password) * 2); + + while (*password) { + *p++ = *password++; + *p++ = '\0'; + } + + md4sum (buf, p - buf, hash); + memset (hash + 16, 0, 5); + + g_free (buf); +} + +typedef struct { + guint16 length; + guint16 length2; + guint16 offset; + guchar zero_pad[2]; +} NTLMString; + +#define NTLM_CHALLENGE_NONCE_OFFSET 24 +#define NTLM_CHALLENGE_NONCE_LENGTH 8 +#define NTLM_CHALLENGE_DOMAIN_STRING_OFFSET 12 + +#define NTLM_CHALLENGE_FLAGS_OFFSET 20 +#define NTLM_FLAGS_NEGOTIATE_NTLMV2 0x00080000 + +#define NTLM_RESPONSE_HEADER "NTLMSSP\x00\x03\x00\x00\x00" +#define NTLM_RESPONSE_FLAGS 0x8201 +#define NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY 0x00080000 + +typedef struct { + guchar header[12]; + + NTLMString lm_resp; + NTLMString nt_resp; + NTLMString domain; + NTLMString user; + NTLMString host; + NTLMString session_key; + + guint32 flags; +} NTLMResponse; + +static void +ntlm_set_string (NTLMString *string, int *offset, int len) +{ + string->offset = GUINT16_TO_LE (*offset); + string->length = string->length2 = GUINT16_TO_LE (len); + *offset += len; +} + +static char * +soup_ntlm_request (void) +{ + return g_strdup ("NTLM TlRMTVNTUAABAAAABYIIAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAAwAAAA"); +} + +static gboolean +soup_ntlm_parse_challenge (const char *challenge, + char **nonce, + char **default_domain, + gboolean *ntlmv2_session) +{ + gsize clen; + NTLMString domain; + guchar *chall; + guint32 flags; + + chall = g_base64_decode (challenge, &clen); + if (clen < NTLM_CHALLENGE_DOMAIN_STRING_OFFSET || + clen < NTLM_CHALLENGE_NONCE_OFFSET + NTLM_CHALLENGE_NONCE_LENGTH) { + g_free (chall); + return FALSE; + } + + memcpy (&flags, chall + NTLM_CHALLENGE_FLAGS_OFFSET, sizeof(flags)); + flags = GUINT_FROM_LE (flags); + *ntlmv2_session = (flags & NTLM_FLAGS_NEGOTIATE_NTLMV2) ? TRUE : FALSE; + + if (default_domain) { + memcpy (&domain, chall + NTLM_CHALLENGE_DOMAIN_STRING_OFFSET, sizeof (domain)); + domain.length = GUINT16_FROM_LE (domain.length); + domain.offset = GUINT16_FROM_LE (domain.offset); + + if (clen < domain.length + domain.offset) { + g_free (chall); + return FALSE; + } + + *default_domain = g_convert ((char *)chall + domain.offset, + domain.length, "UTF-8", "UCS-2LE", + NULL, NULL, NULL); + } + + if (nonce) { + *nonce = g_memdup (chall + NTLM_CHALLENGE_NONCE_OFFSET, + NTLM_CHALLENGE_NONCE_LENGTH); + } + + g_free (chall); + return TRUE; +} + +static void +calc_ntlm2_session_response (const char *nonce, + guchar nt_hash[21], + guchar lm_hash[21], + guchar *lm_resp, + gsize lm_resp_sz, + guchar *nt_resp) +{ + guint32 client_nonce[2]; + guchar ntlmv2_hash[16]; + GChecksum *ntlmv2_cksum; + gsize ntlmv2_hash_sz = sizeof (ntlmv2_hash); + + /* FIXME: if GLib ever gets a more secure random number + * generator, use it here + */ + client_nonce[0] = g_random_int(); + client_nonce[1] = g_random_int(); + + ntlmv2_cksum = g_checksum_new (G_CHECKSUM_MD5); + g_checksum_update (ntlmv2_cksum, (const guchar *) nonce, 8); + g_checksum_update (ntlmv2_cksum, (const guchar *) client_nonce, sizeof (client_nonce)); + g_checksum_get_digest (ntlmv2_cksum, ntlmv2_hash, &ntlmv2_hash_sz); + g_checksum_free (ntlmv2_cksum); + + /* Send the padded client nonce as a fake lm_resp */ + memset (lm_resp, 0, lm_resp_sz); + memcpy (lm_resp, client_nonce, sizeof (client_nonce)); + + /* Compute nt_hash as usual but with a new nonce */ + calc_response (nt_hash, ntlmv2_hash, nt_resp); +} + + +static char * +soup_ntlm_response (const char *nonce, + const char *user, + guchar nt_hash[21], + guchar lm_hash[21], + const char *host, + const char *domain, + gboolean ntlmv2_session) +{ + int offset; + gsize hlen, dlen, ulen; + guchar lm_resp[24], nt_resp[24]; + char *user_conv, *host_conv, *domain_conv; + NTLMResponse resp; + char *out, *p; + int state, save; + + if (ntlmv2_session) { + calc_ntlm2_session_response (nonce, nt_hash, lm_hash, + lm_resp, sizeof(lm_resp), nt_resp); + } else { + /* Compute a regular response */ + calc_response (nt_hash, (guchar *) nonce, nt_resp); + calc_response (lm_hash, (guchar *) nonce, lm_resp); + } + + memset (&resp, 0, sizeof (resp)); + memcpy (resp.header, NTLM_RESPONSE_HEADER, sizeof (resp.header)); + resp.flags = GUINT32_TO_LE (NTLM_RESPONSE_FLAGS); + if (ntlmv2_session) + resp.flags |= GUINT32_TO_LE (NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY); + + offset = sizeof (resp); + + if (!host) + host = "UNKNOWN"; + + domain_conv = g_convert (domain, -1, "UCS-2LE", "UTF-8", NULL, &dlen, NULL); + user_conv = g_convert (user, -1, "UCS-2LE", "UTF-8", NULL, &ulen, NULL); + host_conv = g_convert (host, -1, "UCS-2LE", "UTF-8", NULL, &hlen, NULL); + + ntlm_set_string (&resp.domain, &offset, dlen); + ntlm_set_string (&resp.user, &offset, ulen); + ntlm_set_string (&resp.host, &offset, hlen); + ntlm_set_string (&resp.lm_resp, &offset, sizeof (lm_resp)); + ntlm_set_string (&resp.nt_resp, &offset, sizeof (nt_resp)); + + out = g_malloc (((offset + 3) * 4) / 3 + 6); + strncpy (out, "NTLM ", 5); + p = out + 5; + + state = save = 0; + + p += g_base64_encode_step ((const guchar *) &resp, sizeof (resp), + FALSE, p, &state, &save); + p += g_base64_encode_step ((const guchar *) domain_conv, dlen, + FALSE, p, &state, &save); + p += g_base64_encode_step ((const guchar *) user_conv, ulen, + FALSE, p, &state, &save); + p += g_base64_encode_step ((const guchar *) host_conv, hlen, + FALSE, p, &state, &save); + p += g_base64_encode_step (lm_resp, sizeof (lm_resp), + FALSE, p, &state, &save); + p += g_base64_encode_step (nt_resp, sizeof (nt_resp), + FALSE, p, &state, &save); + p += g_base64_encode_close (FALSE, p, &state, &save); + *p = '\0'; + + g_free (domain_conv); + g_free (user_conv); + g_free (host_conv); + + return out; +} + +/* DES utils */ +/* Set up a key schedule based on a 56bit key */ +static void +setup_schedule (const guchar *key_56, DES_KS ks) +{ + guchar key[8]; + int i, c, bit; + + key[0] = (key_56[0]) ; + key[1] = (key_56[1] >> 1) | ((key_56[0] << 7) & 0xFF); + key[2] = (key_56[2] >> 2) | ((key_56[1] << 6) & 0xFF); + key[3] = (key_56[3] >> 3) | ((key_56[2] << 5) & 0xFF); + key[4] = (key_56[4] >> 4) | ((key_56[3] << 4) & 0xFF); + key[5] = (key_56[5] >> 5) | ((key_56[4] << 3) & 0xFF); + key[6] = (key_56[6] >> 6) | ((key_56[5] << 2) & 0xFF); + key[7] = ((key_56[6] << 1) & 0xFF); + + /* Fix parity */ + for (i = 0; i < 8; i++) { + for (c = bit = 0; bit < 8; bit++) + if (key[i] & (1 << bit)) + c++; + if (!(c & 1)) + key[i] ^= 0x01; + } + + deskey (ks, key, 0); +} + +static void +calc_response (const guchar *key, const guchar *plaintext, guchar *results) +{ + DES_KS ks; + + memcpy (results, plaintext, 8); + memcpy (results + 8, plaintext, 8); + memcpy (results + 16, plaintext, 8); + + setup_schedule (key, ks); + des (ks, results); + + setup_schedule (key + 7, ks); + des (ks, results + 8); + + setup_schedule (key + 14, ks); + des (ks, results + 16); +} + + +/* + * MD4 encoder. (The one everyone else uses is not GPL-compatible; + * this is a reimplementation from spec.) This doesn't need to be + * efficient for our purposes, although it would be nice to fix + * it to not malloc()... + */ + +#define F(X,Y,Z) ( ((X)&(Y)) | ((~(X))&(Z)) ) +#define G(X,Y,Z) ( ((X)&(Y)) | ((X)&(Z)) | ((Y)&(Z)) ) +#define H(X,Y,Z) ( (X)^(Y)^(Z) ) +#define ROT(val, n) ( ((val) << (n)) | ((val) >> (32 - (n))) ) + +static void +md4sum (const unsigned char *in, int nbytes, unsigned char digest[16]) +{ + unsigned char *M; + guint32 A, B, C, D, AA, BB, CC, DD, X[16]; + int pbytes, nbits = nbytes * 8, i, j; + + /* There is *always* padding of at least one bit. */ + pbytes = ((119 - (nbytes % 64)) % 64) + 1; + M = alloca (nbytes + pbytes + 8); + memcpy (M, in, nbytes); + memset (M + nbytes, 0, pbytes + 8); + M[nbytes] = 0x80; + M[nbytes + pbytes] = nbits & 0xFF; + M[nbytes + pbytes + 1] = (nbits >> 8) & 0xFF; + M[nbytes + pbytes + 2] = (nbits >> 16) & 0xFF; + M[nbytes + pbytes + 3] = (nbits >> 24) & 0xFF; + + A = 0x67452301; + B = 0xEFCDAB89; + C = 0x98BADCFE; + D = 0x10325476; + + for (i = 0; i < nbytes + pbytes + 8; i += 64) { + for (j = 0; j < 16; j++) { + X[j] = (M[i + j*4]) | + (M[i + j*4 + 1] << 8) | + (M[i + j*4 + 2] << 16) | + (M[i + j*4 + 3] << 24); + } + + AA = A; + BB = B; + CC = C; + DD = D; + + A = ROT (A + F(B, C, D) + X[0], 3); + D = ROT (D + F(A, B, C) + X[1], 7); + C = ROT (C + F(D, A, B) + X[2], 11); + B = ROT (B + F(C, D, A) + X[3], 19); + A = ROT (A + F(B, C, D) + X[4], 3); + D = ROT (D + F(A, B, C) + X[5], 7); + C = ROT (C + F(D, A, B) + X[6], 11); + B = ROT (B + F(C, D, A) + X[7], 19); + A = ROT (A + F(B, C, D) + X[8], 3); + D = ROT (D + F(A, B, C) + X[9], 7); + C = ROT (C + F(D, A, B) + X[10], 11); + B = ROT (B + F(C, D, A) + X[11], 19); + A = ROT (A + F(B, C, D) + X[12], 3); + D = ROT (D + F(A, B, C) + X[13], 7); + C = ROT (C + F(D, A, B) + X[14], 11); + B = ROT (B + F(C, D, A) + X[15], 19); + + A = ROT (A + G(B, C, D) + X[0] + 0x5A827999, 3); + D = ROT (D + G(A, B, C) + X[4] + 0x5A827999, 5); + C = ROT (C + G(D, A, B) + X[8] + 0x5A827999, 9); + B = ROT (B + G(C, D, A) + X[12] + 0x5A827999, 13); + A = ROT (A + G(B, C, D) + X[1] + 0x5A827999, 3); + D = ROT (D + G(A, B, C) + X[5] + 0x5A827999, 5); + C = ROT (C + G(D, A, B) + X[9] + 0x5A827999, 9); + B = ROT (B + G(C, D, A) + X[13] + 0x5A827999, 13); + A = ROT (A + G(B, C, D) + X[2] + 0x5A827999, 3); + D = ROT (D + G(A, B, C) + X[6] + 0x5A827999, 5); + C = ROT (C + G(D, A, B) + X[10] + 0x5A827999, 9); + B = ROT (B + G(C, D, A) + X[14] + 0x5A827999, 13); + A = ROT (A + G(B, C, D) + X[3] + 0x5A827999, 3); + D = ROT (D + G(A, B, C) + X[7] + 0x5A827999, 5); + C = ROT (C + G(D, A, B) + X[11] + 0x5A827999, 9); + B = ROT (B + G(C, D, A) + X[15] + 0x5A827999, 13); + + A = ROT (A + H(B, C, D) + X[0] + 0x6ED9EBA1, 3); + D = ROT (D + H(A, B, C) + X[8] + 0x6ED9EBA1, 9); + C = ROT (C + H(D, A, B) + X[4] + 0x6ED9EBA1, 11); + B = ROT (B + H(C, D, A) + X[12] + 0x6ED9EBA1, 15); + A = ROT (A + H(B, C, D) + X[2] + 0x6ED9EBA1, 3); + D = ROT (D + H(A, B, C) + X[10] + 0x6ED9EBA1, 9); + C = ROT (C + H(D, A, B) + X[6] + 0x6ED9EBA1, 11); + B = ROT (B + H(C, D, A) + X[14] + 0x6ED9EBA1, 15); + A = ROT (A + H(B, C, D) + X[1] + 0x6ED9EBA1, 3); + D = ROT (D + H(A, B, C) + X[9] + 0x6ED9EBA1, 9); + C = ROT (C + H(D, A, B) + X[5] + 0x6ED9EBA1, 11); + B = ROT (B + H(C, D, A) + X[13] + 0x6ED9EBA1, 15); + A = ROT (A + H(B, C, D) + X[3] + 0x6ED9EBA1, 3); + D = ROT (D + H(A, B, C) + X[11] + 0x6ED9EBA1, 9); + C = ROT (C + H(D, A, B) + X[7] + 0x6ED9EBA1, 11); + B = ROT (B + H(C, D, A) + X[15] + 0x6ED9EBA1, 15); + + A += AA; + B += BB; + C += CC; + D += DD; + } + + digest[0] = A & 0xFF; + digest[1] = (A >> 8) & 0xFF; + digest[2] = (A >> 16) & 0xFF; + digest[3] = (A >> 24) & 0xFF; + digest[4] = B & 0xFF; + digest[5] = (B >> 8) & 0xFF; + digest[6] = (B >> 16) & 0xFF; + digest[7] = (B >> 24) & 0xFF; + digest[8] = C & 0xFF; + digest[9] = (C >> 8) & 0xFF; + digest[10] = (C >> 16) & 0xFF; + digest[11] = (C >> 24) & 0xFF; + digest[12] = D & 0xFF; + digest[13] = (D >> 8) & 0xFF; + digest[14] = (D >> 16) & 0xFF; + digest[15] = (D >> 24) & 0xFF; +} + + +/* Public domain DES implementation from Phil Karn */ +static const guint32 Spbox[8][64] = { + { 0x01010400,0x00000000,0x00010000,0x01010404, + 0x01010004,0x00010404,0x00000004,0x00010000, + 0x00000400,0x01010400,0x01010404,0x00000400, + 0x01000404,0x01010004,0x01000000,0x00000004, + 0x00000404,0x01000400,0x01000400,0x00010400, + 0x00010400,0x01010000,0x01010000,0x01000404, + 0x00010004,0x01000004,0x01000004,0x00010004, + 0x00000000,0x00000404,0x00010404,0x01000000, + 0x00010000,0x01010404,0x00000004,0x01010000, + 0x01010400,0x01000000,0x01000000,0x00000400, + 0x01010004,0x00010000,0x00010400,0x01000004, + 0x00000400,0x00000004,0x01000404,0x00010404, + 0x01010404,0x00010004,0x01010000,0x01000404, + 0x01000004,0x00000404,0x00010404,0x01010400, + 0x00000404,0x01000400,0x01000400,0x00000000, + 0x00010004,0x00010400,0x00000000,0x01010004 }, + { 0x80108020,0x80008000,0x00008000,0x00108020, + 0x00100000,0x00000020,0x80100020,0x80008020, + 0x80000020,0x80108020,0x80108000,0x80000000, + 0x80008000,0x00100000,0x00000020,0x80100020, + 0x00108000,0x00100020,0x80008020,0x00000000, + 0x80000000,0x00008000,0x00108020,0x80100000, + 0x00100020,0x80000020,0x00000000,0x00108000, + 0x00008020,0x80108000,0x80100000,0x00008020, + 0x00000000,0x00108020,0x80100020,0x00100000, + 0x80008020,0x80100000,0x80108000,0x00008000, + 0x80100000,0x80008000,0x00000020,0x80108020, + 0x00108020,0x00000020,0x00008000,0x80000000, + 0x00008020,0x80108000,0x00100000,0x80000020, + 0x00100020,0x80008020,0x80000020,0x00100020, + 0x00108000,0x00000000,0x80008000,0x00008020, + 0x80000000,0x80100020,0x80108020,0x00108000 }, + { 0x00000208,0x08020200,0x00000000,0x08020008, + 0x08000200,0x00000000,0x00020208,0x08000200, + 0x00020008,0x08000008,0x08000008,0x00020000, + 0x08020208,0x00020008,0x08020000,0x00000208, + 0x08000000,0x00000008,0x08020200,0x00000200, + 0x00020200,0x08020000,0x08020008,0x00020208, + 0x08000208,0x00020200,0x00020000,0x08000208, + 0x00000008,0x08020208,0x00000200,0x08000000, + 0x08020200,0x08000000,0x00020008,0x00000208, + 0x00020000,0x08020200,0x08000200,0x00000000, + 0x00000200,0x00020008,0x08020208,0x08000200, + 0x08000008,0x00000200,0x00000000,0x08020008, + 0x08000208,0x00020000,0x08000000,0x08020208, + 0x00000008,0x00020208,0x00020200,0x08000008, + 0x08020000,0x08000208,0x00000208,0x08020000, + 0x00020208,0x00000008,0x08020008,0x00020200 }, + { 0x00802001,0x00002081,0x00002081,0x00000080, + 0x00802080,0x00800081,0x00800001,0x00002001, + 0x00000000,0x00802000,0x00802000,0x00802081, + 0x00000081,0x00000000,0x00800080,0x00800001, + 0x00000001,0x00002000,0x00800000,0x00802001, + 0x00000080,0x00800000,0x00002001,0x00002080, + 0x00800081,0x00000001,0x00002080,0x00800080, + 0x00002000,0x00802080,0x00802081,0x00000081, + 0x00800080,0x00800001,0x00802000,0x00802081, + 0x00000081,0x00000000,0x00000000,0x00802000, + 0x00002080,0x00800080,0x00800081,0x00000001, + 0x00802001,0x00002081,0x00002081,0x00000080, + 0x00802081,0x00000081,0x00000001,0x00002000, + 0x00800001,0x00002001,0x00802080,0x00800081, + 0x00002001,0x00002080,0x00800000,0x00802001, + 0x00000080,0x00800000,0x00002000,0x00802080 }, + { 0x00000100,0x02080100,0x02080000,0x42000100, + 0x00080000,0x00000100,0x40000000,0x02080000, + 0x40080100,0x00080000,0x02000100,0x40080100, + 0x42000100,0x42080000,0x00080100,0x40000000, + 0x02000000,0x40080000,0x40080000,0x00000000, + 0x40000100,0x42080100,0x42080100,0x02000100, + 0x42080000,0x40000100,0x00000000,0x42000000, + 0x02080100,0x02000000,0x42000000,0x00080100, + 0x00080000,0x42000100,0x00000100,0x02000000, + 0x40000000,0x02080000,0x42000100,0x40080100, + 0x02000100,0x40000000,0x42080000,0x02080100, + 0x40080100,0x00000100,0x02000000,0x42080000, + 0x42080100,0x00080100,0x42000000,0x42080100, + 0x02080000,0x00000000,0x40080000,0x42000000, + 0x00080100,0x02000100,0x40000100,0x00080000, + 0x00000000,0x40080000,0x02080100,0x40000100 }, + { 0x20000010,0x20400000,0x00004000,0x20404010, + 0x20400000,0x00000010,0x20404010,0x00400000, + 0x20004000,0x00404010,0x00400000,0x20000010, + 0x00400010,0x20004000,0x20000000,0x00004010, + 0x00000000,0x00400010,0x20004010,0x00004000, + 0x00404000,0x20004010,0x00000010,0x20400010, + 0x20400010,0x00000000,0x00404010,0x20404000, + 0x00004010,0x00404000,0x20404000,0x20000000, + 0x20004000,0x00000010,0x20400010,0x00404000, + 0x20404010,0x00400000,0x00004010,0x20000010, + 0x00400000,0x20004000,0x20000000,0x00004010, + 0x20000010,0x20404010,0x00404000,0x20400000, + 0x00404010,0x20404000,0x00000000,0x20400010, + 0x00000010,0x00004000,0x20400000,0x00404010, + 0x00004000,0x00400010,0x20004010,0x00000000, + 0x20404000,0x20000000,0x00400010,0x20004010 }, + { 0x00200000,0x04200002,0x04000802,0x00000000, + 0x00000800,0x04000802,0x00200802,0x04200800, + 0x04200802,0x00200000,0x00000000,0x04000002, + 0x00000002,0x04000000,0x04200002,0x00000802, + 0x04000800,0x00200802,0x00200002,0x04000800, + 0x04000002,0x04200000,0x04200800,0x00200002, + 0x04200000,0x00000800,0x00000802,0x04200802, + 0x00200800,0x00000002,0x04000000,0x00200800, + 0x04000000,0x00200800,0x00200000,0x04000802, + 0x04000802,0x04200002,0x04200002,0x00000002, + 0x00200002,0x04000000,0x04000800,0x00200000, + 0x04200800,0x00000802,0x00200802,0x04200800, + 0x00000802,0x04000002,0x04200802,0x04200000, + 0x00200800,0x00000000,0x00000002,0x04200802, + 0x00000000,0x00200802,0x04200000,0x00000800, + 0x04000002,0x04000800,0x00000800,0x00200002 }, + { 0x10001040,0x00001000,0x00040000,0x10041040, + 0x10000000,0x10001040,0x00000040,0x10000000, + 0x00040040,0x10040000,0x10041040,0x00041000, + 0x10041000,0x00041040,0x00001000,0x00000040, + 0x10040000,0x10000040,0x10001000,0x00001040, + 0x00041000,0x00040040,0x10040040,0x10041000, + 0x00001040,0x00000000,0x00000000,0x10040040, + 0x10000040,0x10001000,0x00041040,0x00040000, + 0x00041040,0x00040000,0x10041000,0x00001000, + 0x00000040,0x10040040,0x00001000,0x00041040, + 0x10001000,0x00000040,0x10000040,0x10040000, + 0x10040040,0x10000000,0x00040000,0x10001040, + 0x00000000,0x10041040,0x00040040,0x10000040, + 0x10040000,0x10001000,0x10001040,0x00000000, + 0x10041040,0x00041000,0x00041000,0x00001040, + 0x00001040,0x00040040,0x10000000,0x10041000 } +}; + +#undef F +#define F(l,r,key){\ + work = ((r >> 4) | (r << 28)) ^ key[0];\ + l ^= Spbox[6][work & 0x3f];\ + l ^= Spbox[4][(work >> 8) & 0x3f];\ + l ^= Spbox[2][(work >> 16) & 0x3f];\ + l ^= Spbox[0][(work >> 24) & 0x3f];\ + work = r ^ key[1];\ + l ^= Spbox[7][work & 0x3f];\ + l ^= Spbox[5][(work >> 8) & 0x3f];\ + l ^= Spbox[3][(work >> 16) & 0x3f];\ + l ^= Spbox[1][(work >> 24) & 0x3f];\ +} +/* Encrypt or decrypt a block of data in ECB mode */ +static void +des (guint32 ks[16][2], unsigned char block[8]) +{ + guint32 left,right,work; + + /* Read input block and place in left/right in big-endian order */ + left = ((guint32)block[0] << 24) + | ((guint32)block[1] << 16) + | ((guint32)block[2] << 8) + | (guint32)block[3]; + right = ((guint32)block[4] << 24) + | ((guint32)block[5] << 16) + | ((guint32)block[6] << 8) + | (guint32)block[7]; + + /* Hoey's clever initial permutation algorithm, from Outerbridge + * (see Schneier p 478) + * + * The convention here is the same as Outerbridge: rotate each + * register left by 1 bit, i.e., so that "left" contains permuted + * input bits 2, 3, 4, ... 1 and "right" contains 33, 34, 35, ... 32 + * (using origin-1 numbering as in the FIPS). This allows us to avoid + * one of the two rotates that would otherwise be required in each of + * the 16 rounds. + */ + work = ((left >> 4) ^ right) & 0x0f0f0f0f; + right ^= work; + left ^= work << 4; + work = ((left >> 16) ^ right) & 0xffff; + right ^= work; + left ^= work << 16; + work = ((right >> 2) ^ left) & 0x33333333; + left ^= work; + right ^= (work << 2); + work = ((right >> 8) ^ left) & 0xff00ff; + left ^= work; + right ^= (work << 8); + right = (right << 1) | (right >> 31); + work = (left ^ right) & 0xaaaaaaaa; + left ^= work; + right ^= work; + left = (left << 1) | (left >> 31); + + /* Now do the 16 rounds */ + F(left,right,ks[0]); + F(right,left,ks[1]); + F(left,right,ks[2]); + F(right,left,ks[3]); + F(left,right,ks[4]); + F(right,left,ks[5]); + F(left,right,ks[6]); + F(right,left,ks[7]); + F(left,right,ks[8]); + F(right,left,ks[9]); + F(left,right,ks[10]); + F(right,left,ks[11]); + F(left,right,ks[12]); + F(right,left,ks[13]); + F(left,right,ks[14]); + F(right,left,ks[15]); + + /* Inverse permutation, also from Hoey via Outerbridge and Schneier */ + right = (right << 31) | (right >> 1); + work = (left ^ right) & 0xaaaaaaaa; + left ^= work; + right ^= work; + left = (left >> 1) | (left << 31); + work = ((left >> 8) ^ right) & 0xff00ff; + right ^= work; + left ^= work << 8; + work = ((left >> 2) ^ right) & 0x33333333; + right ^= work; + left ^= work << 2; + work = ((right >> 16) ^ left) & 0xffff; + left ^= work; + right ^= work << 16; + work = ((right >> 4) ^ left) & 0x0f0f0f0f; + left ^= work; + right ^= work << 4; + + /* Put the block back into the user's buffer with final swap */ + block[0] = right >> 24; + block[1] = right >> 16; + block[2] = right >> 8; + block[3] = right; + block[4] = left >> 24; + block[5] = left >> 16; + block[6] = left >> 8; + block[7] = left; +} + +/* Key schedule-related tables from FIPS-46 */ + +/* permuted choice table (key) */ +static const unsigned char pc1[] = { + 57, 49, 41, 33, 25, 17, 9, + 1, 58, 50, 42, 34, 26, 18, + 10, 2, 59, 51, 43, 35, 27, + 19, 11, 3, 60, 52, 44, 36, + + 63, 55, 47, 39, 31, 23, 15, + 7, 62, 54, 46, 38, 30, 22, + 14, 6, 61, 53, 45, 37, 29, + 21, 13, 5, 28, 20, 12, 4 +}; + +/* number left rotations of pc1 */ +static const unsigned char totrot[] = { + 1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28 +}; + +/* permuted choice key (table) */ +static const unsigned char pc2[] = { + 14, 17, 11, 24, 1, 5, + 3, 28, 15, 6, 21, 10, + 23, 19, 12, 4, 26, 8, + 16, 7, 27, 20, 13, 2, + 41, 52, 31, 37, 47, 55, + 30, 40, 51, 45, 33, 48, + 44, 49, 39, 56, 34, 53, + 46, 42, 50, 36, 29, 32 +}; + +/* End of DES-defined tables */ + + +/* bit 0 is left-most in byte */ +static const int bytebit[] = { + 0200,0100,040,020,010,04,02,01 +}; + + +/* Generate key schedule for encryption or decryption + * depending on the value of "decrypt" + */ +static void +deskey (DES_KS k, unsigned char *key, int decrypt) +{ + unsigned char pc1m[56]; /* place to modify pc1 into */ + unsigned char pcr[56]; /* place to rotate pc1 into */ + register int i,j,l; + int m; + unsigned char ks[8]; + + for (j=0; j<56; j++) { /* convert pc1 to bits of key */ + l=pc1[j]-1; /* integer bit location */ + m = l & 07; /* find bit */ + pc1m[j]=(key[l>>3] & /* find which key byte l is in */ + bytebit[m]) /* and which bit of that byte */ + ? 1 : 0; /* and store 1-bit result */ + } + for (i=0; i<16; i++) { /* key chunk for each iteration */ + memset(ks,0,sizeof(ks)); /* Clear key schedule */ + for (j=0; j<56; j++) /* rotate pc1 the right amount */ + pcr[j] = pc1m[(l=j+totrot[decrypt? 15-i : i])<(j<28? 28 : 56) ? l: l-28]; + /* rotate left and right halves independently */ + for (j=0; j<48; j++){ /* select bits individually */ + /* check bit that goes to ks[j] */ + if (pcr[pc2[j]-1]){ + /* mask it in if it's there */ + l= j % 6; + ks[j/6] |= bytebit[l] >> 2; + } + } + /* Now convert to packed odd/even interleaved form */ + k[i][0] = ((guint32)ks[0] << 24) + | ((guint32)ks[2] << 16) + | ((guint32)ks[4] << 8) + | ((guint32)ks[6]); + k[i][1] = ((guint32)ks[1] << 24) + | ((guint32)ks[3] << 16) + | ((guint32)ks[5] << 8) + | ((guint32)ks[7]); + } +} diff --git a/libsoup/soup-auth-ntlm.h b/libsoup/soup-auth-ntlm.h new file mode 100644 index 0000000..43c4085 --- /dev/null +++ b/libsoup/soup-auth-ntlm.h @@ -0,0 +1,27 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2007 Red Hat, Inc. + */ + +#ifndef SOUP_AUTH_NTLM_H +#define SOUP_AUTH_NTLM_H 1 + +#include "soup-connection-auth.h" + +#define SOUP_AUTH_NTLM(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), SOUP_TYPE_AUTH_NTLM, SoupAuthNTLM)) +#define SOUP_AUTH_NTLM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_AUTH_NTLM, SoupAuthNTLMClass)) +#define SOUP_IS_AUTH_NTLM(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), SOUP_TYPE_AUTH_NTLM)) +#define SOUP_IS_AUTH_NTLM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SOUP_TYPE_AUTH_NTLM)) +#define SOUP_AUTH_NTLM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_AUTH_NTLM, SoupAuthNTLMClass)) + +typedef struct { + SoupConnectionAuth parent; + +} SoupAuthNTLM; + +typedef struct { + SoupConnectionAuthClass parent_class; + +} SoupAuthNTLMClass; + +#endif /* SOUP_AUTH_NTLM_H */ diff --git a/libsoup/soup-auth.c b/libsoup/soup-auth.c new file mode 100644 index 0000000..7abf6e1 --- /dev/null +++ b/libsoup/soup-auth.c @@ -0,0 +1,578 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-auth.c: HTTP Authentication framework + * + * Copyright (C) 2001-2003, Ximian, Inc. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "soup-auth.h" +#include "soup.h" +#include "soup-connection-auth.h" + +/** + * SECTION:soup-auth + * @short_description: HTTP client-side authentication support + * @see_also: #SoupSession + * + * #SoupAuth objects store the authentication data associated with a + * given bit of web space. They are created automatically by + * #SoupSession. + **/ + +/** + * SoupAuth: + * + * The abstract base class for handling authentication. Specific HTTP + * Authentication mechanisms are implemented by its subclasses, but + * applications never need to be aware of the specific subclasses + * being used. + **/ + +typedef struct { + gboolean proxy; + char *host; +} SoupAuthPrivate; + +G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (SoupAuth, soup_auth, G_TYPE_OBJECT) + +enum { + PROP_0, + + PROP_SCHEME_NAME, + PROP_REALM, + PROP_HOST, + PROP_IS_FOR_PROXY, + PROP_IS_AUTHENTICATED, + + LAST_PROP +}; + +static void +soup_auth_init (SoupAuth *auth) +{ +} + +static void +soup_auth_finalize (GObject *object) +{ + SoupAuth *auth = SOUP_AUTH (object); + SoupAuthPrivate *priv = soup_auth_get_instance_private (auth); + + g_free (auth->realm); + g_free (priv->host); + + G_OBJECT_CLASS (soup_auth_parent_class)->finalize (object); +} + +static void +soup_auth_set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + SoupAuth *auth = SOUP_AUTH (object); + SoupAuthPrivate *priv = soup_auth_get_instance_private (auth); + + switch (prop_id) { + case PROP_REALM: + g_free (auth->realm); + auth->realm = g_value_dup_string (value); + break; + case PROP_HOST: + g_free (priv->host); + priv->host = g_value_dup_string (value); + break; + case PROP_IS_FOR_PROXY: + priv->proxy = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +soup_auth_get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + SoupAuth *auth = SOUP_AUTH (object); + SoupAuthPrivate *priv = soup_auth_get_instance_private (auth); + + switch (prop_id) { + case PROP_SCHEME_NAME: + g_value_set_string (value, soup_auth_get_scheme_name (auth)); + break; + case PROP_REALM: + g_value_set_string (value, soup_auth_get_realm (auth)); + break; + case PROP_HOST: + g_value_set_string (value, soup_auth_get_host (auth)); + break; + case PROP_IS_FOR_PROXY: + g_value_set_boolean (value, priv->proxy); + break; + case PROP_IS_AUTHENTICATED: + g_value_set_boolean (value, soup_auth_is_authenticated (auth)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static gboolean +auth_can_authenticate (SoupAuth *auth) +{ + return TRUE; +} + +static void +soup_auth_class_init (SoupAuthClass *auth_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (auth_class); + + auth_class->can_authenticate = auth_can_authenticate; + + object_class->finalize = soup_auth_finalize; + object_class->set_property = soup_auth_set_property; + object_class->get_property = soup_auth_get_property; + + /* properties */ + /** + * SOUP_AUTH_SCHEME_NAME: + * + * An alias for the #SoupAuth:scheme-name property. (The + * authentication scheme name.) + **/ + g_object_class_install_property ( + object_class, PROP_SCHEME_NAME, + g_param_spec_string (SOUP_AUTH_SCHEME_NAME, + "Scheme name", + "Authentication scheme name", + NULL, + G_PARAM_READABLE)); + /** + * SOUP_AUTH_REALM: + * + * An alias for the #SoupAuth:realm property. (The + * authentication realm.) + **/ + g_object_class_install_property ( + object_class, PROP_REALM, + g_param_spec_string (SOUP_AUTH_REALM, + "Realm", + "Authentication realm", + NULL, + G_PARAM_READWRITE)); + /** + * SOUP_AUTH_HOST: + * + * An alias for the #SoupAuth:host property. (The + * host being authenticated to.) + **/ + g_object_class_install_property ( + object_class, PROP_HOST, + g_param_spec_string (SOUP_AUTH_HOST, + "Host", + "Authentication host", + NULL, + G_PARAM_READWRITE)); + /** + * SOUP_AUTH_IS_FOR_PROXY: + * + * An alias for the #SoupAuth:is-for-proxy property. (Whether + * or not the auth is for a proxy server.) + **/ + g_object_class_install_property ( + object_class, PROP_IS_FOR_PROXY, + g_param_spec_boolean (SOUP_AUTH_IS_FOR_PROXY, + "For Proxy", + "Whether or not the auth is for a proxy server", + FALSE, + G_PARAM_READWRITE)); + /** + * SOUP_AUTH_IS_AUTHENTICATED: + * + * An alias for the #SoupAuth:is-authenticated property. + * (Whether or not the auth has been authenticated.) + **/ + g_object_class_install_property ( + object_class, PROP_IS_AUTHENTICATED, + g_param_spec_boolean (SOUP_AUTH_IS_AUTHENTICATED, + "Authenticated", + "Whether or not the auth is authenticated", + FALSE, + G_PARAM_READABLE)); +} + +/** + * soup_auth_new: + * @type: the type of auth to create (a subtype of #SoupAuth) + * @msg: the #SoupMessage the auth is being created for + * @auth_header: the WWW-Authenticate/Proxy-Authenticate header + * + * Creates a new #SoupAuth of type @type with the information from + * @msg and @auth_header. + * + * This is called by #SoupSession; you will normally not create auths + * yourself. + * + * Return value: (nullable): the new #SoupAuth, or %NULL if it could + * not be created + **/ +SoupAuth * +soup_auth_new (GType type, SoupMessage *msg, const char *auth_header) +{ + SoupAuth *auth; + GHashTable *params; + const char *scheme, *realm; + + g_return_val_if_fail (g_type_is_a (type, SOUP_TYPE_AUTH), NULL); + g_return_val_if_fail (SOUP_IS_MESSAGE (msg), NULL); + g_return_val_if_fail (auth_header != NULL, NULL); + + auth = g_object_new (type, + SOUP_AUTH_IS_FOR_PROXY, (msg->status_code == SOUP_STATUS_PROXY_UNAUTHORIZED), + SOUP_AUTH_HOST, soup_message_get_uri (msg)->host, + NULL); + + scheme = soup_auth_get_scheme_name (auth); + if (g_ascii_strncasecmp (auth_header, scheme, strlen (scheme)) != 0) { + g_object_unref (auth); + return NULL; + } + + params = soup_header_parse_param_list (auth_header + strlen (scheme)); + if (!params) + params = g_hash_table_new (NULL, NULL); + + realm = g_hash_table_lookup (params, "realm"); + if (realm) + auth->realm = g_strdup (realm); + + if (!SOUP_AUTH_GET_CLASS (auth)->update (auth, msg, params)) { + g_object_unref (auth); + auth = NULL; + } + soup_header_free_param_list (params); + return auth; +} + +/** + * soup_auth_update: + * @auth: a #SoupAuth + * @msg: the #SoupMessage @auth is being updated for + * @auth_header: the WWW-Authenticate/Proxy-Authenticate header + * + * Updates @auth with the information from @msg and @auth_header, + * possibly un-authenticating it. As with soup_auth_new(), this is + * normally only used by #SoupSession. + * + * Return value: %TRUE if @auth is still a valid (but potentially + * unauthenticated) #SoupAuth. %FALSE if something about @auth_params + * could not be parsed or incorporated into @auth at all. + **/ +gboolean +soup_auth_update (SoupAuth *auth, SoupMessage *msg, const char *auth_header) +{ + GHashTable *params; + const char *scheme, *realm; + gboolean was_authenticated, success; + + g_return_val_if_fail (SOUP_IS_AUTH (auth), FALSE); + g_return_val_if_fail (SOUP_IS_MESSAGE (msg), FALSE); + g_return_val_if_fail (auth_header != NULL, FALSE); + + scheme = soup_auth_get_scheme_name (auth); + if (g_ascii_strncasecmp (auth_header, scheme, strlen (scheme)) != 0) + return FALSE; + + params = soup_header_parse_param_list (auth_header + strlen (scheme)); + if (!params) + params = g_hash_table_new (NULL, NULL); + + realm = g_hash_table_lookup (params, "realm"); + if (realm && auth->realm && strcmp (realm, auth->realm) != 0) { + soup_header_free_param_list (params); + return FALSE; + } + + was_authenticated = soup_auth_is_authenticated (auth); + success = SOUP_AUTH_GET_CLASS (auth)->update (auth, msg, params); + if (was_authenticated != soup_auth_is_authenticated (auth)) + g_object_notify (G_OBJECT (auth), SOUP_AUTH_IS_AUTHENTICATED); + soup_header_free_param_list (params); + return success; +} + +/** + * soup_auth_authenticate: + * @auth: a #SoupAuth + * @username: the username provided by the user or client + * @password: the password provided by the user or client + * + * Call this on an auth to authenticate it; normally this will cause + * the auth's message to be requeued with the new authentication info. + **/ +void +soup_auth_authenticate (SoupAuth *auth, const char *username, const char *password) +{ + gboolean was_authenticated; + + g_return_if_fail (SOUP_IS_AUTH (auth)); + g_return_if_fail (username != NULL); + g_return_if_fail (password != NULL); + + was_authenticated = soup_auth_is_authenticated (auth); + SOUP_AUTH_GET_CLASS (auth)->authenticate (auth, username, password); + if (was_authenticated != soup_auth_is_authenticated (auth)) + g_object_notify (G_OBJECT (auth), SOUP_AUTH_IS_AUTHENTICATED); +} + +/** + * soup_auth_is_for_proxy: + * @auth: a #SoupAuth + * + * Tests whether or not @auth is associated with a proxy server rather + * than an "origin" server. + * + * Return value: %TRUE or %FALSE + **/ +gboolean +soup_auth_is_for_proxy (SoupAuth *auth) +{ + SoupAuthPrivate *priv = soup_auth_get_instance_private (auth); + + g_return_val_if_fail (SOUP_IS_AUTH (auth), FALSE); + + return priv->proxy; +} + +/** + * soup_auth_get_scheme_name: + * @auth: a #SoupAuth + * + * Returns @auth's scheme name. (Eg, "Basic", "Digest", or "NTLM") + * + * Return value: the scheme name + **/ +const char * +soup_auth_get_scheme_name (SoupAuth *auth) +{ + g_return_val_if_fail (SOUP_IS_AUTH (auth), NULL); + + return SOUP_AUTH_GET_CLASS (auth)->scheme_name; +} + +/** + * soup_auth_get_host: + * @auth: a #SoupAuth + * + * Returns the host that @auth is associated with. + * + * Return value: the hostname + **/ +const char * +soup_auth_get_host (SoupAuth *auth) +{ + SoupAuthPrivate *priv = soup_auth_get_instance_private (auth); + + g_return_val_if_fail (SOUP_IS_AUTH (auth), NULL); + + return priv->host; +} + +/** + * soup_auth_get_realm: + * @auth: a #SoupAuth + * + * Returns @auth's realm. This is an identifier that distinguishes + * separate authentication spaces on a given server, and may be some + * string that is meaningful to the user. (Although it is probably not + * localized.) + * + * Return value: the realm name + **/ +const char * +soup_auth_get_realm (SoupAuth *auth) +{ + g_return_val_if_fail (SOUP_IS_AUTH (auth), NULL); + + return auth->realm; +} + +/** + * soup_auth_get_info: + * @auth: a #SoupAuth + * + * Gets an opaque identifier for @auth, for use as a hash key or the + * like. #SoupAuth objects from the same server with the same + * identifier refer to the same authentication domain (eg, the URLs + * associated with them take the same usernames and passwords). + * + * Return value: the identifier + **/ +char * +soup_auth_get_info (SoupAuth *auth) +{ + g_return_val_if_fail (SOUP_IS_AUTH (auth), NULL); + + if (SOUP_IS_CONNECTION_AUTH (auth)) + return g_strdup (SOUP_AUTH_GET_CLASS (auth)->scheme_name); + else { + return g_strdup_printf ("%s:%s", + SOUP_AUTH_GET_CLASS (auth)->scheme_name, + auth->realm); + } +} + +/** + * soup_auth_is_authenticated: + * @auth: a #SoupAuth + * + * Tests if @auth has been given a username and password + * + * Return value: %TRUE if @auth has been given a username and password + **/ +gboolean +soup_auth_is_authenticated (SoupAuth *auth) +{ + g_return_val_if_fail (SOUP_IS_AUTH (auth), TRUE); + + return SOUP_AUTH_GET_CLASS (auth)->is_authenticated (auth); +} + +/** + * soup_auth_get_authorization: + * @auth: a #SoupAuth + * @msg: the #SoupMessage to be authorized + * + * Generates an appropriate "Authorization" header for @msg. (The + * session will only call this if soup_auth_is_authenticated() + * returned %TRUE.) + * + * Return value: the "Authorization" header, which must be freed. + **/ +char * +soup_auth_get_authorization (SoupAuth *auth, SoupMessage *msg) +{ + g_return_val_if_fail (SOUP_IS_AUTH (auth), NULL); + g_return_val_if_fail (msg != NULL, NULL); + + return SOUP_AUTH_GET_CLASS (auth)->get_authorization (auth, msg); +} + +/** + * soup_auth_is_ready: + * @auth: a #SoupAuth + * @msg: a #SoupMessage + * + * Tests if @auth is ready to make a request for @msg with. For most + * auths, this is equivalent to soup_auth_is_authenticated(), but for + * some auth types (eg, NTLM), the auth may be sendable (eg, as an + * authentication request) even before it is authenticated. + * + * Return value: %TRUE if @auth is ready to make a request with. + * + * Since: 2.42 + **/ +gboolean +soup_auth_is_ready (SoupAuth *auth, + SoupMessage *msg) +{ + g_return_val_if_fail (SOUP_IS_AUTH (auth), TRUE); + g_return_val_if_fail (SOUP_IS_MESSAGE (msg), TRUE); + + if (SOUP_AUTH_GET_CLASS (auth)->is_ready) + return SOUP_AUTH_GET_CLASS (auth)->is_ready (auth, msg); + else + return SOUP_AUTH_GET_CLASS (auth)->is_authenticated (auth); +} + +/** + * soup_auth_can_authenticate: + * @auth: a #SoupAuth + * + * Tests if @auth is able to authenticate by providing credentials to the + * soup_auth_authenticate(). + * + * Return value: %TRUE if @auth is able to accept credentials. + * + * Since: 2.54 + **/ +gboolean +soup_auth_can_authenticate (SoupAuth *auth) +{ + g_return_val_if_fail (SOUP_IS_AUTH (auth), FALSE); + + return SOUP_AUTH_GET_CLASS (auth)->can_authenticate (auth); +} + +/** + * soup_auth_get_protection_space: + * @auth: a #SoupAuth + * @source_uri: the URI of the request that @auth was generated in + * response to. + * + * Returns a list of paths on the server which @auth extends over. + * (All subdirectories of these paths are also assumed to be part + * of @auth's protection space, unless otherwise discovered not to + * be.) + * + * Return value: (element-type utf8) (transfer full): the list of + * paths, which can be freed with soup_auth_free_protection_space(). + **/ +GSList * +soup_auth_get_protection_space (SoupAuth *auth, SoupURI *source_uri) +{ + g_return_val_if_fail (SOUP_IS_AUTH (auth), NULL); + g_return_val_if_fail (source_uri != NULL, NULL); + + return SOUP_AUTH_GET_CLASS (auth)->get_protection_space (auth, source_uri); +} + +/** + * soup_auth_free_protection_space: (skip) + * @auth: a #SoupAuth + * @space: the return value from soup_auth_get_protection_space() + * + * Frees @space. + **/ +void +soup_auth_free_protection_space (SoupAuth *auth, GSList *space) +{ + g_slist_free_full (space, g_free); +} + +/** + * soup_auth_get_saved_users: + * + * Return value: (transfer full) (element-type utf8): + */ +GSList * +soup_auth_get_saved_users (SoupAuth *auth) +{ + return NULL; +} + +const char * +soup_auth_get_saved_password (SoupAuth *auth, const char *user) +{ + return NULL; +} + +void +soup_auth_has_saved_password (SoupAuth *auth, const char *username, + const char *password) +{ +} + +void +soup_auth_save_password (SoupAuth *auth, const char *username, + const char *password) +{ +} diff --git a/libsoup/soup-auth.h b/libsoup/soup-auth.h new file mode 100644 index 0000000..0defcc6 --- /dev/null +++ b/libsoup/soup-auth.h @@ -0,0 +1,149 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2001-2003, Ximian, Inc. + */ + +#ifndef SOUP_AUTH_H +#define SOUP_AUTH_H 1 + +#include +#include + +G_BEGIN_DECLS + +#define SOUP_TYPE_AUTH (soup_auth_get_type ()) +#define SOUP_AUTH(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SOUP_TYPE_AUTH, SoupAuth)) +#define SOUP_AUTH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_AUTH, SoupAuthClass)) +#define SOUP_IS_AUTH(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SOUP_TYPE_AUTH)) +#define SOUP_IS_AUTH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), SOUP_TYPE_AUTH)) +#define SOUP_AUTH_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_AUTH, SoupAuthClass)) + +struct _SoupAuth { + GObject parent; + + char *realm; +}; + +typedef struct { + GObjectClass parent_class; + + const char *scheme_name; + guint strength; + + gboolean (*update) (SoupAuth *auth, + SoupMessage *msg, + GHashTable *auth_header); + + GSList * (*get_protection_space) (SoupAuth *auth, + SoupURI *source_uri); + + void (*authenticate) (SoupAuth *auth, + const char *username, + const char *password); + gboolean (*is_authenticated) (SoupAuth *auth); + + char * (*get_authorization) (SoupAuth *auth, + SoupMessage *msg); + + gboolean (*is_ready) (SoupAuth *auth, + SoupMessage *msg); + + gboolean (*can_authenticate) (SoupAuth *auth); + + /* Padding for future expansion */ + void (*_libsoup_reserved3) (void); + void (*_libsoup_reserved4) (void); +} SoupAuthClass; + +#define SOUP_AUTH_SCHEME_NAME "scheme-name" +#define SOUP_AUTH_REALM "realm" +#define SOUP_AUTH_HOST "host" +#define SOUP_AUTH_IS_FOR_PROXY "is-for-proxy" +#define SOUP_AUTH_IS_AUTHENTICATED "is-authenticated" + +SOUP_AVAILABLE_IN_2_4 +GType soup_auth_get_type (void); + +SOUP_AVAILABLE_IN_2_4 +SoupAuth *soup_auth_new (GType type, + SoupMessage *msg, + const char *auth_header); +SOUP_AVAILABLE_IN_2_4 +gboolean soup_auth_update (SoupAuth *auth, + SoupMessage *msg, + const char *auth_header); + +SOUP_AVAILABLE_IN_2_4 +gboolean soup_auth_is_for_proxy (SoupAuth *auth); +SOUP_AVAILABLE_IN_2_4 +const char *soup_auth_get_scheme_name (SoupAuth *auth); +SOUP_AVAILABLE_IN_2_4 +const char *soup_auth_get_host (SoupAuth *auth); +SOUP_AVAILABLE_IN_2_4 +const char *soup_auth_get_realm (SoupAuth *auth); +SOUP_AVAILABLE_IN_2_4 +char *soup_auth_get_info (SoupAuth *auth); + +SOUP_AVAILABLE_IN_2_4 +void soup_auth_authenticate (SoupAuth *auth, + const char *username, + const char *password); +SOUP_AVAILABLE_IN_2_4 +gboolean soup_auth_is_authenticated (SoupAuth *auth); +SOUP_AVAILABLE_IN_2_42 +gboolean soup_auth_is_ready (SoupAuth *auth, + SoupMessage *msg); +SOUP_AVAILABLE_IN_2_54 +gboolean soup_auth_can_authenticate (SoupAuth *auth); + +SOUP_AVAILABLE_IN_2_4 +char *soup_auth_get_authorization (SoupAuth *auth, + SoupMessage *msg); + +SOUP_AVAILABLE_IN_2_4 +GSList *soup_auth_get_protection_space (SoupAuth *auth, + SoupURI *source_uri); +SOUP_AVAILABLE_IN_2_4 +void soup_auth_free_protection_space (SoupAuth *auth, + GSList *space); + +/* The actual auth types, which can be added/removed as features */ + +#define SOUP_TYPE_AUTH_BASIC (soup_auth_basic_get_type ()) +SOUP_AVAILABLE_IN_2_4 +GType soup_auth_basic_get_type (void); +#define SOUP_TYPE_AUTH_DIGEST (soup_auth_digest_get_type ()) +SOUP_AVAILABLE_IN_2_4 +GType soup_auth_digest_get_type (void); +#define SOUP_TYPE_AUTH_NTLM (soup_auth_ntlm_get_type ()) +SOUP_AVAILABLE_IN_2_4 +GType soup_auth_ntlm_get_type (void); +#define SOUP_TYPE_AUTH_NEGOTIATE (soup_auth_negotiate_get_type ()) +SOUP_AVAILABLE_IN_2_54 +GType soup_auth_negotiate_get_type (void); + +/* Deprecated SoupPasswordManager-related APIs: all are now no-ops */ +SOUP_AVAILABLE_IN_2_28 +SOUP_DEPRECATED_IN_2_28 +GSList *soup_auth_get_saved_users (SoupAuth *auth); +SOUP_AVAILABLE_IN_2_28 +SOUP_DEPRECATED_IN_2_28 +const char *soup_auth_get_saved_password (SoupAuth *auth, + const char *user); +SOUP_AVAILABLE_IN_2_28 +SOUP_DEPRECATED_IN_2_28 +void soup_auth_save_password (SoupAuth *auth, + const char *username, + const char *password); +SOUP_AVAILABLE_IN_2_28 +SOUP_DEPRECATED_IN_2_28 +void soup_auth_has_saved_password (SoupAuth *auth, + const char *username, + const char *password); + +SOUP_AVAILABLE_IN_2_54 +gboolean soup_auth_negotiate_supported (void); + +G_END_DECLS + +#endif /* SOUP_AUTH_H */ diff --git a/libsoup/soup-autocleanups.h b/libsoup/soup-autocleanups.h new file mode 100644 index 0000000..910abe7 --- /dev/null +++ b/libsoup/soup-autocleanups.h @@ -0,0 +1,68 @@ +/* + * Copyright 2015 Red Hat, Inc. + * + * 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 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, see . + */ + +#if !defined (__SOUP_H_INSIDE__) && !defined (LIBSOUP_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef SOUP_AUTOCLEANUPS_H +#define SOUP_AUTOCLEANUPS_H + +#if SOUP_VERSION_MAX_ALLOWED >= SOUP_VERSION_2_52 +#ifndef __GI_SCANNER__ +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC + +G_DEFINE_AUTOPTR_CLEANUP_FUNC(SoupAddress, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC(SoupAuth, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC(SoupAuthDomain, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC(SoupAuthDomainBasic, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC(SoupAuthDomainDigest, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC(SoupAuthManager, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC(SoupBuffer, soup_buffer_free) +G_DEFINE_AUTOPTR_CLEANUP_FUNC(SoupCache, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC(SoupContentDecoder, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC(SoupContentSniffer, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC(SoupCookie, soup_cookie_free) +G_DEFINE_AUTOPTR_CLEANUP_FUNC(SoupCookieJar, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC(SoupCookieJarDB, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC(SoupCookieJarText, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC(SoupDate, soup_date_free) +G_DEFINE_AUTOPTR_CLEANUP_FUNC(SoupLogger, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC(SoupMessage, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC(SoupMessageBody, soup_message_body_free) +G_DEFINE_AUTOPTR_CLEANUP_FUNC(SoupMessageHeaders, soup_message_headers_free) +G_DEFINE_AUTOPTR_CLEANUP_FUNC(SoupMultipart, soup_multipart_free) +G_DEFINE_AUTOPTR_CLEANUP_FUNC(SoupMultipartInputStream, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC(SoupRequest, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC(SoupRequestData, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC(SoupRequestFile, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC(SoupRequestHTTP, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC(SoupServer, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC(SoupSession, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC(SoupSessionAsync, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC(SoupSessionFeature, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC(SoupSessionSync, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC(SoupSocket, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC(SoupURI, soup_uri_free) +G_DEFINE_AUTOPTR_CLEANUP_FUNC(SoupWebsocketConnection, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC(SoupXMLRPCParams, soup_xmlrpc_params_free) + +#endif +#endif +#endif + +#endif /* SOUP_AUTOCLEANUPS_H */ diff --git a/libsoup/soup-body-input-stream.c b/libsoup/soup-body-input-stream.c new file mode 100644 index 0000000..32ad074 --- /dev/null +++ b/libsoup/soup-body-input-stream.c @@ -0,0 +1,515 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-body-input-stream.c + * + * Copyright 2012 Red Hat, Inc. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include + +#include "soup-body-input-stream.h" +#include "soup.h" +#include "soup-filter-input-stream.h" + +typedef enum { + SOUP_BODY_INPUT_STREAM_STATE_CHUNK_SIZE, + SOUP_BODY_INPUT_STREAM_STATE_CHUNK_END, + SOUP_BODY_INPUT_STREAM_STATE_CHUNK, + SOUP_BODY_INPUT_STREAM_STATE_TRAILERS, + SOUP_BODY_INPUT_STREAM_STATE_DONE +} SoupBodyInputStreamState; + +struct _SoupBodyInputStreamPrivate { + GInputStream *base_stream; + + SoupEncoding encoding; + goffset read_length; + SoupBodyInputStreamState chunked_state; + gboolean eof; + + goffset pos; +}; + +enum { + CLOSED, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +enum { + PROP_0, + + PROP_ENCODING, + PROP_CONTENT_LENGTH +}; + +static void soup_body_input_stream_pollable_init (GPollableInputStreamInterface *pollable_interface, gpointer interface_data); +static void soup_body_input_stream_seekable_init (GSeekableIface *seekable_interface); + +G_DEFINE_TYPE_WITH_CODE (SoupBodyInputStream, soup_body_input_stream, G_TYPE_FILTER_INPUT_STREAM, + G_ADD_PRIVATE (SoupBodyInputStream) + G_IMPLEMENT_INTERFACE (G_TYPE_POLLABLE_INPUT_STREAM, + soup_body_input_stream_pollable_init) + G_IMPLEMENT_INTERFACE (G_TYPE_SEEKABLE, + soup_body_input_stream_seekable_init)) + +static void +soup_body_input_stream_init (SoupBodyInputStream *bistream) +{ + bistream->priv = soup_body_input_stream_get_instance_private (bistream); + bistream->priv->encoding = SOUP_ENCODING_NONE; +} + +static void +soup_body_input_stream_constructed (GObject *object) +{ + SoupBodyInputStream *bistream = SOUP_BODY_INPUT_STREAM (object); + + bistream->priv->base_stream = g_filter_input_stream_get_base_stream (G_FILTER_INPUT_STREAM (bistream)); + + if (bistream->priv->encoding == SOUP_ENCODING_NONE || + (bistream->priv->encoding == SOUP_ENCODING_CONTENT_LENGTH && + bistream->priv->read_length == 0)) + bistream->priv->eof = TRUE; +} + +static void +soup_body_input_stream_set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + SoupBodyInputStream *bistream = SOUP_BODY_INPUT_STREAM (object); + + switch (prop_id) { + case PROP_ENCODING: + bistream->priv->encoding = g_value_get_enum (value); + if (bistream->priv->encoding == SOUP_ENCODING_CHUNKED) + bistream->priv->chunked_state = SOUP_BODY_INPUT_STREAM_STATE_CHUNK_SIZE; + break; + case PROP_CONTENT_LENGTH: + bistream->priv->read_length = g_value_get_int64 (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +soup_body_input_stream_get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + SoupBodyInputStream *bistream = SOUP_BODY_INPUT_STREAM (object); + + switch (prop_id) { + case PROP_ENCODING: + g_value_set_enum (value, bistream->priv->encoding); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static gssize +soup_body_input_stream_read_raw (SoupBodyInputStream *bistream, + void *buffer, + gsize count, + gboolean blocking, + GCancellable *cancellable, + GError **error) +{ + gssize nread; + + nread = g_pollable_stream_read (bistream->priv->base_stream, + buffer, count, + blocking, + cancellable, error); + if (nread == 0) { + bistream->priv->eof = TRUE; + if (bistream->priv->encoding != SOUP_ENCODING_EOF) { + g_set_error_literal (error, G_IO_ERROR, + G_IO_ERROR_PARTIAL_INPUT, + _("Connection terminated unexpectedly")); + return -1; + } + } + return nread; +} + +static gssize +soup_body_input_stream_read_chunked (SoupBodyInputStream *bistream, + void *buffer, + gsize count, + gboolean blocking, + GCancellable *cancellable, + GError **error) +{ + SoupFilterInputStream *fstream = SOUP_FILTER_INPUT_STREAM (bistream->priv->base_stream); + char metabuf[128]; + gssize nread; + gboolean got_line; + +again: + switch (bistream->priv->chunked_state) { + case SOUP_BODY_INPUT_STREAM_STATE_CHUNK_SIZE: + nread = soup_filter_input_stream_read_line ( + fstream, metabuf, sizeof (metabuf), blocking, + &got_line, cancellable, error); + if (nread <= 0) + return nread; + if (!got_line) { + g_set_error_literal (error, G_IO_ERROR, + G_IO_ERROR_PARTIAL_INPUT, + _("Connection terminated unexpectedly")); + return -1; + } + + bistream->priv->read_length = strtoul (metabuf, NULL, 16); + if (bistream->priv->read_length > 0) + bistream->priv->chunked_state = SOUP_BODY_INPUT_STREAM_STATE_CHUNK; + else + bistream->priv->chunked_state = SOUP_BODY_INPUT_STREAM_STATE_TRAILERS; + break; + + case SOUP_BODY_INPUT_STREAM_STATE_CHUNK: + nread = soup_body_input_stream_read_raw ( + bistream, buffer, + MIN (count, bistream->priv->read_length), + blocking, cancellable, error); + if (nread > 0) { + bistream->priv->read_length -= nread; + if (bistream->priv->read_length == 0) + bistream->priv->chunked_state = SOUP_BODY_INPUT_STREAM_STATE_CHUNK_END; + } + return nread; + + case SOUP_BODY_INPUT_STREAM_STATE_CHUNK_END: + nread = soup_filter_input_stream_read_line ( + SOUP_FILTER_INPUT_STREAM (bistream->priv->base_stream), + metabuf, sizeof (metabuf), blocking, + &got_line, cancellable, error); + if (nread <= 0) + return nread; + if (!got_line) { + g_set_error_literal (error, G_IO_ERROR, + G_IO_ERROR_PARTIAL_INPUT, + _("Connection terminated unexpectedly")); + return -1; + } + + bistream->priv->chunked_state = SOUP_BODY_INPUT_STREAM_STATE_CHUNK_SIZE; + break; + + case SOUP_BODY_INPUT_STREAM_STATE_TRAILERS: + nread = soup_filter_input_stream_read_line ( + fstream, buffer, count, blocking, + &got_line, cancellable, error); + if (nread <= 0) + return nread; + + if (strncmp (buffer, "\r\n", nread) || strncmp (buffer, "\n", nread)) { + bistream->priv->chunked_state = SOUP_BODY_INPUT_STREAM_STATE_DONE; + bistream->priv->eof = TRUE; + } + break; + + case SOUP_BODY_INPUT_STREAM_STATE_DONE: + return 0; + } + + goto again; +} + +static gssize +read_internal (GInputStream *stream, + void *buffer, + gsize count, + gboolean blocking, + GCancellable *cancellable, + GError **error) +{ + SoupBodyInputStream *bistream = SOUP_BODY_INPUT_STREAM (stream); + gssize nread; + + if (bistream->priv->eof) + return 0; + + switch (bistream->priv->encoding) { + case SOUP_ENCODING_NONE: + return 0; + + case SOUP_ENCODING_CHUNKED: + return soup_body_input_stream_read_chunked (bistream, buffer, count, + blocking, cancellable, error); + + case SOUP_ENCODING_CONTENT_LENGTH: + case SOUP_ENCODING_EOF: + if (bistream->priv->read_length != -1) { + count = MIN (count, bistream->priv->read_length); + if (count == 0) + return 0; + } + + nread = soup_body_input_stream_read_raw (bistream, buffer, count, + blocking, cancellable, error); + if (bistream->priv->read_length != -1 && nread > 0) + bistream->priv->read_length -= nread; + + if (bistream->priv->encoding == SOUP_ENCODING_CONTENT_LENGTH) + bistream->priv->pos += nread; + return nread; + + default: + g_return_val_if_reached (-1); + } +} + +static gssize +soup_body_input_stream_skip (GInputStream *stream, + gsize count, + GCancellable *cancellable, + GError **error) +{ + SoupBodyInputStreamPrivate *priv = SOUP_BODY_INPUT_STREAM(stream)->priv; + gssize skipped; + + skipped = g_input_stream_skip (G_FILTER_INPUT_STREAM (stream)->base_stream, + MIN (count, priv->read_length), + cancellable, error); + + if (skipped == 0) + priv->eof = TRUE; + else if (skipped > 0) + priv->pos += skipped; + + return skipped; +} + +static gssize +soup_body_input_stream_read_fn (GInputStream *stream, + void *buffer, + gsize count, + GCancellable *cancellable, + GError **error) +{ + return read_internal (stream, buffer, count, TRUE, + cancellable, error); +} + +static gboolean +soup_body_input_stream_close_fn (GInputStream *stream, + GCancellable *cancellable, + GError **error) +{ + g_signal_emit (stream, signals[CLOSED], 0); + + return G_INPUT_STREAM_CLASS (soup_body_input_stream_parent_class)->close_fn (stream, cancellable, error); +} + +static gboolean +soup_body_input_stream_is_readable (GPollableInputStream *stream) +{ + SoupBodyInputStream *bistream = SOUP_BODY_INPUT_STREAM (stream); + + return bistream->priv->eof || + g_pollable_input_stream_is_readable (G_POLLABLE_INPUT_STREAM (bistream->priv->base_stream)); +} + +static gboolean +soup_body_input_stream_can_poll (GPollableInputStream *pollable) +{ + GInputStream *base_stream = SOUP_BODY_INPUT_STREAM (pollable)->priv->base_stream; + + return G_IS_POLLABLE_INPUT_STREAM (base_stream) && + g_pollable_input_stream_can_poll (G_POLLABLE_INPUT_STREAM (base_stream)); +} + +static gssize +soup_body_input_stream_read_nonblocking (GPollableInputStream *stream, + void *buffer, + gsize count, + GError **error) +{ + return read_internal (G_INPUT_STREAM (stream), buffer, count, FALSE, + NULL, error); +} + +static GSource * +soup_body_input_stream_create_source (GPollableInputStream *stream, + GCancellable *cancellable) +{ + SoupBodyInputStream *bistream = SOUP_BODY_INPUT_STREAM (stream); + GSource *base_source, *pollable_source; + + if (bistream->priv->eof) + base_source = g_timeout_source_new (0); + else + base_source = g_pollable_input_stream_create_source (G_POLLABLE_INPUT_STREAM (bistream->priv->base_stream), cancellable); + g_source_set_dummy_callback (base_source); + + pollable_source = g_pollable_source_new (G_OBJECT (stream)); + g_source_add_child_source (pollable_source, base_source); + g_source_unref (base_source); + + return pollable_source; +} + +static void +soup_body_input_stream_class_init (SoupBodyInputStreamClass *stream_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (stream_class); + GInputStreamClass *input_stream_class = G_INPUT_STREAM_CLASS (stream_class); + + object_class->constructed = soup_body_input_stream_constructed; + object_class->set_property = soup_body_input_stream_set_property; + object_class->get_property = soup_body_input_stream_get_property; + + input_stream_class->skip = soup_body_input_stream_skip; + input_stream_class->read_fn = soup_body_input_stream_read_fn; + input_stream_class->close_fn = soup_body_input_stream_close_fn; + + signals[CLOSED] = + g_signal_new ("closed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + NULL, + G_TYPE_NONE, 0); + + g_object_class_install_property ( + object_class, PROP_ENCODING, + g_param_spec_enum ("encoding", + "Encoding", + "Message body encoding", + SOUP_TYPE_ENCODING, + SOUP_ENCODING_NONE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + g_object_class_install_property ( + object_class, PROP_CONTENT_LENGTH, + g_param_spec_int64 ("content-length", + "Content-Length", + "Message body Content-Length", + -1, G_MAXINT64, -1, + G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); +} + +static void +soup_body_input_stream_pollable_init (GPollableInputStreamInterface *pollable_interface, + gpointer interface_data) +{ + pollable_interface->can_poll = soup_body_input_stream_can_poll; + pollable_interface->is_readable = soup_body_input_stream_is_readable; + pollable_interface->read_nonblocking = soup_body_input_stream_read_nonblocking; + pollable_interface->create_source = soup_body_input_stream_create_source; +} + +static goffset +soup_body_input_stream_tell (GSeekable *seekable) +{ + return SOUP_BODY_INPUT_STREAM (seekable)->priv->pos; +} + +static gboolean +soup_body_input_stream_can_seek (GSeekable *seekable) +{ + SoupBodyInputStreamPrivate *priv = SOUP_BODY_INPUT_STREAM (seekable)->priv; + + return priv->encoding == SOUP_ENCODING_CONTENT_LENGTH + && G_IS_SEEKABLE (priv->base_stream) + && g_seekable_can_seek (G_SEEKABLE (priv->base_stream)); +} + +static gboolean +soup_body_input_stream_seek (GSeekable *seekable, + goffset offset, + GSeekType type, + GCancellable *cancellable, + GError **error) +{ + SoupBodyInputStreamPrivate *priv = SOUP_BODY_INPUT_STREAM (seekable)->priv; + goffset position, end_position; + + end_position = priv->pos + priv->read_length; + switch (type) { + case G_SEEK_CUR: + position = priv->pos + offset; + break; + case G_SEEK_SET: + position = offset; + break; + case G_SEEK_END: + position = end_position + offset; + break; + default: + g_return_val_if_reached (FALSE); + } + + if (position < 0 || position >= end_position) { + g_set_error_literal (error, + G_IO_ERROR, + G_IO_ERROR_INVALID_ARGUMENT, + _("Invalid seek request")); + return FALSE; + } + + if (!g_seekable_seek (G_SEEKABLE (priv->base_stream), position - priv->pos, + G_SEEK_CUR, cancellable, error)) + return FALSE; + + priv->pos = position; + + return TRUE; +} + +static gboolean +soup_body_input_stream_can_truncate (GSeekable *seekable) +{ + return FALSE; +} + +static gboolean +soup_body_input_stream_truncate_fn (GSeekable *seekable, + goffset offset, + GCancellable *cancellable, + GError **error) +{ + g_set_error_literal (error, + G_IO_ERROR, + G_IO_ERROR_NOT_SUPPORTED, + _("Cannot truncate SoupBodyInputStream")); + return FALSE; +} + +static void +soup_body_input_stream_seekable_init (GSeekableIface *seekable_interface) +{ + seekable_interface->tell = soup_body_input_stream_tell; + seekable_interface->can_seek = soup_body_input_stream_can_seek; + seekable_interface->seek = soup_body_input_stream_seek; + seekable_interface->can_truncate = soup_body_input_stream_can_truncate; + seekable_interface->truncate_fn = soup_body_input_stream_truncate_fn; +} + +GInputStream * +soup_body_input_stream_new (GInputStream *base_stream, + SoupEncoding encoding, + goffset content_length) +{ + if (encoding == SOUP_ENCODING_CHUNKED) + g_return_val_if_fail (SOUP_IS_FILTER_INPUT_STREAM (base_stream), NULL); + + return g_object_new (SOUP_TYPE_BODY_INPUT_STREAM, + "base-stream", base_stream, + "close-base-stream", FALSE, + "encoding", encoding, + "content-length", content_length, + NULL); +} diff --git a/libsoup/soup-body-input-stream.h b/libsoup/soup-body-input-stream.h new file mode 100644 index 0000000..7732e5e --- /dev/null +++ b/libsoup/soup-body-input-stream.h @@ -0,0 +1,48 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright 2012 Red Hat, Inc. + */ + +#ifndef SOUP_BODY_INPUT_STREAM_H +#define SOUP_BODY_INPUT_STREAM_H 1 + +#include "soup-types.h" +#include "soup-filter-input-stream.h" +#include "soup-message-headers.h" + +G_BEGIN_DECLS + +#define SOUP_TYPE_BODY_INPUT_STREAM (soup_body_input_stream_get_type ()) +#define SOUP_BODY_INPUT_STREAM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SOUP_TYPE_BODY_INPUT_STREAM, SoupBodyInputStream)) +#define SOUP_BODY_INPUT_STREAM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_BODY_INPUT_STREAM, SoupBodyInputStreamClass)) +#define SOUP_IS_BODY_INPUT_STREAM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SOUP_TYPE_BODY_INPUT_STREAM)) +#define SOUP_IS_BODY_INPUT_STREAM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), SOUP_TYPE_BODY_INPUT_STREAM)) +#define SOUP_BODY_INPUT_STREAM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_BODY_INPUT_STREAM, SoupBodyInputStreamClass)) + +typedef struct _SoupBodyInputStreamPrivate SoupBodyInputStreamPrivate; + +typedef struct { + GFilterInputStream parent; + + SoupBodyInputStreamPrivate *priv; +} SoupBodyInputStream; + +typedef struct { + GFilterInputStreamClass parent_class; + + /* Padding for future expansion */ + void (*_libsoup_reserved1) (void); + void (*_libsoup_reserved2) (void); + void (*_libsoup_reserved3) (void); + void (*_libsoup_reserved4) (void); +} SoupBodyInputStreamClass; + +GType soup_body_input_stream_get_type (void); + +GInputStream *soup_body_input_stream_new (GInputStream *base_stream, + SoupEncoding encoding, + goffset content_length); + +G_END_DECLS + +#endif /* SOUP_BODY_INPUT_STREAM_H */ diff --git a/libsoup/soup-body-output-stream.c b/libsoup/soup-body-output-stream.c new file mode 100644 index 0000000..58e9b3e --- /dev/null +++ b/libsoup/soup-body-output-stream.c @@ -0,0 +1,340 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-body-output-stream.c + * + * Copyright 2012 Red Hat, Inc. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "soup-body-output-stream.h" +#include "soup.h" + +typedef enum { + SOUP_BODY_OUTPUT_STREAM_STATE_CHUNK_SIZE, + SOUP_BODY_OUTPUT_STREAM_STATE_CHUNK_END, + SOUP_BODY_OUTPUT_STREAM_STATE_CHUNK, + SOUP_BODY_OUTPUT_STREAM_STATE_TRAILERS, + SOUP_BODY_OUTPUT_STREAM_STATE_DONE +} SoupBodyOutputStreamState; + +struct _SoupBodyOutputStreamPrivate { + GOutputStream *base_stream; + char buf[20]; + + SoupEncoding encoding; + goffset write_length; + goffset written; + SoupBodyOutputStreamState chunked_state; + gboolean eof; +}; + +enum { + PROP_0, + + PROP_ENCODING, + PROP_CONTENT_LENGTH +}; + +static void soup_body_output_stream_pollable_init (GPollableOutputStreamInterface *pollable_interface, gpointer interface_data); + +G_DEFINE_TYPE_WITH_CODE (SoupBodyOutputStream, soup_body_output_stream, G_TYPE_FILTER_OUTPUT_STREAM, + G_ADD_PRIVATE (SoupBodyOutputStream) + G_IMPLEMENT_INTERFACE (G_TYPE_POLLABLE_OUTPUT_STREAM, + soup_body_output_stream_pollable_init)) + + +static void +soup_body_output_stream_init (SoupBodyOutputStream *stream) +{ + stream->priv = soup_body_output_stream_get_instance_private (stream); +} + +static void +soup_body_output_stream_constructed (GObject *object) +{ + SoupBodyOutputStream *bostream = SOUP_BODY_OUTPUT_STREAM (object); + + bostream->priv->base_stream = g_filter_output_stream_get_base_stream (G_FILTER_OUTPUT_STREAM (bostream)); +} + +static void +soup_body_output_stream_set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + SoupBodyOutputStream *bostream = SOUP_BODY_OUTPUT_STREAM (object); + + switch (prop_id) { + case PROP_ENCODING: + bostream->priv->encoding = g_value_get_enum (value); + if (bostream->priv->encoding == SOUP_ENCODING_CHUNKED) + bostream->priv->chunked_state = SOUP_BODY_OUTPUT_STREAM_STATE_CHUNK_SIZE; + break; + case PROP_CONTENT_LENGTH: + bostream->priv->write_length = g_value_get_uint64 (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +soup_body_output_stream_get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + SoupBodyOutputStream *bostream = SOUP_BODY_OUTPUT_STREAM (object); + + switch (prop_id) { + case PROP_ENCODING: + g_value_set_enum (value, bostream->priv->encoding); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static gssize +soup_body_output_stream_write_raw (SoupBodyOutputStream *bostream, + const void *buffer, + gsize count, + gboolean blocking, + GCancellable *cancellable, + GError **error) +{ + gssize nwrote, my_count; + + /* If the caller tries to write too much to a Content-Length + * encoded stream, we truncate at the right point, but keep + * accepting additional data until they stop. + */ + if (bostream->priv->write_length) { + my_count = MIN (count, bostream->priv->write_length - bostream->priv->written); + if (my_count == 0) { + bostream->priv->eof = TRUE; + return count; + } + } else + my_count = count; + + nwrote = g_pollable_stream_write (bostream->priv->base_stream, + buffer, my_count, + blocking, cancellable, error); + + if (nwrote > 0 && bostream->priv->write_length) + bostream->priv->written += nwrote; + + if (nwrote == my_count && my_count != count) + nwrote = count; + + return nwrote; +} + +static gssize +soup_body_output_stream_write_chunked (SoupBodyOutputStream *bostream, + const void *buffer, + gsize count, + gboolean blocking, + GCancellable *cancellable, + GError **error) +{ + char *buf = bostream->priv->buf; + gssize nwrote, len; + +again: + len = strlen (buf); + if (len) { + nwrote = g_pollable_stream_write (bostream->priv->base_stream, + buf, len, blocking, + cancellable, error); + if (nwrote < 0) + return nwrote; + memmove (buf, buf + nwrote, len + 1 - nwrote); + goto again; + } + + switch (bostream->priv->chunked_state) { + case SOUP_BODY_OUTPUT_STREAM_STATE_CHUNK_SIZE: + g_snprintf (buf, sizeof (bostream->priv->buf), + "%lx\r\n", (gulong)count); + + if (count > 0) + bostream->priv->chunked_state = SOUP_BODY_OUTPUT_STREAM_STATE_CHUNK; + else + bostream->priv->chunked_state = SOUP_BODY_OUTPUT_STREAM_STATE_TRAILERS; + break; + + case SOUP_BODY_OUTPUT_STREAM_STATE_CHUNK: + nwrote = g_pollable_stream_write (bostream->priv->base_stream, + buffer, count, blocking, + cancellable, error); + if (nwrote < (gssize)count) + return nwrote; + + bostream->priv->chunked_state = SOUP_BODY_OUTPUT_STREAM_STATE_CHUNK_END; + break; + + case SOUP_BODY_OUTPUT_STREAM_STATE_CHUNK_END: + strncpy (buf, "\r\n", sizeof (bostream->priv->buf)); + bostream->priv->chunked_state = SOUP_BODY_OUTPUT_STREAM_STATE_DONE; + break; + + case SOUP_BODY_OUTPUT_STREAM_STATE_TRAILERS: + strncpy (buf, "\r\n", sizeof (bostream->priv->buf)); + bostream->priv->chunked_state = SOUP_BODY_OUTPUT_STREAM_STATE_DONE; + break; + + case SOUP_BODY_OUTPUT_STREAM_STATE_DONE: + bostream->priv->chunked_state = SOUP_BODY_OUTPUT_STREAM_STATE_CHUNK_SIZE; + return count; + } + + goto again; +} + +static gssize +soup_body_output_stream_write_fn (GOutputStream *stream, + const void *buffer, + gsize count, + GCancellable *cancellable, + GError **error) +{ + SoupBodyOutputStream *bostream = SOUP_BODY_OUTPUT_STREAM (stream); + + if (bostream->priv->eof) + return count; + + switch (bostream->priv->encoding) { + case SOUP_ENCODING_CHUNKED: + return soup_body_output_stream_write_chunked (bostream, buffer, count, + TRUE, cancellable, error); + + default: + return soup_body_output_stream_write_raw (bostream, buffer, count, + TRUE, cancellable, error); + } +} + +static gboolean +soup_body_output_stream_close_fn (GOutputStream *stream, + GCancellable *cancellable, + GError **error) +{ + SoupBodyOutputStream *bostream = SOUP_BODY_OUTPUT_STREAM (stream); + + if (bostream->priv->encoding == SOUP_ENCODING_CHUNKED && + bostream->priv->chunked_state == SOUP_BODY_OUTPUT_STREAM_STATE_CHUNK_SIZE) { + if (soup_body_output_stream_write_chunked (bostream, NULL, 0, TRUE, cancellable, error) == -1) + return FALSE; + } + + return G_OUTPUT_STREAM_CLASS (soup_body_output_stream_parent_class)->close_fn (stream, cancellable, error); +} + +static gboolean +soup_body_output_stream_is_writable (GPollableOutputStream *stream) +{ + SoupBodyOutputStream *bostream = SOUP_BODY_OUTPUT_STREAM (stream); + + return bostream->priv->eof || + g_pollable_output_stream_is_writable (G_POLLABLE_OUTPUT_STREAM (bostream->priv->base_stream)); +} + +static gssize +soup_body_output_stream_write_nonblocking (GPollableOutputStream *stream, + const void *buffer, + gsize count, + GError **error) +{ + SoupBodyOutputStream *bostream = SOUP_BODY_OUTPUT_STREAM (stream); + + if (bostream->priv->eof) + return count; + + switch (bostream->priv->encoding) { + case SOUP_ENCODING_CHUNKED: + return soup_body_output_stream_write_chunked (bostream, buffer, count, + FALSE, NULL, error); + + default: + return soup_body_output_stream_write_raw (bostream, buffer, count, + FALSE, NULL, error); + } +} + +static GSource * +soup_body_output_stream_create_source (GPollableOutputStream *stream, + GCancellable *cancellable) +{ + SoupBodyOutputStream *bostream = SOUP_BODY_OUTPUT_STREAM (stream); + GSource *base_source, *pollable_source; + + if (bostream->priv->eof) + base_source = g_timeout_source_new (0); + else + base_source = g_pollable_output_stream_create_source (G_POLLABLE_OUTPUT_STREAM (bostream->priv->base_stream), cancellable); + g_source_set_dummy_callback (base_source); + + pollable_source = g_pollable_source_new (G_OBJECT (stream)); + g_source_add_child_source (pollable_source, base_source); + g_source_unref (base_source); + + return pollable_source; +} + +static void +soup_body_output_stream_class_init (SoupBodyOutputStreamClass *stream_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (stream_class); + GOutputStreamClass *output_stream_class = G_OUTPUT_STREAM_CLASS (stream_class); + + object_class->constructed = soup_body_output_stream_constructed; + object_class->set_property = soup_body_output_stream_set_property; + object_class->get_property = soup_body_output_stream_get_property; + + output_stream_class->write_fn = soup_body_output_stream_write_fn; + output_stream_class->close_fn = soup_body_output_stream_close_fn; + + g_object_class_install_property ( + object_class, PROP_ENCODING, + g_param_spec_enum ("encoding", + "Encoding", + "Message body encoding", + SOUP_TYPE_ENCODING, + SOUP_ENCODING_NONE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + g_object_class_install_property ( + object_class, PROP_CONTENT_LENGTH, + g_param_spec_uint64 ("content-length", + "Content-Length", + "Message body Content-Length", + 0, G_MAXUINT64, 0, + G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); +} + +static void +soup_body_output_stream_pollable_init (GPollableOutputStreamInterface *pollable_interface, + gpointer interface_data) +{ + pollable_interface->is_writable = soup_body_output_stream_is_writable; + pollable_interface->write_nonblocking = soup_body_output_stream_write_nonblocking; + pollable_interface->create_source = soup_body_output_stream_create_source; +} + +GOutputStream * +soup_body_output_stream_new (GOutputStream *base_stream, + SoupEncoding encoding, + goffset content_length) +{ + return g_object_new (SOUP_TYPE_BODY_OUTPUT_STREAM, + "base-stream", base_stream, + "close-base-stream", FALSE, + "encoding", encoding, + "content-length", content_length, + NULL); +} diff --git a/libsoup/soup-body-output-stream.h b/libsoup/soup-body-output-stream.h new file mode 100644 index 0000000..8bd8970 --- /dev/null +++ b/libsoup/soup-body-output-stream.h @@ -0,0 +1,47 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright 2012 Red Hat, Inc. + */ + +#ifndef SOUP_BODY_OUTPUT_STREAM_H +#define SOUP_BODY_OUTPUT_STREAM_H 1 + +#include "soup-types.h" +#include "soup-message-headers.h" + +G_BEGIN_DECLS + +#define SOUP_TYPE_BODY_OUTPUT_STREAM (soup_body_output_stream_get_type ()) +#define SOUP_BODY_OUTPUT_STREAM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SOUP_TYPE_BODY_OUTPUT_STREAM, SoupBodyOutputStream)) +#define SOUP_BODY_OUTPUT_STREAM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_BODY_OUTPUT_STREAM, SoupBodyOutputStreamClass)) +#define SOUP_IS_BODY_OUTPUT_STREAM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SOUP_TYPE_BODY_OUTPUT_STREAM)) +#define SOUP_IS_BODY_OUTPUT_STREAM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), SOUP_TYPE_BODY_OUTPUT_STREAM)) +#define SOUP_BODY_OUTPUT_STREAM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_BODY_OUTPUT_STREAM, SoupBodyOutputStreamClass)) + +typedef struct _SoupBodyOutputStreamPrivate SoupBodyOutputStreamPrivate; + +typedef struct { + GFilterOutputStream parent; + + SoupBodyOutputStreamPrivate *priv; +} SoupBodyOutputStream; + +typedef struct { + GFilterOutputStreamClass parent_class; + + /* Padding for future expansion */ + void (*_libsoup_reserved1) (void); + void (*_libsoup_reserved2) (void); + void (*_libsoup_reserved3) (void); + void (*_libsoup_reserved4) (void); +} SoupBodyOutputStreamClass; + +GType soup_body_output_stream_get_type (void); + +GOutputStream *soup_body_output_stream_new (GOutputStream *base_stream, + SoupEncoding encoding, + goffset content_length); + +G_END_DECLS + +#endif /* SOUP_BODY_OUTPUT_STREAM_H */ diff --git a/libsoup/soup-cache-client-input-stream.c b/libsoup/soup-cache-client-input-stream.c new file mode 100644 index 0000000..11bb260 --- /dev/null +++ b/libsoup/soup-cache-client-input-stream.c @@ -0,0 +1,98 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-cache-client-input-stream.c + * + * Copyright 2015 Igalia S.L. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "soup-cache-client-input-stream.h" +#include "soup.h" +#include "soup-message-private.h" + +enum { + SIGNAL_EOF, + SIGNAL_CLOSED, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +G_DEFINE_TYPE (SoupCacheClientInputStream, soup_cache_client_input_stream, G_TYPE_FILTER_INPUT_STREAM) + +static void +soup_cache_client_input_stream_init (SoupCacheClientInputStream *stream) +{ +} + +static gssize +soup_cache_client_input_stream_read_fn (GInputStream *stream, + void *buffer, + gsize count, + GCancellable *cancellable, + GError **error) +{ + gssize nread; + + nread = G_INPUT_STREAM_CLASS (soup_cache_client_input_stream_parent_class)-> + read_fn (stream, buffer, count, cancellable, error); + + if (nread == 0) + g_signal_emit (stream, signals[SIGNAL_EOF], 0); + + return nread; +} + + +static gboolean +soup_cache_client_input_stream_close_fn (GInputStream *stream, + GCancellable *cancellable, + GError **error) +{ + gboolean success; + + success = G_INPUT_STREAM_CLASS (soup_cache_client_input_stream_parent_class)-> + close_fn (stream, cancellable, error); + + g_signal_emit (stream, signals[SIGNAL_CLOSED], 0); + + return success; +} + +static void +soup_cache_client_input_stream_class_init (SoupCacheClientInputStreamClass *stream_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (stream_class); + GInputStreamClass *input_stream_class = G_INPUT_STREAM_CLASS (stream_class); + + input_stream_class->read_fn = soup_cache_client_input_stream_read_fn; + input_stream_class->close_fn = soup_cache_client_input_stream_close_fn; + + signals[SIGNAL_EOF] = + g_signal_new ("eof", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + NULL, + G_TYPE_NONE, 0); + signals[SIGNAL_CLOSED] = + g_signal_new ("closed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + NULL, + G_TYPE_NONE, 0); +} + +GInputStream * +soup_cache_client_input_stream_new (GInputStream *base_stream) +{ + return g_object_new (SOUP_TYPE_CACHE_CLIENT_INPUT_STREAM, + "base-stream", base_stream, + NULL); +} diff --git a/libsoup/soup-cache-client-input-stream.h b/libsoup/soup-cache-client-input-stream.h new file mode 100644 index 0000000..17f8359 --- /dev/null +++ b/libsoup/soup-cache-client-input-stream.h @@ -0,0 +1,36 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright 2015 Igalia S.L. + */ + +#ifndef SOUP_CACHE_CLIENT_INPUT_STREAM_H +#define SOUP_CACHE_CLIENT_INPUT_STREAM_H 1 + +#include "soup-types.h" + +G_BEGIN_DECLS + +#define SOUP_TYPE_CACHE_CLIENT_INPUT_STREAM (soup_cache_client_input_stream_get_type ()) +#define SOUP_CACHE_CLIENT_INPUT_STREAM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SOUP_TYPE_CACHE_CLIENT_INPUT_STREAM, SoupCacheClientInputStream)) +#define SOUP_CACHE_CLIENT_INPUT_STREAM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_CACHE_CLIENT_INPUT_STREAM, SoupCacheClientInputStreamClass)) +#define SOUP_IS_CACHE_CLIENT_INPUT_STREAM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SOUP_TYPE_CACHE_CLIENT_INPUT_STREAM)) +#define SOUP_IS_CACHE_CLIENT_INPUT_STREAM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), SOUP_TYPE_CACHE_CLIENT_INPUT_STREAM)) +#define SOUP_CACHE_CLIENT_INPUT_STREAM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_CACHE_CLIENT_INPUT_STREAM, SoupCacheClientInputStreamClass)) + +typedef struct _SoupCacheClientInputStreamPrivate SoupCacheClientInputStreamPrivate; + +typedef struct { + GFilterInputStream parent; +} SoupCacheClientInputStream; + +typedef struct { + GFilterInputStreamClass parent_class; +} SoupCacheClientInputStreamClass; + +GType soup_cache_client_input_stream_get_type (void); + +GInputStream *soup_cache_client_input_stream_new (GInputStream *base_stream); + +G_END_DECLS + +#endif /* SOUP_CACHE_CLIENT_INPUT_STREAM_H */ diff --git a/libsoup/soup-cache-input-stream.c b/libsoup/soup-cache-input-stream.c new file mode 100644 index 0000000..e93b43f --- /dev/null +++ b/libsoup/soup-cache-input-stream.c @@ -0,0 +1,350 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2012 Igalia, S.L. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include "soup-cache-input-stream.h" +#include "soup-message-body.h" + +/* properties */ +enum { + PROP_0, + + PROP_OUTPUT_STREAM, + + LAST_PROP +}; + +enum { + CACHING_FINISHED, + + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +struct _SoupCacheInputStreamPrivate +{ + GOutputStream *output_stream; + GCancellable *cancellable; + gsize bytes_written; + + gboolean read_finished; + SoupBuffer *current_writing_buffer; + GQueue *buffer_queue; +}; + +static void soup_cache_input_stream_pollable_init (GPollableInputStreamInterface *pollable_interface, gpointer interface_data); + +G_DEFINE_TYPE_WITH_CODE (SoupCacheInputStream, soup_cache_input_stream, SOUP_TYPE_FILTER_INPUT_STREAM, + G_ADD_PRIVATE (SoupCacheInputStream) + G_IMPLEMENT_INTERFACE (G_TYPE_POLLABLE_INPUT_STREAM, + soup_cache_input_stream_pollable_init)) + + +static void soup_cache_input_stream_write_next_buffer (SoupCacheInputStream *istream); + +static inline void +notify_and_clear (SoupCacheInputStream *istream, GError *error) +{ + SoupCacheInputStreamPrivate *priv = istream->priv; + + g_signal_emit (istream, signals[CACHING_FINISHED], 0, priv->bytes_written, error); + + g_clear_object (&priv->cancellable); + g_clear_object (&priv->output_stream); + g_clear_error (&error); +} + +static inline void +try_write_next_buffer (SoupCacheInputStream *istream) +{ + SoupCacheInputStreamPrivate *priv = istream->priv; + + if (priv->current_writing_buffer == NULL && priv->buffer_queue->length) + soup_cache_input_stream_write_next_buffer (istream); + else if (priv->read_finished) + notify_and_clear (istream, NULL); + else if (g_input_stream_is_closed (G_INPUT_STREAM (istream))) { + GError *error = NULL; + g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_CLOSED, + _("Network stream unexpectedly closed")); + notify_and_clear (istream, error); + } +} + +static void +file_replaced_cb (GObject *source, + GAsyncResult *res, + gpointer user_data) +{ + SoupCacheInputStream *istream = SOUP_CACHE_INPUT_STREAM (user_data); + SoupCacheInputStreamPrivate *priv = istream->priv; + GError *error = NULL; + + priv->output_stream = (GOutputStream *) g_file_replace_finish (G_FILE (source), res, &error); + + if (error) + notify_and_clear (istream, error); + else + try_write_next_buffer (istream); + + g_object_unref (istream); +} + +static void +soup_cache_input_stream_init (SoupCacheInputStream *self) +{ + SoupCacheInputStreamPrivate *priv = soup_cache_input_stream_get_instance_private (self); + + priv->buffer_queue = g_queue_new (); + self->priv = priv; +} + +static void +soup_cache_input_stream_get_property (GObject *object, + guint property_id, GValue *value, GParamSpec *pspec) +{ + SoupCacheInputStream *self = SOUP_CACHE_INPUT_STREAM (object); + SoupCacheInputStreamPrivate *priv = self->priv; + + switch (property_id) { + case PROP_OUTPUT_STREAM: + g_value_set_object (value, priv->output_stream); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +soup_cache_input_stream_set_property (GObject *object, + guint property_id, const GValue *value, GParamSpec *pspec) +{ + SoupCacheInputStream *self = SOUP_CACHE_INPUT_STREAM (object); + SoupCacheInputStreamPrivate *priv = self->priv; + + switch (property_id) { + case PROP_OUTPUT_STREAM: + priv->output_stream = g_value_dup_object (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +soup_cache_input_stream_finalize (GObject *object) +{ + SoupCacheInputStream *self = (SoupCacheInputStream *)object; + SoupCacheInputStreamPrivate *priv = self->priv; + + g_clear_object (&priv->cancellable); + g_clear_object (&priv->output_stream); + g_clear_pointer (&priv->current_writing_buffer, soup_buffer_free); + g_queue_free_full (priv->buffer_queue, (GDestroyNotify) soup_buffer_free); + + G_OBJECT_CLASS (soup_cache_input_stream_parent_class)->finalize (object); +} + +static void +write_ready_cb (GObject *source, GAsyncResult *result, SoupCacheInputStream *istream) +{ + GOutputStream *ostream = G_OUTPUT_STREAM (source); + SoupCacheInputStreamPrivate *priv = istream->priv; + gssize write_size; + gsize pending; + GError *error = NULL; + + write_size = g_output_stream_write_finish (ostream, result, &error); + if (error) { + notify_and_clear (istream, error); + g_object_unref (istream); + return; + } + + /* Check that we have written everything */ + pending = priv->current_writing_buffer->length - write_size; + if (pending) { + SoupBuffer *subbuffer = soup_buffer_new_subbuffer (priv->current_writing_buffer, + write_size, pending); + g_queue_push_head (priv->buffer_queue, subbuffer); + } + + priv->bytes_written += write_size; + g_clear_pointer (&priv->current_writing_buffer, soup_buffer_free); + + try_write_next_buffer (istream); + g_object_unref (istream); +} + +static void +soup_cache_input_stream_write_next_buffer (SoupCacheInputStream *istream) +{ + SoupCacheInputStreamPrivate *priv = istream->priv; + SoupBuffer *buffer = g_queue_pop_head (priv->buffer_queue); + int priority; + + g_assert (priv->output_stream && !g_output_stream_is_closed (priv->output_stream)); + + g_clear_pointer (&priv->current_writing_buffer, soup_buffer_free); + priv->current_writing_buffer = buffer; + + if (priv->buffer_queue->length > 10) + priority = G_PRIORITY_DEFAULT; + else + priority = G_PRIORITY_LOW; + + g_output_stream_write_async (priv->output_stream, buffer->data, buffer->length, + priority, priv->cancellable, + (GAsyncReadyCallback) write_ready_cb, + g_object_ref (istream)); +} + +static gssize +read_internal (GInputStream *stream, + void *buffer, + gsize count, + gboolean blocking, + GCancellable *cancellable, + GError **error) +{ + SoupCacheInputStream *istream = SOUP_CACHE_INPUT_STREAM (stream); + SoupCacheInputStreamPrivate *priv = istream->priv; + GInputStream *base_stream; + gssize nread; + + base_stream = g_filter_input_stream_get_base_stream (G_FILTER_INPUT_STREAM (stream)); + nread = g_pollable_stream_read (base_stream, buffer, count, blocking, + cancellable, error); + + if (G_UNLIKELY (nread == -1 || priv->read_finished)) + return nread; + + if (nread == 0) { + priv->read_finished = TRUE; + + if (priv->current_writing_buffer == NULL && priv->output_stream) + notify_and_clear (istream, NULL); + } else { + SoupBuffer *soup_buffer = soup_buffer_new (SOUP_MEMORY_COPY, buffer, nread); + g_queue_push_tail (priv->buffer_queue, soup_buffer); + + if (priv->current_writing_buffer == NULL && priv->output_stream) + soup_cache_input_stream_write_next_buffer (istream); + } + + return nread; +} + +static gssize +soup_cache_input_stream_read_fn (GInputStream *stream, + void *buffer, + gsize count, + GCancellable *cancellable, + GError **error) +{ + return read_internal (stream, buffer, count, TRUE, + cancellable, error); +} + +static gssize +soup_cache_input_stream_read_nonblocking (GPollableInputStream *stream, + void *buffer, + gsize count, + GError **error) +{ + return read_internal (G_INPUT_STREAM (stream), buffer, count, FALSE, + NULL, error); +} + +static void +soup_cache_input_stream_pollable_init (GPollableInputStreamInterface *pollable_interface, + gpointer interface_data) +{ + pollable_interface->read_nonblocking = soup_cache_input_stream_read_nonblocking; +} + +static gboolean +soup_cache_input_stream_close_fn (GInputStream *stream, + GCancellable *cancellable, + GError **error) +{ + SoupCacheInputStream *istream = SOUP_CACHE_INPUT_STREAM (stream); + SoupCacheInputStreamPrivate *priv = istream->priv; + + if (!priv->read_finished) { + if (priv->output_stream) { + /* Cancel any pending write operation or return an error if none. */ + if (g_output_stream_has_pending (priv->output_stream)) + g_cancellable_cancel (priv->cancellable); + else { + GError *notify_error = NULL; + g_set_error_literal (¬ify_error, G_IO_ERROR, G_IO_ERROR_PARTIAL_INPUT, + _("Failed to completely cache the resource")); + notify_and_clear (istream, notify_error); + } + } else if (priv->cancellable) + /* The file_replace_async() hasn't finished yet */ + g_cancellable_cancel (priv->cancellable); + } + + return G_INPUT_STREAM_CLASS (soup_cache_input_stream_parent_class)->close_fn (stream, cancellable, error); +} + +static void +soup_cache_input_stream_class_init (SoupCacheInputStreamClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GInputStreamClass *istream_class = G_INPUT_STREAM_CLASS (klass); + + gobject_class->get_property = soup_cache_input_stream_get_property; + gobject_class->set_property = soup_cache_input_stream_set_property; + gobject_class->finalize = soup_cache_input_stream_finalize; + + istream_class->read_fn = soup_cache_input_stream_read_fn; + istream_class->close_fn = soup_cache_input_stream_close_fn; + + g_object_class_install_property (gobject_class, PROP_OUTPUT_STREAM, + g_param_spec_object ("output-stream", "Output stream", + "the output stream where to write.", + G_TYPE_OUTPUT_STREAM, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + + signals[CACHING_FINISHED] = + g_signal_new ("caching-finished", + G_OBJECT_CLASS_TYPE (gobject_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (SoupCacheInputStreamClass, caching_finished), + NULL, NULL, + NULL, + G_TYPE_NONE, 2, + G_TYPE_INT, G_TYPE_ERROR); +} + +GInputStream * +soup_cache_input_stream_new (GInputStream *base_stream, + GFile *file) +{ + SoupCacheInputStream *istream = g_object_new (SOUP_TYPE_CACHE_INPUT_STREAM, + "base-stream", base_stream, + "close-base-stream", FALSE, + NULL); + + istream->priv->cancellable = g_cancellable_new (); + g_file_replace_async (file, NULL, FALSE, + G_FILE_CREATE_PRIVATE | G_FILE_CREATE_REPLACE_DESTINATION, + G_PRIORITY_DEFAULT, istream->priv->cancellable, + file_replaced_cb, g_object_ref (istream)); + + return (GInputStream *) istream; +} diff --git a/libsoup/soup-cache-input-stream.h b/libsoup/soup-cache-input-stream.h new file mode 100644 index 0000000..92b1d7b --- /dev/null +++ b/libsoup/soup-cache-input-stream.h @@ -0,0 +1,46 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-cache-input-stream.h - Header for SoupCacheInputStream + */ + +#ifndef __SOUP_CACHE_INPUT_STREAM_H__ +#define __SOUP_CACHE_INPUT_STREAM_H__ + +#include "soup-filter-input-stream.h" + +G_BEGIN_DECLS + +#define SOUP_TYPE_CACHE_INPUT_STREAM (soup_cache_input_stream_get_type()) +#define SOUP_CACHE_INPUT_STREAM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SOUP_TYPE_CACHE_INPUT_STREAM, SoupCacheInputStream)) +#define SOUP_CACHE_INPUT_STREAM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_CACHE_INPUT_STREAM, SoupCacheInputStreamClass)) +#define SOUP_IS_CACHE_INPUT_STREAM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SOUP_TYPE_CACHE_INPUT_STREAM)) +#define SOUP_IS_CACHE_INPUT_STREAM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SOUP_TYPE_CACHE_INPUT_STREAM)) +#define SOUP_CACHE_INPUT_STREAM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_CACHE_INPUT_STREAM, SoupCacheInputStreamClass)) + +typedef struct _SoupCacheInputStream SoupCacheInputStream; +typedef struct _SoupCacheInputStreamClass SoupCacheInputStreamClass; +typedef struct _SoupCacheInputStreamPrivate SoupCacheInputStreamPrivate; + +struct _SoupCacheInputStreamClass +{ + SoupFilterInputStreamClass parent_class; + + /* signals */ + void (*caching_finished) (SoupCacheInputStream *istream, gsize bytes_written, GError *error); +}; + +struct _SoupCacheInputStream +{ + SoupFilterInputStream parent; + + SoupCacheInputStreamPrivate *priv; +}; + +GType soup_cache_input_stream_get_type (void) G_GNUC_CONST; + +GInputStream *soup_cache_input_stream_new (GInputStream *base_stream, + GFile *file); + +G_END_DECLS + +#endif /* __SOUP_CACHE_INPUT_STREAM_H__ */ diff --git a/libsoup/soup-cache-private.h b/libsoup/soup-cache-private.h new file mode 100644 index 0000000..e17fc0d --- /dev/null +++ b/libsoup/soup-cache-private.h @@ -0,0 +1,46 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-cache-private.h: + * + * Copyright (C) 2010 Igalia, S.L. + * + * 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, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef SOUP_CACHE_PRIVATE_H +#define SOUP_CACHE_PRIVATE_H 1 + +#include "soup-cache.h" +#include + +G_BEGIN_DECLS + +SoupCacheResponse soup_cache_has_response (SoupCache *cache, + SoupMessage *msg); +GInputStream *soup_cache_send_response (SoupCache *cache, + SoupMessage *msg); +SoupCacheability soup_cache_get_cacheability (SoupCache *cache, + SoupMessage *msg); +SoupMessage *soup_cache_generate_conditional_request (SoupCache *cache, + SoupMessage *original); +void soup_cache_cancel_conditional_request (SoupCache *cache, + SoupMessage *msg); +void soup_cache_update_from_conditional_request (SoupCache *cache, + SoupMessage *msg); + +G_END_DECLS + +#endif /* SOUP_CACHE_PRIVATE_H */ diff --git a/libsoup/soup-cache.c b/libsoup/soup-cache.c new file mode 100644 index 0000000..682625e --- /dev/null +++ b/libsoup/soup-cache.c @@ -0,0 +1,1666 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-cache.c + * + * Copyright (C) 2009, 2010 Igalia S.L. + * + * 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, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/* TODO: + * - Need to hook the feature in the sync SoupSession. + * - Need more tests. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include "soup-cache.h" +#include "soup-body-input-stream.h" +#include "soup-cache-client-input-stream.h" +#include "soup-cache-input-stream.h" +#include "soup-cache-private.h" +#include "soup-content-processor.h" +#include "soup-message-private.h" +#include "soup.h" +#include "soup-message-private.h" + +/** + * SECTION:soup-cache + * @short_description: Caching support + * + * #SoupCache implements a file-based cache for HTTP resources. + */ + +static SoupSessionFeatureInterface *soup_cache_default_feature_interface; +static void soup_cache_session_feature_init (SoupSessionFeatureInterface *feature_interface, gpointer interface_data); + +static SoupContentProcessorInterface *soup_cache_default_content_processor_interface; +static void soup_cache_content_processor_init (SoupContentProcessorInterface *interface, gpointer interface_data); + +#define DEFAULT_MAX_SIZE 50 * 1024 * 1024 +#define MAX_ENTRY_DATA_PERCENTAGE 10 /* Percentage of the total size + of the cache that can be + filled by a single entry */ + +/* + * Version 2: cache is now saved in soup.cache2. Added the version + * number to the beginning of the file. + * + * Version 3: added HTTP status code to the cache entries. + * + * Version 4: replaced several types. + * - freshness_lifetime,corrected_initial_age,response_time: time_t -> guint32 + * - status_code: guint -> guint16 + * - hits: guint -> guint32 + * + * Version 5: key is no longer stored on disk as it can be easily + * built from the URI. Apart from that some fields in the + * SoupCacheEntry have changed: + * - entry key is now a uint32 instead of a (char *). + * - added uri, used to check for collisions + * - removed filename, it's built from the entry key. + */ +#define SOUP_CACHE_CURRENT_VERSION 5 + +#define OLD_SOUP_CACHE_FILE "soup.cache" +#define SOUP_CACHE_FILE "soup.cache2" + +#define SOUP_CACHE_HEADERS_FORMAT "{ss}" +#define SOUP_CACHE_PHEADERS_FORMAT "(sbuuuuuqa" SOUP_CACHE_HEADERS_FORMAT ")" +#define SOUP_CACHE_ENTRIES_FORMAT "(qa" SOUP_CACHE_PHEADERS_FORMAT ")" + +/* Basically the same format than above except that some strings are + prepended with &. This way the GVariant returns a pointer to the + data instead of duplicating the string */ +#define SOUP_CACHE_DECODE_HEADERS_FORMAT "{&s&s}" + + +typedef struct _SoupCacheEntry { + guint32 key; + char *uri; + guint32 freshness_lifetime; + gboolean must_revalidate; + gsize length; + guint32 corrected_initial_age; + guint32 response_time; + gboolean dirty; + gboolean being_validated; + SoupMessageHeaders *headers; + guint32 hits; + GCancellable *cancellable; + guint16 status_code; +} SoupCacheEntry; + +struct _SoupCachePrivate { + char *cache_dir; + GHashTable *cache; + guint n_pending; + SoupSession *session; + SoupCacheType cache_type; + guint size; + guint max_size; + guint max_entry_data_size; /* Computed value. Here for performance reasons */ + GList *lru_start; +}; + +enum { + PROP_0, + PROP_CACHE_DIR, + PROP_CACHE_TYPE +}; + +G_DEFINE_TYPE_WITH_CODE (SoupCache, soup_cache, G_TYPE_OBJECT, + G_ADD_PRIVATE (SoupCache) + G_IMPLEMENT_INTERFACE (SOUP_TYPE_SESSION_FEATURE, + soup_cache_session_feature_init) + G_IMPLEMENT_INTERFACE (SOUP_TYPE_CONTENT_PROCESSOR, + soup_cache_content_processor_init)) + +static gboolean soup_cache_entry_remove (SoupCache *cache, SoupCacheEntry *entry, gboolean purge); +static void make_room_for_new_entry (SoupCache *cache, guint length_to_add); +static gboolean cache_accepts_entries_of_size (SoupCache *cache, guint length_to_add); + +static GFile * +get_file_from_entry (SoupCache *cache, SoupCacheEntry *entry) +{ + char *filename = g_strdup_printf ("%s%s%u", cache->priv->cache_dir, + G_DIR_SEPARATOR_S, (guint) entry->key); + GFile *file = g_file_new_for_path (filename); + g_free (filename); + + return file; +} + +static SoupCacheability +get_cacheability (SoupCache *cache, SoupMessage *msg) +{ + SoupCacheability cacheability; + const char *cache_control, *content_type; + gboolean has_max_age = FALSE; + + /* 1. The request method must be cacheable */ + if (msg->method == SOUP_METHOD_GET) + cacheability = SOUP_CACHE_CACHEABLE; + else if (msg->method == SOUP_METHOD_HEAD || + msg->method == SOUP_METHOD_TRACE || + msg->method == SOUP_METHOD_CONNECT) + return SOUP_CACHE_UNCACHEABLE; + else + return (SOUP_CACHE_UNCACHEABLE | SOUP_CACHE_INVALIDATES); + + content_type = soup_message_headers_get_content_type (msg->response_headers, NULL); + if (content_type && !g_ascii_strcasecmp (content_type, "multipart/x-mixed-replace")) + return SOUP_CACHE_UNCACHEABLE; + + cache_control = soup_message_headers_get_list (msg->response_headers, "Cache-Control"); + if (cache_control && *cache_control) { + GHashTable *hash; + SoupCachePrivate *priv = soup_cache_get_instance_private (cache); + + hash = soup_header_parse_param_list (cache_control); + + /* Shared caches MUST NOT store private resources */ + if (priv->cache_type == SOUP_CACHE_SHARED) { + if (g_hash_table_lookup_extended (hash, "private", NULL, NULL)) { + soup_header_free_param_list (hash); + return SOUP_CACHE_UNCACHEABLE; + } + } + + /* 2. The 'no-store' cache directive does not appear in the + * headers + */ + if (g_hash_table_lookup_extended (hash, "no-store", NULL, NULL)) { + soup_header_free_param_list (hash); + return SOUP_CACHE_UNCACHEABLE; + } + + if (g_hash_table_lookup_extended (hash, "max-age", NULL, NULL)) + has_max_age = TRUE; + + /* This does not appear in section 2.1, but I think it makes + * sense to check it too? + */ + if (g_hash_table_lookup_extended (hash, "no-cache", NULL, NULL)) { + soup_header_free_param_list (hash); + return SOUP_CACHE_UNCACHEABLE; + } + + soup_header_free_param_list (hash); + } + + /* Section 13.9 */ + if ((soup_message_get_uri (msg))->query && + !soup_message_headers_get_one (msg->response_headers, "Expires") && + !has_max_age) + return SOUP_CACHE_UNCACHEABLE; + + switch (msg->status_code) { + case SOUP_STATUS_PARTIAL_CONTENT: + /* We don't cache partial responses, but they only + * invalidate cached full responses if the headers + * don't match. + */ + cacheability = SOUP_CACHE_UNCACHEABLE; + break; + + case SOUP_STATUS_NOT_MODIFIED: + /* A 304 response validates an existing cache entry */ + cacheability = SOUP_CACHE_VALIDATES; + break; + + case SOUP_STATUS_MULTIPLE_CHOICES: + case SOUP_STATUS_MOVED_PERMANENTLY: + case SOUP_STATUS_GONE: + /* FIXME: cacheable unless indicated otherwise */ + cacheability = SOUP_CACHE_UNCACHEABLE; + break; + + case SOUP_STATUS_FOUND: + case SOUP_STATUS_TEMPORARY_REDIRECT: + /* FIXME: cacheable if explicitly indicated */ + cacheability = SOUP_CACHE_UNCACHEABLE; + break; + + case SOUP_STATUS_SEE_OTHER: + case SOUP_STATUS_FORBIDDEN: + case SOUP_STATUS_NOT_FOUND: + case SOUP_STATUS_METHOD_NOT_ALLOWED: + return (SOUP_CACHE_UNCACHEABLE | SOUP_CACHE_INVALIDATES); + + default: + /* Any 5xx status or any 4xx status not handled above + * is uncacheable but doesn't break the cache. + */ + if ((msg->status_code >= SOUP_STATUS_BAD_REQUEST && + msg->status_code <= SOUP_STATUS_FAILED_DEPENDENCY) || + msg->status_code >= SOUP_STATUS_INTERNAL_SERVER_ERROR) + return SOUP_CACHE_UNCACHEABLE; + + /* An unrecognized 2xx, 3xx, or 4xx response breaks + * the cache. + */ + if ((msg->status_code > SOUP_STATUS_PARTIAL_CONTENT && + msg->status_code < SOUP_STATUS_MULTIPLE_CHOICES) || + (msg->status_code > SOUP_STATUS_TEMPORARY_REDIRECT && + msg->status_code < SOUP_STATUS_INTERNAL_SERVER_ERROR)) + return (SOUP_CACHE_UNCACHEABLE | SOUP_CACHE_INVALIDATES); + break; + } + + return cacheability; +} + +/* NOTE: this function deletes the file pointed by the file argument + * and also unref's the GFile object representing it. + */ +static void +soup_cache_entry_free (SoupCacheEntry *entry) +{ + g_free (entry->uri); + g_clear_pointer (&entry->headers, soup_message_headers_free); + g_clear_object (&entry->cancellable); + + g_slice_free (SoupCacheEntry, entry); +} + +static void +copy_headers (const char *name, const char *value, SoupMessageHeaders *headers) +{ + soup_message_headers_append (headers, name, value); +} + +static void +remove_headers (const char *name, const char *value, SoupMessageHeaders *headers) +{ + soup_message_headers_remove (headers, name); +} + +static char *hop_by_hop_headers[] = {"Connection", "Keep-Alive", "Proxy-Authenticate", "Proxy-Authorization", "TE", "Trailer", "Transfer-Encoding", "Upgrade"}; + +static void +copy_end_to_end_headers (SoupMessageHeaders *source, SoupMessageHeaders *destination) +{ + int i; + + soup_message_headers_foreach (source, (SoupMessageHeadersForeachFunc) copy_headers, destination); + for (i = 0; i < G_N_ELEMENTS (hop_by_hop_headers); i++) + soup_message_headers_remove (destination, hop_by_hop_headers[i]); + soup_message_headers_clean_connection_headers (destination); +} + +static guint +soup_cache_entry_get_current_age (SoupCacheEntry *entry) +{ + time_t now = time (NULL); + time_t resident_time; + + resident_time = now - entry->response_time; + return entry->corrected_initial_age + resident_time; +} + +static gboolean +soup_cache_entry_is_fresh_enough (SoupCacheEntry *entry, gint min_fresh) +{ + guint limit = (min_fresh == -1) ? soup_cache_entry_get_current_age (entry) : (guint) min_fresh; + return entry->freshness_lifetime > limit; +} + +static inline guint32 +get_cache_key_from_uri (const char *uri) +{ + return (guint32) g_str_hash (uri); +} + +static void +soup_cache_entry_set_freshness (SoupCacheEntry *entry, SoupMessage *msg, SoupCache *cache) +{ + const char *cache_control; + const char *expires, *date, *last_modified; + + /* Reset these values. We have to do this to ensure that + * revalidations overwrite previous values for the headers. + */ + entry->must_revalidate = FALSE; + entry->freshness_lifetime = 0; + + cache_control = soup_message_headers_get_list (entry->headers, "Cache-Control"); + if (cache_control && *cache_control) { + const char *max_age, *s_maxage; + gint64 freshness_lifetime = 0; + GHashTable *hash; + SoupCachePrivate *priv = soup_cache_get_instance_private (cache); + + hash = soup_header_parse_param_list (cache_control); + + /* Should we re-validate the entry when it goes stale */ + entry->must_revalidate = g_hash_table_lookup_extended (hash, "must-revalidate", NULL, NULL); + + /* Section 2.3.1 */ + if (priv->cache_type == SOUP_CACHE_SHARED) { + s_maxage = g_hash_table_lookup (hash, "s-maxage"); + if (s_maxage) { + freshness_lifetime = g_ascii_strtoll (s_maxage, NULL, 10); + if (freshness_lifetime) { + /* Implies proxy-revalidate. TODO: is it true? */ + entry->must_revalidate = TRUE; + soup_header_free_param_list (hash); + return; + } + } + } + + /* If 'max-age' cache directive is present, use that */ + max_age = g_hash_table_lookup (hash, "max-age"); + if (max_age) + freshness_lifetime = g_ascii_strtoll (max_age, NULL, 10); + + if (freshness_lifetime) { + entry->freshness_lifetime = (guint32) MIN (freshness_lifetime, G_MAXUINT32); + soup_header_free_param_list (hash); + return; + } + + soup_header_free_param_list (hash); + } + + /* If the 'Expires' response header is present, use its value + * minus the value of the 'Date' response header + */ + expires = soup_message_headers_get_one (entry->headers, "Expires"); + date = soup_message_headers_get_one (entry->headers, "Date"); + if (expires && date) { + SoupDate *expires_d, *date_d; + time_t expires_t, date_t; + + expires_d = soup_date_new_from_string (expires); + if (expires_d) { + date_d = soup_date_new_from_string (date); + + expires_t = soup_date_to_time_t (expires_d); + date_t = soup_date_to_time_t (date_d); + + soup_date_free (expires_d); + soup_date_free (date_d); + + if (expires_t && date_t) { + entry->freshness_lifetime = (guint32) MAX (expires_t - date_t, 0); + return; + } + } else { + /* If Expires is not a valid date we should + treat it as already expired, see section + 3.3 */ + entry->freshness_lifetime = 0; + return; + } + } + + /* Otherwise an heuristic may be used */ + + /* Heuristics MUST NOT be used with stored responses with + these status codes (section 2.3.1.1) */ + if (entry->status_code != SOUP_STATUS_OK && + entry->status_code != SOUP_STATUS_NON_AUTHORITATIVE && + entry->status_code != SOUP_STATUS_PARTIAL_CONTENT && + entry->status_code != SOUP_STATUS_MULTIPLE_CHOICES && + entry->status_code != SOUP_STATUS_MOVED_PERMANENTLY && + entry->status_code != SOUP_STATUS_GONE) + goto expire; + + /* TODO: attach warning 113 if response's current_age is more + than 24h (section 2.3.1.1) when using heuristics */ + + /* Last-Modified based heuristic */ + last_modified = soup_message_headers_get_one (entry->headers, "Last-Modified"); + if (last_modified) { + SoupDate *soup_date; + time_t now, last_modified_t; + + soup_date = soup_date_new_from_string (last_modified); + last_modified_t = soup_date_to_time_t (soup_date); + now = time (NULL); + +#define HEURISTIC_FACTOR 0.1 /* From Section 2.3.1.1 */ + + entry->freshness_lifetime = MAX (0, (now - last_modified_t) * HEURISTIC_FACTOR); + soup_date_free (soup_date); + } + + return; + + expire: + /* If all else fails, make the entry expire immediately */ + entry->freshness_lifetime = 0; +} + +static SoupCacheEntry * +soup_cache_entry_new (SoupCache *cache, SoupMessage *msg, time_t request_time, time_t response_time) +{ + SoupCacheEntry *entry; + const char *date; + + entry = g_slice_new0 (SoupCacheEntry); + entry->dirty = FALSE; + entry->being_validated = FALSE; + entry->status_code = msg->status_code; + entry->response_time = response_time; + entry->uri = soup_uri_to_string (soup_message_get_uri (msg), FALSE); + + /* Headers */ + entry->headers = soup_message_headers_new (SOUP_MESSAGE_HEADERS_RESPONSE); + copy_end_to_end_headers (msg->response_headers, entry->headers); + + /* LRU list */ + entry->hits = 0; + + /* Section 2.3.1, Freshness Lifetime */ + soup_cache_entry_set_freshness (entry, msg, cache); + + /* Section 2.3.2, Calculating Age */ + date = soup_message_headers_get_one (entry->headers, "Date"); + + if (date) { + SoupDate *soup_date; + const char *age; + time_t date_value, apparent_age, corrected_received_age, response_delay, age_value = 0; + + soup_date = soup_date_new_from_string (date); + date_value = soup_date_to_time_t (soup_date); + soup_date_free (soup_date); + + age = soup_message_headers_get_one (entry->headers, "Age"); + if (age) + age_value = g_ascii_strtoll (age, NULL, 10); + + apparent_age = MAX (0, entry->response_time - date_value); + corrected_received_age = MAX (apparent_age, age_value); + response_delay = entry->response_time - request_time; + entry->corrected_initial_age = corrected_received_age + response_delay; + } else { + /* Is this correct ? */ + entry->corrected_initial_age = time (NULL); + } + + return entry; +} + +static gboolean +soup_cache_entry_remove (SoupCache *cache, SoupCacheEntry *entry, gboolean purge) +{ + GList *lru_item; + + if (entry->dirty) { + g_cancellable_cancel (entry->cancellable); + return FALSE; + } + + g_assert (!entry->dirty); + g_assert (g_list_length (cache->priv->lru_start) == g_hash_table_size (cache->priv->cache)); + + if (!g_hash_table_remove (cache->priv->cache, GUINT_TO_POINTER (entry->key))) + return FALSE; + + /* Remove from LRU */ + lru_item = g_list_find (cache->priv->lru_start, entry); + cache->priv->lru_start = g_list_delete_link (cache->priv->lru_start, lru_item); + + /* Adjust cache size */ + cache->priv->size -= entry->length; + + g_assert (g_list_length (cache->priv->lru_start) == g_hash_table_size (cache->priv->cache)); + + /* Free resources */ + if (purge) { + GFile *file = get_file_from_entry (cache, entry); + g_file_delete (file, NULL, NULL); + g_object_unref (file); + } + soup_cache_entry_free (entry); + + return TRUE; +} + +static gint +lru_compare_func (gconstpointer a, gconstpointer b) +{ + SoupCacheEntry *entry_a = (SoupCacheEntry *)a; + SoupCacheEntry *entry_b = (SoupCacheEntry *)b; + + /* The rationale of this sorting func is + * + * 1. sort by hits -> LRU algorithm, then + * + * 2. sort by freshness lifetime, we better discard first + * entries that are close to expire + * + * 3. sort by size, replace first small size resources as they + * are cheaper to download + */ + + /* Sort by hits */ + if (entry_a->hits != entry_b->hits) + return entry_a->hits - entry_b->hits; + + /* Sort by freshness_lifetime */ + if (entry_a->freshness_lifetime != entry_b->freshness_lifetime) + return entry_a->freshness_lifetime - entry_b->freshness_lifetime; + + /* Sort by size */ + return entry_a->length - entry_b->length; +} + +static gboolean +cache_accepts_entries_of_size (SoupCache *cache, guint length_to_add) +{ + /* We could add here some more heuristics. TODO: review how + this is done by other HTTP caches */ + + return length_to_add <= cache->priv->max_entry_data_size; +} + +static void +make_room_for_new_entry (SoupCache *cache, guint length_to_add) +{ + GList *lru_entry = cache->priv->lru_start; + + /* Check that there is enough room for the new entry. This is + an approximation as we're not working out the size of the + cache file or the size of the headers for performance + reasons. TODO: check if that would be really that expensive */ + + while (lru_entry && + (length_to_add + cache->priv->size > cache->priv->max_size)) { + SoupCacheEntry *old_entry = (SoupCacheEntry *)lru_entry->data; + + /* Discard entries. Once cancelled resources will be + * freed in close_ready_cb + */ + if (soup_cache_entry_remove (cache, old_entry, TRUE)) + lru_entry = cache->priv->lru_start; + else + lru_entry = g_list_next (lru_entry); + } +} + +static gboolean +soup_cache_entry_insert (SoupCache *cache, + SoupCacheEntry *entry, + gboolean sort) +{ + guint length_to_add = 0; + SoupCacheEntry *old_entry; + + /* Fill the key */ + entry->key = get_cache_key_from_uri ((const char *) entry->uri); + + if (soup_message_headers_get_encoding (entry->headers) == SOUP_ENCODING_CONTENT_LENGTH) + length_to_add = soup_message_headers_get_content_length (entry->headers); + + /* Check if we are going to store the resource depending on its size */ + if (length_to_add) { + if (!cache_accepts_entries_of_size (cache, length_to_add)) + return FALSE; + + /* Make room for new entry if needed */ + make_room_for_new_entry (cache, length_to_add); + } + + /* Remove any previous entry */ + if ((old_entry = g_hash_table_lookup (cache->priv->cache, GUINT_TO_POINTER (entry->key))) != NULL) { + if (!soup_cache_entry_remove (cache, old_entry, TRUE)) + return FALSE; + } + + /* Add to hash table */ + g_hash_table_insert (cache->priv->cache, GUINT_TO_POINTER (entry->key), entry); + + /* Compute new cache size */ + cache->priv->size += length_to_add; + + /* Update LRU */ + if (sort) + cache->priv->lru_start = g_list_insert_sorted (cache->priv->lru_start, entry, lru_compare_func); + else + cache->priv->lru_start = g_list_prepend (cache->priv->lru_start, entry); + + g_assert (g_list_length (cache->priv->lru_start) == g_hash_table_size (cache->priv->cache)); + + return TRUE; +} + +static SoupCacheEntry* +soup_cache_entry_lookup (SoupCache *cache, + SoupMessage *msg) +{ + SoupCacheEntry *entry; + guint32 key; + char *uri = NULL; + + uri = soup_uri_to_string (soup_message_get_uri (msg), FALSE); + key = get_cache_key_from_uri ((const char *) uri); + + entry = g_hash_table_lookup (cache->priv->cache, GUINT_TO_POINTER (key)); + + if (entry != NULL && (strcmp (entry->uri, uri) != 0)) + entry = NULL; + + g_free (uri); + return entry; +} + +GInputStream * +soup_cache_send_response (SoupCache *cache, SoupMessage *msg) +{ + SoupCacheEntry *entry; + GInputStream *file_stream, *body_stream, *cache_stream, *client_stream; + GFile *file; + + g_return_val_if_fail (SOUP_IS_CACHE (cache), NULL); + g_return_val_if_fail (SOUP_IS_MESSAGE (msg), NULL); + + entry = soup_cache_entry_lookup (cache, msg); + g_return_val_if_fail (entry, NULL); + + file = get_file_from_entry (cache, entry); + file_stream = G_INPUT_STREAM (g_file_read (file, NULL, NULL)); + g_object_unref (file); + + /* Do not change the original message if there is no resource */ + if (!file_stream) + return NULL; + + body_stream = soup_body_input_stream_new (file_stream, SOUP_ENCODING_CONTENT_LENGTH, entry->length); + g_object_unref (file_stream); + + if (!body_stream) + return NULL; + + /* If we are told to send a response from cache any validation + in course is over by now */ + entry->being_validated = FALSE; + + /* Message starting */ + soup_message_starting (msg); + + /* Status */ + soup_message_set_status (msg, entry->status_code); + + /* Headers */ + copy_end_to_end_headers (entry->headers, msg->response_headers); + + /* Create the cache stream. */ + soup_message_disable_feature (msg, SOUP_TYPE_CACHE); + cache_stream = soup_message_setup_body_istream (body_stream, msg, + cache->priv->session, + SOUP_STAGE_ENTITY_BODY); + g_object_unref (body_stream); + + client_stream = soup_cache_client_input_stream_new (cache_stream); + g_object_unref (cache_stream); + + return client_stream; +} + +static void +msg_got_headers_cb (SoupMessage *msg, gpointer user_data) +{ + g_object_set_data (G_OBJECT (msg), "response-time", GINT_TO_POINTER (time (NULL))); + g_signal_handlers_disconnect_by_func (msg, msg_got_headers_cb, user_data); +} + +static void +msg_starting_cb (SoupMessage *msg, gpointer user_data) +{ + g_object_set_data (G_OBJECT (msg), "request-time", GINT_TO_POINTER (time (NULL))); + g_signal_connect (msg, "got-headers", G_CALLBACK (msg_got_headers_cb), user_data); + g_signal_handlers_disconnect_by_func (msg, msg_starting_cb, user_data); +} + +static void +request_queued (SoupSessionFeature *feature, SoupSession *session, SoupMessage *msg) +{ + g_signal_connect (msg, "starting", G_CALLBACK (msg_starting_cb), feature); +} + +static void +attach (SoupSessionFeature *feature, SoupSession *session) +{ + SoupCache *cache = SOUP_CACHE (feature); + cache->priv->session = session; + + soup_cache_default_feature_interface->attach (feature, session); +} + +static void +soup_cache_session_feature_init (SoupSessionFeatureInterface *feature_interface, + gpointer interface_data) +{ + soup_cache_default_feature_interface = + g_type_default_interface_peek (SOUP_TYPE_SESSION_FEATURE); + + feature_interface->attach = attach; + feature_interface->request_queued = request_queued; +} + +typedef struct { + SoupCache *cache; + SoupCacheEntry *entry; +} StreamHelper; + +static void +istream_caching_finished (SoupCacheInputStream *istream, + gsize bytes_written, + GError *error, + gpointer user_data) +{ + StreamHelper *helper = (StreamHelper *) user_data; + SoupCache *cache = helper->cache; + SoupCacheEntry *entry = helper->entry; + + --cache->priv->n_pending; + + entry->dirty = FALSE; + entry->length = bytes_written; + g_clear_object (&entry->cancellable); + + if (error) { + /* Update cache size */ + if (soup_message_headers_get_encoding (entry->headers) == SOUP_ENCODING_CONTENT_LENGTH) + cache->priv->size -= soup_message_headers_get_content_length (entry->headers); + + soup_cache_entry_remove (cache, entry, TRUE); + helper->entry = entry = NULL; + goto cleanup; + } + + if (soup_message_headers_get_encoding (entry->headers) != SOUP_ENCODING_CONTENT_LENGTH) { + + if (cache_accepts_entries_of_size (cache, entry->length)) { + make_room_for_new_entry (cache, entry->length); + cache->priv->size += entry->length; + } else { + soup_cache_entry_remove (cache, entry, TRUE); + helper->entry = entry = NULL; + } + } + + cleanup: + g_object_unref (helper->cache); + g_slice_free (StreamHelper, helper); +} + +static GInputStream* +soup_cache_content_processor_wrap_input (SoupContentProcessor *processor, + GInputStream *base_stream, + SoupMessage *msg, + GError **error) +{ + SoupCache *cache = (SoupCache*) processor; + SoupCacheEntry *entry; + SoupCacheability cacheability; + GInputStream *istream; + GFile *file; + StreamHelper *helper; + time_t request_time, response_time; + + /* First of all, check if we should cache the resource. */ + cacheability = soup_cache_get_cacheability (cache, msg); + entry = soup_cache_entry_lookup (cache, msg); + + if (cacheability & SOUP_CACHE_INVALIDATES) { + if (entry) + soup_cache_entry_remove (cache, entry, TRUE); + return NULL; + } + + if (cacheability & SOUP_CACHE_VALIDATES) { + /* It's possible to get a CACHE_VALIDATES with no + * entry in the hash table. This could happen if for + * example the soup client is the one creating the + * conditional request. + */ + if (entry) + soup_cache_update_from_conditional_request (cache, msg); + return NULL; + } + + if (!(cacheability & SOUP_CACHE_CACHEABLE)) + return NULL; + + /* Check if we are already caching this resource */ + if (entry && (entry->dirty || entry->being_validated)) + return NULL; + + /* Create a new entry, deleting any old one if present */ + if (entry) + soup_cache_entry_remove (cache, entry, TRUE); + + request_time = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (msg), "request-time")); + response_time = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (msg), "response-time")); + entry = soup_cache_entry_new (cache, msg, request_time, response_time); + entry->hits = 1; + entry->dirty = TRUE; + + /* Do not continue if it can not be stored */ + if (!soup_cache_entry_insert (cache, entry, TRUE)) { + soup_cache_entry_free (entry); + return NULL; + } + + entry->cancellable = g_cancellable_new (); + ++cache->priv->n_pending; + + helper = g_slice_new (StreamHelper); + helper->cache = g_object_ref (cache); + helper->entry = entry; + + file = get_file_from_entry (cache, entry); + istream = soup_cache_input_stream_new (base_stream, file); + g_object_unref (file); + + g_signal_connect (istream, "caching-finished", G_CALLBACK (istream_caching_finished), helper); + + return istream; +} + +static void +soup_cache_content_processor_init (SoupContentProcessorInterface *processor_interface, + gpointer interface_data) +{ + soup_cache_default_content_processor_interface = + g_type_default_interface_peek (SOUP_TYPE_CONTENT_PROCESSOR); + + processor_interface->processing_stage = SOUP_STAGE_ENTITY_BODY; + processor_interface->wrap_input = soup_cache_content_processor_wrap_input; +} + +static void +soup_cache_init (SoupCache *cache) +{ + SoupCachePrivate *priv; + + priv = cache->priv = soup_cache_get_instance_private (cache); + + priv->cache = g_hash_table_new (g_direct_hash, g_direct_equal); + /* LRU */ + priv->lru_start = NULL; + + /* */ + priv->n_pending = 0; + + /* Cache size */ + priv->max_size = DEFAULT_MAX_SIZE; + priv->max_entry_data_size = priv->max_size / MAX_ENTRY_DATA_PERCENTAGE; + priv->size = 0; +} + +static void +remove_cache_item (gpointer data, + gpointer user_data) +{ + soup_cache_entry_remove ((SoupCache *) user_data, (SoupCacheEntry *) data, FALSE); +} + +static void +soup_cache_finalize (GObject *object) +{ + SoupCachePrivate *priv; + GList *entries; + + priv = SOUP_CACHE (object)->priv; + + /* Cannot use g_hash_table_foreach as callbacks must not modify the hash table */ + entries = g_hash_table_get_values (priv->cache); + g_list_foreach (entries, remove_cache_item, object); + g_list_free (entries); + + g_hash_table_destroy (priv->cache); + g_free (priv->cache_dir); + + g_list_free (priv->lru_start); + + G_OBJECT_CLASS (soup_cache_parent_class)->finalize (object); +} + +static void +soup_cache_set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + SoupCachePrivate *priv = SOUP_CACHE (object)->priv; + + switch (prop_id) { + case PROP_CACHE_DIR: + g_assert (!priv->cache_dir); + + priv->cache_dir = g_value_dup_string (value); + + if (!priv->cache_dir) + /* Set a default cache dir, different for each user */ + priv->cache_dir = g_build_filename (g_get_user_cache_dir (), + "httpcache", + NULL); + + /* Create directory if it does not exist */ + if (!g_file_test (priv->cache_dir, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) + g_mkdir_with_parents (priv->cache_dir, 0700); + break; + case PROP_CACHE_TYPE: + priv->cache_type = g_value_get_enum (value); + /* TODO: clear private entries and issue a warning if moving to shared? */ + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +soup_cache_get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + SoupCachePrivate *priv = SOUP_CACHE (object)->priv; + + switch (prop_id) { + case PROP_CACHE_DIR: + g_value_set_string (value, priv->cache_dir); + break; + case PROP_CACHE_TYPE: + g_value_set_enum (value, priv->cache_type); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +soup_cache_class_init (SoupCacheClass *cache_class) +{ + GObjectClass *gobject_class = (GObjectClass *)cache_class; + + gobject_class->finalize = soup_cache_finalize; + gobject_class->set_property = soup_cache_set_property; + gobject_class->get_property = soup_cache_get_property; + + cache_class->get_cacheability = get_cacheability; + + g_object_class_install_property (gobject_class, PROP_CACHE_DIR, + g_param_spec_string ("cache-dir", + "Cache directory", + "The directory to store the cache files", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property (gobject_class, PROP_CACHE_TYPE, + g_param_spec_enum ("cache-type", + "Cache type", + "Whether the cache is private or shared", + SOUP_TYPE_CACHE_TYPE, + SOUP_CACHE_SINGLE_USER, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); +} + +/** + * SoupCacheType: + * @SOUP_CACHE_SINGLE_USER: a single-user cache + * @SOUP_CACHE_SHARED: a shared cache + * + * The type of cache; this affects what kinds of responses will be + * saved. + * + * Since: 2.34 + */ + +/** + * soup_cache_new: + * @cache_dir: (allow-none): the directory to store the cached data, or %NULL + * to use the default one. Note that since the cache isn't safe to access for + * multiple processes at once, and the default directory isn't namespaced by + * process, clients are strongly discouraged from passing %NULL. + * @cache_type: the #SoupCacheType of the cache + * + * Creates a new #SoupCache. + * + * Returns: a new #SoupCache + * + * Since: 2.34 + */ +SoupCache * +soup_cache_new (const char *cache_dir, SoupCacheType cache_type) +{ + return g_object_new (SOUP_TYPE_CACHE, + "cache-dir", cache_dir, + "cache-type", cache_type, + NULL); +} + +/** + * soup_cache_has_response: + * @cache: a #SoupCache + * @msg: a #SoupMessage + * + * This function calculates whether the @cache object has a proper + * response for the request @msg given the flags both in the request + * and the cached reply and the time ellapsed since it was cached. + * + * Returns: whether or not the @cache has a valid response for @msg + * + * Since: 2.34 + */ +SoupCacheResponse +soup_cache_has_response (SoupCache *cache, SoupMessage *msg) +{ + SoupCacheEntry *entry; + const char *cache_control; + gpointer value; + int max_age, max_stale, min_fresh; + GList *lru_item, *item; + + entry = soup_cache_entry_lookup (cache, msg); + + /* 1. The presented Request-URI and that of stored response + * match + */ + if (!entry) + return SOUP_CACHE_RESPONSE_STALE; + + /* Increase hit count. Take sorting into account */ + entry->hits++; + lru_item = g_list_find (cache->priv->lru_start, entry); + item = lru_item; + while (item->next && lru_compare_func (item->data, item->next->data) > 0) + item = g_list_next (item); + + if (item != lru_item) { + cache->priv->lru_start = g_list_remove_link (cache->priv->lru_start, lru_item); + item = g_list_insert_sorted (item, lru_item->data, lru_compare_func); + g_list_free (lru_item); + } + + if (entry->dirty || entry->being_validated) + return SOUP_CACHE_RESPONSE_STALE; + + /* 2. The request method associated with the stored response + * allows it to be used for the presented request + */ + + /* In practice this means we only return our resource for GET, + * cacheability for other methods is a TODO in the RFC + * (TODO: although we could return the headers for HEAD + * probably). + */ + if (msg->method != SOUP_METHOD_GET) + return SOUP_CACHE_RESPONSE_STALE; + + /* 3. Selecting request-headers nominated by the stored + * response (if any) match those presented. + */ + + /* TODO */ + + /* 4. The request is a conditional request issued by the client. + */ + if (soup_message_headers_get_one (msg->request_headers, "If-Modified-Since") || + soup_message_headers_get_list (msg->request_headers, "If-None-Match")) + return SOUP_CACHE_RESPONSE_STALE; + + /* 5. The presented request and stored response are free from + * directives that would prevent its use. + */ + + max_age = max_stale = min_fresh = -1; + + /* For HTTP 1.0 compatibility. RFC2616 section 14.9.4 + */ + if (soup_message_headers_header_contains (msg->request_headers, "Pragma", "no-cache")) + return SOUP_CACHE_RESPONSE_STALE; + + cache_control = soup_message_headers_get_list (msg->request_headers, "Cache-Control"); + if (cache_control && *cache_control) { + GHashTable *hash = soup_header_parse_param_list (cache_control); + + if (g_hash_table_lookup_extended (hash, "no-store", NULL, NULL)) { + soup_header_free_param_list (hash); + return SOUP_CACHE_RESPONSE_STALE; + } + + if (g_hash_table_lookup_extended (hash, "no-cache", NULL, NULL)) { + soup_header_free_param_list (hash); + return SOUP_CACHE_RESPONSE_STALE; + } + + if (g_hash_table_lookup_extended (hash, "max-age", NULL, &value) && value) { + max_age = (int)MIN (g_ascii_strtoll (value, NULL, 10), G_MAXINT32); + /* Forcing cache revalidaton + */ + if (!max_age) { + soup_header_free_param_list (hash); + return SOUP_CACHE_RESPONSE_NEEDS_VALIDATION; + } + } + + /* max-stale can have no value set, we need to use _extended */ + if (g_hash_table_lookup_extended (hash, "max-stale", NULL, &value)) { + if (value) + max_stale = (int)MIN (g_ascii_strtoll (value, NULL, 10), G_MAXINT32); + else + max_stale = G_MAXINT32; + } + + value = g_hash_table_lookup (hash, "min-fresh"); + if (value) + min_fresh = (int)MIN (g_ascii_strtoll (value, NULL, 10), G_MAXINT32); + + soup_header_free_param_list (hash); + + if (max_age > 0) { + guint current_age = soup_cache_entry_get_current_age (entry); + + /* If we are over max-age and max-stale is not + set, do not use the value from the cache + without validation */ + if ((guint) max_age <= current_age && max_stale == -1) + return SOUP_CACHE_RESPONSE_NEEDS_VALIDATION; + } + } + + /* 6. The stored response is either: fresh, allowed to be + * served stale or succesfully validated + */ + if (!soup_cache_entry_is_fresh_enough (entry, min_fresh)) { + /* Not fresh, can it be served stale? */ + + /* When the must-revalidate directive is present in a + * response received by a cache, that cache MUST NOT + * use the entry after it becomes stale + */ + /* TODO consider also proxy-revalidate & s-maxage */ + if (entry->must_revalidate) + return SOUP_CACHE_RESPONSE_NEEDS_VALIDATION; + + if (max_stale != -1) { + /* G_MAXINT32 means we accept any staleness */ + if (max_stale == G_MAXINT32) + return SOUP_CACHE_RESPONSE_FRESH; + + if ((soup_cache_entry_get_current_age (entry) - entry->freshness_lifetime) <= (guint) max_stale) + return SOUP_CACHE_RESPONSE_FRESH; + } + + return SOUP_CACHE_RESPONSE_NEEDS_VALIDATION; + } + + return SOUP_CACHE_RESPONSE_FRESH; +} + +/** + * soup_cache_get_cacheability: + * @cache: a #SoupCache + * @msg: a #SoupMessage + * + * Calculates whether the @msg can be cached or not. + * + * Returns: a #SoupCacheability value indicating whether the @msg can be cached or not. + * + * Since: 2.34 + */ +SoupCacheability +soup_cache_get_cacheability (SoupCache *cache, SoupMessage *msg) +{ + g_return_val_if_fail (SOUP_IS_CACHE (cache), SOUP_CACHE_UNCACHEABLE); + g_return_val_if_fail (SOUP_IS_MESSAGE (msg), SOUP_CACHE_UNCACHEABLE); + + return SOUP_CACHE_GET_CLASS (cache)->get_cacheability (cache, msg); +} + +static gboolean +force_flush_timeout (gpointer data) +{ + gboolean *forced = (gboolean *)data; + *forced = TRUE; + + return FALSE; +} + +/** + * soup_cache_flush: + * @cache: a #SoupCache + * + * This function will force all pending writes in the @cache to be + * committed to disk. For doing so it will iterate the #GMainContext + * associated with @cache's session as long as needed. + * + * Contrast with soup_cache_dump(), which writes out the cache index + * file. + * + * Since: 2.34 + */ +void +soup_cache_flush (SoupCache *cache) +{ + GMainContext *async_context; + SoupSession *session; + GSource *timeout; + gboolean forced = FALSE; + + g_return_if_fail (SOUP_IS_CACHE (cache)); + + session = cache->priv->session; + g_return_if_fail (SOUP_IS_SESSION (session)); + async_context = soup_session_get_async_context (session); + + /* We give cache 10 secs to finish */ + timeout = soup_add_timeout (async_context, 10000, force_flush_timeout, &forced); + + while (!forced && cache->priv->n_pending > 0) + g_main_context_iteration (async_context, FALSE); + + if (!forced) + g_source_destroy (timeout); + else + g_warning ("Cache flush finished despite %d pending requests", cache->priv->n_pending); +} + +typedef void (* SoupCacheForeachFileFunc) (SoupCache *cache, const char *name, gpointer user_data); + +static void +soup_cache_foreach_file (SoupCache *cache, SoupCacheForeachFileFunc func, gpointer user_data) +{ + GDir *dir; + const char *name; + SoupCachePrivate *priv = cache->priv; + + dir = g_dir_open (priv->cache_dir, 0, NULL); + while ((name = g_dir_read_name (dir))) { + if (g_str_has_prefix (name, "soup.")) + continue; + + func (cache, name, user_data); + } + g_dir_close (dir); +} + +static void +clear_cache_item (gpointer data, + gpointer user_data) +{ + soup_cache_entry_remove ((SoupCache *) user_data, (SoupCacheEntry *) data, TRUE); +} + +static void +delete_cache_file (SoupCache *cache, const char *name, gpointer user_data) +{ + gchar *path; + + path = g_build_filename (cache->priv->cache_dir, name, NULL); + g_unlink (path); + g_free (path); +} + +static void +clear_cache_files (SoupCache *cache) +{ + soup_cache_foreach_file (cache, delete_cache_file, NULL); +} + +/** + * soup_cache_clear: + * @cache: a #SoupCache + * + * Will remove all entries in the @cache plus all the cache files. + * + * Since: 2.34 + */ +void +soup_cache_clear (SoupCache *cache) +{ + GList *entries; + + g_return_if_fail (SOUP_IS_CACHE (cache)); + g_return_if_fail (cache->priv->cache); + + /* Cannot use g_hash_table_foreach as callbacks must not modify the hash table */ + entries = g_hash_table_get_values (cache->priv->cache); + g_list_foreach (entries, clear_cache_item, cache); + g_list_free (entries); + + /* Remove also any file not associated with a cache entry. */ + clear_cache_files (cache); +} + +SoupMessage * +soup_cache_generate_conditional_request (SoupCache *cache, SoupMessage *original) +{ + SoupMessage *msg; + SoupURI *uri; + SoupCacheEntry *entry; + const char *last_modified, *etag; + SoupMessagePrivate *origpriv; + GSList *f; + + g_return_val_if_fail (SOUP_IS_CACHE (cache), NULL); + g_return_val_if_fail (SOUP_IS_MESSAGE (original), NULL); + + /* Add the validator entries in the header from the cached data */ + entry = soup_cache_entry_lookup (cache, original); + g_return_val_if_fail (entry, NULL); + + last_modified = soup_message_headers_get_one (entry->headers, "Last-Modified"); + etag = soup_message_headers_get_one (entry->headers, "ETag"); + + if (!last_modified && !etag) + return NULL; + + entry->being_validated = TRUE; + + /* Copy the data we need from the original message */ + uri = soup_message_get_uri (original); + msg = soup_message_new_from_uri (original->method, uri); + soup_message_set_flags (msg, soup_message_get_flags (original)); + soup_message_disable_feature (msg, SOUP_TYPE_CACHE); + + soup_message_headers_foreach (original->request_headers, + (SoupMessageHeadersForeachFunc)copy_headers, + msg->request_headers); + + origpriv = SOUP_MESSAGE_GET_PRIVATE (original); + for (f = origpriv->disabled_features; f; f = f->next) + soup_message_disable_feature (msg, (GType) GPOINTER_TO_SIZE (f->data)); + + if (last_modified) + soup_message_headers_append (msg->request_headers, + "If-Modified-Since", + last_modified); + if (etag) + soup_message_headers_append (msg->request_headers, + "If-None-Match", + etag); + + return msg; +} + +void +soup_cache_cancel_conditional_request (SoupCache *cache, + SoupMessage *msg) +{ + SoupCacheEntry *entry; + + entry = soup_cache_entry_lookup (cache, msg); + if (entry) + entry->being_validated = FALSE; + + soup_session_cancel_message (cache->priv->session, msg, SOUP_STATUS_CANCELLED); +} + +void +soup_cache_update_from_conditional_request (SoupCache *cache, + SoupMessage *msg) +{ + SoupCacheEntry *entry = soup_cache_entry_lookup (cache, msg); + if (!entry) + return; + + entry->being_validated = FALSE; + + if (msg->status_code == SOUP_STATUS_NOT_MODIFIED) { + soup_message_headers_foreach (msg->response_headers, + (SoupMessageHeadersForeachFunc) remove_headers, + entry->headers); + copy_end_to_end_headers (msg->response_headers, entry->headers); + + soup_cache_entry_set_freshness (entry, msg, cache); + } +} + +static void +pack_entry (gpointer data, + gpointer user_data) +{ + SoupCacheEntry *entry = (SoupCacheEntry *) data; + SoupMessageHeadersIter iter; + const char *header_key, *header_value; + GVariantBuilder *entries_builder = (GVariantBuilder *)user_data; + + /* Do not store non-consolidated entries */ + if (entry->dirty || !entry->key) + return; + + g_variant_builder_open (entries_builder, G_VARIANT_TYPE (SOUP_CACHE_PHEADERS_FORMAT)); + g_variant_builder_add (entries_builder, "s", entry->uri); + g_variant_builder_add (entries_builder, "b", entry->must_revalidate); + g_variant_builder_add (entries_builder, "u", entry->freshness_lifetime); + g_variant_builder_add (entries_builder, "u", entry->corrected_initial_age); + g_variant_builder_add (entries_builder, "u", entry->response_time); + g_variant_builder_add (entries_builder, "u", entry->hits); + g_variant_builder_add (entries_builder, "u", entry->length); + g_variant_builder_add (entries_builder, "q", entry->status_code); + + /* Pack headers */ + g_variant_builder_open (entries_builder, G_VARIANT_TYPE ("a" SOUP_CACHE_HEADERS_FORMAT)); + soup_message_headers_iter_init (&iter, entry->headers); + while (soup_message_headers_iter_next (&iter, &header_key, &header_value)) { + if (g_utf8_validate (header_value, -1, NULL)) + g_variant_builder_add (entries_builder, SOUP_CACHE_HEADERS_FORMAT, + header_key, header_value); + } + g_variant_builder_close (entries_builder); /* "a" SOUP_CACHE_HEADERS_FORMAT */ + g_variant_builder_close (entries_builder); /* SOUP_CACHE_PHEADERS_FORMAT */ +} + +/** + * soup_cache_dump: + * @cache: a #SoupCache + * + * Synchronously writes the cache index out to disk. Contrast with + * soup_cache_flush(), which writes pending cache + * entries to disk. + * + * You must call this before exiting if you want your cache data to + * persist between sessions. + * + * Since: 2.34. + */ +void +soup_cache_dump (SoupCache *cache) +{ + SoupCachePrivate *priv = soup_cache_get_instance_private (cache); + char *filename; + GVariantBuilder entries_builder; + GVariant *cache_variant; + + if (!g_list_length (cache->priv->lru_start)) + return; + + /* Create the builder and iterate over all entries */ + g_variant_builder_init (&entries_builder, G_VARIANT_TYPE (SOUP_CACHE_ENTRIES_FORMAT)); + g_variant_builder_add (&entries_builder, "q", SOUP_CACHE_CURRENT_VERSION); + g_variant_builder_open (&entries_builder, G_VARIANT_TYPE ("a" SOUP_CACHE_PHEADERS_FORMAT)); + g_list_foreach (cache->priv->lru_start, pack_entry, &entries_builder); + g_variant_builder_close (&entries_builder); + + /* Serialize and dump */ + cache_variant = g_variant_builder_end (&entries_builder); + g_variant_ref_sink (cache_variant); + filename = g_build_filename (priv->cache_dir, SOUP_CACHE_FILE, NULL); + g_file_set_contents (filename, (const char *) g_variant_get_data (cache_variant), + g_variant_get_size (cache_variant), NULL); + g_free (filename); + g_variant_unref (cache_variant); +} + +static inline guint32 +get_key_from_cache_filename (const char *name) +{ + guint64 key; + + key = g_ascii_strtoull (name, NULL, 10); + return key ? (guint32)key : 0; +} + +static void +insert_cache_file (SoupCache *cache, const char *name, GHashTable *leaked_entries) +{ + gchar *path; + + path = g_build_filename (cache->priv->cache_dir, name, NULL); + if (g_file_test (path, G_FILE_TEST_IS_REGULAR)) { + guint32 key = get_key_from_cache_filename (name); + + if (key) { + g_hash_table_insert (leaked_entries, GUINT_TO_POINTER (key), path); + return; + } + } + g_free (path); +} + +/** + * soup_cache_load: + * @cache: a #SoupCache + * + * Loads the contents of @cache's index into memory. + * + * Since: 2.34 + */ +void +soup_cache_load (SoupCache *cache) +{ + gboolean must_revalidate; + guint32 freshness_lifetime, hits; + guint32 corrected_initial_age, response_time; + char *url, *filename = NULL, *contents = NULL; + GVariant *cache_variant; + GVariantIter *entries_iter = NULL, *headers_iter = NULL; + gsize length; + SoupCacheEntry *entry; + SoupCachePrivate *priv = cache->priv; + guint16 version, status_code; + GHashTable *leaked_entries = NULL; + GHashTableIter iter; + gpointer value; + + filename = g_build_filename (priv->cache_dir, SOUP_CACHE_FILE, NULL); + if (!g_file_get_contents (filename, &contents, &length, NULL)) { + g_free (filename); + g_free (contents); + clear_cache_files (cache); + return; + } + g_free (filename); + + cache_variant = g_variant_new_from_data (G_VARIANT_TYPE (SOUP_CACHE_ENTRIES_FORMAT), + (const char *) contents, length, FALSE, g_free, contents); + g_variant_get (cache_variant, SOUP_CACHE_ENTRIES_FORMAT, &version, &entries_iter); + if (version != SOUP_CACHE_CURRENT_VERSION) { + g_variant_iter_free (entries_iter); + g_variant_unref (cache_variant); + clear_cache_files (cache); + return; + } + + leaked_entries = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free); + soup_cache_foreach_file (cache, (SoupCacheForeachFileFunc)insert_cache_file, leaked_entries); + + while (g_variant_iter_loop (entries_iter, SOUP_CACHE_PHEADERS_FORMAT, + &url, &must_revalidate, &freshness_lifetime, &corrected_initial_age, + &response_time, &hits, &length, &status_code, + &headers_iter)) { + const char *header_key, *header_value; + SoupMessageHeaders *headers; + SoupMessageHeadersIter soup_headers_iter; + + /* SoupMessage Headers */ + headers = soup_message_headers_new (SOUP_MESSAGE_HEADERS_RESPONSE); + while (g_variant_iter_loop (headers_iter, SOUP_CACHE_HEADERS_FORMAT, &header_key, &header_value)) + if (*header_key && *header_value) + soup_message_headers_append (headers, header_key, header_value); + + /* Check that we have headers */ + soup_message_headers_iter_init (&soup_headers_iter, headers); + if (!soup_message_headers_iter_next (&soup_headers_iter, &header_key, &header_value)) { + soup_message_headers_free (headers); + continue; + } + + /* Insert in cache */ + entry = g_slice_new0 (SoupCacheEntry); + entry->uri = g_strdup (url); + entry->must_revalidate = must_revalidate; + entry->freshness_lifetime = freshness_lifetime; + entry->corrected_initial_age = corrected_initial_age; + entry->response_time = response_time; + entry->hits = hits; + entry->length = length; + entry->headers = headers; + entry->status_code = status_code; + + if (!soup_cache_entry_insert (cache, entry, FALSE)) + soup_cache_entry_free (entry); + else + g_hash_table_remove (leaked_entries, GUINT_TO_POINTER (entry->key)); + } + + /* Remove the leaked files */ + g_hash_table_iter_init (&iter, leaked_entries); + while (g_hash_table_iter_next (&iter, NULL, &value)) + g_unlink ((char *)value); + g_hash_table_destroy (leaked_entries); + + cache->priv->lru_start = g_list_reverse (cache->priv->lru_start); + + /* frees */ + g_variant_iter_free (entries_iter); + g_variant_unref (cache_variant); +} + +/** + * soup_cache_set_max_size: + * @cache: a #SoupCache + * @max_size: the maximum size of the cache, in bytes + * + * Sets the maximum size of the cache. + * + * Since: 2.34 + */ +void +soup_cache_set_max_size (SoupCache *cache, + guint max_size) +{ + cache->priv->max_size = max_size; + cache->priv->max_entry_data_size = cache->priv->max_size / MAX_ENTRY_DATA_PERCENTAGE; +} + +/** + * soup_cache_get_max_size: + * @cache: a #SoupCache + * + * Gets the maximum size of the cache. + * + * Return value: the maximum size of the cache, in bytes. + * + * Since: 2.34 + */ +guint +soup_cache_get_max_size (SoupCache *cache) +{ + return cache->priv->max_size; +} diff --git a/libsoup/soup-cache.h b/libsoup/soup-cache.h new file mode 100644 index 0000000..ce19b5e --- /dev/null +++ b/libsoup/soup-cache.h @@ -0,0 +1,102 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-cache.h: + * + * Copyright (C) 2009, 2010 Igalia, S.L. + * + * 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, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef SOUP_CACHE_H +#define SOUP_CACHE_H 1 + +#include +#include + +G_BEGIN_DECLS + +#define SOUP_TYPE_CACHE (soup_cache_get_type ()) +#define SOUP_CACHE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SOUP_TYPE_CACHE, SoupCache)) +#define SOUP_CACHE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_CACHE, SoupCacheClass)) +#define SOUP_IS_CACHE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SOUP_TYPE_CACHE)) +#define SOUP_IS_CACHE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), SOUP_TYPE_CACHE)) +#define SOUP_CACHE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_CACHE, SoupCacheClass)) + +typedef struct _SoupCache SoupCache; +typedef struct _SoupCachePrivate SoupCachePrivate; + +typedef enum { + SOUP_CACHE_CACHEABLE = (1 << 0), + SOUP_CACHE_UNCACHEABLE = (1 << 1), + SOUP_CACHE_INVALIDATES = (1 << 2), + SOUP_CACHE_VALIDATES = (1 << 3) +} SoupCacheability; + +typedef enum { + SOUP_CACHE_RESPONSE_FRESH, + SOUP_CACHE_RESPONSE_NEEDS_VALIDATION, + SOUP_CACHE_RESPONSE_STALE +} SoupCacheResponse; + +typedef enum { + SOUP_CACHE_SINGLE_USER, + SOUP_CACHE_SHARED +} SoupCacheType; + +struct _SoupCache { + GObject parent_instance; + + SoupCachePrivate *priv; +}; + +typedef struct { + GObjectClass parent_class; + + /* methods */ + SoupCacheability (*get_cacheability) (SoupCache *cache, + SoupMessage *msg); + + /* Padding for future expansion */ + void (*_libsoup_reserved1)(void); + void (*_libsoup_reserved2)(void); + void (*_libsoup_reserved3)(void); +} SoupCacheClass; + +SOUP_AVAILABLE_IN_2_34 +GType soup_cache_get_type (void); +SOUP_AVAILABLE_IN_2_34 +SoupCache *soup_cache_new (const char *cache_dir, + SoupCacheType cache_type); +SOUP_AVAILABLE_IN_2_34 +void soup_cache_flush (SoupCache *cache); +SOUP_AVAILABLE_IN_2_34 +void soup_cache_clear (SoupCache *cache); + +SOUP_AVAILABLE_IN_2_34 +void soup_cache_dump (SoupCache *cache); +SOUP_AVAILABLE_IN_2_34 +void soup_cache_load (SoupCache *cache); + +SOUP_AVAILABLE_IN_2_34 +void soup_cache_set_max_size (SoupCache *cache, + guint max_size); +SOUP_AVAILABLE_IN_2_34 +guint soup_cache_get_max_size (SoupCache *cache); + +G_END_DECLS + +#endif /* SOUP_CACHE_H */ + diff --git a/libsoup/soup-client-input-stream.c b/libsoup/soup-client-input-stream.c new file mode 100644 index 0000000..c305dd8 --- /dev/null +++ b/libsoup/soup-client-input-stream.c @@ -0,0 +1,262 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-client-input-stream.c + * + * Copyright 2010-2012 Red Hat, Inc. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "soup-client-input-stream.h" +#include "soup.h" +#include "soup-message-private.h" + +struct _SoupClientInputStreamPrivate { + SoupMessage *msg; +}; + +enum { + SIGNAL_EOF, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +enum { + PROP_0, + + PROP_MESSAGE +}; + +static GPollableInputStreamInterface *soup_client_input_stream_parent_pollable_interface; +static void soup_client_input_stream_pollable_init (GPollableInputStreamInterface *pollable_interface, gpointer interface_data); + +G_DEFINE_TYPE_WITH_CODE (SoupClientInputStream, soup_client_input_stream, SOUP_TYPE_FILTER_INPUT_STREAM, + G_ADD_PRIVATE (SoupClientInputStream) + G_IMPLEMENT_INTERFACE (G_TYPE_POLLABLE_INPUT_STREAM, + soup_client_input_stream_pollable_init)) + +static void +soup_client_input_stream_init (SoupClientInputStream *stream) +{ + stream->priv = soup_client_input_stream_get_instance_private (stream); +} + +static void +soup_client_input_stream_finalize (GObject *object) +{ + SoupClientInputStream *cistream = SOUP_CLIENT_INPUT_STREAM (object); + + g_clear_object (&cistream->priv->msg); + + G_OBJECT_CLASS (soup_client_input_stream_parent_class)->finalize (object); +} + +static void +soup_client_input_stream_set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + SoupClientInputStream *cistream = SOUP_CLIENT_INPUT_STREAM (object); + + switch (prop_id) { + case PROP_MESSAGE: + cistream->priv->msg = g_value_dup_object (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +soup_client_input_stream_get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + SoupClientInputStream *cistream = SOUP_CLIENT_INPUT_STREAM (object); + + switch (prop_id) { + case PROP_MESSAGE: + g_value_set_object (value, cistream->priv->msg); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static gssize +soup_client_input_stream_read_fn (GInputStream *stream, + void *buffer, + gsize count, + GCancellable *cancellable, + GError **error) +{ + gssize nread; + + nread = G_INPUT_STREAM_CLASS (soup_client_input_stream_parent_class)-> + read_fn (stream, buffer, count, cancellable, error); + + if (nread == 0) + g_signal_emit (stream, signals[SIGNAL_EOF], 0); + + return nread; +} + +static gssize +soup_client_input_stream_read_nonblocking (GPollableInputStream *stream, + void *buffer, + gsize count, + GError **error) +{ + gssize nread; + + nread = soup_client_input_stream_parent_pollable_interface-> + read_nonblocking (stream, buffer, count, error); + + if (nread == 0) + g_signal_emit (stream, signals[SIGNAL_EOF], 0); + + return nread; +} + +static gboolean +soup_client_input_stream_close_fn (GInputStream *stream, + GCancellable *cancellable, + GError **error) +{ + SoupClientInputStream *cistream = SOUP_CLIENT_INPUT_STREAM (stream); + gboolean success; + + success = soup_message_io_run_until_finish (cistream->priv->msg, TRUE, + NULL, error); + soup_message_io_finished (cistream->priv->msg); + return success; +} + +static gboolean +idle_finish_close (gpointer user_data) +{ + GTask *task = user_data; + + g_task_return_boolean (task, TRUE); + g_object_unref (task); + return FALSE; +} + +static gboolean +close_async_ready (SoupMessage *msg, gpointer user_data) +{ + GTask *task = user_data; + SoupClientInputStream *cistream = g_task_get_source_object (task); + GError *error = NULL; + + if (!soup_message_io_run_until_finish (cistream->priv->msg, FALSE, + g_task_get_cancellable (task), + &error) && + g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) { + g_error_free (error); + return TRUE; + } + + soup_message_io_finished (cistream->priv->msg); + + if (error) { + g_task_return_error (task, error); + g_object_unref (task); + return FALSE; + } + + /* Due to a historical accident, SoupSessionAsync relies on us + * waiting one extra cycle after run_until_finish() returns. + * Ugh. FIXME later when it's easier to do. + */ + soup_add_idle (g_main_context_get_thread_default (), + idle_finish_close, task); + return FALSE; +} + +static void +soup_client_input_stream_close_async (GInputStream *stream, + gint priority, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + SoupClientInputStream *cistream = SOUP_CLIENT_INPUT_STREAM (stream); + GTask *task; + GSource *source; + + task = g_task_new (stream, cancellable, callback, user_data); + g_task_set_priority (task, priority); + + if (close_async_ready (cistream->priv->msg, task) == G_SOURCE_CONTINUE) { + source = soup_message_io_get_source (cistream->priv->msg, + cancellable, NULL, NULL); + + g_task_attach_source (task, source, (GSourceFunc) close_async_ready); + g_source_unref (source); + } +} + +static gboolean +soup_client_input_stream_close_finish (GInputStream *stream, + GAsyncResult *result, + GError **error) +{ + return g_task_propagate_boolean (G_TASK (result), error); +} + +static void +soup_client_input_stream_class_init (SoupClientInputStreamClass *stream_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (stream_class); + GInputStreamClass *input_stream_class = G_INPUT_STREAM_CLASS (stream_class); + + object_class->finalize = soup_client_input_stream_finalize; + object_class->set_property = soup_client_input_stream_set_property; + object_class->get_property = soup_client_input_stream_get_property; + + input_stream_class->read_fn = soup_client_input_stream_read_fn; + input_stream_class->close_fn = soup_client_input_stream_close_fn; + input_stream_class->close_async = soup_client_input_stream_close_async; + input_stream_class->close_finish = soup_client_input_stream_close_finish; + + signals[SIGNAL_EOF] = + g_signal_new ("eof", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + NULL, + G_TYPE_NONE, 0); + + g_object_class_install_property ( + object_class, PROP_MESSAGE, + g_param_spec_object ("message", + "Message", + "Message", + SOUP_TYPE_MESSAGE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); +} + +static void +soup_client_input_stream_pollable_init (GPollableInputStreamInterface *pollable_interface, + gpointer interface_data) +{ + soup_client_input_stream_parent_pollable_interface = + g_type_interface_peek_parent (pollable_interface); + + pollable_interface->read_nonblocking = soup_client_input_stream_read_nonblocking; +} + +GInputStream * +soup_client_input_stream_new (GInputStream *base_stream, + SoupMessage *msg) +{ + return g_object_new (SOUP_TYPE_CLIENT_INPUT_STREAM, + "base-stream", base_stream, + "message", msg, + NULL); +} diff --git a/libsoup/soup-client-input-stream.h b/libsoup/soup-client-input-stream.h new file mode 100644 index 0000000..098c607 --- /dev/null +++ b/libsoup/soup-client-input-stream.h @@ -0,0 +1,46 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright 2010-2012 Red Hat, Inc. + */ + +#ifndef SOUP_CLIENT_INPUT_STREAM_H +#define SOUP_CLIENT_INPUT_STREAM_H 1 + +#include "soup-types.h" +#include "soup-filter-input-stream.h" + +G_BEGIN_DECLS + +#define SOUP_TYPE_CLIENT_INPUT_STREAM (soup_client_input_stream_get_type ()) +#define SOUP_CLIENT_INPUT_STREAM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SOUP_TYPE_CLIENT_INPUT_STREAM, SoupClientInputStream)) +#define SOUP_CLIENT_INPUT_STREAM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_CLIENT_INPUT_STREAM, SoupClientInputStreamClass)) +#define SOUP_IS_CLIENT_INPUT_STREAM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SOUP_TYPE_CLIENT_INPUT_STREAM)) +#define SOUP_IS_CLIENT_INPUT_STREAM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), SOUP_TYPE_CLIENT_INPUT_STREAM)) +#define SOUP_CLIENT_INPUT_STREAM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_CLIENT_INPUT_STREAM, SoupClientInputStreamClass)) + +typedef struct _SoupClientInputStreamPrivate SoupClientInputStreamPrivate; + +typedef struct { + SoupFilterInputStream parent; + + SoupClientInputStreamPrivate *priv; +} SoupClientInputStream; + +typedef struct { + SoupFilterInputStreamClass parent_class; + + /* Padding for future expansion */ + void (*_libsoup_reserved1) (void); + void (*_libsoup_reserved2) (void); + void (*_libsoup_reserved3) (void); + void (*_libsoup_reserved4) (void); +} SoupClientInputStreamClass; + +GType soup_client_input_stream_get_type (void); + +GInputStream *soup_client_input_stream_new (GInputStream *base_stream, + SoupMessage *msg); + +G_END_DECLS + +#endif /* SOUP_CLIENT_INPUT_STREAM_H */ diff --git a/libsoup/soup-connection-auth.c b/libsoup/soup-connection-auth.c new file mode 100644 index 0000000..f55cfe6 --- /dev/null +++ b/libsoup/soup-connection-auth.c @@ -0,0 +1,190 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-connection-auth.c: Abstract base class for hacky Microsoft + * connection-based auth mechanisms (NTLM and Negotiate) + * + * Copyright (C) 2010 Red Hat, Inc. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include "soup-connection-auth.h" +#include "soup.h" +#include "soup-connection.h" +#include "soup-message-private.h" + +struct SoupConnectionAuthPrivate { + GHashTable *conns; +}; + +G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (SoupConnectionAuth, soup_connection_auth, SOUP_TYPE_AUTH) + +static void +soup_connection_auth_init (SoupConnectionAuth *auth) +{ + auth->priv = soup_connection_auth_get_instance_private (auth); + + auth->priv->conns = g_hash_table_new (NULL, NULL); +} + +static void connection_disconnected (SoupConnection *conn, gpointer user_data); + +static void +soup_connection_auth_free_connection_state (SoupConnectionAuth *auth, + SoupConnection *conn, + gpointer state) +{ + g_signal_handlers_disconnect_by_func (conn, G_CALLBACK (connection_disconnected), auth); + SOUP_CONNECTION_AUTH_GET_CLASS (auth)->free_connection_state (auth, state); +} + +static void +connection_disconnected (SoupConnection *conn, gpointer user_data) +{ + SoupConnectionAuth *auth = user_data; + gpointer state; + + state = g_hash_table_lookup (auth->priv->conns, conn); + g_hash_table_remove (auth->priv->conns, conn); + soup_connection_auth_free_connection_state (auth, conn, state); +} + +static void +soup_connection_auth_finalize (GObject *object) +{ + SoupConnectionAuth *auth = SOUP_CONNECTION_AUTH (object); + GHashTableIter iter; + gpointer conn, state; + + g_hash_table_iter_init (&iter, auth->priv->conns); + while (g_hash_table_iter_next (&iter, &conn, &state)) { + soup_connection_auth_free_connection_state (auth, conn, state); + g_hash_table_iter_remove (&iter); + } + g_hash_table_destroy (auth->priv->conns); + + G_OBJECT_CLASS (soup_connection_auth_parent_class)->finalize (object); +} + + +/** + * soup_connection_auth_get_connection_state_for_message: + * @auth: a #SoupConnectionAuth + * @msg: a #SoupMessage + * + * Returns an associated connection state object for the given @auth and @msg. + * + * This function is only useful from within implementations of SoupConnectionAuth + * subclasses. + * + * Return value: (transfer none): the connection state + * + * Since: 2.58 + **/ +gpointer +soup_connection_auth_get_connection_state_for_message (SoupConnectionAuth *auth, + SoupMessage *msg) +{ + SoupConnection *conn; + gpointer state; + + g_return_val_if_fail (SOUP_IS_CONNECTION_AUTH (auth), NULL); + g_return_val_if_fail (SOUP_IS_MESSAGE (msg), NULL); + + conn = soup_message_get_connection (msg); + state = g_hash_table_lookup (auth->priv->conns, conn); + if (state) + return state; + + state = SOUP_CONNECTION_AUTH_GET_CLASS (auth)->create_connection_state (auth); + if (conn) { + g_signal_connect (conn, "disconnected", + G_CALLBACK (connection_disconnected), auth); + } + + g_hash_table_insert (auth->priv->conns, conn, state); + return state; +} + +static gboolean +soup_connection_auth_update (SoupAuth *auth, + SoupMessage *msg, + GHashTable *auth_params) +{ + SoupConnectionAuth *cauth = SOUP_CONNECTION_AUTH (auth); + gpointer conn = soup_connection_auth_get_connection_state_for_message (cauth, msg); + GHashTableIter iter; + GString *auth_header; + gpointer key, value; + gboolean result; + + /* Recreate @auth_header out of @auth_params. If the + * base64 data ended with 1 or more "="s, then it + * will have been parsed as key=value. Otherwise + * it will all have been parsed as key, and value + * will be %NULL. + */ + auth_header = g_string_new (soup_auth_get_scheme_name (auth)); + g_hash_table_iter_init (&iter, auth_params); + if (g_hash_table_iter_next (&iter, &key, &value)) { + if (value) { + g_string_append_printf (auth_header, " %s=%s", + (char *)key, + (char *)value); + } else { + g_string_append_printf (auth_header, " %s", + (char *)key); + } + + if (g_hash_table_iter_next (&iter, &key, &value)) { + g_string_free (auth_header, TRUE); + return FALSE; + } + } + + result = SOUP_CONNECTION_AUTH_GET_CLASS (auth)-> + update_connection (cauth, msg, auth_header->str, conn); + + g_string_free (auth_header, TRUE); + return result; +} + +static char * +soup_connection_auth_get_authorization (SoupAuth *auth, + SoupMessage *msg) +{ + SoupConnectionAuth *cauth = SOUP_CONNECTION_AUTH (auth); + gpointer conn = soup_connection_auth_get_connection_state_for_message (cauth, msg); + + return SOUP_CONNECTION_AUTH_GET_CLASS (auth)-> + get_connection_authorization (cauth, msg, conn); +} + +static gboolean +soup_connection_auth_is_ready (SoupAuth *auth, + SoupMessage *msg) +{ + SoupConnectionAuth *cauth = SOUP_CONNECTION_AUTH (auth); + gpointer conn = soup_connection_auth_get_connection_state_for_message (cauth, msg); + + return SOUP_CONNECTION_AUTH_GET_CLASS (auth)-> + is_connection_ready (SOUP_CONNECTION_AUTH (auth), msg, conn); +} + +static void +soup_connection_auth_class_init (SoupConnectionAuthClass *connauth_class) +{ + SoupAuthClass *auth_class = SOUP_AUTH_CLASS (connauth_class); + GObjectClass *object_class = G_OBJECT_CLASS (connauth_class); + + auth_class->update = soup_connection_auth_update; + auth_class->get_authorization = soup_connection_auth_get_authorization; + auth_class->is_ready = soup_connection_auth_is_ready; + + object_class->finalize = soup_connection_auth_finalize; +} diff --git a/libsoup/soup-connection-auth.h b/libsoup/soup-connection-auth.h new file mode 100644 index 0000000..c5fbe7b --- /dev/null +++ b/libsoup/soup-connection-auth.h @@ -0,0 +1,55 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2010 Red Hat, Inc. + */ + +#ifndef SOUP_CONNECTION_AUTH_H +#define SOUP_CONNECTION_AUTH_H 1 + +#include + +G_BEGIN_DECLS + +#define SOUP_TYPE_CONNECTION_AUTH (soup_connection_auth_get_type ()) +#define SOUP_CONNECTION_AUTH(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), SOUP_TYPE_CONNECTION_AUTH, SoupConnectionAuth)) +#define SOUP_CONNECTION_AUTH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_CONNECTION_AUTH, SoupConnectionAuthClass)) +#define SOUP_IS_CONNECTION_AUTH(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), SOUP_TYPE_CONNECTION_AUTH)) +#define SOUP_IS_CONNECTION_AUTH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SOUP_TYPE_CONNECTION_AUTH)) +#define SOUP_CONNECTION_AUTH_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_CONNECTION_AUTH, SoupConnectionAuthClass)) + +typedef struct SoupConnectionAuthPrivate SoupConnectionAuthPrivate; + +typedef struct { + SoupAuth parent; + + SoupConnectionAuthPrivate *priv; +} SoupConnectionAuth; + +typedef struct { + SoupAuthClass parent_class; + + gpointer (*create_connection_state) (SoupConnectionAuth *auth); + void (*free_connection_state) (SoupConnectionAuth *auth, + gpointer conn); + + gboolean (*update_connection) (SoupConnectionAuth *auth, + SoupMessage *msg, + const char *auth_header, + gpointer conn); + char *(*get_connection_authorization) (SoupConnectionAuth *auth, + SoupMessage *msg, + gpointer conn); + gboolean (*is_connection_ready) (SoupConnectionAuth *auth, + SoupMessage *msg, + gpointer conn); +} SoupConnectionAuthClass; + +GType soup_connection_auth_get_type (void); + +SOUP_AVAILABLE_IN_2_58 +gpointer soup_connection_auth_get_connection_state_for_message + (SoupConnectionAuth *auth, + SoupMessage *message); +G_END_DECLS + +#endif /* SOUP_CONNECTION_AUTH_H */ diff --git a/libsoup/soup-connection.c b/libsoup/soup-connection.c new file mode 100644 index 0000000..5fb4d78 --- /dev/null +++ b/libsoup/soup-connection.c @@ -0,0 +1,719 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-connection.c: A single HTTP/HTTPS connection + * + * Copyright (C) 2000-2003, Ximian, Inc. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "soup-connection.h" +#include "soup.h" +#include "soup-message-queue.h" +#include "soup-socket-private.h" +#include "soup-misc-private.h" + +typedef struct { + SoupSocket *socket; + SoupSocketProperties *socket_props; + + SoupURI *remote_uri, *proxy_uri; + gboolean ssl; + + SoupMessage *current_msg; + SoupConnectionState state; + time_t unused_timeout; + GSource *idle_timeout_src; + gboolean reusable; +} SoupConnectionPrivate; + +G_DEFINE_TYPE_WITH_PRIVATE (SoupConnection, soup_connection, G_TYPE_OBJECT) + +enum { + EVENT, + DISCONNECTED, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +enum { + PROP_0, + + PROP_REMOTE_URI, + PROP_SOCKET_PROPERTIES, + PROP_STATE, + PROP_SSL, + + LAST_PROP +}; + +static void stop_idle_timer (SoupConnectionPrivate *priv); + +/* Number of seconds after which we close a connection that hasn't yet + * been used. + */ +#define SOUP_CONNECTION_UNUSED_TIMEOUT 3 + +static void +soup_connection_init (SoupConnection *conn) +{ +} + +static void +soup_connection_finalize (GObject *object) +{ + SoupConnectionPrivate *priv = soup_connection_get_instance_private (SOUP_CONNECTION (object)); + + g_clear_pointer (&priv->remote_uri, soup_uri_free); + g_clear_pointer (&priv->proxy_uri, soup_uri_free); + g_clear_pointer (&priv->socket_props, soup_socket_properties_unref); + g_clear_object (&priv->current_msg); + + if (priv->socket) { + g_signal_handlers_disconnect_by_data (priv->socket, object); + g_object_unref (priv->socket); + } + + G_OBJECT_CLASS (soup_connection_parent_class)->finalize (object); +} + +static void +soup_connection_dispose (GObject *object) +{ + SoupConnection *conn = SOUP_CONNECTION (object); + SoupConnectionPrivate *priv = soup_connection_get_instance_private (conn); + + stop_idle_timer (priv); + + G_OBJECT_CLASS (soup_connection_parent_class)->dispose (object); +} + +static void +soup_connection_set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + SoupConnectionPrivate *priv = soup_connection_get_instance_private (SOUP_CONNECTION (object)); + + switch (prop_id) { + case PROP_REMOTE_URI: + priv->remote_uri = g_value_dup_boxed (value); + break; + case PROP_SOCKET_PROPERTIES: + priv->socket_props = g_value_dup_boxed (value); + break; + case PROP_STATE: + soup_connection_set_state (SOUP_CONNECTION (object), g_value_get_uint (value)); + break; + case PROP_SSL: + priv->ssl = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +soup_connection_get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + SoupConnectionPrivate *priv = soup_connection_get_instance_private (SOUP_CONNECTION (object)); + + switch (prop_id) { + case PROP_REMOTE_URI: + g_value_set_boxed (value, priv->remote_uri); + break; + case PROP_SOCKET_PROPERTIES: + g_value_set_boxed (value, priv->socket_props); + break; + case PROP_STATE: + g_value_set_enum (value, priv->state); + break; + case PROP_SSL: + g_value_set_boolean (value, priv->ssl); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +soup_connection_class_init (SoupConnectionClass *connection_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (connection_class); + + /* virtual method override */ + object_class->dispose = soup_connection_dispose; + object_class->finalize = soup_connection_finalize; + object_class->set_property = soup_connection_set_property; + object_class->get_property = soup_connection_get_property; + + /* signals */ + signals[EVENT] = + g_signal_new ("event", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + 0, + NULL, NULL, + NULL, + G_TYPE_NONE, 2, + G_TYPE_SOCKET_CLIENT_EVENT, + G_TYPE_IO_STREAM); + signals[DISCONNECTED] = + g_signal_new ("disconnected", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (SoupConnectionClass, disconnected), + NULL, NULL, + NULL, + G_TYPE_NONE, 0); + + /* properties */ + g_object_class_install_property ( + object_class, PROP_REMOTE_URI, + g_param_spec_boxed (SOUP_CONNECTION_REMOTE_URI, + "Remote URI", + "The URI of the HTTP server", + SOUP_TYPE_URI, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + g_object_class_install_property ( + object_class, PROP_SOCKET_PROPERTIES, + g_param_spec_boxed (SOUP_CONNECTION_SOCKET_PROPERTIES, + "Socket properties", + "Socket properties", + SOUP_TYPE_SOCKET_PROPERTIES, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + g_object_class_install_property ( + object_class, PROP_STATE, + g_param_spec_enum (SOUP_CONNECTION_STATE, + "Connection state", + "Current state of connection", + SOUP_TYPE_CONNECTION_STATE, SOUP_CONNECTION_NEW, + G_PARAM_READWRITE)); + g_object_class_install_property ( + object_class, PROP_SSL, + g_param_spec_boolean (SOUP_CONNECTION_SSL, + "Connection uses TLS", + "Whether the connection should use TLS", + FALSE, G_PARAM_READWRITE)); +} + +static void +soup_connection_event (SoupConnection *conn, + GSocketClientEvent event, + GIOStream *connection) +{ + SoupConnectionPrivate *priv = soup_connection_get_instance_private (conn); + + if (!connection && priv->socket) + connection = soup_socket_get_connection (priv->socket); + + g_signal_emit (conn, signals[EVENT], 0, + event, connection); +} + +static gboolean +idle_timeout (gpointer conn) +{ + soup_connection_disconnect (conn); + return FALSE; +} + +static void +start_idle_timer (SoupConnection *conn) +{ + SoupConnectionPrivate *priv = soup_connection_get_instance_private (conn); + + if (priv->socket_props->idle_timeout > 0 && !priv->idle_timeout_src) { + priv->idle_timeout_src = + soup_add_timeout (priv->socket_props->async_context, + priv->socket_props->idle_timeout * 1000, + idle_timeout, conn); + } +} + +static void +stop_idle_timer (SoupConnectionPrivate *priv) +{ + if (priv->idle_timeout_src) { + g_source_destroy (priv->idle_timeout_src); + priv->idle_timeout_src = NULL; + } +} + +static void +current_msg_got_body (SoupMessage *msg, gpointer user_data) +{ + SoupConnection *conn = user_data; + SoupConnectionPrivate *priv = soup_connection_get_instance_private (conn); + + priv->unused_timeout = 0; + + if (priv->proxy_uri && + msg->method == SOUP_METHOD_CONNECT && + SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) { + soup_connection_event (conn, G_SOCKET_CLIENT_PROXY_NEGOTIATED, NULL); + + /* We're now effectively no longer proxying */ + g_clear_pointer (&priv->proxy_uri, soup_uri_free); + } + + priv->reusable = soup_message_is_keepalive (msg); +} + +static void +clear_current_msg (SoupConnection *conn) +{ + SoupConnectionPrivate *priv = soup_connection_get_instance_private (conn); + SoupMessage *msg; + + msg = priv->current_msg; + priv->current_msg = NULL; + + g_signal_handlers_disconnect_by_func (msg, G_CALLBACK (current_msg_got_body), conn); + g_object_unref (msg); +} + +static void +set_current_msg (SoupConnection *conn, SoupMessage *msg) +{ + SoupConnectionPrivate *priv = soup_connection_get_instance_private (conn); + + g_return_if_fail (priv->state == SOUP_CONNECTION_IN_USE); + + g_object_freeze_notify (G_OBJECT (conn)); + + if (priv->current_msg) { + g_return_if_fail (priv->current_msg->method == SOUP_METHOD_CONNECT); + clear_current_msg (conn); + } + + stop_idle_timer (priv); + + priv->current_msg = g_object_ref (msg); + priv->reusable = FALSE; + + g_signal_connect (msg, "got-body", + G_CALLBACK (current_msg_got_body), conn); + + if (priv->proxy_uri && msg->method == SOUP_METHOD_CONNECT) + soup_connection_event (conn, G_SOCKET_CLIENT_PROXY_NEGOTIATING, NULL); + + g_object_thaw_notify (G_OBJECT (conn)); +} + +static void +re_emit_socket_event (SoupSocket *socket, + GSocketClientEvent event, + GIOStream *connection, + gpointer user_data) +{ + SoupConnection *conn = user_data; + + /* We handle COMPLETE ourselves */ + if (event != G_SOCKET_CLIENT_COMPLETE) + soup_connection_event (conn, event, connection); +} + +static void +socket_connect_finished (GTask *task, SoupSocket *sock, GError *error) +{ + SoupConnection *conn = g_task_get_source_object (task); + SoupConnectionPrivate *priv = soup_connection_get_instance_private (conn); + + if (!error) { + if (!priv->ssl || !priv->proxy_uri) { + soup_connection_event (conn, + G_SOCKET_CLIENT_COMPLETE, + NULL); + } + + soup_connection_set_state (conn, SOUP_CONNECTION_IN_USE); + priv->unused_timeout = time (NULL) + SOUP_CONNECTION_UNUSED_TIMEOUT; + start_idle_timer (conn); + + g_task_return_boolean (task, TRUE); + } else + g_task_return_error (task, error); + g_object_unref (task); +} + +static void +socket_handshake_complete (GObject *object, GAsyncResult *result, gpointer user_data) +{ + SoupSocket *sock = SOUP_SOCKET (object); + GTask *task = user_data; + GError *error = NULL; + + soup_socket_handshake_finish (sock, result, &error); + socket_connect_finished (task, sock, error); +} + +static void +socket_connect_complete (GObject *object, GAsyncResult *result, gpointer user_data) +{ + SoupSocket *sock = SOUP_SOCKET (object); + GTask *task = user_data; + SoupConnection *conn = g_task_get_source_object (task); + SoupConnectionPrivate *priv = soup_connection_get_instance_private (conn); + GError *error = NULL; + + if (!soup_socket_connect_finish_internal (sock, result, &error)) { + socket_connect_finished (task, sock, error); + return; + } + + priv->proxy_uri = soup_socket_get_http_proxy_uri (sock); + + if (priv->ssl && !priv->proxy_uri) { + soup_socket_handshake_async (sock, priv->remote_uri->host, + g_task_get_cancellable (task), + socket_handshake_complete, task); + return; + } + + socket_connect_finished (task, sock, NULL); +} + +void +soup_connection_connect_async (SoupConnection *conn, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + SoupConnectionPrivate *priv; + SoupAddress *remote_addr; + GTask *task; + + g_return_if_fail (SOUP_IS_CONNECTION (conn)); + priv = soup_connection_get_instance_private (conn); + g_return_if_fail (priv->socket == NULL); + + soup_connection_set_state (conn, SOUP_CONNECTION_CONNECTING); + + /* Set the protocol to ensure correct proxy resolution. */ + remote_addr = + g_object_new (SOUP_TYPE_ADDRESS, + SOUP_ADDRESS_NAME, priv->remote_uri->host, + SOUP_ADDRESS_PORT, priv->remote_uri->port, + SOUP_ADDRESS_PROTOCOL, priv->remote_uri->scheme, + NULL); + + priv->socket = + soup_socket_new (SOUP_SOCKET_REMOTE_ADDRESS, remote_addr, + SOUP_SOCKET_SOCKET_PROPERTIES, priv->socket_props, + NULL); + g_object_unref (remote_addr); + + g_signal_connect (priv->socket, "event", + G_CALLBACK (re_emit_socket_event), conn); + + soup_socket_properties_push_async_context (priv->socket_props); + task = g_task_new (conn, cancellable, callback, user_data); + + soup_socket_connect_async_internal (priv->socket, cancellable, + socket_connect_complete, task); + soup_socket_properties_pop_async_context (priv->socket_props); +} + +gboolean +soup_connection_connect_finish (SoupConnection *conn, + GAsyncResult *result, + GError **error) +{ + return g_task_propagate_boolean (G_TASK (result), error); +} + +gboolean +soup_connection_connect_sync (SoupConnection *conn, + GCancellable *cancellable, + GError **error) +{ + SoupConnectionPrivate *priv; + SoupAddress *remote_addr; + + g_return_val_if_fail (SOUP_IS_CONNECTION (conn), FALSE); + priv = soup_connection_get_instance_private (conn); + g_return_val_if_fail (priv->socket == NULL, FALSE); + + soup_connection_set_state (conn, SOUP_CONNECTION_CONNECTING); + + /* Set the protocol to ensure correct proxy resolution. */ + remote_addr = + g_object_new (SOUP_TYPE_ADDRESS, + SOUP_ADDRESS_NAME, priv->remote_uri->host, + SOUP_ADDRESS_PORT, priv->remote_uri->port, + SOUP_ADDRESS_PROTOCOL, priv->remote_uri->scheme, + NULL); + + priv->socket = + soup_socket_new (SOUP_SOCKET_REMOTE_ADDRESS, remote_addr, + SOUP_SOCKET_SOCKET_PROPERTIES, priv->socket_props, + SOUP_SOCKET_FLAG_NONBLOCKING, FALSE, + NULL); + g_object_unref (remote_addr); + + g_signal_connect (priv->socket, "event", + G_CALLBACK (re_emit_socket_event), conn); + if (!soup_socket_connect_sync_internal (priv->socket, cancellable, error)) + return FALSE; + + priv->proxy_uri = soup_socket_get_http_proxy_uri (priv->socket); + + if (priv->ssl && !priv->proxy_uri) { + if (!soup_socket_handshake_sync (priv->socket, + priv->remote_uri->host, + cancellable, error)) + return FALSE; + } + + if (!priv->ssl || !priv->proxy_uri) { + soup_connection_event (conn, + G_SOCKET_CLIENT_COMPLETE, + NULL); + } + soup_connection_set_state (conn, SOUP_CONNECTION_IN_USE); + priv->unused_timeout = time (NULL) + SOUP_CONNECTION_UNUSED_TIMEOUT; + start_idle_timer (conn); + + return TRUE; +} + +gboolean +soup_connection_is_tunnelled (SoupConnection *conn) +{ + SoupConnectionPrivate *priv; + + g_return_val_if_fail (SOUP_IS_CONNECTION (conn), FALSE); + priv = soup_connection_get_instance_private (conn); + + return priv->ssl && priv->proxy_uri != NULL; +} + +gboolean +soup_connection_start_ssl_sync (SoupConnection *conn, + GCancellable *cancellable, + GError **error) +{ + SoupConnectionPrivate *priv; + + g_return_val_if_fail (SOUP_IS_CONNECTION (conn), FALSE); + priv = soup_connection_get_instance_private (conn); + + if (soup_socket_handshake_sync (priv->socket, priv->remote_uri->host, + cancellable, error)) { + soup_connection_event (conn, G_SOCKET_CLIENT_COMPLETE, NULL); + return TRUE; + } else + return FALSE; +} + +static void +start_ssl_completed (GObject *object, GAsyncResult *result, gpointer user_data) +{ + GTask *task = user_data; + SoupConnection *conn = g_task_get_source_object (task); + SoupConnectionPrivate *priv = soup_connection_get_instance_private (conn); + GError *error = NULL; + + if (soup_socket_handshake_finish (priv->socket, result, &error)) { + soup_connection_event (conn, G_SOCKET_CLIENT_COMPLETE, NULL); + g_task_return_boolean (task, TRUE); + } else + g_task_return_error (task, error); + g_object_unref (task); +} + +void +soup_connection_start_ssl_async (SoupConnection *conn, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + SoupConnectionPrivate *priv; + GTask *task; + + g_return_if_fail (SOUP_IS_CONNECTION (conn)); + priv = soup_connection_get_instance_private (conn); + + soup_socket_properties_push_async_context (priv->socket_props); + task = g_task_new (conn, cancellable, callback, user_data); + + soup_socket_handshake_async (priv->socket, priv->remote_uri->host, + cancellable, start_ssl_completed, task); + + soup_socket_properties_pop_async_context (priv->socket_props); +} + +gboolean +soup_connection_start_ssl_finish (SoupConnection *conn, + GAsyncResult *result, + GError **error) +{ + return g_task_propagate_boolean (G_TASK (result), error); +} + +/** + * soup_connection_disconnect: + * @conn: a connection + * + * Disconnects @conn's socket and emits a %disconnected signal. + * After calling this, @conn will be essentially useless. + **/ +void +soup_connection_disconnect (SoupConnection *conn) +{ + SoupConnectionPrivate *priv; + SoupConnectionState old_state; + + g_return_if_fail (SOUP_IS_CONNECTION (conn)); + priv = soup_connection_get_instance_private (conn); + + old_state = priv->state; + if (old_state != SOUP_CONNECTION_DISCONNECTED) + soup_connection_set_state (conn, SOUP_CONNECTION_DISCONNECTED); + + if (priv->socket) { + SoupSocket *socket = priv->socket; + + g_signal_handlers_disconnect_by_func (socket, G_CALLBACK (re_emit_socket_event), conn); + + priv->socket = NULL; + soup_socket_disconnect (socket); + g_object_unref (socket); + } + + if (old_state != SOUP_CONNECTION_DISCONNECTED) + g_signal_emit (conn, signals[DISCONNECTED], 0); +} + +SoupSocket * +soup_connection_get_socket (SoupConnection *conn) +{ + SoupConnectionPrivate *priv = soup_connection_get_instance_private (conn); + + g_return_val_if_fail (SOUP_IS_CONNECTION (conn), NULL); + + return priv->socket; +} + +SoupURI * +soup_connection_get_remote_uri (SoupConnection *conn) +{ + SoupConnectionPrivate *priv = soup_connection_get_instance_private (conn); + + g_return_val_if_fail (SOUP_IS_CONNECTION (conn), NULL); + + return priv->remote_uri; +} + +SoupURI * +soup_connection_get_proxy_uri (SoupConnection *conn) +{ + SoupConnectionPrivate *priv = soup_connection_get_instance_private (conn); + + g_return_val_if_fail (SOUP_IS_CONNECTION (conn), NULL); + + return priv->proxy_uri; +} + +gboolean +soup_connection_is_via_proxy (SoupConnection *conn) +{ + SoupConnectionPrivate *priv = soup_connection_get_instance_private (conn); + + g_return_val_if_fail (SOUP_IS_CONNECTION (conn), FALSE); + + return priv->proxy_uri != NULL; +} + +SoupConnectionState +soup_connection_get_state (SoupConnection *conn) +{ + SoupConnectionPrivate *priv; + + g_return_val_if_fail (SOUP_IS_CONNECTION (conn), + SOUP_CONNECTION_DISCONNECTED); + priv = soup_connection_get_instance_private (conn); + + if (priv->state == SOUP_CONNECTION_IDLE && + (!soup_socket_is_connected (priv->socket) || + soup_socket_is_readable (priv->socket))) + soup_connection_set_state (conn, SOUP_CONNECTION_REMOTE_DISCONNECTED); + + if (priv->state == SOUP_CONNECTION_IDLE && + priv->unused_timeout && priv->unused_timeout < time (NULL)) + soup_connection_set_state (conn, SOUP_CONNECTION_REMOTE_DISCONNECTED); + + return priv->state; +} + +void +soup_connection_set_state (SoupConnection *conn, SoupConnectionState state) +{ + SoupConnectionPrivate *priv; + + g_return_if_fail (SOUP_IS_CONNECTION (conn)); + g_return_if_fail (state >= SOUP_CONNECTION_NEW && + state <= SOUP_CONNECTION_DISCONNECTED); + + g_object_freeze_notify (G_OBJECT (conn)); + + priv = soup_connection_get_instance_private (conn); + + if (priv->current_msg) { + g_warn_if_fail (state == SOUP_CONNECTION_IDLE || + state == SOUP_CONNECTION_DISCONNECTED); + clear_current_msg (conn); + } + + if (state == SOUP_CONNECTION_IDLE && !priv->reusable) { + /* This will recursively call set_state() */ + soup_connection_disconnect (conn); + } else { + priv->state = state; + + if (priv->state == SOUP_CONNECTION_IDLE) + start_idle_timer (conn); + + g_object_notify (G_OBJECT (conn), "state"); + } + + g_object_thaw_notify (G_OBJECT (conn)); +} + +gboolean +soup_connection_get_ever_used (SoupConnection *conn) +{ + SoupConnectionPrivate *priv = soup_connection_get_instance_private (conn); + + g_return_val_if_fail (SOUP_IS_CONNECTION (conn), FALSE); + + return priv->unused_timeout == 0; +} + +void +soup_connection_send_request (SoupConnection *conn, + SoupMessageQueueItem *item, + SoupMessageCompletionFn completion_cb, + gpointer user_data) +{ + SoupConnectionPrivate *priv; + + g_return_if_fail (SOUP_IS_CONNECTION (conn)); + g_return_if_fail (item != NULL); + priv = soup_connection_get_instance_private (conn); + g_return_if_fail (priv->state != SOUP_CONNECTION_NEW && + priv->state != SOUP_CONNECTION_DISCONNECTED); + + if (item->msg != priv->current_msg) + set_current_msg (conn, item->msg); + else + priv->reusable = FALSE; + + soup_message_send_request (item, completion_cb, user_data); +} diff --git a/libsoup/soup-connection.h b/libsoup/soup-connection.h new file mode 100644 index 0000000..fe817de --- /dev/null +++ b/libsoup/soup-connection.h @@ -0,0 +1,85 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2000-2003, Ximian, Inc. + */ + +#ifndef SOUP_CONNECTION_H +#define SOUP_CONNECTION_H 1 + +#include "soup-types.h" +#include "soup-message-private.h" +#include "soup-misc.h" + +G_BEGIN_DECLS + +#define SOUP_TYPE_CONNECTION (soup_connection_get_type ()) +#define SOUP_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SOUP_TYPE_CONNECTION, SoupConnection)) +#define SOUP_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_CONNECTION, SoupConnectionClass)) +#define SOUP_IS_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SOUP_TYPE_CONNECTION)) +#define SOUP_IS_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), SOUP_TYPE_CONNECTION)) +#define SOUP_CONNECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_CONNECTION, SoupConnectionClass)) + +struct _SoupConnection { + GObject parent; + +}; + +typedef struct { + GObjectClass parent_class; + + /* signals */ + void (*disconnected) (SoupConnection *); + +} SoupConnectionClass; + +GType soup_connection_get_type (void); + + +#define SOUP_CONNECTION_REMOTE_URI "remote-uri" +#define SOUP_CONNECTION_SOCKET_PROPERTIES "socket-properties" +#define SOUP_CONNECTION_STATE "state" +#define SOUP_CONNECTION_SSL "ssl" + +void soup_connection_connect_async (SoupConnection *conn, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean soup_connection_connect_finish (SoupConnection *conn, + GAsyncResult *result, + GError **error); +gboolean soup_connection_connect_sync (SoupConnection *conn, + GCancellable *cancellable, + GError **error); +gboolean soup_connection_start_ssl_sync (SoupConnection *conn, + GCancellable *cancellable, + GError **error); +void soup_connection_start_ssl_async (SoupConnection *conn, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean soup_connection_start_ssl_finish (SoupConnection *conn, + GAsyncResult *result, + GError **error); + +void soup_connection_disconnect (SoupConnection *conn); + +SoupSocket *soup_connection_get_socket (SoupConnection *conn); +SoupURI *soup_connection_get_remote_uri (SoupConnection *conn); +SoupURI *soup_connection_get_proxy_uri (SoupConnection *conn); +gboolean soup_connection_is_via_proxy (SoupConnection *conn); +gboolean soup_connection_is_tunnelled (SoupConnection *conn); + +SoupConnectionState soup_connection_get_state (SoupConnection *conn); +void soup_connection_set_state (SoupConnection *conn, + SoupConnectionState state); + +gboolean soup_connection_get_ever_used (SoupConnection *conn); + +void soup_connection_send_request (SoupConnection *conn, + SoupMessageQueueItem *item, + SoupMessageCompletionFn completion_cb, + gpointer user_data); + +G_END_DECLS + +#endif /* SOUP_CONNECTION_H */ diff --git a/libsoup/soup-content-decoder.c b/libsoup/soup-content-decoder.c new file mode 100644 index 0000000..080904a --- /dev/null +++ b/libsoup/soup-content-decoder.c @@ -0,0 +1,237 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-content-decoder.c + * + * Copyright (C) 2009 Red Hat, Inc. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "soup-content-decoder.h" +#include "soup-converter-wrapper.h" +#include "soup.h" +#include "soup-message-private.h" + +/** + * SECTION:soup-content-decoder + * @short_description: Content-Encoding handler + * + * #SoupContentDecoder handles adding the "Accept-Encoding" header on + * outgoing messages, and processing the "Content-Encoding" header on + * incoming ones. Currently it supports the "gzip" and "deflate" + * content codings. + * + * If you are using a plain #SoupSession (ie, not #SoupSessionAsync or + * #SoupSessionSync), then a #SoupContentDecoder will automatically be + * added to the session by default. (You can use + * %SOUP_SESSION_REMOVE_FEATURE_BY_TYPE at construct time if you don't + * want this.) If you are using one of the deprecated #SoupSession + * subclasses, you can add a #SoupContentDecoder to your session with + * soup_session_add_feature() or soup_session_add_feature_by_type(). + * + * If #SoupContentDecoder successfully decodes the Content-Encoding, + * it will set the %SOUP_MESSAGE_CONTENT_DECODED flag on the message, + * and the message body and the chunks in the #SoupMessage::got_chunk + * signals will contain the decoded data; however, the message headers + * will be unchanged (and so "Content-Encoding" will still be present, + * "Content-Length" will describe the original encoded length, etc). + * + * If "Content-Encoding" contains any encoding types that + * #SoupContentDecoder doesn't recognize, then none of the encodings + * will be decoded (and the %SOUP_MESSAGE_CONTENT_DECODED flag will + * not be set). + * + * (Note that currently there is no way to (automatically) use + * Content-Encoding when sending a request body, or to pick specific + * encoding types to support.) + * + * Since: 2.30 + **/ + +struct _SoupContentDecoderPrivate { + GHashTable *decoders; +}; + +typedef GConverter * (*SoupContentDecoderCreator) (void); + +static void soup_content_decoder_session_feature_init (SoupSessionFeatureInterface *feature_interface, gpointer interface_data); + +static SoupContentProcessorInterface *soup_content_decoder_default_content_processor_interface; +static void soup_content_decoder_content_processor_init (SoupContentProcessorInterface *interface, gpointer interface_data); + + +G_DEFINE_TYPE_WITH_CODE (SoupContentDecoder, soup_content_decoder, G_TYPE_OBJECT, + G_ADD_PRIVATE (SoupContentDecoder) + G_IMPLEMENT_INTERFACE (SOUP_TYPE_SESSION_FEATURE, + soup_content_decoder_session_feature_init) + G_IMPLEMENT_INTERFACE (SOUP_TYPE_CONTENT_PROCESSOR, + soup_content_decoder_content_processor_init)) + +static GSList * +soup_content_decoder_get_decoders_for_msg (SoupContentDecoder *decoder, SoupMessage *msg) +{ + const char *header; + GSList *encodings, *e, *decoders = NULL; + SoupContentDecoderCreator converter_creator; + GConverter *converter; + + header = soup_message_headers_get_list (msg->response_headers, + "Content-Encoding"); + if (!header) + return NULL; + + /* Workaround for an apache bug (bgo 613361) */ + if (!g_ascii_strcasecmp (header, "gzip") || + !g_ascii_strcasecmp (header, "x-gzip")) { + const char *content_type = soup_message_headers_get_content_type (msg->response_headers, NULL); + + if (content_type && + (!g_ascii_strcasecmp (content_type, "application/gzip") || + !g_ascii_strcasecmp (content_type, "application/x-gzip"))) + return NULL; + } + + /* OK, really, no one is ever going to use more than one + * encoding, but we'll be robust. + */ + encodings = soup_header_parse_list (header); + if (!encodings) + return NULL; + + for (e = encodings; e; e = e->next) { + if (!g_hash_table_lookup (decoder->priv->decoders, e->data)) { + soup_header_free_list (encodings); + return NULL; + } + } + + for (e = encodings; e; e = e->next) { + converter_creator = g_hash_table_lookup (decoder->priv->decoders, e->data); + converter = converter_creator (); + + /* Content-Encoding lists the codings in the order + * they were applied in, so we put decoders in reverse + * order so the last-applied will be the first + * decoded. + */ + decoders = g_slist_prepend (decoders, converter); + } + soup_header_free_list (encodings); + + return decoders; +} + +static GInputStream* +soup_content_decoder_content_processor_wrap_input (SoupContentProcessor *processor, + GInputStream *base_stream, + SoupMessage *msg, + GError **error) +{ + GSList *decoders, *d; + GInputStream *istream; + + decoders = soup_content_decoder_get_decoders_for_msg (SOUP_CONTENT_DECODER (processor), msg); + if (!decoders) + return NULL; + + istream = g_object_ref (base_stream); + for (d = decoders; d; d = d->next) { + GConverter *decoder, *wrapper; + GInputStream *filter; + + decoder = d->data; + wrapper = soup_converter_wrapper_new (decoder, msg); + filter = g_object_new (G_TYPE_CONVERTER_INPUT_STREAM, + "base-stream", istream, + "converter", wrapper, + NULL); + g_object_unref (istream); + g_object_unref (wrapper); + istream = filter; + } + + g_slist_free_full (decoders, g_object_unref); + + return istream; +} + +static void +soup_content_decoder_content_processor_init (SoupContentProcessorInterface *processor_interface, + gpointer interface_data) +{ + soup_content_decoder_default_content_processor_interface = + g_type_default_interface_peek (SOUP_TYPE_CONTENT_PROCESSOR); + + processor_interface->processing_stage = SOUP_STAGE_CONTENT_ENCODING; + processor_interface->wrap_input = soup_content_decoder_content_processor_wrap_input; +} + +/* This is constant for now */ +#define ACCEPT_ENCODING_HEADER "gzip, deflate" + +static GConverter * +gzip_decoder_creator (void) +{ + return (GConverter *)g_zlib_decompressor_new (G_ZLIB_COMPRESSOR_FORMAT_GZIP); +} + +static GConverter * +zlib_decoder_creator (void) +{ + return (GConverter *)g_zlib_decompressor_new (G_ZLIB_COMPRESSOR_FORMAT_ZLIB); +} + +static void +soup_content_decoder_init (SoupContentDecoder *decoder) +{ + decoder->priv = soup_content_decoder_get_instance_private (decoder); + + decoder->priv->decoders = g_hash_table_new (g_str_hash, g_str_equal); + /* Hardcoded for now */ + g_hash_table_insert (decoder->priv->decoders, "gzip", + gzip_decoder_creator); + g_hash_table_insert (decoder->priv->decoders, "x-gzip", + gzip_decoder_creator); + g_hash_table_insert (decoder->priv->decoders, "deflate", + zlib_decoder_creator); +} + +static void +soup_content_decoder_finalize (GObject *object) +{ + SoupContentDecoder *decoder = SOUP_CONTENT_DECODER (object); + + g_hash_table_destroy (decoder->priv->decoders); + + G_OBJECT_CLASS (soup_content_decoder_parent_class)->finalize (object); +} + +static void +soup_content_decoder_class_init (SoupContentDecoderClass *decoder_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (decoder_class); + + object_class->finalize = soup_content_decoder_finalize; +} + +static void +soup_content_decoder_request_queued (SoupSessionFeature *feature, + SoupSession *session, + SoupMessage *msg) +{ + if (!soup_message_headers_get_one (msg->request_headers, + "Accept-Encoding")) { + soup_message_headers_append (msg->request_headers, + "Accept-Encoding", + ACCEPT_ENCODING_HEADER); + } +} + +static void +soup_content_decoder_session_feature_init (SoupSessionFeatureInterface *feature_interface, + gpointer interface_data) +{ + feature_interface->request_queued = soup_content_decoder_request_queued; +} diff --git a/libsoup/soup-content-decoder.h b/libsoup/soup-content-decoder.h new file mode 100644 index 0000000..471f813 --- /dev/null +++ b/libsoup/soup-content-decoder.h @@ -0,0 +1,45 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2009 Red Hat, Inc. + */ + +#ifndef SOUP_CONTENT_DECODER_H +#define SOUP_CONTENT_DECODER_H 1 + +#include +#include + +G_BEGIN_DECLS + +#define SOUP_TYPE_CONTENT_DECODER (soup_content_decoder_get_type ()) +#define SOUP_CONTENT_DECODER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SOUP_TYPE_CONTENT_DECODER, SoupContentDecoder)) +#define SOUP_CONTENT_DECODER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_CONTENT_DECODER, SoupContentDecoderClass)) +#define SOUP_IS_CONTENT_DECODER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SOUP_TYPE_CONTENT_DECODER)) +#define SOUP_IS_CONTENT_DECODER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), SOUP_TYPE_CONTENT_DECODER)) +#define SOUP_CONTENT_DECODER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_CONTENT_DECODER, SoupContentDecoderClass)) + +typedef struct _SoupContentDecoderPrivate SoupContentDecoderPrivate; + +typedef struct { + GObject parent; + + SoupContentDecoderPrivate *priv; +} SoupContentDecoder; + +typedef struct { + GObjectClass parent_class; + + /* Padding for future expansion */ + void (*_libsoup_reserved1) (void); + void (*_libsoup_reserved2) (void); + void (*_libsoup_reserved3) (void); + void (*_libsoup_reserved4) (void); + void (*_libsoup_reserved5) (void); +} SoupContentDecoderClass; + +SOUP_AVAILABLE_IN_2_30 +GType soup_content_decoder_get_type (void); + +G_END_DECLS + +#endif /* SOUP_CONTENT_DECODER_H */ diff --git a/libsoup/soup-content-processor.c b/libsoup/soup-content-processor.c new file mode 100644 index 0000000..ca1bd16 --- /dev/null +++ b/libsoup/soup-content-processor.c @@ -0,0 +1,49 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2012 Igalia, S.L. + */ + + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "soup-content-processor.h" +#include "soup.h" + +G_DEFINE_INTERFACE (SoupContentProcessor, soup_content_processor, G_TYPE_OBJECT) + +static GInputStream * +soup_content_processor_real_wrap_input (SoupContentProcessor *processor, + GInputStream *base_stream, + SoupMessage *msg, + GError **error) +{ + g_return_val_if_reached (NULL); +} + +static void +soup_content_processor_default_init (SoupContentProcessorInterface *interface) +{ + interface->processing_stage = SOUP_STAGE_INVALID; + interface->wrap_input = soup_content_processor_real_wrap_input; +} + +GInputStream * +soup_content_processor_wrap_input (SoupContentProcessor *processor, + GInputStream *base_stream, + SoupMessage *msg, + GError **error) +{ + g_return_val_if_fail (SOUP_IS_CONTENT_PROCESSOR (processor), NULL); + + return SOUP_CONTENT_PROCESSOR_GET_INTERFACE (processor)->wrap_input (processor, base_stream, msg, error); +} + +SoupProcessingStage +soup_content_processor_get_processing_stage (SoupContentProcessor *processor) +{ + g_return_val_if_fail (SOUP_IS_CONTENT_PROCESSOR (processor), SOUP_STAGE_INVALID); + + return SOUP_CONTENT_PROCESSOR_GET_INTERFACE (processor)->processing_stage; +} diff --git a/libsoup/soup-content-processor.h b/libsoup/soup-content-processor.h new file mode 100644 index 0000000..8ee04b2 --- /dev/null +++ b/libsoup/soup-content-processor.h @@ -0,0 +1,56 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2012 Igalia, S.L. + */ + + +#ifndef SOUP_CONTENT_PROCESSOR_H +#define SOUP_CONTENT_PROCESSOR_H 1 + +#include +#include + +G_BEGIN_DECLS + +#define SOUP_TYPE_CONTENT_PROCESSOR (soup_content_processor_get_type ()) +#define SOUP_CONTENT_PROCESSOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SOUP_TYPE_CONTENT_PROCESSOR, SoupContentProcessor)) +#define SOUP_IS_CONTENT_PROCESSOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SOUP_TYPE_CONTENT_PROCESSOR)) +#define SOUP_CONTENT_PROCESSOR_GET_INTERFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), SOUP_TYPE_CONTENT_PROCESSOR, SoupContentProcessorInterface)) + +typedef enum { + SOUP_STAGE_INVALID, + + SOUP_STAGE_MESSAGE_BODY, /* Raw network data */ + SOUP_STAGE_TRANSFER_ENCODING, /* SoupBodyInputStream is here */ + SOUP_STAGE_ENTITY_BODY, /* Has Transfer-Encoding removed */ + SOUP_STAGE_CONTENT_ENCODING, /* SoupContentDecoder works here */ + SOUP_STAGE_BODY_DATA /* Actual body data */ +} SoupProcessingStage; + +typedef struct _SoupContentProcessor SoupContentProcessor; +typedef struct _SoupContentProcessorInterface SoupContentProcessorInterface; + +struct _SoupContentProcessorInterface { + GTypeInterface parent; + + SoupProcessingStage processing_stage; + + /* methods */ + GInputStream* (*wrap_input) (SoupContentProcessor *processor, + GInputStream *base_stream, + SoupMessage *msg, + GError **error); +}; + +GType soup_content_processor_get_type (void); + +GInputStream *soup_content_processor_wrap_input (SoupContentProcessor *processor, + GInputStream *base_stream, + SoupMessage *msg, + GError **error); + +SoupProcessingStage soup_content_processor_get_processing_stage (SoupContentProcessor *processor); + +G_END_DECLS + +#endif /* SOUP_CONTENT_PROCESSOR_H */ diff --git a/libsoup/soup-content-sniffer-stream.c b/libsoup/soup-content-sniffer-stream.c new file mode 100644 index 0000000..7f74c70 --- /dev/null +++ b/libsoup/soup-content-sniffer-stream.c @@ -0,0 +1,357 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-content-sniffer-stream.c + * + * Copyright (C) 2010 Red Hat, Inc. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "soup-content-sniffer-stream.h" +#include "soup.h" + +enum { + PROP_0, + + PROP_SNIFFER, + PROP_MESSAGE, +}; + +struct _SoupContentSnifferStreamPrivate { + SoupContentSniffer *sniffer; + SoupMessage *msg; + + guchar *buffer; + gsize buffer_size, buffer_nread; + gboolean sniffing; + GError *error; + + char *sniffed_type; + GHashTable *sniffed_params; +}; + +static void soup_content_sniffer_stream_pollable_init (GPollableInputStreamInterface *pollable_interface, gpointer interface_data); + +G_DEFINE_TYPE_WITH_CODE (SoupContentSnifferStream, soup_content_sniffer_stream, G_TYPE_FILTER_INPUT_STREAM, + G_ADD_PRIVATE (SoupContentSnifferStream) + G_IMPLEMENT_INTERFACE (G_TYPE_POLLABLE_INPUT_STREAM, + soup_content_sniffer_stream_pollable_init)) + +static void +soup_content_sniffer_stream_finalize (GObject *object) +{ + SoupContentSnifferStream *sniffer = SOUP_CONTENT_SNIFFER_STREAM (object); + + g_clear_object (&sniffer->priv->sniffer); + g_clear_object (&sniffer->priv->msg); + g_free (sniffer->priv->buffer); + g_clear_error (&sniffer->priv->error); + g_free (sniffer->priv->sniffed_type); + g_clear_pointer (&sniffer->priv->sniffed_params, g_hash_table_unref); + + G_OBJECT_CLASS (soup_content_sniffer_stream_parent_class)->finalize (object); +} + +static void +soup_content_sniffer_stream_set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + SoupContentSnifferStream *sniffer = SOUP_CONTENT_SNIFFER_STREAM (object); + + switch (prop_id) { + case PROP_SNIFFER: + sniffer->priv->sniffer = g_value_dup_object (value); + /* FIXME: supposed to wait until after got-headers for this */ + sniffer->priv->buffer_size = soup_content_sniffer_get_buffer_size (sniffer->priv->sniffer); + sniffer->priv->buffer = g_malloc (sniffer->priv->buffer_size); + break; + case PROP_MESSAGE: + sniffer->priv->msg = g_value_dup_object (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +soup_content_sniffer_stream_get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + SoupContentSnifferStream *sniffer = SOUP_CONTENT_SNIFFER_STREAM (object); + + switch (prop_id) { + case PROP_SNIFFER: + g_value_set_object (value, sniffer->priv->sniffer); + break; + case PROP_MESSAGE: + g_value_set_object (value, sniffer->priv->msg); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static gssize +read_and_sniff (GInputStream *stream, gboolean blocking, + GCancellable *cancellable, GError **error) +{ + SoupContentSnifferStreamPrivate *priv = SOUP_CONTENT_SNIFFER_STREAM (stream)->priv; + gssize nread; + GError *my_error = NULL; + SoupBuffer *buf; + + do { + nread = g_pollable_stream_read (G_FILTER_INPUT_STREAM (stream)->base_stream, + priv->buffer + priv->buffer_nread, + priv->buffer_size - priv->buffer_nread, + blocking, cancellable, &my_error); + if (nread <= 0) + break; + priv->buffer_nread += nread; + } while (priv->buffer_nread < priv->buffer_size); + + /* If we got EAGAIN or cancellation before filling the buffer, + * just return that right away. Likewise if we got any other + * error without ever reading any data. Otherwise, save the + * error to return after we're done sniffing. + */ + if (my_error) { + if (g_error_matches (my_error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK) || + g_error_matches (my_error, G_IO_ERROR, G_IO_ERROR_CANCELLED) || + priv->buffer_nread == 0) { + g_propagate_error (error, my_error); + return -1; + } else + priv->error = my_error; + } + + /* Sniff, then return the data */ + buf = soup_buffer_new (SOUP_MEMORY_TEMPORARY, priv->buffer, priv->buffer_nread); + priv->sniffed_type = + soup_content_sniffer_sniff (priv->sniffer, priv->msg, buf, + &priv->sniffed_params); + soup_buffer_free (buf); + priv->sniffing = FALSE; + + return priv->buffer_nread; +} + +static gssize +read_internal (GInputStream *stream, + void *buffer, + gsize count, + gboolean blocking, + GCancellable *cancellable, + GError **error) +{ + SoupContentSnifferStream *sniffer = SOUP_CONTENT_SNIFFER_STREAM (stream); + gssize nread; + + if (sniffer->priv->error) { + g_propagate_error (error, sniffer->priv->error); + sniffer->priv->error = NULL; + return -1; + } + + if (sniffer->priv->sniffing) { + nread = read_and_sniff (stream, blocking, cancellable, error); + if (nread <= 0) + return nread; + } + + if (sniffer->priv->buffer) { + nread = MIN (count, sniffer->priv->buffer_nread); + if (buffer) + memcpy (buffer, sniffer->priv->buffer, nread); + if (nread == sniffer->priv->buffer_nread) { + g_free (sniffer->priv->buffer); + sniffer->priv->buffer = NULL; + } else { + /* FIXME, inefficient */ + memmove (sniffer->priv->buffer, + sniffer->priv->buffer + nread, + sniffer->priv->buffer_nread - nread); + sniffer->priv->buffer_nread -= nread; + } + } else { + nread = g_pollable_stream_read (G_FILTER_INPUT_STREAM (stream)->base_stream, + buffer, count, blocking, + cancellable, error); + } + return nread; +} + +static gssize +soup_content_sniffer_stream_read (GInputStream *stream, + void *buffer, + gsize count, + GCancellable *cancellable, + GError **error) +{ + return read_internal (stream, buffer, count, TRUE, + cancellable, error); +} + +static gssize +soup_content_sniffer_stream_skip (GInputStream *stream, + gsize count, + GCancellable *cancellable, + GError **error) +{ + SoupContentSnifferStream *sniffer = SOUP_CONTENT_SNIFFER_STREAM (stream); + gssize nskipped; + + if (sniffer->priv->sniffing) { + /* Read into the internal buffer... */ + nskipped = soup_content_sniffer_stream_read (stream, NULL, 0, cancellable, error); + if (nskipped == -1) + return -1; + /* Now fall through */ + } + + if (sniffer->priv->buffer) { + nskipped = MIN (count, sniffer->priv->buffer_nread); + if (nskipped == sniffer->priv->buffer_nread) { + g_free (sniffer->priv->buffer); + sniffer->priv->buffer = NULL; + } else { + /* FIXME */ + memmove (sniffer->priv->buffer, + sniffer->priv->buffer + nskipped, + sniffer->priv->buffer_nread - nskipped); + sniffer->priv->buffer_nread -= nskipped; + } + } else { + nskipped = G_INPUT_STREAM_CLASS (soup_content_sniffer_stream_parent_class)-> + skip (stream, count, cancellable, error); + } + return nskipped; +} + +static gboolean +soup_content_sniffer_stream_can_poll (GPollableInputStream *pollable) +{ + GInputStream *base_stream = G_FILTER_INPUT_STREAM (pollable)->base_stream; + + return G_IS_POLLABLE_INPUT_STREAM (base_stream) && + g_pollable_input_stream_can_poll (G_POLLABLE_INPUT_STREAM (base_stream)); +} + + +static gboolean +soup_content_sniffer_stream_is_readable (GPollableInputStream *stream) +{ + SoupContentSnifferStream *sniffer = SOUP_CONTENT_SNIFFER_STREAM (stream); + + if (sniffer->priv->error || + (!sniffer->priv->sniffing && sniffer->priv->buffer)) + return TRUE; + + return g_pollable_input_stream_is_readable (G_POLLABLE_INPUT_STREAM (G_FILTER_INPUT_STREAM (stream)->base_stream)); +} + +static gssize +soup_content_sniffer_stream_read_nonblocking (GPollableInputStream *stream, + void *buffer, + gsize count, + GError **error) +{ + return read_internal (G_INPUT_STREAM (stream), buffer, count, + FALSE, NULL, error); +} + +static GSource * +soup_content_sniffer_stream_create_source (GPollableInputStream *stream, + GCancellable *cancellable) +{ + SoupContentSnifferStream *sniffer = SOUP_CONTENT_SNIFFER_STREAM (stream); + GSource *base_source, *pollable_source; + + if (sniffer->priv->error || + (!sniffer->priv->sniffing && sniffer->priv->buffer)) + base_source = g_timeout_source_new (0); + else + base_source = g_pollable_input_stream_create_source (G_POLLABLE_INPUT_STREAM (G_FILTER_INPUT_STREAM (stream)->base_stream), cancellable); + + g_source_set_dummy_callback (base_source); + pollable_source = g_pollable_source_new (G_OBJECT (stream)); + g_source_add_child_source (pollable_source, base_source); + g_source_unref (base_source); + + return pollable_source; +} + +static void +soup_content_sniffer_stream_init (SoupContentSnifferStream *sniffer) +{ + sniffer->priv = soup_content_sniffer_stream_get_instance_private (sniffer); + sniffer->priv->sniffing = TRUE; +} + +static void +soup_content_sniffer_stream_class_init (SoupContentSnifferStreamClass *sniffer_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (sniffer_class); + GInputStreamClass *input_stream_class = + G_INPUT_STREAM_CLASS (sniffer_class); + + object_class->finalize = soup_content_sniffer_stream_finalize; + object_class->set_property = soup_content_sniffer_stream_set_property; + object_class->get_property = soup_content_sniffer_stream_get_property; + + input_stream_class->read_fn = soup_content_sniffer_stream_read; + input_stream_class->skip = soup_content_sniffer_stream_skip; + + g_object_class_install_property ( + object_class, PROP_SNIFFER, + g_param_spec_object ("sniffer", + "Sniffer", + "The stream's SoupContentSniffer", + SOUP_TYPE_CONTENT_SNIFFER, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + g_object_class_install_property ( + object_class, PROP_MESSAGE, + g_param_spec_object ("message", + "Message", + "The stream's SoupMessage", + SOUP_TYPE_MESSAGE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); +} + +static void +soup_content_sniffer_stream_pollable_init (GPollableInputStreamInterface *pollable_interface, + gpointer interface_data) +{ + pollable_interface->can_poll = soup_content_sniffer_stream_can_poll; + pollable_interface->is_readable = soup_content_sniffer_stream_is_readable; + pollable_interface->read_nonblocking = soup_content_sniffer_stream_read_nonblocking; + pollable_interface->create_source = soup_content_sniffer_stream_create_source; +} + +gboolean +soup_content_sniffer_stream_is_ready (SoupContentSnifferStream *sniffer, + gboolean blocking, + GCancellable *cancellable, + GError **error) +{ + if (!sniffer->priv->sniffing) + return TRUE; + + return read_and_sniff (G_INPUT_STREAM (sniffer), blocking, + cancellable, error) != -1; +} + +const char * +soup_content_sniffer_stream_sniff (SoupContentSnifferStream *sniffer, + GHashTable **params) +{ + if (params) + *params = sniffer->priv->sniffed_params; + return sniffer->priv->sniffed_type; +} diff --git a/libsoup/soup-content-sniffer-stream.h b/libsoup/soup-content-sniffer-stream.h new file mode 100644 index 0000000..ab230f3 --- /dev/null +++ b/libsoup/soup-content-sniffer-stream.h @@ -0,0 +1,49 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2010 Red Hat, Inc. + */ + +#ifndef SOUP_CONTENT_SNIFFER_STREAM_H +#define SOUP_CONTENT_SNIFFER_STREAM_H 1 + +#include +#include + +G_BEGIN_DECLS + +#define SOUP_TYPE_CONTENT_SNIFFER_STREAM (soup_content_sniffer_stream_get_type ()) +#define SOUP_CONTENT_SNIFFER_STREAM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), SOUP_TYPE_CONTENT_SNIFFER_STREAM, SoupContentSnifferStream)) +#define SOUP_CONTENT_SNIFFER_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), SOUP_TYPE_CONTENT_SNIFFER_STREAM, SoupContentSnifferStreamClass)) +#define SOUP_IS_CONTENT_SNIFFER_STREAM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), SOUP_TYPE_CONTENT_SNIFFER_STREAM)) +#define SOUP_IS_CONTENT_SNIFFER_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), SOUP_TYPE_CONTENT_SNIFFER_STREAM)) +#define SOUP_CONTENT_SNIFFER_STREAM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), SOUP_TYPE_CONTENT_SNIFFER_STREAM, SoupContentSnifferStreamClass)) + +typedef struct _SoupContentSnifferStream SoupContentSnifferStream; +typedef struct _SoupContentSnifferStreamPrivate SoupContentSnifferStreamPrivate; +typedef struct _SoupContentSnifferStreamClass SoupContentSnifferStreamClass; + +struct _SoupContentSnifferStream { + GFilterInputStream parent_instance; + + /*< private >*/ + SoupContentSnifferStreamPrivate *priv; +}; + +struct _SoupContentSnifferStreamClass { + GFilterInputStreamClass parent_class; + +}; + +GType soup_content_sniffer_stream_get_type (void) G_GNUC_CONST; + +gboolean soup_content_sniffer_stream_is_ready (SoupContentSnifferStream *sniffer, + gboolean blocking, + GCancellable *cancellable, + GError **error); +const char *soup_content_sniffer_stream_sniff (SoupContentSnifferStream *sniffer, + GHashTable **params); + + +G_END_DECLS + +#endif /* SOUP_CONTENT_SNIFFER_STREAM_H */ diff --git a/libsoup/soup-content-sniffer.c b/libsoup/soup-content-sniffer.c new file mode 100644 index 0000000..7573fde --- /dev/null +++ b/libsoup/soup-content-sniffer.c @@ -0,0 +1,952 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-content-sniffer.c + * + * Copyright (C) 2009, 2013 Gustavo Noronha Silva. + * + * This code implements the following specification: + * + * http://mimesniff.spec.whatwg.org/ as of 11 June 2013 + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "soup-content-sniffer.h" +#include "soup.h" +#include "soup-content-processor.h" +#include "soup-content-sniffer-stream.h" +#include "soup-message-private.h" + +/** + * SECTION:soup-content-sniffer + * @short_description: Content sniffing for SoupSession + * + * A #SoupContentSniffer tries to detect the actual content type of + * the files that are being downloaded by looking at some of the data + * before the #SoupMessage emits its #SoupMessage::got-headers signal. + * #SoupContentSniffer implements #SoupSessionFeature, so you can add + * content sniffing to a session with soup_session_add_feature() or + * soup_session_add_feature_by_type(). + * + * Since: 2.28 + **/ + +static void soup_content_sniffer_session_feature_init (SoupSessionFeatureInterface *feature_interface, gpointer interface_data); + +static SoupContentProcessorInterface *soup_content_sniffer_default_content_processor_interface; +static void soup_content_sniffer_content_processor_init (SoupContentProcessorInterface *interface, gpointer interface_data); + + +G_DEFINE_TYPE_WITH_CODE (SoupContentSniffer, soup_content_sniffer, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (SOUP_TYPE_SESSION_FEATURE, + soup_content_sniffer_session_feature_init) + G_IMPLEMENT_INTERFACE (SOUP_TYPE_CONTENT_PROCESSOR, + soup_content_sniffer_content_processor_init)) + + +static GInputStream * +soup_content_sniffer_content_processor_wrap_input (SoupContentProcessor *processor, + GInputStream *base_stream, + SoupMessage *msg, + GError **error) +{ + return g_object_new (SOUP_TYPE_CONTENT_SNIFFER_STREAM, + "base-stream", base_stream, + "message", msg, + "sniffer", SOUP_CONTENT_SNIFFER (processor), + NULL); +} + +static void +soup_content_sniffer_content_processor_init (SoupContentProcessorInterface *processor_interface, + gpointer interface_data) +{ + soup_content_sniffer_default_content_processor_interface = + g_type_default_interface_peek (SOUP_TYPE_CONTENT_PROCESSOR); + + processor_interface->processing_stage = SOUP_STAGE_BODY_DATA; + processor_interface->wrap_input = soup_content_sniffer_content_processor_wrap_input; +} + +static void +soup_content_sniffer_init (SoupContentSniffer *content_sniffer) +{ +} + +typedef struct { + const guchar *mask; + const guchar *pattern; + guint pattern_length; + const char *sniffed_type; +} SoupContentSnifferMediaPattern; + +static char* +sniff_media (SoupContentSniffer *sniffer, + SoupBuffer *buffer, + SoupContentSnifferMediaPattern table[], + int table_length) +{ + const guchar *resource = (const guchar *)buffer->data; + guint resource_length = MIN (512, buffer->length); + int i; + + for (i = 0; i < table_length; i++) { + SoupContentSnifferMediaPattern *type_row = &(table[i]); + guint j; + + if (resource_length < type_row->pattern_length) + continue; + + for (j = 0; j < type_row->pattern_length; j++) { + if ((type_row->mask[j] & resource[j]) != type_row->pattern[j]) + break; + } + + /* This means our comparison above matched completely */ + if (j == type_row->pattern_length) + return g_strdup (type_row->sniffed_type); + } + + return NULL; +} + +/* This table is based on the MIMESNIFF spec; + * See 6.1 Matching an image type pattern + */ +static SoupContentSnifferMediaPattern image_types_table[] = { + + /* Windows icon signature. */ + { (const guchar *)"\xFF\xFF\xFF\xFF", + (const guchar *)"\x00\x00\x01\x00", + 4, + "image/x-icon" }, + + /* Windows cursor signature. */ + { (const guchar *)"\xFF\xFF\xFF\xFF", + (const guchar *)"\x00\x00\x02\x00", + 4, + "image/x-icon" }, + + /* BMP. */ + { (const guchar *)"\xFF\xFF", + (const guchar *)"BM", + 2, + "image/bmp" }, + + /* GIFs. */ + { (const guchar *)"\xFF\xFF\xFF\xFF\xFF\xFF", + (const guchar *)"GIF87a", + 6, + "image/gif" }, + + { (const guchar *)"\xFF\xFF\xFF\xFF\xFF\xFF", + (const guchar *)"GIF89a", + 6, + "image/gif" }, + + /* WEBP. */ + { (const guchar *)"\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF", + (const guchar *)"RIFF\x00\x00\x00\x00WEBPVP", + 14, + "image/webp" }, + + /* PNG. */ + { (const guchar *)"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", + (const guchar *)"\x89PNG\x0D\x0A\x1A\x0A", + 8, + "image/png" }, + + /* JPEG. */ + { (const guchar *)"\xFF\xFF\xFF", + (const guchar *)"\xFF\xD8\xFF", + 3, + "image/jpeg" }, +}; + +static char* +sniff_images (SoupContentSniffer *sniffer, SoupBuffer *buffer) +{ + return sniff_media (sniffer, + buffer, + image_types_table, + G_N_ELEMENTS (image_types_table)); +} + +/* This table is based on the MIMESNIFF spec; + * See 6.2 Matching an audio or video type pattern + */ +static SoupContentSnifferMediaPattern audio_video_types_table[] = { + { (const guchar *)"\xFF\xFF\xFF\xFF", + (const guchar *)"\x1A\x45\xDF\xA3", + 4, + "video/webm" }, + + { (const guchar *)"\xFF\xFF\xFF\xFF", + (const guchar *)".snd", + 4, + "audio/basic" }, + + + { (const guchar *)"\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF", + (const guchar *)"FORM\0\0\0\0AIFF", + 12, + "audio/aiff" }, + + { (const guchar *)"\xFF\xFF\xFF", + (const guchar *)"ID3", + 3, + "audio/mpeg" }, + + { (const guchar *)"\xFF\xFF\xFF\xFF\xFF", + (const guchar *)"OggS\0", + 5, + "application/ogg" }, + + { (const guchar *)"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", + (const guchar *)"MThd\x00\x00\x00\x06", + 8, + "audio/midi" }, + + { (const guchar *)"\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF", + (const guchar *)"RIFF\x00\x00\x00\x00AVI ", + 12, + "video/avi" }, + + { (const guchar *)"\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF", + (const guchar *)"RIFF\x00\x00\x00\x00WAVE", + 12, + "audio/wave" }, +}; + +static gboolean +sniff_mp4 (SoupContentSniffer *sniffer, SoupBuffer *buffer) +{ + const char *resource = (const char *)buffer->data; + guint resource_length = MIN (512, buffer->length); + guint32 box_size = *((guint32*)resource); + guint i; + +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + box_size = ((box_size >> 24) | + ((box_size << 8) & 0x00FF0000) | + ((box_size >> 8) & 0x0000FF00) | + (box_size << 24)); +#endif + + if (resource_length < 12 || resource_length < box_size || box_size % 4 != 0) + return FALSE; + + if (!g_str_has_prefix (resource + 4, "ftyp")) + return FALSE; + + if (!g_str_has_prefix (resource + 8, "mp4")) + return FALSE; + + for (i = 16; i < box_size && i < resource_length; i = i + 4) { + if (g_str_has_prefix (resource + i, "mp4")) + return TRUE; + } + + return FALSE; +} + +static char* +sniff_audio_video (SoupContentSniffer *sniffer, SoupBuffer *buffer) +{ + char *sniffed_type; + + sniffed_type = sniff_media (sniffer, + buffer, + audio_video_types_table, + G_N_ELEMENTS (audio_video_types_table)); + + if (sniffed_type != NULL) + return sniffed_type; + + if (sniff_mp4 (sniffer, buffer)) + return g_strdup ("video/mp4"); + + return NULL; +} + +/* This table is based on the MIMESNIFF spec; + * See 7.1 Identifying a resource with an unknown MIME type + */ +typedef struct { + /* @has_ws is TRUE if @pattern contains "generic" whitespace */ + gboolean has_ws; + /* @has_tag_termination is TRUE if we should check for a tag-terminating + * byte (0x20 " " or 0x3E ">") after the pattern match. + */ + gboolean has_tag_termination; + const guchar *mask; + const guchar *pattern; + guint pattern_length; + const char *sniffed_type; + gboolean scriptable; +} SoupContentSnifferPattern; + + +/* When has_ws is TRUE, spaces in the pattern will indicate where insignificant space + * is allowed. Those spaces are marked with \x00 on the mask. + */ +static SoupContentSnifferPattern types_table[] = { + /* Scriptable types. */ + + { TRUE, TRUE, + (const guchar *)"\x00\xFF\xFF\xDF\xDF\xDF\xDF\xDF\xDF\xDF\xFF\xDF\xDF\xDF\xDF", + (const guchar *)" data; + guint resource_length = MIN (512, buffer->length); + guint i; + + for (i = 0; i < G_N_ELEMENTS (types_table); i++) { + SoupContentSnifferPattern *type_row = &(types_table[i]); + + if (!sniff_scriptable && type_row->scriptable) + continue; + + if (type_row->has_ws) { + guint index_stream = 0; + guint index_pattern = 0; + gboolean skip_row = FALSE; + + while ((index_stream < resource_length) && + (index_pattern <= type_row->pattern_length)) { + /* Skip insignificant white space ("WS" in the spec) */ + if (type_row->pattern[index_pattern] == ' ') { + if (resource[index_stream] == '\x09' || + resource[index_stream] == '\x0a' || + resource[index_stream] == '\x0c' || + resource[index_stream] == '\x0d' || + resource[index_stream] == '\x20') + index_stream++; + else + index_pattern++; + } else { + if ((type_row->mask[index_pattern] & resource[index_stream]) != type_row->pattern[index_pattern]) { + skip_row = TRUE; + break; + } + index_pattern++; + index_stream++; + } + } + + if (skip_row) + continue; + + if (index_pattern > type_row->pattern_length) { + if (type_row->has_tag_termination && + resource[index_stream] != '\x20' && + resource[index_stream] != '\x3E') + continue; + + return g_strdup (type_row->sniffed_type); + } + } else { + guint j; + + if (resource_length < type_row->pattern_length) + continue; + + for (j = 0; j < type_row->pattern_length; j++) { + if ((type_row->mask[j] & resource[j]) != type_row->pattern[j]) + break; + } + + /* This means our comparison above matched completely */ + if (j == type_row->pattern_length) + return g_strdup (type_row->sniffed_type); + } + } + + sniffed_type = sniff_images (sniffer, buffer); + + if (sniffed_type != NULL) + return sniffed_type; + + sniffed_type = sniff_audio_video (sniffer, buffer); + + if (sniffed_type != NULL) + return sniffed_type; + + for (i = 0; i < resource_length; i++) { + if (byte_looks_binary[resource[i]]) + return g_strdup ("application/octet-stream"); + } + + return g_strdup ("text/plain"); +} + +/* MIMESNIFF: 7.2 Sniffing a mislabeled binary resource */ +static char* +sniff_text_or_binary (SoupContentSniffer *sniffer, SoupBuffer *buffer) +{ + const guchar *resource = (const guchar *)buffer->data; + int resource_length = MIN (512, buffer->length); + gboolean looks_binary = FALSE; + int i; + + /* 2. Detecting UTF-16BE, UTF-16LE BOMs means it's text/plain */ + if (resource_length >= 2) { + if ((resource[0] == 0xFE && resource[1] == 0xFF) || + (resource[0] == 0xFF && resource[1] == 0xFE)) + return g_strdup ("text/plain"); + } + + /* 3. UTF-8 BOM. */ + if (resource_length >= 3) { + if (resource[0] == 0xEF && resource[1] == 0xBB && resource[2] == 0xBF) + return g_strdup ("text/plain"); + } + + /* 4. Look to see if any of the first n bytes looks binary */ + for (i = 0; i < resource_length; i++) { + if (byte_looks_binary[resource[i]]) { + looks_binary = TRUE; + break; + } + } + + if (!looks_binary) + return g_strdup ("text/plain"); + + /* 5. Execute 7.1 Identifying a resource with an unknown MIME type. + * TODO: sniff-scriptable needs to be unset. + */ + return sniff_unknown (sniffer, buffer, TRUE); +} + +static gboolean +skip_insignificant_space (const char *resource, int *pos, int resource_length) +{ + while ((resource[*pos] == '\x09') || + (resource[*pos] == '\x20') || + (resource[*pos] == '\x0A') || + (resource[*pos] == '\x0D')) { + *pos = *pos + 1; + + if (*pos > resource_length) + return TRUE; + } + + return FALSE; +} + +static char* +sniff_feed_or_html (SoupContentSniffer *sniffer, SoupBuffer *buffer) +{ + const char *resource = (const char *)buffer->data; + int resource_length = MIN (512, buffer->length); + int pos = 0; + + if (resource_length < 3) + goto text_html; + + /* Skip a leading UTF-8 BOM */ + if (resource[0] == 0xEF && resource[1] == 0xBB && resource[2] == 0xBF) + pos = 3; + + look_for_tag: + if (pos > resource_length) + goto text_html; + + if (skip_insignificant_space (resource, &pos, resource_length)) + goto text_html; + + if (resource[pos] != '<') + return g_strdup ("text/html"); + + pos++; + + if ((pos + 2) > resource_length) + goto text_html; + + /* Skip comments. */ + if (g_str_has_prefix (resource + pos, "!--")) { + pos = pos + 3; + + if ((pos + 2) > resource_length) + goto text_html; + + while (!g_str_has_prefix (resource + pos, "-->")) { + pos++; + + if ((pos + 2) > resource_length) + goto text_html; + } + + pos = pos + 3; + + goto look_for_tag; + } + + if (pos > resource_length) + goto text_html; + + if (resource[pos] == '!') { + do { + pos++; + + if (pos > resource_length) + goto text_html; + } while (resource[pos] != '>'); + + pos++; + + goto look_for_tag; + } else if (resource[pos] == '?') { + do { + pos++; + + if ((pos + 1) > resource_length) + goto text_html; + } while (!g_str_has_prefix (resource + pos, "?>")); + + pos = pos + 2; + + goto look_for_tag; + } + + if ((pos + 3) > resource_length) + goto text_html; + + if (g_str_has_prefix (resource + pos, "rss")) + return g_strdup ("application/rss+xml"); + + if ((pos + 4) > resource_length) + goto text_html; + + if (g_str_has_prefix (resource + pos, "feed")) + return g_strdup ("application/atom+xml"); + + if ((pos + 7) > resource_length) + goto text_html; + + if (g_str_has_prefix (resource + pos, "rdf:RDF")) { + pos = pos + 7; + + if (skip_insignificant_space (resource, &pos, resource_length)) + goto text_html; + + if ((pos + 32) > resource_length) + goto text_html; + + if (g_str_has_prefix (resource + pos, "xmlns=\"http://purl.org/rss/1.0/\"")) { + pos = pos + 32; + + if (skip_insignificant_space (resource, &pos, resource_length)) + goto text_html; + + if ((pos + 55) > resource_length) + goto text_html; + + if (g_str_has_prefix (resource + pos, "xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"")) + return g_strdup ("application/rss+xml"); + } + + if ((pos + 55) > resource_length) + goto text_html; + + if (g_str_has_prefix (resource + pos, "xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"")) { + pos = pos + 55; + + if (skip_insignificant_space (resource, &pos, resource_length)) + goto text_html; + + if ((pos + 32) > resource_length) + goto text_html; + + if (g_str_has_prefix (resource + pos, "xmlns=\"http://purl.org/rss/1.0/\"")) + return g_strdup ("application/rss+xml"); + } + } + + text_html: + return g_strdup ("text/html"); +} + +static char * +soup_content_sniffer_real_sniff (SoupContentSniffer *sniffer, SoupMessage *msg, + SoupBuffer *buffer, GHashTable **params) +{ + const char *content_type; + const char *x_content_type_options; + char *sniffed_type = NULL; + gboolean no_sniff = FALSE; + + content_type = soup_message_headers_get_content_type (msg->response_headers, params); + + /* MIMESNIFF: 7 Determining the sniffed MIME type of a resource. */ + + x_content_type_options = soup_message_headers_get_one (msg->response_headers, "X-Content-Type-Options"); + if (!g_strcmp0 (x_content_type_options, "nosniff")) + no_sniff = TRUE; + + /* 1. Unknown/undefined supplied type with sniff-scritable = !nosniff. */ + if ((content_type == NULL) || + !g_ascii_strcasecmp (content_type, "unknown/unknown") || + !g_ascii_strcasecmp (content_type, "application/unknown") || + !g_ascii_strcasecmp (content_type, "*/*")) + return sniff_unknown (sniffer, buffer, !no_sniff); + + /* 2. If nosniff is specified in X-Content-Type-Options use the supplied MIME type. */ + if (no_sniff) + return g_strdup (content_type); + + /* 3. check-for-apache-bug */ + if ((content_type != NULL) && + (g_str_equal (content_type, "text/plain") || + g_str_equal (content_type, "text/plain; charset=ISO-8859-1") || + g_str_equal (content_type, "text/plain; charset=iso-8859-1") || + g_str_equal (content_type, "text/plain; charset=UTF-8"))) + return sniff_text_or_binary (sniffer, buffer); + + /* 4. XML types sent by the server are always used. */ + if (g_str_has_suffix (content_type, "+xml") || + !g_ascii_strcasecmp (content_type, "text/xml") || + !g_ascii_strcasecmp (content_type, "application/xml")) + return g_strdup (content_type); + + /* 5. Distinguish feed from HTML. */ + if (!g_ascii_strcasecmp (content_type, "text/html")) + return sniff_feed_or_html (sniffer, buffer); + + /* 6. Image types. + */ + if (!g_ascii_strncasecmp (content_type, "image/", 6)) { + sniffed_type = sniff_images (sniffer, buffer); + if (sniffed_type != NULL) + return sniffed_type; + return g_strdup (content_type); + } + + /* 7. Audio and video types. */ + if (!g_ascii_strncasecmp (content_type, "audio/", 6) || + !g_ascii_strncasecmp (content_type, "video/", 6) || + !g_ascii_strcasecmp (content_type, "application/ogg")) { + sniffed_type = sniff_audio_video (sniffer, buffer); + if (sniffed_type != NULL) + return sniffed_type; + return g_strdup (content_type); + } + + /* If we got text/plain, use text_or_binary */ + if (g_str_equal (content_type, "text/plain")) { + return sniff_text_or_binary (sniffer, buffer); + } + + return g_strdup (content_type); +} + +static gsize +soup_content_sniffer_real_get_buffer_size (SoupContentSniffer *sniffer) +{ + return 512; +} + +static void +soup_content_sniffer_got_headers_cb (SoupMessage *msg, SoupContentSniffer *sniffer) +{ + SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); + + priv->bytes_for_sniffing = soup_content_sniffer_get_buffer_size (sniffer); +} + +static void +soup_content_sniffer_request_queued (SoupSessionFeature *feature, + SoupSession *session, + SoupMessage *msg) +{ + SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); + + priv->sniffer = g_object_ref (SOUP_CONTENT_SNIFFER (feature)); + g_signal_connect (msg, "got-headers", + G_CALLBACK (soup_content_sniffer_got_headers_cb), + feature); +} + +static void +soup_content_sniffer_request_unqueued (SoupSessionFeature *feature, + SoupSession *session, + SoupMessage *msg) +{ + SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); + + g_object_unref (priv->sniffer); + priv->sniffer = NULL; + + g_signal_handlers_disconnect_by_func (msg, soup_content_sniffer_got_headers_cb, feature); +} + +static void +soup_content_sniffer_class_init (SoupContentSnifferClass *content_sniffer_class) +{ + content_sniffer_class->sniff = soup_content_sniffer_real_sniff; + content_sniffer_class->get_buffer_size = soup_content_sniffer_real_get_buffer_size; +} + +static void +soup_content_sniffer_session_feature_init (SoupSessionFeatureInterface *feature_interface, + gpointer interface_data) +{ + feature_interface->request_queued = soup_content_sniffer_request_queued; + feature_interface->request_unqueued = soup_content_sniffer_request_unqueued; +} + +/** + * soup_content_sniffer_new: + * + * Creates a new #SoupContentSniffer. + * + * Returns: a new #SoupContentSniffer + * + * Since: 2.28 + **/ +SoupContentSniffer * +soup_content_sniffer_new (void) +{ + return g_object_new (SOUP_TYPE_CONTENT_SNIFFER, NULL); +} + +/** + * soup_content_sniffer_sniff: + * @sniffer: a #SoupContentSniffer + * @msg: the message to sniff + * @buffer: a buffer containing the start of @msg's response body + * @params: (element-type utf8 utf8) (out) (transfer full) (allow-none): return + * location for Content-Type parameters (eg, "charset"), or %NULL + * + * Sniffs @buffer to determine its Content-Type. The result may also + * be influenced by the Content-Type declared in @msg's response + * headers. + * + * Return value: the sniffed Content-Type of @buffer; this will never be %NULL, + * but may be "application/octet-stream". + * + * Since: 2.28 + */ +char * +soup_content_sniffer_sniff (SoupContentSniffer *sniffer, + SoupMessage *msg, SoupBuffer *buffer, + GHashTable **params) +{ + g_return_val_if_fail (SOUP_IS_CONTENT_SNIFFER (sniffer), NULL); + g_return_val_if_fail (SOUP_IS_MESSAGE (msg), NULL); + g_return_val_if_fail (buffer != NULL, NULL); + + return SOUP_CONTENT_SNIFFER_GET_CLASS (sniffer)->sniff (sniffer, msg, buffer, params); +} + +/** + * soup_content_sniffer_get_buffer_size: + * @sniffer: a #SoupContentSniffer + * + * Gets the number of bytes @sniffer needs in order to properly sniff + * a buffer. + * + * Return value: the number of bytes to sniff + * + * Since: 2.28 + */ +gsize +soup_content_sniffer_get_buffer_size (SoupContentSniffer *sniffer) +{ + g_return_val_if_fail (SOUP_IS_CONTENT_SNIFFER (sniffer), 0); + + return SOUP_CONTENT_SNIFFER_GET_CLASS (sniffer)->get_buffer_size (sniffer); +} diff --git a/libsoup/soup-content-sniffer.h b/libsoup/soup-content-sniffer.h new file mode 100644 index 0000000..eb1e4bd --- /dev/null +++ b/libsoup/soup-content-sniffer.h @@ -0,0 +1,62 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2009 Gustavo Noronha Silva. + */ + +#ifndef SOUP_CONTENT_SNIFFER_H +#define SOUP_CONTENT_SNIFFER_H 1 + +#include +#include + +G_BEGIN_DECLS + +#define SOUP_TYPE_CONTENT_SNIFFER (soup_content_sniffer_get_type ()) +#define SOUP_CONTENT_SNIFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SOUP_TYPE_CONTENT_SNIFFER, SoupContentSniffer)) +#define SOUP_CONTENT_SNIFFER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_CONTENT_SNIFFER, SoupContentSnifferClass)) +#define SOUP_IS_CONTENT_SNIFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SOUP_TYPE_CONTENT_SNIFFER)) +#define SOUP_IS_CONTENT_SNIFFER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), SOUP_TYPE_CONTENT_SNIFFER)) +#define SOUP_CONTENT_SNIFFER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_CONTENT_SNIFFER, SoupContentSnifferClass)) + +typedef struct _SoupContentSnifferPrivate SoupContentSnifferPrivate; + +typedef struct { + GObject parent; + + SoupContentSnifferPrivate *priv; +} SoupContentSniffer; + +typedef struct { + GObjectClass parent_class; + + char* (*sniff) (SoupContentSniffer *sniffer, + SoupMessage *msg, + SoupBuffer *buffer, + GHashTable **params); + gsize (*get_buffer_size) (SoupContentSniffer *sniffer); + + /* Padding for future expansion */ + void (*_libsoup_reserved1) (void); + void (*_libsoup_reserved2) (void); + void (*_libsoup_reserved3) (void); + void (*_libsoup_reserved4) (void); + void (*_libsoup_reserved5) (void); +} SoupContentSnifferClass; + +SOUP_AVAILABLE_IN_2_28 +GType soup_content_sniffer_get_type (void); + +SOUP_AVAILABLE_IN_2_28 +SoupContentSniffer *soup_content_sniffer_new (void); + +SOUP_AVAILABLE_IN_2_28 +char *soup_content_sniffer_sniff (SoupContentSniffer *sniffer, + SoupMessage *msg, + SoupBuffer *buffer, + GHashTable **params); +SOUP_AVAILABLE_IN_2_28 +gsize soup_content_sniffer_get_buffer_size (SoupContentSniffer *sniffer); + +G_END_DECLS + +#endif /* SOUP_CONTENT_SNIFFER_H */ diff --git a/libsoup/soup-converter-wrapper.c b/libsoup/soup-converter-wrapper.c new file mode 100644 index 0000000..133a3eb --- /dev/null +++ b/libsoup/soup-converter-wrapper.c @@ -0,0 +1,345 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-converter-wrapper.c + * + * Copyright 2011 Red Hat, Inc. + */ + +#include "config.h" + +#include + +#include + +#include "soup-converter-wrapper.h" +#include "soup.h" + +/* SoupConverterWrapper is a GConverter that wraps another GConverter. + * Mostly it is transparent, but it implements four special fallbacks + * for Content-Encoding handling: (1) "deflate" can mean either raw + * deflate or zlib-encoded deflate, (2) the server may mistakenly + * claim that a response is encoded when actually it isn't, (3) the + * response may contain trailing junk after the end of the encoded + * portion that we want to ignore, (4) the response may be truncated + * at an arbitrary point rather than containing a complete compressed + * representation. + * + * If the wrapped conversion succeeds, then the wrapper will set the + * %SOUP_MESSAGE_CONTENT_DECODED flag on its message. + */ + +enum { + PROP_0, + PROP_BASE_CONVERTER, + PROP_MESSAGE +}; + +struct _SoupConverterWrapperPrivate +{ + GConverter *base_converter; + SoupMessage *msg; + gboolean try_deflate_fallback; + gboolean started; + gboolean discarding; +}; + +static void soup_converter_wrapper_iface_init (GConverterIface *iface); + +G_DEFINE_TYPE_WITH_CODE (SoupConverterWrapper, soup_converter_wrapper, G_TYPE_OBJECT, + G_ADD_PRIVATE (SoupConverterWrapper) + G_IMPLEMENT_INTERFACE (G_TYPE_CONVERTER, + soup_converter_wrapper_iface_init)) + +static void +soup_converter_wrapper_init (SoupConverterWrapper *converter) +{ + converter->priv = soup_converter_wrapper_get_instance_private (converter); +} + +static void +soup_converter_wrapper_finalize (GObject *object) +{ + SoupConverterWrapperPrivate *priv = SOUP_CONVERTER_WRAPPER (object)->priv; + + g_clear_object (&priv->base_converter); + g_clear_object (&priv->msg); + + G_OBJECT_CLASS (soup_converter_wrapper_parent_class)->finalize (object); +} + + +static void +soup_converter_wrapper_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + SoupConverterWrapperPrivate *priv = SOUP_CONVERTER_WRAPPER (object)->priv; + + switch (prop_id) { + case PROP_BASE_CONVERTER: + priv->base_converter = g_value_dup_object (value); + if (G_IS_ZLIB_DECOMPRESSOR (priv->base_converter)) { + GZlibCompressorFormat format; + + g_object_get (G_OBJECT (priv->base_converter), + "format", &format, + NULL); + if (format == G_ZLIB_COMPRESSOR_FORMAT_ZLIB) + priv->try_deflate_fallback = TRUE; + } + break; + + case PROP_MESSAGE: + priv->msg = g_value_dup_object (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +soup_converter_wrapper_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + SoupConverterWrapperPrivate *priv = SOUP_CONVERTER_WRAPPER (object)->priv; + + switch (prop_id) { + case PROP_BASE_CONVERTER: + g_value_set_object (value, priv->base_converter); + break; + + case PROP_MESSAGE: + g_value_set_object (value, priv->msg); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +soup_converter_wrapper_class_init (SoupConverterWrapperClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->finalize = soup_converter_wrapper_finalize; + gobject_class->get_property = soup_converter_wrapper_get_property; + gobject_class->set_property = soup_converter_wrapper_set_property; + + g_object_class_install_property (gobject_class, + PROP_BASE_CONVERTER, + g_param_spec_object ("base-converter", + "Base GConverter", + "GConverter to wrap", + G_TYPE_CONVERTER, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, + PROP_MESSAGE, + g_param_spec_object ("message", + "Message", + "Associated SoupMessage", + SOUP_TYPE_MESSAGE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); +} + +GConverter * +soup_converter_wrapper_new (GConverter *base_converter, + SoupMessage *msg) +{ + return g_object_new (SOUP_TYPE_CONVERTER_WRAPPER, + "base-converter", base_converter, + "message", msg, + NULL); +} + +static void +soup_converter_wrapper_reset (GConverter *converter) +{ + SoupConverterWrapperPrivate *priv = SOUP_CONVERTER_WRAPPER (converter)->priv; + + if (priv->base_converter) + g_converter_reset (priv->base_converter); +} + +static GConverterResult +soup_converter_wrapper_fallback_convert (GConverter *converter, + const void *inbuf, + gsize inbuf_size, + void *outbuf, + gsize outbuf_size, + GConverterFlags flags, + gsize *bytes_read, + gsize *bytes_written, + GError **error) +{ + SoupConverterWrapperPrivate *priv = SOUP_CONVERTER_WRAPPER (converter)->priv; + + if (outbuf_size == 0) { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_NO_SPACE, + _("Output buffer is too small")); + return G_CONVERTER_ERROR; + } + + if (priv->discarding) { + *bytes_read = inbuf_size; + *bytes_written = 0; + } else if (outbuf_size >= inbuf_size) { + memcpy (outbuf, inbuf, inbuf_size); + *bytes_read = *bytes_written = inbuf_size; + } else { + memcpy (outbuf, inbuf, outbuf_size); + *bytes_read = *bytes_written = outbuf_size; + } + + if (*bytes_read < inbuf_size) + return G_CONVERTER_CONVERTED; + + if (flags & G_CONVERTER_INPUT_AT_END) + return G_CONVERTER_FINISHED; + else if (flags & G_CONVERTER_FLUSH) + return G_CONVERTER_FLUSHED; + else if (inbuf_size) + return G_CONVERTER_CONVERTED; + else { + /* Force it to either read more input or + * try again with G_CONVERTER_INPUT_AT_END. + */ + g_set_error_literal (error, G_IO_ERROR, + G_IO_ERROR_PARTIAL_INPUT, + ""); + return G_CONVERTER_ERROR; + } +} + +static GConverterResult +soup_converter_wrapper_real_convert (GConverter *converter, + const void *inbuf, + gsize inbuf_size, + void *outbuf, + gsize outbuf_size, + GConverterFlags flags, + gsize *bytes_read, + gsize *bytes_written, + GError **error) +{ + SoupConverterWrapperPrivate *priv = SOUP_CONVERTER_WRAPPER (converter)->priv; + GConverterResult result; + GError *my_error = NULL; + + try_again: + result = g_converter_convert (priv->base_converter, + inbuf, inbuf_size, + outbuf, outbuf_size, + flags, bytes_read, bytes_written, + &my_error); + if (result != G_CONVERTER_ERROR) { + if (!priv->started) { + SoupMessageFlags message_flags = soup_message_get_flags (priv->msg); + soup_message_set_flags (priv->msg, message_flags | SOUP_MESSAGE_CONTENT_DECODED); + priv->started = TRUE; + } + + if (result == G_CONVERTER_FINISHED && + !(flags & G_CONVERTER_INPUT_AT_END)) { + /* We need to keep reading (and discarding) + * input to the end of the message body. + */ + g_clear_object (&priv->base_converter); + priv->discarding = TRUE; + + if (*bytes_written) + return G_CONVERTER_CONVERTED; + else { + g_set_error_literal (error, G_IO_ERROR, + G_IO_ERROR_PARTIAL_INPUT, + ""); + return G_CONVERTER_ERROR; + } + } + + return result; + } + + if (g_error_matches (my_error, G_IO_ERROR, G_IO_ERROR_PARTIAL_INPUT) && + inbuf_size == 0 && (flags & G_CONVERTER_INPUT_AT_END)) { + /* Server claimed compression but there was no message body. */ + g_error_free (my_error); + *bytes_written = 0; + return G_CONVERTER_FINISHED; + } + + if (!g_error_matches (my_error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA) || + priv->started) { + g_propagate_error (error, my_error); + return result; + } + g_clear_error (&my_error); + + /* Deflate hack: some servers (especially Apache with + * mod_deflate) return raw compressed data without the zlib + * headers when the client claims to support deflate. + */ + if (priv->try_deflate_fallback) { + priv->try_deflate_fallback = FALSE; + g_object_unref (priv->base_converter); + priv->base_converter = (GConverter *) + g_zlib_decompressor_new (G_ZLIB_COMPRESSOR_FORMAT_RAW); + goto try_again; + } + + /* Passthrough hack: some servers mistakenly claim to be + * sending encoded data when in fact they aren't, so fall + * back to just not decoding. + */ + g_clear_object (&priv->base_converter); + return soup_converter_wrapper_fallback_convert (converter, + inbuf, inbuf_size, + outbuf, outbuf_size, + flags, bytes_read, + bytes_written, error); +} + +static GConverterResult +soup_converter_wrapper_convert (GConverter *converter, + const void *inbuf, + gsize inbuf_size, + void *outbuf, + gsize outbuf_size, + GConverterFlags flags, + gsize *bytes_read, + gsize *bytes_written, + GError **error) +{ + SoupConverterWrapperPrivate *priv = SOUP_CONVERTER_WRAPPER (converter)->priv; + + if (priv->base_converter) { + return soup_converter_wrapper_real_convert (converter, + inbuf, inbuf_size, + outbuf, outbuf_size, + flags, bytes_read, + bytes_written, error); + } else { + return soup_converter_wrapper_fallback_convert (converter, + inbuf, inbuf_size, + outbuf, outbuf_size, + flags, bytes_read, + bytes_written, error); + } +} + +static void +soup_converter_wrapper_iface_init (GConverterIface *iface) +{ + iface->convert = soup_converter_wrapper_convert; + iface->reset = soup_converter_wrapper_reset; +} diff --git a/libsoup/soup-converter-wrapper.h b/libsoup/soup-converter-wrapper.h new file mode 100644 index 0000000..62ed9da --- /dev/null +++ b/libsoup/soup-converter-wrapper.h @@ -0,0 +1,45 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright 2011 Red Hat, Inc. + */ + +#ifndef SOUP_CONVERTER_WRAPPER_H +#define SOUP_CONVERTER_WRAPPER_H 1 + +#include + +G_BEGIN_DECLS + +#define SOUP_TYPE_CONVERTER_WRAPPER (soup_converter_wrapper_get_type ()) +#define SOUP_CONVERTER_WRAPPER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SOUP_TYPE_CONVERTER_WRAPPER, SoupConverterWrapper)) +#define SOUP_CONVERTER_WRAPPER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_CONVERTER_WRAPPER, SoupConverterWrapperClass)) +#define SOUP_IS_CONVERTER_WRAPPER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SOUP_TYPE_CONVERTER_WRAPPER)) +#define SOUP_IS_CONVERTER_WRAPPER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), SOUP_TYPE_CONVERTER_WRAPPER)) +#define SOUP_CONVERTER_WRAPPER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_CONVERTER_WRAPPER, SoupConverterWrapperClass)) + +typedef struct _SoupConverterWrapperPrivate SoupConverterWrapperPrivate; + +typedef struct { + GObject parent; + + SoupConverterWrapperPrivate *priv; +} SoupConverterWrapper; + +typedef struct { + GObjectClass parent_class; + + /* Padding for future expansion */ + void (*_libsoup_reserved1) (void); + void (*_libsoup_reserved2) (void); + void (*_libsoup_reserved3) (void); + void (*_libsoup_reserved4) (void); +} SoupConverterWrapperClass; + +GType soup_converter_wrapper_get_type (void); + +GConverter *soup_converter_wrapper_new (GConverter *base_converter, + SoupMessage *msg); + +G_END_DECLS + +#endif /* SOUP_CONVERTER_WRAPPER_H */ diff --git a/libsoup/soup-cookie-jar-db.c b/libsoup/soup-cookie-jar-db.c new file mode 100644 index 0000000..0274038 --- /dev/null +++ b/libsoup/soup-cookie-jar-db.c @@ -0,0 +1,333 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-cookie-jar-db.c: database-based cookie storage + * + * Using danw's soup-cookie-jar-text as template + * Copyright (C) 2008 Diego Escalante Urrelo + * Copyright (C) 2009 Collabora Ltd. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include + +#include "soup-cookie-jar-db.h" +#include "soup.h" + +/** + * SECTION:soup-cookie-jar-db + * @short_description: Database-based Cookie Jar + * + * #SoupCookieJarDB is a #SoupCookieJar that reads cookies from and + * writes them to a sqlite database in the new Mozilla format. + * + * (This is identical to SoupCookieJarSqlite in + * libsoup-gnome; it has just been moved into libsoup proper, and + * renamed to avoid conflicting.) + **/ + +enum { + PROP_0, + + PROP_FILENAME, + + LAST_PROP +}; + +typedef struct { + char *filename; + sqlite3 *db; +} SoupCookieJarDBPrivate; + +G_DEFINE_TYPE_WITH_PRIVATE (SoupCookieJarDB, soup_cookie_jar_db, SOUP_TYPE_COOKIE_JAR) + +static void load (SoupCookieJar *jar); + +static void +soup_cookie_jar_db_init (SoupCookieJarDB *db) +{ +} + +static void +soup_cookie_jar_db_finalize (GObject *object) +{ + SoupCookieJarDBPrivate *priv = + soup_cookie_jar_db_get_instance_private (SOUP_COOKIE_JAR_DB (object)); + + g_free (priv->filename); + g_clear_pointer (&priv->db, sqlite3_close); + + G_OBJECT_CLASS (soup_cookie_jar_db_parent_class)->finalize (object); +} + +static void +soup_cookie_jar_db_set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + SoupCookieJarDBPrivate *priv = + soup_cookie_jar_db_get_instance_private (SOUP_COOKIE_JAR_DB (object)); + + switch (prop_id) { + case PROP_FILENAME: + priv->filename = g_value_dup_string (value); + load (SOUP_COOKIE_JAR (object)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +soup_cookie_jar_db_get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + SoupCookieJarDBPrivate *priv = + soup_cookie_jar_db_get_instance_private (SOUP_COOKIE_JAR_DB (object)); + + switch (prop_id) { + case PROP_FILENAME: + g_value_set_string (value, priv->filename); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/** + * soup_cookie_jar_db_new: + * @filename: the filename to read to/write from, or %NULL + * @read_only: %TRUE if @filename is read-only + * + * Creates a #SoupCookieJarDB. + * + * @filename will be read in at startup to create an initial set of + * cookies. If @read_only is %FALSE, then the non-session cookies will + * be written to @filename when the 'changed' signal is emitted from + * the jar. (If @read_only is %TRUE, then the cookie jar will only be + * used for this session, and changes made to it will be lost when the + * jar is destroyed.) + * + * Return value: the new #SoupCookieJar + * + * Since: 2.42 + **/ +SoupCookieJar * +soup_cookie_jar_db_new (const char *filename, gboolean read_only) +{ + g_return_val_if_fail (filename != NULL, NULL); + + return g_object_new (SOUP_TYPE_COOKIE_JAR_DB, + SOUP_COOKIE_JAR_DB_FILENAME, filename, + SOUP_COOKIE_JAR_READ_ONLY, read_only, + NULL); +} + +#define QUERY_ALL "SELECT id, name, value, host, path, expiry, lastAccessed, isSecure, isHttpOnly FROM moz_cookies;" +#define CREATE_TABLE "CREATE TABLE moz_cookies (id INTEGER PRIMARY KEY, name TEXT, value TEXT, host TEXT, path TEXT,expiry INTEGER, lastAccessed INTEGER, isSecure INTEGER, isHttpOnly INTEGER)" +#define QUERY_INSERT "INSERT INTO moz_cookies VALUES(NULL, %Q, %Q, %Q, %Q, %d, NULL, %d, %d);" +#define QUERY_DELETE "DELETE FROM moz_cookies WHERE name=%Q AND host=%Q;" + +enum { + COL_ID, + COL_NAME, + COL_VALUE, + COL_HOST, + COL_PATH, + COL_EXPIRY, + COL_LAST_ACCESS, + COL_SECURE, + COL_HTTP_ONLY, + N_COL, +}; + +static int +callback (void *data, int argc, char **argv, char **colname) +{ + SoupCookie *cookie = NULL; + SoupCookieJar *jar = SOUP_COOKIE_JAR (data); + + char *name, *value, *host, *path; + gulong expire_time; + time_t now; + int max_age; + gboolean http_only = FALSE, secure = FALSE; + + now = time (NULL); + + name = argv[COL_NAME]; + value = argv[COL_VALUE]; + host = argv[COL_HOST]; + path = argv[COL_PATH]; + expire_time = strtoul (argv[COL_EXPIRY], NULL, 10); + + if (now >= expire_time) + return 0; + max_age = (expire_time - now <= G_MAXINT ? expire_time - now : G_MAXINT); + + http_only = (g_strcmp0 (argv[COL_HTTP_ONLY], "1") == 0); + secure = (g_strcmp0 (argv[COL_SECURE], "1") == 0); + + cookie = soup_cookie_new (name, value, host, path, max_age); + + if (secure) + soup_cookie_set_secure (cookie, TRUE); + if (http_only) + soup_cookie_set_http_only (cookie, TRUE); + + soup_cookie_jar_add_cookie (jar, cookie); + + return 0; +} + +static void +try_create_table (sqlite3 *db) +{ + char *error = NULL; + + if (sqlite3_exec (db, CREATE_TABLE, NULL, NULL, &error)) { + g_warning ("Failed to execute query: %s", error); + sqlite3_free (error); + } +} + +static void +exec_query_with_try_create_table (sqlite3 *db, + const char *sql, + int (*callback)(void*,int,char**,char**), + void *argument) +{ + char *error = NULL; + gboolean try_create = TRUE; + +try_exec: + if (sqlite3_exec (db, sql, callback, argument, &error)) { + if (try_create) { + try_create = FALSE; + try_create_table (db); + sqlite3_free (error); + error = NULL; + goto try_exec; + } else { + g_warning ("Failed to execute query: %s", error); + sqlite3_free (error); + } + } +} + +/* Follows sqlite3 convention; returns TRUE on error */ +static gboolean +open_db (SoupCookieJar *jar) +{ + SoupCookieJarDBPrivate *priv = + soup_cookie_jar_db_get_instance_private (SOUP_COOKIE_JAR_DB (jar)); + + char *error = NULL; + + if (sqlite3_open (priv->filename, &priv->db)) { + sqlite3_close (priv->db); + priv->db = NULL; + g_warning ("Can't open %s", priv->filename); + return TRUE; + } + + if (sqlite3_exec (priv->db, "PRAGMA synchronous = OFF; PRAGMA secure_delete = 1;", NULL, NULL, &error)) { + g_warning ("Failed to execute query: %s", error); + sqlite3_free (error); + } + + return FALSE; +} + +static void +load (SoupCookieJar *jar) +{ + SoupCookieJarDBPrivate *priv = + soup_cookie_jar_db_get_instance_private (SOUP_COOKIE_JAR_DB (jar)); + + if (priv->db == NULL) { + if (open_db (jar)) + return; + } + + exec_query_with_try_create_table (priv->db, QUERY_ALL, callback, jar); +} + +static void +soup_cookie_jar_db_changed (SoupCookieJar *jar, + SoupCookie *old_cookie, + SoupCookie *new_cookie) +{ + SoupCookieJarDBPrivate *priv = + soup_cookie_jar_db_get_instance_private (SOUP_COOKIE_JAR_DB (jar)); + char *query; + + if (priv->db == NULL) { + if (open_db (jar)) + return; + } + + if (old_cookie) { + query = sqlite3_mprintf (QUERY_DELETE, + old_cookie->name, + old_cookie->domain); + exec_query_with_try_create_table (priv->db, query, NULL, NULL); + sqlite3_free (query); + } + + if (new_cookie && new_cookie->expires) { + gulong expires; + + expires = (gulong)soup_date_to_time_t (new_cookie->expires); + query = sqlite3_mprintf (QUERY_INSERT, + new_cookie->name, + new_cookie->value, + new_cookie->domain, + new_cookie->path, + expires, + new_cookie->secure, + new_cookie->http_only); + exec_query_with_try_create_table (priv->db, query, NULL, NULL); + sqlite3_free (query); + } +} + +static gboolean +soup_cookie_jar_db_is_persistent (SoupCookieJar *jar) +{ + return TRUE; +} + +static void +soup_cookie_jar_db_class_init (SoupCookieJarDBClass *db_class) +{ + SoupCookieJarClass *cookie_jar_class = + SOUP_COOKIE_JAR_CLASS (db_class); + GObjectClass *object_class = G_OBJECT_CLASS (db_class); + + cookie_jar_class->is_persistent = soup_cookie_jar_db_is_persistent; + cookie_jar_class->changed = soup_cookie_jar_db_changed; + + object_class->finalize = soup_cookie_jar_db_finalize; + object_class->set_property = soup_cookie_jar_db_set_property; + object_class->get_property = soup_cookie_jar_db_get_property; + + /** + * SOUP_COOKIE_JAR_DB_FILENAME: + * + * Alias for the #SoupCookieJarDB:filename property. (The + * cookie-storage filename.) + **/ + g_object_class_install_property ( + object_class, PROP_FILENAME, + g_param_spec_string (SOUP_COOKIE_JAR_DB_FILENAME, + "Filename", + "Cookie-storage filename", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); +} diff --git a/libsoup/soup-cookie-jar-db.h b/libsoup/soup-cookie-jar-db.h new file mode 100644 index 0000000..1a98901 --- /dev/null +++ b/libsoup/soup-cookie-jar-db.h @@ -0,0 +1,46 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2008 Diego Escalante Urrelo + */ + +#ifndef SOUP_COOKIE_JAR_DB_H +#define SOUP_COOKIE_JAR_DB_H 1 + +#include + +G_BEGIN_DECLS + +#define SOUP_TYPE_COOKIE_JAR_DB (soup_cookie_jar_db_get_type ()) +#define SOUP_COOKIE_JAR_DB(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SOUP_TYPE_COOKIE_JAR_DB, SoupCookieJarDB)) +#define SOUP_COOKIE_JAR_DB_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_COOKIE_JAR_DB, SoupCookieJarDBClass)) +#define SOUP_IS_COOKIE_JAR_DB(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SOUP_TYPE_COOKIE_JAR_DB)) +#define SOUP_IS_COOKIE_JAR_DB_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), SOUP_TYPE_COOKIE_JAR_DB)) +#define SOUP_COOKIE_JAR_DB_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_COOKIE_JAR_DB, SoupCookieJarDBClass)) + +typedef struct { + SoupCookieJar parent; + +} SoupCookieJarDB; + +typedef struct { + SoupCookieJarClass parent_class; + + /* Padding for future expansion */ + void (*_libsoup_reserved1) (void); + void (*_libsoup_reserved2) (void); + void (*_libsoup_reserved3) (void); + void (*_libsoup_reserved4) (void); +} SoupCookieJarDBClass; + +#define SOUP_COOKIE_JAR_DB_FILENAME "filename" + +SOUP_AVAILABLE_IN_2_42 +GType soup_cookie_jar_db_get_type (void); + +SOUP_AVAILABLE_IN_2_42 +SoupCookieJar *soup_cookie_jar_db_new (const char *filename, + gboolean read_only); + +G_END_DECLS + +#endif /* SOUP_COOKIE_JAR_DB_H */ diff --git a/libsoup/soup-cookie-jar-sqlite.c b/libsoup/soup-cookie-jar-sqlite.c new file mode 100644 index 0000000..705e047 --- /dev/null +++ b/libsoup/soup-cookie-jar-sqlite.c @@ -0,0 +1,49 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-cookie-jar-sqlite.c: deprecated version of sqlite-based cookie storage + * + * Copyright 2012 Red Hat, Inc. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +/* Avoid deprecation warnings */ +#define SOUP_VERSION_MIN_REQUIRED SOUP_VERSION_2_40 + +#include "soup.h" +#include "soup-cookie-jar-sqlite.h" + +enum { + PROP_0, + + PROP_FILENAME, + + LAST_PROP +}; + +G_DEFINE_TYPE (SoupCookieJarSqlite, soup_cookie_jar_sqlite, SOUP_TYPE_COOKIE_JAR_DB) + +static void +soup_cookie_jar_sqlite_init (SoupCookieJarSqlite *sqlite) +{ +} + +SoupCookieJar * +soup_cookie_jar_sqlite_new (const char *filename, gboolean read_only) +{ + g_return_val_if_fail (filename != NULL, NULL); + + return g_object_new (SOUP_TYPE_COOKIE_JAR_SQLITE, + SOUP_COOKIE_JAR_SQLITE_FILENAME, filename, + SOUP_COOKIE_JAR_READ_ONLY, read_only, + NULL); +} + +static void +soup_cookie_jar_sqlite_class_init (SoupCookieJarSqliteClass *sqlite_class) +{ +} diff --git a/libsoup/soup-cookie-jar-sqlite.h b/libsoup/soup-cookie-jar-sqlite.h new file mode 100644 index 0000000..adc2786 --- /dev/null +++ b/libsoup/soup-cookie-jar-sqlite.h @@ -0,0 +1,43 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2008 Diego Escalante Urrelo + */ + +#ifndef SOUP_COOKIE_JAR_SQLITE_H +#define SOUP_COOKIE_JAR_SQLITE_H 1 + +#include + +G_BEGIN_DECLS + +#define SOUP_TYPE_COOKIE_JAR_SQLITE (soup_cookie_jar_sqlite_get_type ()) +#define SOUP_COOKIE_JAR_SQLITE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SOUP_TYPE_COOKIE_JAR_SQLITE, SoupCookieJarSqlite)) +#define SOUP_COOKIE_JAR_SQLITE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_COOKIE_JAR_SQLITE, SoupCookieJarSqliteClass)) +#define SOUP_IS_COOKIE_JAR_SQLITE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SOUP_TYPE_COOKIE_JAR_SQLITE)) +#define SOUP_IS_COOKIE_JAR_SQLITE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), SOUP_TYPE_COOKIE_JAR_SQLITE)) +#define SOUP_COOKIE_JAR_SQLITE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_COOKIE_JAR_SQLITE, SoupCookieJarSqliteClass)) + +typedef struct { + SoupCookieJarDB parent; + +} SoupCookieJarSqlite; + +typedef struct { + SoupCookieJarDBClass parent_class; + +} SoupCookieJarSqliteClass; + +#define SOUP_COOKIE_JAR_SQLITE_FILENAME "filename" + +SOUP_AVAILABLE_IN_2_26 +SOUP_DEPRECATED_IN_2_42_FOR(soup_cookie_jar_db_get_type) +GType soup_cookie_jar_sqlite_get_type (void); + +SOUP_AVAILABLE_IN_2_26 +SOUP_DEPRECATED_IN_2_42_FOR(soup_cookie_jar_db_new) +SoupCookieJar *soup_cookie_jar_sqlite_new (const char *filename, + gboolean read_only); + +G_END_DECLS + +#endif /* SOUP_COOKIE_JAR_SQLITE_H */ diff --git a/libsoup/soup-cookie-jar-text.c b/libsoup/soup-cookie-jar-text.c new file mode 100644 index 0000000..46e12e5 --- /dev/null +++ b/libsoup/soup-cookie-jar-text.c @@ -0,0 +1,360 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-cookie-jar-text.c: cookies.txt-based cookie storage + * + * Copyright (C) 2007, 2008 Red Hat, Inc. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include "soup-cookie-jar-text.h" +#include "soup.h" + +/** + * SECTION:soup-cookie-jar-text + * @short_description: Text-file-based ("cookies.txt") Cookie Jar + * + * #SoupCookieJarText is a #SoupCookieJar that reads cookies from and + * writes them to a text file in the Mozilla "cookies.txt" format. + **/ + +enum { + PROP_0, + + PROP_FILENAME, + + LAST_PROP +}; + +typedef struct { + char *filename; + +} SoupCookieJarTextPrivate; + +G_DEFINE_TYPE_WITH_PRIVATE (SoupCookieJarText, soup_cookie_jar_text, SOUP_TYPE_COOKIE_JAR) + +static void load (SoupCookieJar *jar); + +static void +soup_cookie_jar_text_init (SoupCookieJarText *text) +{ +} + +static void +soup_cookie_jar_text_finalize (GObject *object) +{ + SoupCookieJarTextPrivate *priv = + soup_cookie_jar_text_get_instance_private (SOUP_COOKIE_JAR_TEXT (object)); + + g_free (priv->filename); + + G_OBJECT_CLASS (soup_cookie_jar_text_parent_class)->finalize (object); +} + +static void +soup_cookie_jar_text_set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + SoupCookieJarTextPrivate *priv = + soup_cookie_jar_text_get_instance_private (SOUP_COOKIE_JAR_TEXT (object)); + + switch (prop_id) { + case PROP_FILENAME: + priv->filename = g_value_dup_string (value); + load (SOUP_COOKIE_JAR (object)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +soup_cookie_jar_text_get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + SoupCookieJarTextPrivate *priv = + soup_cookie_jar_text_get_instance_private (SOUP_COOKIE_JAR_TEXT (object)); + + switch (prop_id) { + case PROP_FILENAME: + g_value_set_string (value, priv->filename); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/** + * soup_cookie_jar_text_new: + * @filename: the filename to read to/write from + * @read_only: %TRUE if @filename is read-only + * + * Creates a #SoupCookieJarText. + * + * @filename will be read in at startup to create an initial set of + * cookies. If @read_only is %FALSE, then the non-session cookies will + * be written to @filename when the 'changed' signal is emitted from + * the jar. (If @read_only is %TRUE, then the cookie jar will only be + * used for this session, and changes made to it will be lost when the + * jar is destroyed.) + * + * Return value: the new #SoupCookieJar + * + * Since: 2.26 + **/ +SoupCookieJar * +soup_cookie_jar_text_new (const char *filename, gboolean read_only) +{ + g_return_val_if_fail (filename != NULL, NULL); + + return g_object_new (SOUP_TYPE_COOKIE_JAR_TEXT, + SOUP_COOKIE_JAR_TEXT_FILENAME, filename, + SOUP_COOKIE_JAR_READ_ONLY, read_only, + NULL); +} + +static SoupCookie* +parse_cookie (char *line, time_t now) +{ + char **result; + SoupCookie *cookie = NULL; + gboolean http_only; + gulong expire_time; + int max_age; + char *host, *path, *secure, *expires, *name, *value; + + if (g_str_has_prefix (line, "#HttpOnly_")) { + http_only = TRUE; + line += strlen ("#HttpOnly_"); + } else if (*line == '#' || g_ascii_isspace (*line)) + return cookie; + else + http_only = FALSE; + + result = g_strsplit (line, "\t", -1); + if (g_strv_length (result) != 7) + goto out; + + /* Check this first */ + expires = result[4]; + expire_time = strtoul (expires, NULL, 10); + if (now >= expire_time) + goto out; + max_age = (expire_time - now <= G_MAXINT ? expire_time - now : G_MAXINT); + + host = result[0]; + + /* result[1] is not used because it's redundat; it's a boolean + * value regarding whether the cookie should be used for + * sub-domains of the domain that is set for the cookie. It is + * TRUE if host starts with '.', and FALSE otherwise. + */ + + path = result[2]; + secure = result[3]; + + name = result[5]; + value = result[6]; + + cookie = soup_cookie_new (name, value, host, path, max_age); + + if (strcmp (secure, "FALSE") != 0) + soup_cookie_set_secure (cookie, TRUE); + if (http_only) + soup_cookie_set_http_only (cookie, TRUE); + + out: + g_strfreev (result); + + return cookie; +} + +static void +parse_line (SoupCookieJar *jar, char *line, time_t now) +{ + SoupCookie *cookie; + + cookie = parse_cookie (line, now); + if (cookie) + soup_cookie_jar_add_cookie (jar, cookie); +} + +static void +load (SoupCookieJar *jar) +{ + SoupCookieJarTextPrivate *priv = + soup_cookie_jar_text_get_instance_private (SOUP_COOKIE_JAR_TEXT (jar)); + char *contents = NULL, *line, *p; + gsize length = 0; + time_t now = time (NULL); + + /* FIXME: error? */ + if (!g_file_get_contents (priv->filename, &contents, &length, NULL)) + return; + + line = contents; + for (p = contents; *p; p++) { + /* \r\n comes out as an extra empty line and gets ignored */ + if (*p == '\r' || *p == '\n') { + *p = '\0'; + parse_line (jar, line, now); + line = p + 1; + } + } + parse_line (jar, line, now); + + g_free (contents); +} + +static void +write_cookie (FILE *out, SoupCookie *cookie) +{ + fseek (out, 0, SEEK_END); + + fprintf (out, "%s%s\t%s\t%s\t%s\t%lu\t%s\t%s\n", + cookie->http_only ? "#HttpOnly_" : "", + cookie->domain, + *cookie->domain == '.' ? "TRUE" : "FALSE", + cookie->path, + cookie->secure ? "TRUE" : "FALSE", + (gulong)soup_date_to_time_t (cookie->expires), + cookie->name, + cookie->value); +} + +static void +delete_cookie (const char *filename, SoupCookie *cookie) +{ + char *contents = NULL, *line, *p; + gsize length = 0; + FILE *f; + SoupCookie *c; + time_t now = time (NULL); + + if (!g_file_get_contents (filename, &contents, &length, NULL)) + return; + + f = fopen (filename, "w"); + if (!f) { + g_free (contents); + return; + } + + line = contents; + for (p = contents; *p; p++) { + /* \r\n comes out as an extra empty line and gets ignored */ + if (*p == '\r' || *p == '\n') { + *p = '\0'; + c = parse_cookie (line, now); + line = p + 1; + if (!c) + continue; + if (!soup_cookie_equal (cookie, c)) + write_cookie (f, c); + soup_cookie_free (c); + } + } + c = parse_cookie (line, now); + if (c) { + if (!soup_cookie_equal (cookie, c)) + write_cookie (f, c); + soup_cookie_free (c); + } + + g_free (contents); + fclose (f); +} + +static void +soup_cookie_jar_text_changed (SoupCookieJar *jar, + SoupCookie *old_cookie, + SoupCookie *new_cookie) +{ + FILE *out; + SoupCookieJarTextPrivate *priv = + soup_cookie_jar_text_get_instance_private (SOUP_COOKIE_JAR_TEXT (jar)); + + /* We can sort of ignore the semantics of the 'changed' + * signal here and simply delete the old cookie if present + * and write the new cookie if present. That will do the + * right thing for all 'added', 'deleted' and 'modified' + * meanings. + */ + /* Also, delete_cookie takes the filename and write_cookie + * a FILE pointer. Seems more convenient that way considering + * the implementations of the functions + */ + if (old_cookie) + delete_cookie (priv->filename, old_cookie); + + if (new_cookie) { + gboolean write_header = FALSE; + + if (!g_file_test (priv->filename, G_FILE_TEST_EXISTS)) + write_header = TRUE; + + out = fopen (priv->filename, "a"); + if (!out) { + /* FIXME: error? */ + return; + } + + if (write_header) { + fprintf (out, "# HTTP Cookie File\n"); + fprintf (out, "# http://www.netscape.com/newsref/std/cookie_spec.html\n"); + fprintf (out, "# This is a generated file! Do not edit.\n"); + fprintf (out, "# To delete cookies, use the Cookie Manager.\n\n"); + } + + if (new_cookie->expires) + write_cookie (out, new_cookie); + + if (fclose (out) != 0) { + /* FIXME: error? */ + return; + } + } +} + +static gboolean +soup_cookie_jar_text_is_persistent (SoupCookieJar *jar) +{ + return TRUE; +} + +static void +soup_cookie_jar_text_class_init (SoupCookieJarTextClass *text_class) +{ + SoupCookieJarClass *cookie_jar_class = + SOUP_COOKIE_JAR_CLASS (text_class); + GObjectClass *object_class = G_OBJECT_CLASS (text_class); + + cookie_jar_class->is_persistent = soup_cookie_jar_text_is_persistent; + cookie_jar_class->changed = soup_cookie_jar_text_changed; + + object_class->finalize = soup_cookie_jar_text_finalize; + object_class->set_property = soup_cookie_jar_text_set_property; + object_class->get_property = soup_cookie_jar_text_get_property; + + /** + * SOUP_COOKIE_JAR_TEXT_FILENAME: + * + * Alias for the #SoupCookieJarText:filename property. (The + * cookie-storage filename.) + **/ + g_object_class_install_property ( + object_class, PROP_FILENAME, + g_param_spec_string (SOUP_COOKIE_JAR_TEXT_FILENAME, + "Filename", + "Cookie-storage filename", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); +} diff --git a/libsoup/soup-cookie-jar-text.h b/libsoup/soup-cookie-jar-text.h new file mode 100644 index 0000000..83b8f28 --- /dev/null +++ b/libsoup/soup-cookie-jar-text.h @@ -0,0 +1,46 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2008 Red Hat, Inc. + */ + +#ifndef SOUP_COOKIE_JAR_TEXT_H +#define SOUP_COOKIE_JAR_TEXT_H 1 + +#include + +G_BEGIN_DECLS + +#define SOUP_TYPE_COOKIE_JAR_TEXT (soup_cookie_jar_text_get_type ()) +#define SOUP_COOKIE_JAR_TEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SOUP_TYPE_COOKIE_JAR_TEXT, SoupCookieJarText)) +#define SOUP_COOKIE_JAR_TEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_COOKIE_JAR_TEXT, SoupCookieJarTextClass)) +#define SOUP_IS_COOKIE_JAR_TEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SOUP_TYPE_COOKIE_JAR_TEXT)) +#define SOUP_IS_COOKIE_JAR_TEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), SOUP_TYPE_COOKIE_JAR_TEXT)) +#define SOUP_COOKIE_JAR_TEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_COOKIE_JAR_TEXT, SoupCookieJarTextClass)) + +typedef struct { + SoupCookieJar parent; + +} SoupCookieJarText; + +typedef struct { + SoupCookieJarClass parent_class; + + /* Padding for future expansion */ + void (*_libsoup_reserved1) (void); + void (*_libsoup_reserved2) (void); + void (*_libsoup_reserved3) (void); + void (*_libsoup_reserved4) (void); +} SoupCookieJarTextClass; + +#define SOUP_COOKIE_JAR_TEXT_FILENAME "filename" + +SOUP_AVAILABLE_IN_2_26 +GType soup_cookie_jar_text_get_type (void); + +SOUP_AVAILABLE_IN_2_26 +SoupCookieJar *soup_cookie_jar_text_new (const char *filename, + gboolean read_only); + +G_END_DECLS + +#endif /* SOUP_COOKIE_JAR_TEXT_H */ diff --git a/libsoup/soup-cookie-jar.c b/libsoup/soup-cookie-jar.c new file mode 100644 index 0000000..b2b7890 --- /dev/null +++ b/libsoup/soup-cookie-jar.c @@ -0,0 +1,894 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-cookie-jar.c + * + * Copyright (C) 2008 Red Hat, Inc. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "soup-cookie-jar.h" +#include "soup-misc-private.h" +#include "soup.h" + +/** + * SECTION:soup-cookie-jar + * @short_description: Automatic cookie handling for SoupSession + * + * A #SoupCookieJar stores #SoupCookies and arrange for them + * to be sent with the appropriate #SoupMessages. + * #SoupCookieJar implements #SoupSessionFeature, so you can add a + * cookie jar to a session with soup_session_add_feature() or + * soup_session_add_feature_by_type(). + * + * Note that the base #SoupCookieJar class does not support any form + * of long-term cookie persistence. + **/ + +enum { + CHANGED, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +enum { + PROP_0, + + PROP_READ_ONLY, + PROP_ACCEPT_POLICY, + + LAST_PROP +}; + +typedef struct { + gboolean constructed, read_only; + GHashTable *domains, *serials; + guint serial; + SoupCookieJarAcceptPolicy accept_policy; +} SoupCookieJarPrivate; + +static void soup_cookie_jar_session_feature_init (SoupSessionFeatureInterface *feature_interface, gpointer interface_data); + +G_DEFINE_TYPE_WITH_CODE (SoupCookieJar, soup_cookie_jar, G_TYPE_OBJECT, + G_ADD_PRIVATE (SoupCookieJar) + G_IMPLEMENT_INTERFACE (SOUP_TYPE_SESSION_FEATURE, + soup_cookie_jar_session_feature_init)) + +static void +soup_cookie_jar_init (SoupCookieJar *jar) +{ + SoupCookieJarPrivate *priv = soup_cookie_jar_get_instance_private (jar); + + priv->domains = g_hash_table_new_full (soup_str_case_hash, + soup_str_case_equal, + g_free, NULL); + priv->serials = g_hash_table_new (NULL, NULL); + priv->accept_policy = SOUP_COOKIE_JAR_ACCEPT_ALWAYS; +} + +static void +soup_cookie_jar_constructed (GObject *object) +{ + SoupCookieJarPrivate *priv = + soup_cookie_jar_get_instance_private (SOUP_COOKIE_JAR (object)); + + priv->constructed = TRUE; +} + +static void +soup_cookie_jar_finalize (GObject *object) +{ + SoupCookieJarPrivate *priv = + soup_cookie_jar_get_instance_private (SOUP_COOKIE_JAR (object)); + GHashTableIter iter; + gpointer key, value; + + g_hash_table_iter_init (&iter, priv->domains); + while (g_hash_table_iter_next (&iter, &key, &value)) + soup_cookies_free (value); + g_hash_table_destroy (priv->domains); + g_hash_table_destroy (priv->serials); + + G_OBJECT_CLASS (soup_cookie_jar_parent_class)->finalize (object); +} + +static void +soup_cookie_jar_set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + SoupCookieJarPrivate *priv = + soup_cookie_jar_get_instance_private (SOUP_COOKIE_JAR (object)); + + switch (prop_id) { + case PROP_READ_ONLY: + priv->read_only = g_value_get_boolean (value); + break; + case PROP_ACCEPT_POLICY: + priv->accept_policy = g_value_get_enum (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +soup_cookie_jar_get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + SoupCookieJarPrivate *priv = + soup_cookie_jar_get_instance_private (SOUP_COOKIE_JAR (object)); + + switch (prop_id) { + case PROP_READ_ONLY: + g_value_set_boolean (value, priv->read_only); + break; + case PROP_ACCEPT_POLICY: + g_value_set_enum (value, priv->accept_policy); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static gboolean +soup_cookie_jar_real_is_persistent (SoupCookieJar *jar) +{ + return FALSE; +} + +static void +soup_cookie_jar_class_init (SoupCookieJarClass *jar_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (jar_class); + + object_class->constructed = soup_cookie_jar_constructed; + object_class->finalize = soup_cookie_jar_finalize; + object_class->set_property = soup_cookie_jar_set_property; + object_class->get_property = soup_cookie_jar_get_property; + + jar_class->is_persistent = soup_cookie_jar_real_is_persistent; + + /** + * SoupCookieJar::changed: + * @jar: the #SoupCookieJar + * @old_cookie: the old #SoupCookie value + * @new_cookie: the new #SoupCookie value + * + * Emitted when @jar changes. If a cookie has been added, + * @new_cookie will contain the newly-added cookie and + * @old_cookie will be %NULL. If a cookie has been deleted, + * @old_cookie will contain the to-be-deleted cookie and + * @new_cookie will be %NULL. If a cookie has been changed, + * @old_cookie will contain its old value, and @new_cookie its + * new value. + **/ + signals[CHANGED] = + g_signal_new ("changed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (SoupCookieJarClass, changed), + NULL, NULL, + NULL, + G_TYPE_NONE, 2, + SOUP_TYPE_COOKIE | G_SIGNAL_TYPE_STATIC_SCOPE, + SOUP_TYPE_COOKIE | G_SIGNAL_TYPE_STATIC_SCOPE); + + /** + * SOUP_COOKIE_JAR_READ_ONLY: + * + * Alias for the #SoupCookieJar:read-only property. (Whether + * or not the cookie jar is read-only.) + **/ + g_object_class_install_property ( + object_class, PROP_READ_ONLY, + g_param_spec_boolean (SOUP_COOKIE_JAR_READ_ONLY, + "Read-only", + "Whether or not the cookie jar is read-only", + FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + /** + * SOUP_COOKIE_JAR_ACCEPT_POLICY: + * + * Alias for the #SoupCookieJar:accept-policy property. + * + * Since: 2.30 + */ + /** + * SoupCookieJar:accept-policy: + * + * The policy the jar should follow to accept or reject cookies + * + * Since: 2.30 + */ + g_object_class_install_property ( + object_class, PROP_ACCEPT_POLICY, + g_param_spec_enum (SOUP_COOKIE_JAR_ACCEPT_POLICY, + "Accept-policy", + "The policy the jar should follow to accept or reject cookies", + SOUP_TYPE_COOKIE_JAR_ACCEPT_POLICY, + SOUP_COOKIE_JAR_ACCEPT_ALWAYS, + G_PARAM_READWRITE)); +} + +/** + * soup_cookie_jar_new: + * + * Creates a new #SoupCookieJar. The base #SoupCookieJar class does + * not support persistent storage of cookies; use a subclass for that. + * + * Returns: a new #SoupCookieJar + * + * Since: 2.24 + **/ +SoupCookieJar * +soup_cookie_jar_new (void) +{ + return g_object_new (SOUP_TYPE_COOKIE_JAR, NULL); +} + +/** + * soup_cookie_jar_save: + * @jar: a #SoupCookieJar + * + * This function exists for backward compatibility, but does not do + * anything any more; cookie jars are saved automatically when they + * are changed. + * + * Since: 2.24 + * + * Deprecated: This is a no-op. + */ +void +soup_cookie_jar_save (SoupCookieJar *jar) +{ + /* Does nothing, obsolete */ +} + +static void +soup_cookie_jar_changed (SoupCookieJar *jar, + SoupCookie *old, SoupCookie *new) +{ + SoupCookieJarPrivate *priv = soup_cookie_jar_get_instance_private (jar); + + if (old && old != new) + g_hash_table_remove (priv->serials, old); + if (new) { + priv->serial++; + g_hash_table_insert (priv->serials, new, GUINT_TO_POINTER (priv->serial)); + } + + if (priv->read_only || !priv->constructed) + return; + + g_signal_emit (jar, signals[CHANGED], 0, old, new); +} + +static int +compare_cookies (gconstpointer a, gconstpointer b, gpointer jar) +{ + SoupCookie *ca = (SoupCookie *)a; + SoupCookie *cb = (SoupCookie *)b; + SoupCookieJarPrivate *priv = soup_cookie_jar_get_instance_private (jar); + int alen, blen; + guint aserial, bserial; + + /* "Cookies with longer path fields are listed before cookies + * with shorter path field." + */ + alen = ca->path ? strlen (ca->path) : 0; + blen = cb->path ? strlen (cb->path) : 0; + if (alen != blen) + return blen - alen; + + /* "Among cookies that have equal length path fields, cookies + * with earlier creation dates are listed before cookies with + * later creation dates." + */ + aserial = GPOINTER_TO_UINT (g_hash_table_lookup (priv->serials, ca)); + bserial = GPOINTER_TO_UINT (g_hash_table_lookup (priv->serials, cb)); + return aserial - bserial; +} + +static GSList * +get_cookies (SoupCookieJar *jar, SoupURI *uri, gboolean for_http, gboolean copy_cookies) +{ + SoupCookieJarPrivate *priv; + GSList *cookies, *domain_cookies; + char *domain, *cur, *next_domain; + GSList *new_head, *cookies_to_remove = NULL, *p; + + priv = soup_cookie_jar_get_instance_private (jar); + + if (!uri->host || !uri->host[0]) + return NULL; + + /* The logic here is a little weird, but the plan is that if + * uri->host is "www.foo.com", we will end up looking up + * cookies for ".www.foo.com", "www.foo.com", ".foo.com", and + * ".com", in that order. (Logic stolen from Mozilla.) + */ + cookies = NULL; + domain = cur = g_strdup_printf (".%s", uri->host); + next_domain = domain + 1; + do { + new_head = domain_cookies = g_hash_table_lookup (priv->domains, cur); + while (domain_cookies) { + GSList *next = domain_cookies->next; + SoupCookie *cookie = domain_cookies->data; + + if (cookie->expires && soup_date_is_past (cookie->expires)) { + cookies_to_remove = g_slist_append (cookies_to_remove, + cookie); + new_head = g_slist_delete_link (new_head, domain_cookies); + g_hash_table_insert (priv->domains, + g_strdup (cur), + new_head); + } else if (soup_cookie_applies_to_uri (cookie, uri) && + (for_http || !cookie->http_only)) + cookies = g_slist_append (cookies, copy_cookies ? soup_cookie_copy (cookie) : cookie); + + domain_cookies = next; + } + cur = next_domain; + if (cur) + next_domain = strchr (cur + 1, '.'); + } while (cur); + g_free (domain); + + for (p = cookies_to_remove; p; p = p->next) { + SoupCookie *cookie = p->data; + + soup_cookie_jar_changed (jar, cookie, NULL); + soup_cookie_free (cookie); + } + g_slist_free (cookies_to_remove); + + return g_slist_sort_with_data (cookies, compare_cookies, jar); +} + +/** + * soup_cookie_jar_get_cookies: + * @jar: a #SoupCookieJar + * @uri: a #SoupURI + * @for_http: whether or not the return value is being passed directly + * to an HTTP operation + * + * Retrieves (in Cookie-header form) the list of cookies that would + * be sent with a request to @uri. + * + * If @for_http is %TRUE, the return value will include cookies marked + * "HttpOnly" (that is, cookies that the server wishes to keep hidden + * from client-side scripting operations such as the JavaScript + * document.cookies property). Since #SoupCookieJar sets the Cookie + * header itself when making the actual HTTP request, you should + * almost certainly be setting @for_http to %FALSE if you are calling + * this. + * + * Return value: (nullable): the cookies, in string form, or %NULL if + * there are no cookies for @uri. + * + * Since: 2.24 + **/ +char * +soup_cookie_jar_get_cookies (SoupCookieJar *jar, SoupURI *uri, + gboolean for_http) +{ + GSList *cookies; + + g_return_val_if_fail (SOUP_IS_COOKIE_JAR (jar), NULL); + g_return_val_if_fail (uri != NULL, NULL); + + cookies = get_cookies (jar, uri, for_http, FALSE); + + if (cookies) { + char *result = soup_cookies_to_cookie_header (cookies); + g_slist_free (cookies); + + if (!*result) { + g_free (result); + result = NULL; + } + return result; + } else + return NULL; +} + +/** + * soup_cookie_jar_get_cookie_list: + * @jar: a #SoupCookieJar + * @uri: a #SoupURI + * @for_http: whether or not the return value is being passed directly + * to an HTTP operation + * + * Retrieves the list of cookies that would be sent with a request to @uri + * as a #GSList of #SoupCookie objects. + * + * If @for_http is %TRUE, the return value will include cookies marked + * "HttpOnly" (that is, cookies that the server wishes to keep hidden + * from client-side scripting operations such as the JavaScript + * document.cookies property). Since #SoupCookieJar sets the Cookie + * header itself when making the actual HTTP request, you should + * almost certainly be setting @for_http to %FALSE if you are calling + * this. + * + * Return value: (transfer full) (element-type Soup.Cookie): a #GSList + * with the cookies in the @jar that would be sent with a request to @uri. + * + * Since: 2.40 + **/ +GSList * +soup_cookie_jar_get_cookie_list (SoupCookieJar *jar, SoupURI *uri, gboolean for_http) +{ + g_return_val_if_fail (SOUP_IS_COOKIE_JAR (jar), NULL); + g_return_val_if_fail (uri != NULL, NULL); + + return get_cookies (jar, uri, for_http, TRUE); +} + +/** + * soup_cookie_jar_add_cookie: + * @jar: a #SoupCookieJar + * @cookie: (transfer full): a #SoupCookie + * + * Adds @cookie to @jar, emitting the 'changed' signal if we are modifying + * an existing cookie or adding a valid new cookie ('valid' means + * that the cookie's expire date is not in the past). + * + * @cookie will be 'stolen' by the jar, so don't free it afterwards. + * + * Since: 2.26 + **/ +void +soup_cookie_jar_add_cookie (SoupCookieJar *jar, SoupCookie *cookie) +{ + SoupCookieJarPrivate *priv; + GSList *old_cookies, *oc, *last = NULL; + SoupCookie *old_cookie; + + g_return_if_fail (SOUP_IS_COOKIE_JAR (jar)); + g_return_if_fail (cookie != NULL); + + /* Never accept cookies for public domains. */ + if (!g_hostname_is_ip_address (cookie->domain) && + soup_tld_domain_is_public_suffix (cookie->domain)) { + soup_cookie_free (cookie); + return; + } + + priv = soup_cookie_jar_get_instance_private (jar); + old_cookies = g_hash_table_lookup (priv->domains, cookie->domain); + for (oc = old_cookies; oc; oc = oc->next) { + old_cookie = oc->data; + if (!strcmp (cookie->name, old_cookie->name) && + !g_strcmp0 (cookie->path, old_cookie->path)) { + if (cookie->expires && soup_date_is_past (cookie->expires)) { + /* The new cookie has an expired date, + * this is the way the the server has + * of telling us that we have to + * remove the cookie. + */ + old_cookies = g_slist_delete_link (old_cookies, oc); + g_hash_table_insert (priv->domains, + g_strdup (cookie->domain), + old_cookies); + soup_cookie_jar_changed (jar, old_cookie, NULL); + soup_cookie_free (old_cookie); + soup_cookie_free (cookie); + } else { + oc->data = cookie; + soup_cookie_jar_changed (jar, old_cookie, cookie); + soup_cookie_free (old_cookie); + } + + return; + } + last = oc; + } + + /* The new cookie is... a new cookie */ + if (cookie->expires && soup_date_is_past (cookie->expires)) { + soup_cookie_free (cookie); + return; + } + + if (last) + last->next = g_slist_append (NULL, cookie); + else { + old_cookies = g_slist_append (NULL, cookie); + g_hash_table_insert (priv->domains, g_strdup (cookie->domain), + old_cookies); + } + + soup_cookie_jar_changed (jar, NULL, cookie); +} + +static const char * +normalize_cookie_domain (const char *domain) +{ + /* Trim any leading dot if present to transform the cookie + * domain into a valid hostname. + */ + if (domain != NULL && domain[0] == '.') + return domain + 1; + return domain; +} + +static gboolean +incoming_cookie_is_third_party (SoupCookie *cookie, SoupURI *first_party) +{ + const char *normalized_cookie_domain; + const char *cookie_base_domain; + const char *first_party_base_domain; + + if (first_party == NULL || first_party->host == NULL) + return TRUE; + + normalized_cookie_domain = normalize_cookie_domain (cookie->domain); + cookie_base_domain = soup_tld_get_base_domain (normalized_cookie_domain, NULL); + if (cookie_base_domain == NULL) + cookie_base_domain = cookie->domain; + + first_party_base_domain = soup_tld_get_base_domain (first_party->host, NULL); + if (first_party_base_domain == NULL) + first_party_base_domain = first_party->host; + return !soup_host_matches_host (cookie_base_domain, first_party_base_domain); +} + +/** + * soup_cookie_jar_add_cookie_with_first_party: + * @jar: a #SoupCookieJar + * @first_party: the URI for the main document + * @cookie: (transfer full): a #SoupCookie + * + * Adds @cookie to @jar, emitting the 'changed' signal if we are modifying + * an existing cookie or adding a valid new cookie ('valid' means + * that the cookie's expire date is not in the past). + * + * @first_party will be used to reject cookies coming from third party + * resources in case such a security policy is set in the @jar. + * + * @cookie will be 'stolen' by the jar, so don't free it afterwards. + * + * Since: 2.40 + **/ +void +soup_cookie_jar_add_cookie_with_first_party (SoupCookieJar *jar, SoupURI *first_party, SoupCookie *cookie) +{ + SoupCookieJarPrivate *priv; + + g_return_if_fail (SOUP_IS_COOKIE_JAR (jar)); + g_return_if_fail (first_party != NULL); + g_return_if_fail (cookie != NULL); + + priv = soup_cookie_jar_get_instance_private (jar); + if (priv->accept_policy == SOUP_COOKIE_JAR_ACCEPT_NEVER) { + soup_cookie_free (cookie); + return; + } + + if (priv->accept_policy == SOUP_COOKIE_JAR_ACCEPT_ALWAYS || + !incoming_cookie_is_third_party (cookie, first_party)) { + /* will steal or free soup_cookie */ + soup_cookie_jar_add_cookie (jar, cookie); + } else { + soup_cookie_free (cookie); + } +} + +/** + * soup_cookie_jar_set_cookie: + * @jar: a #SoupCookieJar + * @uri: the URI setting the cookie + * @cookie: the stringified cookie to set + * + * Adds @cookie to @jar, exactly as though it had appeared in a + * Set-Cookie header returned from a request to @uri. + * + * Keep in mind that if the #SoupCookieJarAcceptPolicy + * %SOUP_COOKIE_JAR_ACCEPT_NO_THIRD_PARTY is set you'll need to use + * soup_cookie_jar_set_cookie_with_first_party(), otherwise the jar + * will have no way of knowing if the cookie is being set by a third + * party or not. + * + * Since: 2.24 + **/ +void +soup_cookie_jar_set_cookie (SoupCookieJar *jar, SoupURI *uri, + const char *cookie) +{ + SoupCookie *soup_cookie; + SoupCookieJarPrivate *priv; + + g_return_if_fail (SOUP_IS_COOKIE_JAR (jar)); + g_return_if_fail (uri != NULL); + g_return_if_fail (cookie != NULL); + + if (!uri->host) + return; + + priv = soup_cookie_jar_get_instance_private (jar); + if (priv->accept_policy == SOUP_COOKIE_JAR_ACCEPT_NEVER) + return; + + g_return_if_fail (priv->accept_policy != SOUP_COOKIE_JAR_ACCEPT_NO_THIRD_PARTY); + + soup_cookie = soup_cookie_parse (cookie, uri); + if (soup_cookie) { + /* will steal or free soup_cookie */ + soup_cookie_jar_add_cookie (jar, soup_cookie); + } +} + +/** + * soup_cookie_jar_set_cookie_with_first_party: + * @jar: a #SoupCookieJar + * @uri: the URI setting the cookie + * @first_party: the URI for the main document + * @cookie: the stringified cookie to set + * + * Adds @cookie to @jar, exactly as though it had appeared in a + * Set-Cookie header returned from a request to @uri. @first_party + * will be used to reject cookies coming from third party resources in + * case such a security policy is set in the @jar. + * + * Since: 2.30 + **/ +void +soup_cookie_jar_set_cookie_with_first_party (SoupCookieJar *jar, + SoupURI *uri, + SoupURI *first_party, + const char *cookie) +{ + SoupCookie *soup_cookie; + + g_return_if_fail (SOUP_IS_COOKIE_JAR (jar)); + g_return_if_fail (uri != NULL); + g_return_if_fail (first_party != NULL); + g_return_if_fail (cookie != NULL); + + if (!uri->host) + return; + + soup_cookie = soup_cookie_parse (cookie, uri); + if (soup_cookie) + soup_cookie_jar_add_cookie_with_first_party (jar, first_party, soup_cookie); +} + +static void +process_set_cookie_header (SoupMessage *msg, gpointer user_data) +{ + SoupCookieJar *jar = user_data; + SoupCookieJarPrivate *priv = soup_cookie_jar_get_instance_private (jar); + GSList *new_cookies, *nc; + + if (priv->accept_policy == SOUP_COOKIE_JAR_ACCEPT_NEVER) + return; + + new_cookies = soup_cookies_from_response (msg); + for (nc = new_cookies; nc; nc = nc->next) { + SoupURI *first_party = soup_message_get_first_party (msg); + + if ((priv->accept_policy == SOUP_COOKIE_JAR_ACCEPT_NO_THIRD_PARTY && + !incoming_cookie_is_third_party (nc->data, first_party)) || + priv->accept_policy == SOUP_COOKIE_JAR_ACCEPT_ALWAYS) + soup_cookie_jar_add_cookie (jar, nc->data); + else + soup_cookie_free (nc->data); + } + g_slist_free (new_cookies); +} + +static void +msg_starting_cb (SoupMessage *msg, gpointer feature) +{ + SoupCookieJar *jar = SOUP_COOKIE_JAR (feature); + char *cookies; + + cookies = soup_cookie_jar_get_cookies (jar, soup_message_get_uri (msg), TRUE); + if (cookies) { + soup_message_headers_replace (msg->request_headers, + "Cookie", cookies); + g_free (cookies); + } else + soup_message_headers_remove (msg->request_headers, "Cookie"); +} + +static void +soup_cookie_jar_request_queued (SoupSessionFeature *feature, + SoupSession *session, + SoupMessage *msg) +{ + g_signal_connect (msg, "starting", + G_CALLBACK (msg_starting_cb), + feature); + + soup_message_add_header_handler (msg, "got-headers", + "Set-Cookie", + G_CALLBACK (process_set_cookie_header), + feature); +} + +static void +soup_cookie_jar_request_unqueued (SoupSessionFeature *feature, + SoupSession *session, + SoupMessage *msg) +{ + g_signal_handlers_disconnect_by_func (msg, process_set_cookie_header, feature); +} + +static void +soup_cookie_jar_session_feature_init (SoupSessionFeatureInterface *feature_interface, + gpointer interface_data) +{ + feature_interface->request_queued = soup_cookie_jar_request_queued; + feature_interface->request_unqueued = soup_cookie_jar_request_unqueued; +} + +/** + * soup_cookie_jar_all_cookies: + * @jar: a #SoupCookieJar + * + * Constructs a #GSList with every cookie inside the @jar. + * The cookies in the list are a copy of the original, so + * you have to free them when you are done with them. + * + * Return value: (transfer full) (element-type Soup.Cookie): a #GSList + * with all the cookies in the @jar. + * + * Since: 2.26 + **/ +GSList * +soup_cookie_jar_all_cookies (SoupCookieJar *jar) +{ + SoupCookieJarPrivate *priv; + GHashTableIter iter; + GSList *l = NULL; + gpointer key, value; + + g_return_val_if_fail (SOUP_IS_COOKIE_JAR (jar), NULL); + + priv = soup_cookie_jar_get_instance_private (jar); + + g_hash_table_iter_init (&iter, priv->domains); + + while (g_hash_table_iter_next (&iter, &key, &value)) { + GSList *p, *cookies = value; + for (p = cookies; p; p = p->next) + l = g_slist_prepend (l, soup_cookie_copy (p->data)); + } + + return l; +} + +/** + * soup_cookie_jar_delete_cookie: + * @jar: a #SoupCookieJar + * @cookie: a #SoupCookie + * + * Deletes @cookie from @jar, emitting the 'changed' signal. + * + * Since: 2.26 + **/ +void +soup_cookie_jar_delete_cookie (SoupCookieJar *jar, + SoupCookie *cookie) +{ + SoupCookieJarPrivate *priv; + GSList *cookies, *p; + + g_return_if_fail (SOUP_IS_COOKIE_JAR (jar)); + g_return_if_fail (cookie != NULL); + + priv = soup_cookie_jar_get_instance_private (jar); + + cookies = g_hash_table_lookup (priv->domains, cookie->domain); + if (cookies == NULL) + return; + + for (p = cookies; p; p = p->next ) { + SoupCookie *c = (SoupCookie*)p->data; + if (soup_cookie_equal (cookie, c)) { + cookies = g_slist_delete_link (cookies, p); + g_hash_table_insert (priv->domains, + g_strdup (cookie->domain), + cookies); + soup_cookie_jar_changed (jar, c, NULL); + soup_cookie_free (c); + return; + } + } +} + +/** + * SoupCookieJarAcceptPolicy: + * @SOUP_COOKIE_JAR_ACCEPT_ALWAYS: accept all cookies unconditionally. + * @SOUP_COOKIE_JAR_ACCEPT_NEVER: reject all cookies unconditionally. + * @SOUP_COOKIE_JAR_ACCEPT_NO_THIRD_PARTY: accept all cookies set by + * the main document loaded in the application using libsoup. An + * example of the most common case, web browsers, would be: If + * http://www.example.com is the page loaded, accept all cookies set + * by example.com, but if a resource from http://www.third-party.com + * is loaded from that page reject any cookie that it could try to + * set. For libsoup to be able to tell apart first party cookies from + * the rest, the application must call soup_message_set_first_party() + * on each outgoing #SoupMessage, setting the #SoupURI of the main + * document. If no first party is set in a message when this policy is + * in effect, cookies will be assumed to be third party by default. + * + * The policy for accepting or rejecting cookies returned in + * responses. + * + * Since: 2.30 + */ + +/** + * soup_cookie_jar_get_accept_policy: + * @jar: a #SoupCookieJar + * + * Gets @jar's #SoupCookieJarAcceptPolicy + * + * Returns: the #SoupCookieJarAcceptPolicy set in the @jar + * + * Since: 2.30 + **/ +SoupCookieJarAcceptPolicy +soup_cookie_jar_get_accept_policy (SoupCookieJar *jar) +{ + SoupCookieJarPrivate *priv; + + g_return_val_if_fail (SOUP_IS_COOKIE_JAR (jar), SOUP_COOKIE_JAR_ACCEPT_ALWAYS); + + priv = soup_cookie_jar_get_instance_private (jar); + return priv->accept_policy; +} + +/** + * soup_cookie_jar_set_accept_policy: + * @jar: a #SoupCookieJar + * @policy: a #SoupCookieJarAcceptPolicy + * + * Sets @policy as the cookie acceptance policy for @jar. + * + * Since: 2.30 + **/ +void +soup_cookie_jar_set_accept_policy (SoupCookieJar *jar, + SoupCookieJarAcceptPolicy policy) +{ + SoupCookieJarPrivate *priv; + + g_return_if_fail (SOUP_IS_COOKIE_JAR (jar)); + + priv = soup_cookie_jar_get_instance_private (jar); + + if (priv->accept_policy != policy) { + priv->accept_policy = policy; + g_object_notify (G_OBJECT (jar), SOUP_COOKIE_JAR_ACCEPT_POLICY); + } +} + +/** + * soup_cookie_jar_is_persistent: + * @jar: a #SoupCookieJar + * + * Gets whether @jar stores cookies persistenly. + * + * Returns: %TRUE if @jar storage is persistent or %FALSE otherwise. + * + * Since: 2.40 + **/ +gboolean +soup_cookie_jar_is_persistent (SoupCookieJar *jar) +{ + g_return_val_if_fail (SOUP_IS_COOKIE_JAR (jar), FALSE); + + return SOUP_COOKIE_JAR_GET_CLASS (jar)->is_persistent (jar); +} diff --git a/libsoup/soup-cookie-jar.h b/libsoup/soup-cookie-jar.h new file mode 100644 index 0000000..e77f8ab --- /dev/null +++ b/libsoup/soup-cookie-jar.h @@ -0,0 +1,99 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2008 Red Hat, Inc. + */ + +#ifndef SOUP_COOKIE_JAR_H +#define SOUP_COOKIE_JAR_H 1 + +#include + +G_BEGIN_DECLS + +#define SOUP_TYPE_COOKIE_JAR (soup_cookie_jar_get_type ()) +#define SOUP_COOKIE_JAR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SOUP_TYPE_COOKIE_JAR, SoupCookieJar)) +#define SOUP_COOKIE_JAR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_COOKIE_JAR, SoupCookieJarClass)) +#define SOUP_IS_COOKIE_JAR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SOUP_TYPE_COOKIE_JAR)) +#define SOUP_IS_COOKIE_JAR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), SOUP_TYPE_COOKIE_JAR)) +#define SOUP_COOKIE_JAR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_COOKIE_JAR, SoupCookieJarClass)) + +struct _SoupCookieJar { + GObject parent; + +}; + +typedef struct { + GObjectClass parent_class; + + void (*save) (SoupCookieJar *jar); + gboolean (*is_persistent) (SoupCookieJar *jar); + + /* signals */ + void (*changed) (SoupCookieJar *jar, + SoupCookie *old_cookie, + SoupCookie *new_cookie); + + /* Padding for future expansion */ + void (*_libsoup_reserved1) (void); + void (*_libsoup_reserved2) (void); +} SoupCookieJarClass; + +#define SOUP_COOKIE_JAR_READ_ONLY "read-only" +#define SOUP_COOKIE_JAR_ACCEPT_POLICY "accept-policy" + +typedef enum { + SOUP_COOKIE_JAR_ACCEPT_ALWAYS, + SOUP_COOKIE_JAR_ACCEPT_NEVER, + SOUP_COOKIE_JAR_ACCEPT_NO_THIRD_PARTY +} SoupCookieJarAcceptPolicy; + +SOUP_AVAILABLE_IN_2_24 +GType soup_cookie_jar_get_type (void); +SOUP_AVAILABLE_IN_2_24 +SoupCookieJar * soup_cookie_jar_new (void); +SOUP_AVAILABLE_IN_2_24 +char * soup_cookie_jar_get_cookies (SoupCookieJar *jar, + SoupURI *uri, + gboolean for_http); +SOUP_AVAILABLE_IN_2_40 +GSList * soup_cookie_jar_get_cookie_list (SoupCookieJar *jar, + SoupURI *uri, + gboolean for_http); +SOUP_AVAILABLE_IN_2_24 +void soup_cookie_jar_set_cookie (SoupCookieJar *jar, + SoupURI *uri, + const char *cookie); +SOUP_AVAILABLE_IN_2_30 +void soup_cookie_jar_set_cookie_with_first_party (SoupCookieJar *jar, + SoupURI *uri, + SoupURI *first_party, + const char *cookie); +SOUP_AVAILABLE_IN_2_26 +void soup_cookie_jar_add_cookie (SoupCookieJar *jar, + SoupCookie *cookie); +SOUP_AVAILABLE_IN_2_40 +void soup_cookie_jar_add_cookie_with_first_party (SoupCookieJar *jar, + SoupURI *first_party, + SoupCookie *cookie); +SOUP_AVAILABLE_IN_2_26 +void soup_cookie_jar_delete_cookie (SoupCookieJar *jar, + SoupCookie *cookie); +SOUP_AVAILABLE_IN_2_26 +GSList * soup_cookie_jar_all_cookies (SoupCookieJar *jar); +SOUP_AVAILABLE_IN_2_30 +void soup_cookie_jar_set_accept_policy (SoupCookieJar *jar, + SoupCookieJarAcceptPolicy policy); +SOUP_AVAILABLE_IN_2_30 +SoupCookieJarAcceptPolicy soup_cookie_jar_get_accept_policy (SoupCookieJar *jar); +SOUP_AVAILABLE_IN_2_40 +gboolean soup_cookie_jar_is_persistent (SoupCookieJar *jar); + +#ifndef SOUP_DISABLE_DEPRECATED +SOUP_AVAILABLE_IN_2_24 +SOUP_DEPRECATED_IN_2_26 +void soup_cookie_jar_save (SoupCookieJar *jar); +#endif + +G_END_DECLS + +#endif /* SOUP_COOKIE_JAR_H */ diff --git a/libsoup/soup-cookie.c b/libsoup/soup-cookie.c new file mode 100644 index 0000000..7cea82e --- /dev/null +++ b/libsoup/soup-cookie.c @@ -0,0 +1,1062 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-cookie.c + * + * Copyright (C) 2007 Red Hat, Inc. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include "soup-cookie.h" +#include "soup-misc-private.h" +#include "soup.h" + +/** + * SECTION:soup-cookie + * @short_description: HTTP Cookies + * @see_also: #SoupMessage, #SoupCookieJar + * + * #SoupCookie implements HTTP cookies, as described by RFC 6265. + * + * To have a #SoupSession handle cookies for your appliction + * automatically, use a #SoupCookieJar. + **/ + +/** + * SoupCookie: + * @name: the cookie name + * @value: the cookie value + * @domain: the "domain" attribute, or else the hostname that the + * cookie came from. + * @path: the "path" attribute, or %NULL + * @expires: the cookie expiration time, or %NULL for a session cookie + * @secure: %TRUE if the cookie should only be tranferred over SSL + * @http_only: %TRUE if the cookie should not be exposed to scripts + * + * An HTTP cookie. + * + * @name and @value will be set for all cookies. If the cookie is + * generated from a string that appears to have no name, then @name + * will be the empty string. + * + * @domain and @path give the host or domain, and path within that + * host/domain, to restrict this cookie to. If @domain starts with + * ".", that indicates a domain (which matches the string after the + * ".", or any hostname that has @domain as a suffix). Otherwise, it + * is a hostname and must match exactly. + * + * @expires will be non-%NULL if the cookie uses either the original + * "expires" attribute, or the newer "max-age" attribute. If @expires + * is %NULL, it indicates that neither "expires" nor "max-age" was + * specified, and the cookie expires at the end of the session. + * + * If @http_only is set, the cookie should not be exposed to untrusted + * code (eg, javascript), so as to minimize the danger posed by + * cross-site scripting attacks. + * + * Since: 2.24 + **/ + +G_DEFINE_BOXED_TYPE (SoupCookie, soup_cookie, soup_cookie_copy, soup_cookie_free) + +/** + * soup_cookie_copy: + * @cookie: a #SoupCookie + * + * Copies @cookie. + * + * Return value: a copy of @cookie + * + * Since: 2.24 + **/ +SoupCookie * +soup_cookie_copy (SoupCookie *cookie) +{ + SoupCookie *copy = g_slice_new0 (SoupCookie); + + copy->name = g_strdup (cookie->name); + copy->value = g_strdup (cookie->value); + copy->domain = g_strdup (cookie->domain); + copy->path = g_strdup (cookie->path); + if (cookie->expires) + copy->expires = soup_date_copy(cookie->expires); + copy->secure = cookie->secure; + copy->http_only = cookie->http_only; + + return copy; +} + +/** + * soup_cookie_domain_matches: + * @cookie: a #SoupCookie + * @host: a URI + * + * Checks if the @cookie's domain and @host match in the sense that + * @cookie should be sent when making a request to @host, or that + * @cookie should be accepted when receiving a response from @host. + * + * Return value: %TRUE if the domains match, %FALSE otherwise + * + * Since: 2.30 + **/ +gboolean +soup_cookie_domain_matches (SoupCookie *cookie, const char *host) +{ + g_return_val_if_fail (cookie != NULL, FALSE); + g_return_val_if_fail (host != NULL, FALSE); + + return soup_host_matches_host (cookie->domain, host); +} + +static inline const char * +skip_lws (const char *s) +{ + while (g_ascii_isspace (*s)) + s++; + return s; +} + +static inline const char * +unskip_lws (const char *s, const char *start) +{ + while (s > start && g_ascii_isspace (*(s - 1))) + s--; + return s; +} + +#define is_attr_ender(ch) ((ch) < ' ' || (ch) == ';' || (ch) == ',' || (ch) == '=') +#define is_value_ender(ch) ((ch) < ' ' || (ch) == ';') + +static char * +parse_value (const char **val_p, gboolean copy) +{ + const char *start, *end, *p; + char *value; + + p = *val_p; + if (*p == '=') + p++; + start = skip_lws (p); + for (p = start; !is_value_ender (*p); p++) + ; + end = unskip_lws (p, start); + + if (copy) + value = g_strndup (start, end - start); + else + value = NULL; + + *val_p = p; + return value; +} + +static SoupDate * +parse_date (const char **val_p) +{ + char *value; + SoupDate *date; + + value = parse_value (val_p, TRUE); + date = soup_date_new_from_string (value); + g_free (value); + return date; +} + +static SoupCookie * +parse_one_cookie (const char *header, SoupURI *origin) +{ + const char *start, *end, *p; + gboolean has_value; + SoupCookie *cookie; + + g_return_val_if_fail (origin == NULL || origin->host, NULL); + + cookie = g_slice_new0 (SoupCookie); + + /* Parse the NAME */ + start = skip_lws (header); + for (p = start; !is_attr_ender (*p); p++) + ; + if (*p == '=') { + end = unskip_lws (p, start); + cookie->name = g_strndup (start, end - start); + } else { + /* No NAME; Set cookie->name to "" and then rewind to + * re-parse the string as a VALUE. + */ + cookie->name = g_strdup (""); + p = start; + } + + /* Parse the VALUE */ + cookie->value = parse_value (&p, TRUE); + + /* Parse attributes */ + while (*p == ';') { + start = skip_lws (p + 1); + for (p = start; !is_attr_ender (*p); p++) + ; + end = unskip_lws (p, start); + + has_value = (*p == '='); +#define MATCH_NAME(name) ((end - start == strlen (name)) && !g_ascii_strncasecmp (start, name, end - start)) + + if (MATCH_NAME ("domain") && has_value) { + cookie->domain = parse_value (&p, TRUE); + if (!*cookie->domain) { + g_free (cookie->domain); + cookie->domain = NULL; + } + } else if (MATCH_NAME ("expires") && has_value) { + cookie->expires = parse_date (&p); + } else if (MATCH_NAME ("httponly")) { + cookie->http_only = TRUE; + if (has_value) + parse_value (&p, FALSE); + } else if (MATCH_NAME ("max-age") && has_value) { + char *max_age_str = parse_value (&p, TRUE), *mae; + long max_age = strtol (max_age_str, &mae, 10); + if (!*mae) { + if (max_age < 0) + max_age = 0; + soup_cookie_set_max_age (cookie, max_age); + } + g_free (max_age_str); + } else if (MATCH_NAME ("path") && has_value) { + cookie->path = parse_value (&p, TRUE); + if (*cookie->path != '/') { + g_free (cookie->path); + cookie->path = NULL; + } + } else if (MATCH_NAME ("secure")) { + cookie->secure = TRUE; + if (has_value) + parse_value (&p, FALSE); + } else { + /* Ignore unknown attributes, but we still have + * to skip over the value. + */ + if (has_value) + parse_value (&p, FALSE); + } + } + + if (cookie->domain) { + /* Domain must have at least one '.' (not counting an + * initial one. (We check this now, rather than + * bailing out sooner, because we don't want to force + * any cookies after this one in the Set-Cookie header + * to be discarded.) + */ + if (!strchr (cookie->domain + 1, '.')) { + soup_cookie_free (cookie); + return NULL; + } + + /* If the domain string isn't an IP addr, and doesn't + * start with a '.', prepend one. + */ + if (!g_hostname_is_ip_address (cookie->domain) && + cookie->domain[0] != '.') { + char *tmp = g_strdup_printf (".%s", cookie->domain); + g_free (cookie->domain); + cookie->domain = tmp; + } + } + + if (origin) { + /* Sanity-check domain */ + if (cookie->domain) { + if (!soup_cookie_domain_matches (cookie, origin->host)) { + soup_cookie_free (cookie); + return NULL; + } + } else + cookie->domain = g_strdup (origin->host); + + /* The original cookie spec didn't say that pages + * could only set cookies for paths they were under. + * RFC 2109 adds that requirement, but some sites + * depend on the old behavior + * (https://bugzilla.mozilla.org/show_bug.cgi?id=156725#c20). + * So we don't check the path. + */ + + if (!cookie->path) { + char *slash; + + slash = strrchr (origin->path, '/'); + if (!slash || slash == origin->path) + cookie->path = g_strdup ("/"); + else { + cookie->path = g_strndup (origin->path, + slash - origin->path); + } + } + } else if (!cookie->path) { + cookie->path = g_strdup ("/"); + } + + return cookie; +} + +static SoupCookie * +cookie_new_internal (const char *name, const char *value, + const char *domain, const char *path, + int max_age) +{ + SoupCookie *cookie; + + cookie = g_slice_new0 (SoupCookie); + cookie->name = g_strdup (name); + cookie->value = g_strdup (value); + cookie->domain = g_strdup (domain); + cookie->path = g_strdup (path); + soup_cookie_set_max_age (cookie, max_age); + + return cookie; +} + +/** + * soup_cookie_new: + * @name: cookie name + * @value: cookie value + * @domain: cookie domain or hostname + * @path: cookie path, or %NULL + * @max_age: max age of the cookie, or -1 for a session cookie + * + * Creates a new #SoupCookie with the given attributes. (Use + * soup_cookie_set_secure() and soup_cookie_set_http_only() if you + * need to set those attributes on the returned cookie.) + * + * If @domain starts with ".", that indicates a domain (which matches + * the string after the ".", or any hostname that has @domain as a + * suffix). Otherwise, it is a hostname and must match exactly. + * + * @max_age is used to set the "expires" attribute on the cookie; pass + * -1 to not include the attribute (indicating that the cookie expires + * with the current session), 0 for an already-expired cookie, or a + * lifetime in seconds. You can use the constants + * %SOUP_COOKIE_MAX_AGE_ONE_HOUR, %SOUP_COOKIE_MAX_AGE_ONE_DAY, + * %SOUP_COOKIE_MAX_AGE_ONE_WEEK and %SOUP_COOKIE_MAX_AGE_ONE_YEAR (or + * multiples thereof) to calculate this value. (If you really care + * about setting the exact time that the cookie will expire, use + * soup_cookie_set_expires().) + * + * Return value: a new #SoupCookie. + * + * Since: 2.24 + **/ +SoupCookie * +soup_cookie_new (const char *name, const char *value, + const char *domain, const char *path, + int max_age) +{ + g_return_val_if_fail (name != NULL, NULL); + g_return_val_if_fail (value != NULL, NULL); + + /* We ought to return if domain is NULL too, but this used to + * do be incorrectly documented as legal, and it wouldn't + * break anything as long as you called + * soup_cookie_set_domain() immediately after. So we warn but + * don't return, to discourage that behavior but not actually + * break anyone doing it. + */ + g_warn_if_fail (domain != NULL); + + return cookie_new_internal (name, value, domain, path, max_age); +} + +/** + * soup_cookie_parse: + * @header: a cookie string (eg, the value of a Set-Cookie header) + * @origin: origin of the cookie, or %NULL + * + * Parses @header and returns a #SoupCookie. (If @header contains + * multiple cookies, only the first one will be parsed.) + * + * If @header does not have "path" or "domain" attributes, they will + * be defaulted from @origin. If @origin is %NULL, path will default + * to "/", but domain will be left as %NULL. Note that this is not a + * valid state for a #SoupCookie, and you will need to fill in some + * appropriate string for the domain if you want to actually make use + * of the cookie. + * + * Return value: (nullable): a new #SoupCookie, or %NULL if it could + * not be parsed, or contained an illegal "domain" attribute for a + * cookie originating from @origin. + * + * Since: 2.24 + **/ +SoupCookie * +soup_cookie_parse (const char *cookie, SoupURI *origin) +{ + return parse_one_cookie (cookie, origin); +} + +/** + * soup_cookie_get_name: + * @cookie: a #SoupCookie + * + * Gets @cookie's name + * + * Return value: @cookie's name + * + * Since: 2.32 + **/ +const char * +soup_cookie_get_name (SoupCookie *cookie) +{ + return cookie->name; +} + +/** + * soup_cookie_set_name: + * @cookie: a #SoupCookie + * @name: the new name + * + * Sets @cookie's name to @name + * + * Since: 2.24 + **/ +void +soup_cookie_set_name (SoupCookie *cookie, const char *name) +{ + g_free (cookie->name); + cookie->name = g_strdup (name); +} + +/** + * soup_cookie_get_value: + * @cookie: a #SoupCookie + * + * Gets @cookie's value + * + * Return value: @cookie's value + * + * Since: 2.32 + **/ +const char * +soup_cookie_get_value (SoupCookie *cookie) +{ + return cookie->value; +} + +/** + * soup_cookie_set_value: + * @cookie: a #SoupCookie + * @value: the new value + * + * Sets @cookie's value to @value + * + * Since: 2.24 + **/ +void +soup_cookie_set_value (SoupCookie *cookie, const char *value) +{ + g_free (cookie->value); + cookie->value = g_strdup (value); +} + +/** + * soup_cookie_get_domain: + * @cookie: a #SoupCookie + * + * Gets @cookie's domain + * + * Return value: @cookie's domain + * + * Since: 2.32 + **/ +const char * +soup_cookie_get_domain (SoupCookie *cookie) +{ + return cookie->domain; +} + +/** + * soup_cookie_set_domain: + * @cookie: a #SoupCookie + * @domain: the new domain + * + * Sets @cookie's domain to @domain + * + * Since: 2.24 + **/ +void +soup_cookie_set_domain (SoupCookie *cookie, const char *domain) +{ + g_free (cookie->domain); + cookie->domain = g_strdup (domain); +} + +/** + * soup_cookie_get_path: + * @cookie: a #SoupCookie + * + * Gets @cookie's path + * + * Return value: @cookie's path + * + * Since: 2.32 + **/ +const char * +soup_cookie_get_path (SoupCookie *cookie) +{ + return cookie->path; +} + +/** + * soup_cookie_set_path: + * @cookie: a #SoupCookie + * @path: the new path + * + * Sets @cookie's path to @path + * + * Since: 2.24 + **/ +void +soup_cookie_set_path (SoupCookie *cookie, const char *path) +{ + g_free (cookie->path); + cookie->path = g_strdup (path); +} + +/** + * soup_cookie_set_max_age: + * @cookie: a #SoupCookie + * @max_age: the new max age + * + * Sets @cookie's max age to @max_age. If @max_age is -1, the cookie + * is a session cookie, and will expire at the end of the client's + * session. Otherwise, it is the number of seconds until the cookie + * expires. You can use the constants %SOUP_COOKIE_MAX_AGE_ONE_HOUR, + * %SOUP_COOKIE_MAX_AGE_ONE_DAY, %SOUP_COOKIE_MAX_AGE_ONE_WEEK and + * %SOUP_COOKIE_MAX_AGE_ONE_YEAR (or multiples thereof) to calculate + * this value. (A value of 0 indicates that the cookie should be + * considered already-expired.) + * + * (This sets the same property as soup_cookie_set_expires().) + * + * Since: 2.24 + **/ +void +soup_cookie_set_max_age (SoupCookie *cookie, int max_age) +{ + if (cookie->expires) + soup_date_free (cookie->expires); + + if (max_age == -1) + cookie->expires = NULL; + else if (max_age == 0) { + /* Use a date way in the past, to protect against + * clock skew. + */ + cookie->expires = soup_date_new (1970, 1, 1, 0, 0, 0); + } else + cookie->expires = soup_date_new_from_now (max_age); +} + +/** + * SOUP_COOKIE_MAX_AGE_ONE_HOUR: + * + * A constant corresponding to 1 hour, for use with soup_cookie_new() + * and soup_cookie_set_max_age(). + * + * Since: 2.24 + **/ +/** + * SOUP_COOKIE_MAX_AGE_ONE_DAY: + * + * A constant corresponding to 1 day, for use with soup_cookie_new() + * and soup_cookie_set_max_age(). + * + * Since: 2.24 + **/ +/** + * SOUP_COOKIE_MAX_AGE_ONE_WEEK: + * + * A constant corresponding to 1 week, for use with soup_cookie_new() + * and soup_cookie_set_max_age(). + * + * Since: 2.24 + **/ +/** + * SOUP_COOKIE_MAX_AGE_ONE_YEAR: + * + * A constant corresponding to 1 year, for use with soup_cookie_new() + * and soup_cookie_set_max_age(). + * + * Since: 2.24 + **/ + +/** + * soup_cookie_get_expires: + * @cookie: a #SoupCookie + * + * Gets @cookie's expiration time. + * + * Return value: (nullable) (transfer none): @cookie's expiration + * time, which is owned by @cookie and should not be modified or + * freed. + * + * Since: 2.32 + **/ +SoupDate * +soup_cookie_get_expires (SoupCookie *cookie) +{ + return cookie->expires; +} + +/** + * soup_cookie_set_expires: + * @cookie: a #SoupCookie + * @expires: the new expiration time, or %NULL + * + * Sets @cookie's expiration time to @expires. If @expires is %NULL, + * @cookie will be a session cookie and will expire at the end of the + * client's session. + * + * (This sets the same property as soup_cookie_set_max_age().) + * + * Since: 2.24 + **/ +void +soup_cookie_set_expires (SoupCookie *cookie, SoupDate *expires) +{ + if (cookie->expires) + soup_date_free (cookie->expires); + + if (expires) + cookie->expires = soup_date_copy (expires); + else + cookie->expires = NULL; +} + +/** + * soup_cookie_get_secure: + * @cookie: a #SoupCookie + * + * Gets @cookie's secure attribute + * + * Return value: @cookie's secure attribute + * + * Since: 2.32 + **/ +gboolean +soup_cookie_get_secure (SoupCookie *cookie) +{ + return cookie->secure; +} + +/** + * soup_cookie_set_secure: + * @cookie: a #SoupCookie + * @secure: the new value for the secure attribute + * + * Sets @cookie's secure attribute to @secure. If %TRUE, @cookie will + * only be transmitted from the client to the server over secure + * (https) connections. + * + * Since: 2.24 + **/ +void +soup_cookie_set_secure (SoupCookie *cookie, gboolean secure) +{ + cookie->secure = secure; +} + +/** + * soup_cookie_get_http_only: + * @cookie: a #SoupCookie + * + * Gets @cookie's HttpOnly attribute + * + * Return value: @cookie's HttpOnly attribute + * + * Since: 2.32 + **/ +gboolean +soup_cookie_get_http_only (SoupCookie *cookie) +{ + return cookie->http_only; +} + +/** + * soup_cookie_set_http_only: + * @cookie: a #SoupCookie + * @http_only: the new value for the HttpOnly attribute + * + * Sets @cookie's HttpOnly attribute to @http_only. If %TRUE, @cookie + * will be marked as "http only", meaning it should not be exposed to + * web page scripts or other untrusted code. + * + * Since: 2.24 + **/ +void +soup_cookie_set_http_only (SoupCookie *cookie, gboolean http_only) +{ + cookie->http_only = http_only; +} + +static void +serialize_cookie (SoupCookie *cookie, GString *header, gboolean set_cookie) +{ + if (!*cookie->name && !*cookie->value) + return; + + if (header->len) { + if (set_cookie) + g_string_append (header, ", "); + else + g_string_append (header, "; "); + } + + if (set_cookie || *cookie->name) { + g_string_append (header, cookie->name); + g_string_append (header, "="); + } + g_string_append (header, cookie->value); + if (!set_cookie) + return; + + if (cookie->expires) { + char *timestamp; + + g_string_append (header, "; expires="); + timestamp = soup_date_to_string (cookie->expires, + SOUP_DATE_COOKIE); + g_string_append (header, timestamp); + g_free (timestamp); + } + if (cookie->path) { + g_string_append (header, "; path="); + g_string_append (header, cookie->path); + } + if (cookie->domain) { + g_string_append (header, "; domain="); + g_string_append (header, cookie->domain); + } + if (cookie->secure) + g_string_append (header, "; secure"); + if (cookie->http_only) + g_string_append (header, "; HttpOnly"); +} + +/** + * soup_cookie_to_set_cookie_header: + * @cookie: a #SoupCookie + * + * Serializes @cookie in the format used by the Set-Cookie header + * (ie, for sending a cookie from a #SoupServer to a client). + * + * Return value: the header + * + * Since: 2.24 + **/ +char * +soup_cookie_to_set_cookie_header (SoupCookie *cookie) +{ + GString *header = g_string_new (NULL); + + serialize_cookie (cookie, header, TRUE); + return g_string_free (header, FALSE); +} + +/** + * soup_cookie_to_cookie_header: + * @cookie: a #SoupCookie + * + * Serializes @cookie in the format used by the Cookie header (ie, for + * returning a cookie from a #SoupSession to a server). + * + * Return value: the header + * + * Since: 2.24 + **/ +char * +soup_cookie_to_cookie_header (SoupCookie *cookie) +{ + GString *header = g_string_new (NULL); + + serialize_cookie (cookie, header, FALSE); + return g_string_free (header, FALSE); +} + +/** + * soup_cookie_free: + * @cookie: a #SoupCookie + * + * Frees @cookie + * + * Since: 2.24 + **/ +void +soup_cookie_free (SoupCookie *cookie) +{ + g_return_if_fail (cookie != NULL); + + g_free (cookie->name); + g_free (cookie->value); + g_free (cookie->domain); + g_free (cookie->path); + g_clear_pointer (&cookie->expires, soup_date_free); + + g_slice_free (SoupCookie, cookie); +} + +/** + * soup_cookies_from_response: + * @msg: a #SoupMessage containing a "Set-Cookie" response header + * + * Parses @msg's Set-Cookie response headers and returns a #GSList of + * #SoupCookies. Cookies that do not specify "path" or + * "domain" attributes will have their values defaulted from @msg. + * + * Return value: (element-type SoupCookie) (transfer full): a #GSList + * of #SoupCookies, which can be freed with + * soup_cookies_free(). + * + * Since: 2.24 + **/ +GSList * +soup_cookies_from_response (SoupMessage *msg) +{ + SoupURI *origin; + const char *name, *value; + SoupCookie *cookie; + GSList *cookies = NULL; + SoupMessageHeadersIter iter; + + origin = soup_message_get_uri (msg); + + /* We have to use soup_message_headers_iter rather than + * soup_message_headers_get_list() since Set-Cookie isn't + * properly mergeable/unmergeable. + */ + soup_message_headers_iter_init (&iter, msg->response_headers); + while (soup_message_headers_iter_next (&iter, &name, &value)) { + if (g_ascii_strcasecmp (name, "Set-Cookie") != 0) + continue; + + cookie = parse_one_cookie (value, origin); + if (cookie) + cookies = g_slist_prepend (cookies, cookie); + } + return g_slist_reverse (cookies); +} + +/** + * soup_cookies_from_request: + * @msg: a #SoupMessage containing a "Cookie" request header + * + * Parses @msg's Cookie request header and returns a #GSList of + * #SoupCookies. As the "Cookie" header, unlike "Set-Cookie", + * only contains cookie names and values, none of the other + * #SoupCookie fields will be filled in. (Thus, you can't generally + * pass a cookie returned from this method directly to + * soup_cookies_to_response().) + * + * Return value: (element-type SoupCookie) (transfer full): a #GSList + * of #SoupCookies, which can be freed with + * soup_cookies_free(). + * + * Since: 2.24 + **/ +GSList * +soup_cookies_from_request (SoupMessage *msg) +{ + SoupCookie *cookie; + GSList *cookies = NULL; + GHashTable *params; + GHashTableIter iter; + gpointer name, value; + const char *header; + + header = soup_message_headers_get_one (msg->request_headers, "Cookie"); + if (!header) + return NULL; + + params = soup_header_parse_semi_param_list (header); + g_hash_table_iter_init (&iter, params); + while (g_hash_table_iter_next (&iter, &name, &value)) { + if (name && value) { + cookie = cookie_new_internal (name, value, + NULL, NULL, 0); + cookies = g_slist_prepend (cookies, cookie); + } + } + soup_header_free_param_list (params); + + return g_slist_reverse (cookies); +} + +/** + * soup_cookies_to_response: + * @cookies: (element-type SoupCookie): a #GSList of #SoupCookie + * @msg: a #SoupMessage + * + * Appends a "Set-Cookie" response header to @msg for each cookie in + * @cookies. (This is in addition to any other "Set-Cookie" headers + * @msg may already have.) + * + * Since: 2.24 + **/ +void +soup_cookies_to_response (GSList *cookies, SoupMessage *msg) +{ + GString *header; + + header = g_string_new (NULL); + while (cookies) { + serialize_cookie (cookies->data, header, TRUE); + soup_message_headers_append (msg->response_headers, + "Set-Cookie", header->str); + g_string_truncate (header, 0); + cookies = cookies->next; + } + g_string_free (header, TRUE); +} + +/** + * soup_cookies_to_request: + * @cookies: (element-type SoupCookie): a #GSList of #SoupCookie + * @msg: a #SoupMessage + * + * Adds the name and value of each cookie in @cookies to @msg's + * "Cookie" request. (If @msg already has a "Cookie" request header, + * these cookies will be appended to the cookies already present. Be + * careful that you do not append the same cookies twice, eg, when + * requeuing a message.) + * + * Since: 2.24 + **/ +void +soup_cookies_to_request (GSList *cookies, SoupMessage *msg) +{ + GString *header; + + header = g_string_new (soup_message_headers_get_one (msg->request_headers, + "Cookie")); + while (cookies) { + serialize_cookie (cookies->data, header, FALSE); + cookies = cookies->next; + } + soup_message_headers_replace (msg->request_headers, + "Cookie", header->str); + g_string_free (header, TRUE); +} + +/** + * soup_cookies_free: (skip) + * @cookies: (element-type SoupCookie): a #GSList of #SoupCookie + * + * Frees @cookies. + * + * Since: 2.24 + **/ +void +soup_cookies_free (GSList *cookies) +{ + g_slist_free_full (cookies, (GDestroyNotify)soup_cookie_free); +} + +/** + * soup_cookies_to_cookie_header: + * @cookies: (element-type SoupCookie): a #GSList of #SoupCookie + * + * Serializes a #GSList of #SoupCookie into a string suitable for + * setting as the value of the "Cookie" header. + * + * Return value: the serialization of @cookies + * + * Since: 2.24 + **/ +char * +soup_cookies_to_cookie_header (GSList *cookies) +{ + GString *str; + + g_return_val_if_fail (cookies != NULL, NULL); + + str = g_string_new (NULL); + while (cookies) { + serialize_cookie (cookies->data, str, FALSE); + cookies = cookies->next; + } + + return g_string_free (str, FALSE); +} + +/** + * soup_cookie_applies_to_uri: + * @cookie: a #SoupCookie + * @uri: a #SoupURI + * + * Tests if @cookie should be sent to @uri. + * + * (At the moment, this does not check that @cookie's domain matches + * @uri, because it assumes that the caller has already done that. + * But don't rely on that; it may change in the future.) + * + * Return value: %TRUE if @cookie should be sent to @uri, %FALSE if + * not + * + * Since: 2.24 + **/ +gboolean +soup_cookie_applies_to_uri (SoupCookie *cookie, SoupURI *uri) +{ + int plen; + + if (cookie->secure && !soup_uri_is_https (uri, NULL)) + return FALSE; + + if (cookie->expires && soup_date_is_past (cookie->expires)) + return FALSE; + + /* uri->path is required to be non-NULL */ + g_return_val_if_fail (uri->path != NULL, FALSE); + + plen = strlen (cookie->path); + if (plen == 0) + return TRUE; + if (strncmp (cookie->path, uri->path, plen) != 0) + return FALSE; + if (cookie->path[plen - 1] != '/' && + uri->path[plen] && uri->path[plen] != '/') + return FALSE; + + return TRUE; +} + +/** + * soup_cookie_equal: + * @cookie1: a #SoupCookie + * @cookie2: a #SoupCookie + * + * Tests if @cookie1 and @cookie2 are equal. + * + * Note that currently, this does not check that the cookie domains + * match. This may change in the future. + * + * Return value: whether the cookies are equal. + * + * Since: 2.24 + */ +gboolean +soup_cookie_equal (SoupCookie *cookie1, SoupCookie *cookie2) +{ + g_return_val_if_fail (cookie1, FALSE); + g_return_val_if_fail (cookie2, FALSE); + + return (!strcmp (cookie1->name, cookie2->name) && + !strcmp (cookie1->value, cookie2->value) && + !strcmp (cookie1->path, cookie2->path)); +} diff --git a/libsoup/soup-cookie.h b/libsoup/soup-cookie.h new file mode 100644 index 0000000..9624291 --- /dev/null +++ b/libsoup/soup-cookie.h @@ -0,0 +1,122 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright 2007, 2008 Red Hat, Inc. + */ + +#ifndef SOUP_COOKIE_H +#define SOUP_COOKIE_H 1 + +#include + +G_BEGIN_DECLS + +struct _SoupCookie { + char *name; + char *value; + char *domain; + char *path; + SoupDate *expires; + gboolean secure; + gboolean http_only; +}; + +SOUP_AVAILABLE_IN_2_24 +GType soup_cookie_get_type (void); +#define SOUP_TYPE_COOKIE (soup_cookie_get_type()) + +#define SOUP_COOKIE_MAX_AGE_ONE_HOUR (60 * 60) +#define SOUP_COOKIE_MAX_AGE_ONE_DAY (SOUP_COOKIE_MAX_AGE_ONE_HOUR * 24) +#define SOUP_COOKIE_MAX_AGE_ONE_WEEK (SOUP_COOKIE_MAX_AGE_ONE_DAY * 7) +#define SOUP_COOKIE_MAX_AGE_ONE_YEAR (SOUP_COOKIE_MAX_AGE_ONE_DAY * 365.2422) + +SOUP_AVAILABLE_IN_2_24 +SoupCookie *soup_cookie_new (const char *name, + const char *value, + const char *domain, + const char *path, + int max_age); +SOUP_AVAILABLE_IN_2_24 +SoupCookie *soup_cookie_parse (const char *header, + SoupURI *origin); +SOUP_AVAILABLE_IN_2_24 +SoupCookie *soup_cookie_copy (SoupCookie *cookie); + +SOUP_AVAILABLE_IN_2_32 +const char *soup_cookie_get_name (SoupCookie *cookie); +SOUP_AVAILABLE_IN_2_24 +void soup_cookie_set_name (SoupCookie *cookie, + const char *name); +SOUP_AVAILABLE_IN_2_32 +const char *soup_cookie_get_value (SoupCookie *cookie); +SOUP_AVAILABLE_IN_2_24 +void soup_cookie_set_value (SoupCookie *cookie, + const char *value); +SOUP_AVAILABLE_IN_2_32 +const char *soup_cookie_get_domain (SoupCookie *cookie); +SOUP_AVAILABLE_IN_2_24 +void soup_cookie_set_domain (SoupCookie *cookie, + const char *domain); +SOUP_AVAILABLE_IN_2_32 +const char *soup_cookie_get_path (SoupCookie *cookie); +SOUP_AVAILABLE_IN_2_24 +void soup_cookie_set_path (SoupCookie *cookie, + const char *path); +SOUP_AVAILABLE_IN_2_24 +void soup_cookie_set_max_age (SoupCookie *cookie, + int max_age); +SOUP_AVAILABLE_IN_2_32 +SoupDate *soup_cookie_get_expires (SoupCookie *cookie); +SOUP_AVAILABLE_IN_2_24 +void soup_cookie_set_expires (SoupCookie *cookie, + SoupDate *expires); +SOUP_AVAILABLE_IN_2_32 +gboolean soup_cookie_get_secure (SoupCookie *cookie); +SOUP_AVAILABLE_IN_2_24 +void soup_cookie_set_secure (SoupCookie *cookie, + gboolean secure); +SOUP_AVAILABLE_IN_2_32 +gboolean soup_cookie_get_http_only (SoupCookie *cookie); +SOUP_AVAILABLE_IN_2_24 +void soup_cookie_set_http_only (SoupCookie *cookie, + gboolean http_only); + +SOUP_AVAILABLE_IN_2_24 +char *soup_cookie_to_set_cookie_header (SoupCookie *cookie); +SOUP_AVAILABLE_IN_2_24 +char *soup_cookie_to_cookie_header (SoupCookie *cookie); + +SOUP_AVAILABLE_IN_2_24 +gboolean soup_cookie_applies_to_uri (SoupCookie *cookie, + SoupURI *uri); +SOUP_AVAILABLE_IN_2_24 +gboolean soup_cookie_equal (SoupCookie *cookie1, + SoupCookie *cookie2); + +SOUP_AVAILABLE_IN_2_24 +void soup_cookie_free (SoupCookie *cookie); + +SOUP_AVAILABLE_IN_2_24 +GSList *soup_cookies_from_response (SoupMessage *msg); +SOUP_AVAILABLE_IN_2_24 +GSList *soup_cookies_from_request (SoupMessage *msg); + +SOUP_AVAILABLE_IN_2_24 +void soup_cookies_to_response (GSList *cookies, + SoupMessage *msg); +SOUP_AVAILABLE_IN_2_24 +void soup_cookies_to_request (GSList *cookies, + SoupMessage *msg); + +SOUP_AVAILABLE_IN_2_24 +void soup_cookies_free (GSList *cookies); + +SOUP_AVAILABLE_IN_2_24 +char *soup_cookies_to_cookie_header (GSList *cookies); + +SOUP_AVAILABLE_IN_2_30 +gboolean soup_cookie_domain_matches (SoupCookie *cookie, + const char *host); + +G_END_DECLS + +#endif /* SOUP_COOKIE_H */ diff --git a/libsoup/soup-date.c b/libsoup/soup-date.c new file mode 100644 index 0000000..dabae9d --- /dev/null +++ b/libsoup/soup-date.c @@ -0,0 +1,929 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-date.c: Date/time handling + * + * Copyright (C) 2005, Novell, Inc. + * Copyright (C) 2007, Red Hat, Inc. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include "soup-date.h" +#include "soup.h" + +/** + * SoupDate: + * @year: the year, 1 to 9999 + * @month: the month, 1 to 12 + * @day: day of the month, 1 to 31 + * @hour: hour of the day, 0 to 23 + * @minute: minute, 0 to 59 + * @second: second, 0 to 59 (or up to 61 in the case of leap seconds) + * @utc: %TRUE if the date is in UTC + * @offset: offset from UTC + + * A date and time. The date is assumed to be in the (proleptic) + * Gregorian calendar. The time is in UTC if @utc is %TRUE. Otherwise, + * the time is a local time, and @offset gives the offset from UTC in + * minutes (such that adding @offset to the time would give the + * correct UTC time). If @utc is %FALSE and @offset is 0, then the + * %SoupDate represents a "floating" time with no associated timezone + * information. + **/ + +/* Do not internationalize */ +static const char *const months[] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" +}; + +/* Do not internationalize */ +static const char *const days[] = { + "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" +}; + +static const int nonleap_days_in_month[] = { + 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 +}; + +static const int nonleap_days_before[] = { + 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 +}; + +static inline gboolean +is_leap_year (int year) +{ + return (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)); +} + +/* Computes the number of days since proleptic Gregorian 0000-12-31. + * (That is, 0001-01-01 is "1", and 1970-01-01 is 719163. + */ +static int +rata_die_day (SoupDate *date) +{ + int day; + + day = (date->year - 1) * 365 + ((date->year - 1) / 4) - + ((date->year - 1) / 100) + ((date->year - 1) / 400); + day += nonleap_days_before[date->month] + date->day; + if (is_leap_year (date->year) && date->month > 2) + day++; + return day; +} + +#define TIME_T_EPOCH_RATA_DIE_DAY 719163 + +static inline int +days_in_month (int month, int year) +{ + if (month == 2 && is_leap_year (year)) + return 29; + else + return nonleap_days_in_month[month]; +} + +G_DEFINE_BOXED_TYPE (SoupDate, soup_date, soup_date_copy, soup_date_free) + +static void +soup_date_fixup (SoupDate *date) +{ + /* We only correct date->second if it's negative or too high + * to be a leap second. + */ + if (date->second < 0 || date->second > 61) { + date->minute += date->second / 60; + date->second %= 60; + if (date->second < 0) + date->second += 60; + } + + if (date->minute < 0 || date->minute > 59) { + date->hour += date->minute / 60; + date->minute %= 60; + if (date->minute < 0) + date->minute += 60; + } + + if (date->hour < 0 || date->hour > 23) { + date->day += date->hour / 24; + date->hour %= 24; + if (date->hour < 0) + date->hour += 24; + } + + /* Have to make sure month is valid before we can look at the + * day. + */ + if (date->month < 1 || date->month > 12) { + date->year += ((date->month - 1) / 12) + 1; + date->month = ((date->month - 1) % 12) + 1; + if (date->month < 1) + date->month += 12; + } + + if (date->day < 0) { + while (date->day < 0) { + if (date->month == 1) { + date->month = 12; + date->year--; + } else + date->month--; + date->day += days_in_month (date->month, date->year); + } + } else { + while (date->day > days_in_month (date->month, date->year)) { + date->day -= days_in_month (date->month, date->year); + if (date->month == 12) { + date->month = 1; + date->year++; + } else + date->month++; + } + } +} + +/** + * soup_date_new: + * @year: the year (1-9999) + * @month: the month (1-12) + * @day: the day of the month (1-31, as appropriate for @month) + * @hour: the hour (0-23) + * @minute: the minute (0-59) + * @second: the second (0-59, or up to 61 for leap seconds) + * + * Creates a #SoupDate representing the indicated time, UTC. + * + * Return value: a new #SoupDate + **/ +SoupDate * +soup_date_new (int year, int month, int day, + int hour, int minute, int second) +{ + SoupDate *date = g_slice_new (SoupDate); + + date->year = year; + date->month = month; + date->day = day; + date->hour = hour; + date->minute = minute; + date->second = second; + date->utc = TRUE; + date->offset = 0; + + return date; +} + +/** + * soup_date_new_from_now: + * @offset_seconds: offset from current time + * + * Creates a #SoupDate representing a time @offset_seconds after the + * current time (or before it, if @offset_seconds is negative). If + * offset_seconds is 0, returns the current time. + * + * If @offset_seconds would indicate a time not expressible as a + * time_t, the return value will be clamped into range. + * + * Return value: a new #SoupDate + **/ +SoupDate * +soup_date_new_from_now (int offset_seconds) +{ + time_t now = time (NULL); + time_t then = now + offset_seconds; + + if (sizeof (time_t) == 4) { + if (offset_seconds < 0 && then > now) + return soup_date_new_from_time_t (-G_MAXINT); + else if (offset_seconds > 0 && then < now) + return soup_date_new_from_time_t (G_MAXINT); + } + return soup_date_new_from_time_t (then); +} + +static gboolean +parse_iso8601_date (SoupDate *date, const char *date_string) +{ + gulong val; + + if (strlen (date_string) < 15) + return FALSE; + if (date_string[4] == '-' && + date_string[7] == '-' && + date_string[10] == 'T') { + /* YYYY-MM-DD */ + date->year = atoi (date_string); + date->month = atoi (date_string + 5); + date->day = atoi (date_string + 8); + date_string += 11; + } else if (date_string[8] == 'T') { + /* YYYYMMDD */ + val = atoi (date_string); + date->year = val / 10000; + date->month = (val % 10000) / 100; + date->day = val % 100; + date_string += 9; + } else + return FALSE; + + if (strlen (date_string) >= 8 && + date_string[2] == ':' && date_string[5] == ':') { + /* HH:MM:SS */ + date->hour = atoi (date_string); + date->minute = atoi (date_string + 3); + date->second = atoi (date_string + 6); + date_string += 8; + } else if (strlen (date_string) >= 6) { + /* HHMMSS */ + val = strtoul (date_string, (char **)&date_string, 10); + date->hour = val / 10000; + date->minute = (val % 10000) / 100; + date->second = val % 100; + } else + return FALSE; + + if (*date_string == '.' || *date_string == ',') + (void) strtoul (date_string + 1, (char **)&date_string, 10); + + if (*date_string == 'Z') { + date_string++; + date->utc = TRUE; + date->offset = 0; + } else if (*date_string == '+' || *date_string == '-') { + int sign = (*date_string == '+') ? -1 : 1; + val = strtoul (date_string + 1, (char **)&date_string, 10); + if (*date_string == ':') + val = 60 * val + strtoul (date_string + 1, (char **)&date_string, 10); + else + val = 60 * (val / 100) + (val % 100); + date->offset = sign * val; + date->utc = !val; + } else { + date->offset = 0; + date->utc = FALSE; + } + + return !*date_string; +} + +static inline gboolean +parse_day (SoupDate *date, const char **date_string) +{ + char *end; + + date->day = strtoul (*date_string, &end, 10); + if (end == (char *)*date_string) + return FALSE; + + while (*end == ' ' || *end == '-') + end++; + *date_string = end; + return TRUE; +} + +static inline gboolean +parse_month (SoupDate *date, const char **date_string) +{ + int i; + + for (i = 0; i < G_N_ELEMENTS (months); i++) { + if (!g_ascii_strncasecmp (*date_string, months[i], 3)) { + date->month = i + 1; + *date_string += 3; + while (**date_string == ' ' || **date_string == '-') + (*date_string)++; + return TRUE; + } + } + return FALSE; +} + +static inline gboolean +parse_year (SoupDate *date, const char **date_string) +{ + char *end; + + date->year = strtoul (*date_string, &end, 10); + if (end == (char *)*date_string) + return FALSE; + + if (end == (char *)*date_string + 2) { + if (date->year < 70) + date->year += 2000; + else + date->year += 1900; + } else if (end == (char *)*date_string + 3) + date->year += 1900; + + while (*end == ' ' || *end == '-') + end++; + *date_string = end; + return TRUE; +} + +static inline gboolean +parse_time (SoupDate *date, const char **date_string) +{ + char *p, *end; + + date->hour = strtoul (*date_string, &end, 10); + if (end == (char *)*date_string || *end++ != ':') + return FALSE; + p = end; + date->minute = strtoul (p, &end, 10); + if (end == p || *end++ != ':') + return FALSE; + p = end; + date->second = strtoul (p, &end, 10); + if (end == p) + return FALSE; + p = end; + + while (*p == ' ') + p++; + *date_string = p; + return TRUE; +} + +static inline gboolean +parse_timezone (SoupDate *date, const char **date_string) +{ + if (!**date_string) { + date->utc = FALSE; + date->offset = 0; + } else if (**date_string == '+' || **date_string == '-') { + gulong val; + int sign = (**date_string == '+') ? -1 : 1; + val = strtoul (*date_string + 1, (char **)date_string, 10); + if (**date_string == ':') + val = 60 * val + strtoul (*date_string + 1, (char **)date_string, 10); + else + val = 60 * (val / 100) + (val % 100); + date->offset = sign * val; + date->utc = (sign == -1) && !val; + } else if (**date_string == 'Z') { + date->offset = 0; + date->utc = TRUE; + (*date_string)++; + } else if (!strcmp (*date_string, "GMT") || + !strcmp (*date_string, "UTC")) { + date->offset = 0; + date->utc = TRUE; + (*date_string) += 3; + } else if (strchr ("ECMP", **date_string) && + ((*date_string)[1] == 'D' || (*date_string)[1] == 'S') && + (*date_string)[2] == 'T') { + date->offset = -60 * (5 * strcspn ("ECMP", *date_string)); + if ((*date_string)[1] == 'D') + date->offset += 60; + date->utc = FALSE; + } else + return FALSE; + return TRUE; +} + +static gboolean +parse_textual_date (SoupDate *date, const char *date_string) +{ + /* If it starts with a word, it must be a weekday, which we skip */ + if (g_ascii_isalpha (*date_string)) { + while (g_ascii_isalpha (*date_string)) + date_string++; + if (*date_string == ',') + date_string++; + while (g_ascii_isspace (*date_string)) + date_string++; + } + + /* If there's now another word, this must be an asctime-date */ + if (g_ascii_isalpha (*date_string)) { + /* (Sun) Nov 6 08:49:37 1994 */ + if (!parse_month (date, &date_string) || + !parse_day (date, &date_string) || + !parse_time (date, &date_string) || + !parse_year (date, &date_string)) + return FALSE; + + /* There shouldn't be a timezone, but check anyway */ + parse_timezone (date, &date_string); + } else { + /* Non-asctime date, so some variation of + * (Sun,) 06 Nov 1994 08:49:37 GMT + */ + if (!parse_day (date, &date_string) || + !parse_month (date, &date_string) || + !parse_year (date, &date_string) || + !parse_time (date, &date_string)) + return FALSE; + + /* This time there *should* be a timezone, but we + * survive if there isn't. + */ + parse_timezone (date, &date_string); + } + return TRUE; +} + +/** + * SoupDateFormat: + * @SOUP_DATE_HTTP: RFC 1123 format, used by the HTTP "Date" header. Eg + * "Sun, 06 Nov 1994 08:49:37 GMT" + * @SOUP_DATE_COOKIE: The format for the "Expires" timestamp in the + * Netscape cookie specification. Eg, "Sun, 06-Nov-1994 08:49:37 GMT". + * @SOUP_DATE_RFC2822: RFC 2822 format, eg "Sun, 6 Nov 1994 09:49:37 -0100" + * @SOUP_DATE_ISO8601_COMPACT: ISO 8601 date/time with no optional + * punctuation. Eg, "19941106T094937-0100". + * @SOUP_DATE_ISO8601_FULL: ISO 8601 date/time with all optional + * punctuation. Eg, "1994-11-06T09:49:37-01:00". + * @SOUP_DATE_ISO8601_XMLRPC: ISO 8601 date/time as used by XML-RPC. + * Eg, "19941106T09:49:37". + * @SOUP_DATE_ISO8601: An alias for @SOUP_DATE_ISO8601_FULL. + * + * Date formats that soup_date_to_string() can use. + * + * @SOUP_DATE_HTTP and @SOUP_DATE_COOKIE always coerce the time to + * UTC. @SOUP_DATE_ISO8601_XMLRPC uses the time as given, ignoring the + * offset completely. @SOUP_DATE_RFC2822 and the other ISO 8601 + * variants use the local time, appending the offset information if + * available. + * + * This enum may be extended with more values in future releases. + **/ + +/** + * soup_date_new_from_string: + * @date_string: the date in some plausible format + * + * Parses @date_string and tries to extract a date from it. This + * recognizes all of the "HTTP-date" formats from RFC 2616, all ISO + * 8601 formats containing both a time and a date, RFC 2822 dates, + * and reasonable approximations thereof. (Eg, it is lenient about + * whitespace, leading "0"s, etc.) + * + * Return value: (nullable): a new #SoupDate, or %NULL if @date_string + * could not be parsed. + **/ +SoupDate * +soup_date_new_from_string (const char *date_string) +{ + SoupDate *date; + gboolean success; + + g_return_val_if_fail (date_string != NULL, NULL); + + date = g_slice_new (SoupDate); + + while (g_ascii_isspace (*date_string)) + date_string++; + + /* If it starts with a digit, it's either an ISO 8601 date, or + * an RFC2822 date without the optional weekday; in the later + * case, there will be a month name later on, so look for one + * of the month-start letters. + */ + if (g_ascii_isdigit (*date_string) && + !strpbrk (date_string, "JFMASOND")) + success = parse_iso8601_date (date, date_string); + else + success = parse_textual_date (date, date_string); + + if (!success) { + g_slice_free (SoupDate, date); + return NULL; + } + + if (date->year < 1 || date->year > 9999 || + date->month < 1 || date->month > 12 || + date->day < 1 || + date->day > days_in_month (date->month, date->year) || + date->hour < 0 || date->hour > 24 || + date->minute < 0 || date->minute > 59 || + date->second < 0 || date->second > 61) { + soup_date_free (date); + return NULL; + } + if (date->hour == 24) { + /* ISO8601 allows this explicitly. We allow it for + * other types as well just for simplicity. + */ + if (date->minute == 0 && date->second == 0) + soup_date_fixup (date); + else { + soup_date_free (date); + return NULL; + } + } + + return date; +} + +/** + * soup_date_new_from_time_t: + * @when: a time_t + * + * Creates a #SoupDate corresponding to @when + * + * Return value: a new #SoupDate + **/ +SoupDate * +soup_date_new_from_time_t (time_t when) +{ + struct tm tm; + +#ifdef HAVE_GMTIME_R + gmtime_r (&when, &tm); +#else + tm = *gmtime (&when); +#endif + + return soup_date_new (tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, + tm.tm_hour, tm.tm_min, tm.tm_sec); +} + +static const char * +soup_date_weekday (SoupDate *date) +{ + /* Proleptic Gregorian 0001-01-01 was a Monday, which + * corresponds to 1 in the days[] array. + */ + return days[rata_die_day (date) % 7]; +} + +/** + * soup_date_to_string: + * @date: a #SoupDate + * @format: the format to generate the date in + * + * Converts @date to a string in the format described by @format. + * + * Return value: @date as a string + **/ +char * +soup_date_to_string (SoupDate *date, SoupDateFormat format) +{ + g_return_val_if_fail (date != NULL, NULL); + + if (format == SOUP_DATE_HTTP || format == SOUP_DATE_COOKIE) { + /* HTTP and COOKIE formats require UTC timestamp, so coerce + * @date if it's non-UTC. + */ + SoupDate utcdate; + + if (date->offset != 0) { + memcpy (&utcdate, date, sizeof (SoupDate)); + utcdate.minute += utcdate.offset; + utcdate.offset = 0; + utcdate.utc = TRUE; + soup_date_fixup (&utcdate); + date = &utcdate; + } + + switch (format) { + case SOUP_DATE_HTTP: + /* "Sun, 06 Nov 1994 08:49:37 GMT" */ + return g_strdup_printf ( + "%s, %02d %s %04d %02d:%02d:%02d GMT", + soup_date_weekday (date), date->day, + months[date->month - 1], date->year, + date->hour, date->minute, date->second); + + case SOUP_DATE_COOKIE: + /* "Sun, 06-Nov-1994 08:49:37 GMT" */ + return g_strdup_printf ( + "%s, %02d-%s-%04d %02d:%02d:%02d GMT", + soup_date_weekday (date), date->day, + months[date->month - 1], date->year, + date->hour, date->minute, date->second); + + default: + g_return_val_if_reached (NULL); + } + } else if (format == SOUP_DATE_ISO8601_XMLRPC) { + /* Always "floating", ignore offset */ + return g_strdup_printf ("%04d%02d%02dT%02d:%02d:%02d", + date->year, date->month, date->day, + date->hour, date->minute, date->second); + } else { + int hour_offset, minute_offset; + char zone[8], sign; + + /* For other ISO8601 formats or RFC2822, use the + * offset given in @date. For ISO8601 formats, use "Z" + * for UTC, +-offset for non-UTC, and nothing for + * floating. For RFC2822, use +-offset for UTC or + * non-UTC, and -0000 for floating. + */ + hour_offset = abs (date->offset) / 60; + minute_offset = abs (date->offset) - hour_offset * 60; + + switch (format) { + case SOUP_DATE_ISO8601_COMPACT: + /* "19941106T084937[zone]" */ + if (date->utc) + strcpy (zone, "Z"); + else if (date->offset) { + g_snprintf (zone, sizeof (zone), "%c%02d%02d", + date->offset > 0 ? '-' : '+', + hour_offset, minute_offset); + } else + *zone = '\0'; + + return g_strdup_printf ( + "%04d%02d%02dT%02d%02d%02d%s", + date->year, date->month, date->day, + date->hour, date->minute, date->second, + zone); + + case SOUP_DATE_ISO8601_FULL: + /* "1994-11-06T08:49:37[zone]" */ + if (date->utc) + strcpy (zone, "Z"); + else if (date->offset) { + g_snprintf (zone, sizeof (zone), "%c%02d:%02d", + date->offset > 0 ? '-' : '+', + hour_offset, minute_offset); + } else + *zone = '\0'; + + return g_strdup_printf ( + "%04d-%02d-%02dT%02d:%02d:%02d%s", + date->year, date->month, date->day, + date->hour, date->minute, date->second, + zone); + + case SOUP_DATE_RFC2822: + /* "Sun, 6 Nov 1994 09:49:37 -0100" */ + if (date->offset) + sign = (date->offset > 0) ? '-' : '+'; + else + sign = date->utc ? '+' : '-'; + return g_strdup_printf ( + "%s, %d %s %04d %02d:%02d:%02d %c%02d%02d", + soup_date_weekday (date), date->day, + months[date->month - 1], date->year, + date->hour, date->minute, date->second, + sign, hour_offset, minute_offset); + + default: + return NULL; + } + } +} + +/** + * soup_date_to_time_t: + * @date: a #SoupDate + * + * Converts @date to a time_t. + * + * If @date is not representable as a time_t, it will be + * clamped into range. (In particular, some HTTP cookies have + * expiration dates after "Y2.038k" (2038-01-19T03:14:07Z).) + * + * Return value: @date as a time_t + **/ +time_t +soup_date_to_time_t (SoupDate *date) +{ + time_t tt; + GTimeVal val; + + g_return_val_if_fail (date != NULL, 0); + + /* FIXME: offset, etc */ + + if (date->year < 1970) + return 0; + + /* If the year is later than 2038, we're guaranteed to + * overflow a 32-bit time_t. (If it's exactly 2038, we'll + * *probably* overflow, but only by a little, and it's easiest + * to test that at the end by seeing if the result has turned + * negative.) + */ + if (sizeof (time_t) == 4 && date->year > 2038) + return (time_t)0x7fffffff; + + soup_date_to_timeval (date, &val); + tt = val.tv_sec; + + if (sizeof (time_t) == 4 && tt < 0) + return (time_t)0x7fffffff; + return tt; +} + +/** + * soup_date_to_timeval: + * @date: a #SoupDate + * @time: (out): a #GTimeVal structure in which to store the converted time. + * + * Converts @date to a #GTimeVal. + * + * Since: 2.24 + */ +void +soup_date_to_timeval (SoupDate *date, GTimeVal *time) +{ + g_return_if_fail (date != NULL); + g_return_if_fail (time != NULL); + + /* FIXME: offset, etc */ + + time->tv_sec = rata_die_day (date) - TIME_T_EPOCH_RATA_DIE_DAY; + time->tv_sec = ((((time->tv_sec * 24) + date->hour) * 60) + date->minute) * 60 + date->second; + time->tv_usec = 0; +} + +/** + * soup_date_is_past: + * @date: a #SoupDate + * + * Determines if @date is in the past. + * + * Return value: %TRUE if @date is in the past + * + * Since: 2.24 + **/ +gboolean +soup_date_is_past (SoupDate *date) +{ + g_return_val_if_fail (date != NULL, TRUE); + + /* optimization */ + if (date->year < 2010) + return TRUE; + + return soup_date_to_time_t (date) < time (NULL); +} + +/** + * soup_date_get_year: + * @date: a #SoupDate + * + * Gets @date's year. + * + * Return value: @date's year + * + * Since: 2.32 + **/ +int +soup_date_get_year (SoupDate *date) +{ + return date->year; +} + +/** + * soup_date_get_month: + * @date: a #SoupDate + * + * Gets @date's month. + * + * Return value: @date's month + * + * Since: 2.32 + **/ +int +soup_date_get_month (SoupDate *date) +{ + return date->month; +} + +/** + * soup_date_get_day: + * @date: a #SoupDate + * + * Gets @date's day. + * + * Return value: @date's day + * + * Since: 2.32 + **/ +int +soup_date_get_day (SoupDate *date) +{ + return date->day; +} + +/** + * soup_date_get_hour: + * @date: a #SoupDate + * + * Gets @date's hour. + * + * Return value: @date's hour + * + * Since: 2.32 + **/ +int +soup_date_get_hour (SoupDate *date) +{ + return date->hour; +} + +/** + * soup_date_get_minute: + * @date: a #SoupDate + * + * Gets @date's minute. + * + * Return value: @date's minute + * + * Since: 2.32 + **/ +int +soup_date_get_minute (SoupDate *date) +{ + return date->minute; +} + +/** + * soup_date_get_second: + * @date: a #SoupDate + * + * Gets @date's second. + * + * Return value: @date's second + * + * Since: 2.32 + **/ +int +soup_date_get_second (SoupDate *date) +{ + return date->second; +} + +/** + * soup_date_get_utc: + * @date: a #SoupDate + * + * Gets @date's UTC flag + * + * Return value: %TRUE if @date is UTC. + * + * Since: 2.32 + **/ +gboolean +soup_date_get_utc (SoupDate *date) +{ + return date->utc; +} + +/** + * soup_date_get_offset: + * @date: a #SoupDate + * + * Gets @date's offset from UTC. + * + * Return value: @date's offset from UTC. If soup_date_get_utc() + * returns %FALSE but soup_date_get_offset() returns 0, that means the + * date is a "floating" time with no associated offset information. + * + * Since: 2.32 + **/ +int +soup_date_get_offset (SoupDate *date) +{ + return date->offset; +} + +/** + * soup_date_copy: + * @date: a #SoupDate + * + * Copies @date. + * + * Since: 2.24 + **/ +SoupDate * +soup_date_copy (SoupDate *date) +{ + SoupDate *copy; + + g_return_val_if_fail (date != NULL, NULL); + + copy = g_slice_new (SoupDate); + memcpy (copy, date, sizeof (SoupDate)); + return copy; +} + +/** + * soup_date_free: + * @date: a #SoupDate + * + * Frees @date. + * + * Since: 2.24 + **/ +void +soup_date_free (SoupDate *date) +{ + g_return_if_fail (date != NULL); + + g_slice_free (SoupDate, date); +} diff --git a/libsoup/soup-date.h b/libsoup/soup-date.h new file mode 100644 index 0000000..c6414c1 --- /dev/null +++ b/libsoup/soup-date.h @@ -0,0 +1,92 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2005 Novell, Inc. + * Copyright (C) 2007 Red Hat, Inc. + */ + +#ifndef SOUP_DATE_H +#define SOUP_DATE_H 1 + +#include +#include + +G_BEGIN_DECLS + +struct _SoupDate { + int year; + int month; + int day; + + int hour; + int minute; + int second; + + gboolean utc; + int offset; +}; + +typedef enum { + SOUP_DATE_HTTP = 1, + SOUP_DATE_COOKIE, + SOUP_DATE_RFC2822, + SOUP_DATE_ISO8601_COMPACT, + SOUP_DATE_ISO8601_FULL, + SOUP_DATE_ISO8601 = SOUP_DATE_ISO8601_FULL, + SOUP_DATE_ISO8601_XMLRPC +} SoupDateFormat; + +SOUP_AVAILABLE_IN_2_24 +GType soup_date_get_type (void); +#define SOUP_TYPE_DATE (soup_date_get_type ()) + +SOUP_AVAILABLE_IN_2_24 +SoupDate *soup_date_new (int year, + int month, + int day, + int hour, + int minute, + int second); +SOUP_AVAILABLE_IN_2_24 +SoupDate *soup_date_new_from_string (const char *date_string); +SOUP_AVAILABLE_IN_2_24 +SoupDate *soup_date_new_from_time_t (time_t when); +SOUP_AVAILABLE_IN_2_24 +SoupDate *soup_date_new_from_now (int offset_seconds); + +SOUP_AVAILABLE_IN_2_24 +char *soup_date_to_string (SoupDate *date, + SoupDateFormat format); +SOUP_AVAILABLE_IN_2_24 +time_t soup_date_to_time_t (SoupDate *date); +SOUP_AVAILABLE_IN_2_24 +void soup_date_to_timeval (SoupDate *date, + GTimeVal *time); + +SOUP_AVAILABLE_IN_2_24 +gboolean soup_date_is_past (SoupDate *date); + +SOUP_AVAILABLE_IN_2_32 +int soup_date_get_year (SoupDate *date); +SOUP_AVAILABLE_IN_2_32 +int soup_date_get_month (SoupDate *date); +SOUP_AVAILABLE_IN_2_32 +int soup_date_get_day (SoupDate *date); +SOUP_AVAILABLE_IN_2_32 +int soup_date_get_hour (SoupDate *date); +SOUP_AVAILABLE_IN_2_32 +int soup_date_get_minute (SoupDate *date); +SOUP_AVAILABLE_IN_2_32 +int soup_date_get_second (SoupDate *date); +SOUP_AVAILABLE_IN_2_32 +int soup_date_get_utc (SoupDate *date); +SOUP_AVAILABLE_IN_2_32 +int soup_date_get_offset (SoupDate *date); + +SOUP_AVAILABLE_IN_2_24 +SoupDate *soup_date_copy (SoupDate *date); +SOUP_AVAILABLE_IN_2_24 +void soup_date_free (SoupDate *date); + +G_END_DECLS + +#endif /* SOUP_DATE_H */ diff --git a/libsoup/soup-directory-input-stream.c b/libsoup/soup-directory-input-stream.c new file mode 100644 index 0000000..eb8228a --- /dev/null +++ b/libsoup/soup-directory-input-stream.c @@ -0,0 +1,211 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2008, 2010 Red Hat, Inc. + * Copyright (C) 2010 Igalia, S.L. + * + * 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, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "soup-directory-input-stream.h" +#include "soup.h" + +#define INIT_STRING "\n\n\n" +#define ROW_FORMAT "\n" +#define EXIT_STRING "
NameSizeDate Modified%s%s%s
\n\n" + +G_DEFINE_TYPE (SoupDirectoryInputStream, soup_directory_input_stream, G_TYPE_INPUT_STREAM) + +static SoupBuffer * +soup_directory_input_stream_parse_info (SoupDirectoryInputStream *stream, + GFileInfo *info) +{ + SoupBuffer *buffer; + GString *string; + const char *file_name; + char *escaped, *path, *xml_string, *size, *time; + GTimeVal modified; + GDateTime *modification_time; + + if (!g_file_info_get_name (info)) + return NULL; + + file_name = g_file_info_get_display_name (info); + if (!file_name) { + file_name = g_file_info_get_name (info); + /* FIXME: convert somehow? */ + if (!g_utf8_validate (file_name, -1, NULL)) + return NULL; + } + string = g_string_new (""); + + xml_string = g_markup_escape_text (file_name, -1); + escaped = g_uri_escape_string (file_name, NULL, FALSE); + path = g_strconcat (stream->uri, G_DIR_SEPARATOR_S, escaped, NULL); + size = g_format_size (g_file_info_get_size (info)); + g_file_info_get_modification_time (info, &modified); + modification_time = g_date_time_new_from_timeval_local (&modified); + time = g_date_time_format (modification_time, "%X %x"); + g_date_time_unref (modification_time); + + g_string_append_printf (string, ROW_FORMAT, path, xml_string, size, time); + g_string_append (string, "\n"); + buffer = soup_buffer_new (SOUP_MEMORY_TAKE, string->str, string->len); + + g_free (time); + g_free (escaped); + g_free (size); + g_free (path); + g_free (xml_string); + g_string_free (string, FALSE); + + return buffer; +} + +static SoupBuffer * +soup_directory_input_stream_read_next_file (SoupDirectoryInputStream *stream, + GCancellable *cancellable, + GError **error) +{ + GFileInfo *info; + SoupBuffer *buffer; + GError *err = NULL; + + do { + info = g_file_enumerator_next_file (stream->enumerator, cancellable, &err); + if (info == NULL) { + if (err) { + g_propagate_error (error, err); + return NULL; + } else if (!stream->done) { + stream->done = TRUE; + return soup_buffer_new (SOUP_MEMORY_STATIC, + EXIT_STRING, + sizeof (EXIT_STRING)); + } else { + return NULL; + } + } + + buffer = soup_directory_input_stream_parse_info (stream, info); + g_object_unref (info); + } while (buffer == NULL); + + return buffer; +} + +static gssize +soup_directory_input_stream_read (GInputStream *input, + void *buffer, + gsize count, + GCancellable *cancellable, + GError **error) +{ + SoupDirectoryInputStream *stream = SOUP_DIRECTORY_INPUT_STREAM (input); + gsize total, size; + + for (total = 0; total < count; total += size) { + if (stream->buffer == NULL) { + stream->buffer = soup_directory_input_stream_read_next_file (stream, cancellable, error); + if (stream->buffer == NULL) { + /* FIXME: Is this correct or should we forward the error? */ + if (total) + g_clear_error (error); + return total; + } + } + + size = MIN (stream->buffer->length, count - total); + memcpy ((char *)buffer + total, stream->buffer->data, size); + if (size == stream->buffer->length) { + soup_buffer_free (stream->buffer); + stream->buffer = NULL; + } else { + SoupBuffer *sub = soup_buffer_new_subbuffer (stream->buffer, + size, + stream->buffer->length - size); + soup_buffer_free (stream->buffer); + stream->buffer = sub; + } + } + + return total; +} + +static gboolean +soup_directory_input_stream_close (GInputStream *input, + GCancellable *cancellable, + GError **error) +{ + SoupDirectoryInputStream *stream = SOUP_DIRECTORY_INPUT_STREAM (input); + gboolean result; + + if (stream->buffer) { + soup_buffer_free (stream->buffer); + stream->buffer = NULL; + } + + result = g_file_enumerator_close (stream->enumerator, + cancellable, + error); + g_object_unref (stream->enumerator); + stream->enumerator = NULL; + + g_free (stream->uri); + stream->uri = NULL; + + return result; +} + +static void +soup_directory_input_stream_class_init (SoupDirectoryInputStreamClass *stream_class) +{ + GInputStreamClass *inputstream_class = G_INPUT_STREAM_CLASS (stream_class); + + inputstream_class->read_fn = soup_directory_input_stream_read; + inputstream_class->close_fn = soup_directory_input_stream_close; +} + +static void +soup_directory_input_stream_init (SoupDirectoryInputStream *stream) +{ + stream->buffer = soup_buffer_new (SOUP_MEMORY_STATIC, + INIT_STRING, + sizeof (INIT_STRING)); +} + +GInputStream * +soup_directory_input_stream_new (GFileEnumerator *enumerator, + SoupURI *uri) +{ + GInputStream *stream; + + g_return_val_if_fail (G_IS_FILE_ENUMERATOR (enumerator), NULL); + g_return_val_if_fail (uri != NULL, NULL); + + stream = g_object_new (SOUP_TYPE_DIRECTORY_INPUT_STREAM, NULL); + + SOUP_DIRECTORY_INPUT_STREAM (stream)->enumerator = g_object_ref (enumerator); + SOUP_DIRECTORY_INPUT_STREAM (stream)->uri = soup_uri_to_string (uri, FALSE); + + return stream; +} + diff --git a/libsoup/soup-directory-input-stream.h b/libsoup/soup-directory-input-stream.h new file mode 100644 index 0000000..ae2b4ba --- /dev/null +++ b/libsoup/soup-directory-input-stream.h @@ -0,0 +1,62 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2010 Red Hat, Inc. + * Copyright (C) 2010 Igalia, S.L. + * + * 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, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef SOUP_DIRECTORY_INPUT_STREAM_H +#define SOUP_DIRECTORY_INPUT_STREAM_H 1 + +#include +#include +#include + +G_BEGIN_DECLS + +#define SOUP_TYPE_DIRECTORY_INPUT_STREAM (soup_directory_input_stream_get_type ()) +#define SOUP_DIRECTORY_INPUT_STREAM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SOUP_TYPE_DIRECTORY_INPUT_STREAM, SoupDirectoryInputStream)) +#define SOUP_DIRECTORY_INPUT_STREAM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_DIRECTORY_INPUT_STREAM, SoupDirectoryInputStreamClass)) +#define SOUP_IS_DIRECTORY_INPUT_STREAM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SOUP_TYPE_DIRECTORY_INPUT_STREAM)) +#define SOUP_IS_DIRECTORY_INPUT_STREAM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), SOUP_TYPE_DIRECTORY_INPUT_STREAM)) +#define SOUP_DIRECTORY_INPUT_STREAM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_DIRECTORY_INPUT_STREAM, SoupDirectoryInputStreamClass)) + +typedef struct _SoupDirectoryInputStream SoupDirectoryInputStream; +typedef struct _SoupDirectoryInputStreamClass SoupDirectoryInputStreamClass; + +struct _SoupDirectoryInputStream { + GInputStream parent; + + GFileEnumerator *enumerator; + char *uri; + SoupBuffer *buffer; + gboolean done; +}; + +struct _SoupDirectoryInputStreamClass { + GInputStreamClass parent_class; +}; + +GType soup_directory_input_stream_get_type (void); + +GInputStream *soup_directory_input_stream_new (GFileEnumerator *enumerator, + SoupURI *uri); + + +G_END_DECLS + +#endif /* SOUP_DIRECTORY_INPUT_STREAM_H */ diff --git a/libsoup/soup-enum-types.c b/libsoup/soup-enum-types.c new file mode 100644 index 0000000..011d457 --- /dev/null +++ b/libsoup/soup-enum-types.c @@ -0,0 +1,804 @@ + +/* This file is generated by glib-mkenums, do not modify it. This code is licensed under the same license as the containing project. Note that it links to GLib, so must comply with the LGPL linking clauses. */ + +/* Generated by glib-mkenums. Do not edit */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "soup-enum-types.h" + +#define LIBSOUP_USE_UNSTABLE_REQUEST_API +#include "soup.h" +#include "soup-address.h" +#include "soup-auth.h" +#include "soup-auth-domain.h" +#include "soup-auth-domain-basic.h" +#include "soup-auth-domain-digest.h" +#include "soup-auth-manager.h" +#include "soup-autocleanups.h" +#include "soup-cache.h" +#include "soup-content-decoder.h" +#include "soup-content-sniffer.h" +#include "soup-cookie.h" +#include "soup-cookie-jar.h" +#include "soup-cookie-jar-db.h" +#include "soup-cookie-jar-text.h" +#include "soup-date.h" +#include "soup-form.h" +#include "soup-headers.h" +#include "soup-logger.h" +#include "soup-message.h" +#include "soup-message-body.h" +#include "soup-message-headers.h" +#include "soup-method.h" +#include "soup-misc.h" +#include "soup-multipart.h" +#include "soup-multipart-input-stream.h" +#include "soup-password-manager.h" +#include "soup-portability.h" +#include "soup-proxy-resolver.h" +#include "soup-proxy-resolver-default.h" +#include "soup-proxy-uri-resolver.h" +#include "soup-request.h" +#include "soup-request-data.h" +#include "soup-request-file.h" +#include "soup-request-http.h" +#include "soup-requester.h" +#include "soup-server.h" +#include "soup-session.h" +#include "soup-session-async.h" +#include "soup-session-feature.h" +#include "soup-session-sync.h" +#include "soup-socket.h" +#include "soup-status.h" +#include "soup-tld.h" +#include "soup-types.h" +#include "soup-uri.h" +#include "soup-value-utils.h" +#include "soup-websocket.h" +#include "soup-websocket-connection.h" +#include "soup-xmlrpc.h" +#include "soup-xmlrpc-old.h" +#include "soup-cookie-jar-sqlite.h" +#include "soup-gnome.h" +#include "soup-gnome-features.h" +GType +soup_address_family_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { SOUP_ADDRESS_FAMILY_INVALID, "SOUP_ADDRESS_FAMILY_INVALID", "invalid" }, + { SOUP_ADDRESS_FAMILY_IPV4, "SOUP_ADDRESS_FAMILY_IPV4", "ipv4" }, + { SOUP_ADDRESS_FAMILY_IPV6, "SOUP_ADDRESS_FAMILY_IPV6", "ipv6" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("SoupAddressFamily"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +soup_cacheability_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GFlagsValue values[] = { + { SOUP_CACHE_CACHEABLE, "SOUP_CACHE_CACHEABLE", "cacheable" }, + { SOUP_CACHE_UNCACHEABLE, "SOUP_CACHE_UNCACHEABLE", "uncacheable" }, + { SOUP_CACHE_INVALIDATES, "SOUP_CACHE_INVALIDATES", "invalidates" }, + { SOUP_CACHE_VALIDATES, "SOUP_CACHE_VALIDATES", "validates" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_flags_register_static (g_intern_static_string ("SoupCacheability"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +soup_cache_response_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { SOUP_CACHE_RESPONSE_FRESH, "SOUP_CACHE_RESPONSE_FRESH", "fresh" }, + { SOUP_CACHE_RESPONSE_NEEDS_VALIDATION, "SOUP_CACHE_RESPONSE_NEEDS_VALIDATION", "needs-validation" }, + { SOUP_CACHE_RESPONSE_STALE, "SOUP_CACHE_RESPONSE_STALE", "stale" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("SoupCacheResponse"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +soup_cache_type_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { SOUP_CACHE_SINGLE_USER, "SOUP_CACHE_SINGLE_USER", "single-user" }, + { SOUP_CACHE_SHARED, "SOUP_CACHE_SHARED", "shared" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("SoupCacheType"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +soup_cookie_jar_accept_policy_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { SOUP_COOKIE_JAR_ACCEPT_ALWAYS, "SOUP_COOKIE_JAR_ACCEPT_ALWAYS", "always" }, + { SOUP_COOKIE_JAR_ACCEPT_NEVER, "SOUP_COOKIE_JAR_ACCEPT_NEVER", "never" }, + { SOUP_COOKIE_JAR_ACCEPT_NO_THIRD_PARTY, "SOUP_COOKIE_JAR_ACCEPT_NO_THIRD_PARTY", "no-third-party" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("SoupCookieJarAcceptPolicy"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +soup_date_format_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { SOUP_DATE_HTTP, "SOUP_DATE_HTTP", "http" }, + { SOUP_DATE_COOKIE, "SOUP_DATE_COOKIE", "cookie" }, + { SOUP_DATE_RFC2822, "SOUP_DATE_RFC2822", "rfc2822" }, + { SOUP_DATE_ISO8601_COMPACT, "SOUP_DATE_ISO8601_COMPACT", "iso8601-compact" }, + { SOUP_DATE_ISO8601_FULL, "SOUP_DATE_ISO8601_FULL", "iso8601-full" }, + { SOUP_DATE_ISO8601, "SOUP_DATE_ISO8601", "iso8601" }, + { SOUP_DATE_ISO8601_XMLRPC, "SOUP_DATE_ISO8601_XMLRPC", "iso8601-xmlrpc" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("SoupDateFormat"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +soup_logger_log_level_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { SOUP_LOGGER_LOG_NONE, "SOUP_LOGGER_LOG_NONE", "none" }, + { SOUP_LOGGER_LOG_MINIMAL, "SOUP_LOGGER_LOG_MINIMAL", "minimal" }, + { SOUP_LOGGER_LOG_HEADERS, "SOUP_LOGGER_LOG_HEADERS", "headers" }, + { SOUP_LOGGER_LOG_BODY, "SOUP_LOGGER_LOG_BODY", "body" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("SoupLoggerLogLevel"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +soup_memory_use_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { SOUP_MEMORY_STATIC, "SOUP_MEMORY_STATIC", "static" }, + { SOUP_MEMORY_TAKE, "SOUP_MEMORY_TAKE", "take" }, + { SOUP_MEMORY_COPY, "SOUP_MEMORY_COPY", "copy" }, + { SOUP_MEMORY_TEMPORARY, "SOUP_MEMORY_TEMPORARY", "temporary" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("SoupMemoryUse"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +soup_message_headers_type_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { SOUP_MESSAGE_HEADERS_REQUEST, "SOUP_MESSAGE_HEADERS_REQUEST", "request" }, + { SOUP_MESSAGE_HEADERS_RESPONSE, "SOUP_MESSAGE_HEADERS_RESPONSE", "response" }, + { SOUP_MESSAGE_HEADERS_MULTIPART, "SOUP_MESSAGE_HEADERS_MULTIPART", "multipart" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("SoupMessageHeadersType"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +soup_encoding_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { SOUP_ENCODING_UNRECOGNIZED, "SOUP_ENCODING_UNRECOGNIZED", "unrecognized" }, + { SOUP_ENCODING_NONE, "SOUP_ENCODING_NONE", "none" }, + { SOUP_ENCODING_CONTENT_LENGTH, "SOUP_ENCODING_CONTENT_LENGTH", "content-length" }, + { SOUP_ENCODING_EOF, "SOUP_ENCODING_EOF", "eof" }, + { SOUP_ENCODING_CHUNKED, "SOUP_ENCODING_CHUNKED", "chunked" }, + { SOUP_ENCODING_BYTERANGES, "SOUP_ENCODING_BYTERANGES", "byteranges" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("SoupEncoding"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +soup_expectation_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GFlagsValue values[] = { + { SOUP_EXPECTATION_UNRECOGNIZED, "SOUP_EXPECTATION_UNRECOGNIZED", "unrecognized" }, + { SOUP_EXPECTATION_CONTINUE, "SOUP_EXPECTATION_CONTINUE", "continue" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_flags_register_static (g_intern_static_string ("SoupExpectation"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +soup_http_version_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { SOUP_HTTP_1_0, "SOUP_HTTP_1_0", "http-1-0" }, + { SOUP_HTTP_1_1, "SOUP_HTTP_1_1", "http-1-1" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("SoupHTTPVersion"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +soup_message_flags_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GFlagsValue values[] = { + { SOUP_MESSAGE_NO_REDIRECT, "SOUP_MESSAGE_NO_REDIRECT", "no-redirect" }, + { SOUP_MESSAGE_CAN_REBUILD, "SOUP_MESSAGE_CAN_REBUILD", "can-rebuild" }, + { SOUP_MESSAGE_OVERWRITE_CHUNKS, "SOUP_MESSAGE_OVERWRITE_CHUNKS", "overwrite-chunks" }, + { SOUP_MESSAGE_CONTENT_DECODED, "SOUP_MESSAGE_CONTENT_DECODED", "content-decoded" }, + { SOUP_MESSAGE_CERTIFICATE_TRUSTED, "SOUP_MESSAGE_CERTIFICATE_TRUSTED", "certificate-trusted" }, + { SOUP_MESSAGE_NEW_CONNECTION, "SOUP_MESSAGE_NEW_CONNECTION", "new-connection" }, + { SOUP_MESSAGE_IDEMPOTENT, "SOUP_MESSAGE_IDEMPOTENT", "idempotent" }, + { SOUP_MESSAGE_IGNORE_CONNECTION_LIMITS, "SOUP_MESSAGE_IGNORE_CONNECTION_LIMITS", "ignore-connection-limits" }, + { SOUP_MESSAGE_DO_NOT_USE_AUTH_CACHE, "SOUP_MESSAGE_DO_NOT_USE_AUTH_CACHE", "do-not-use-auth-cache" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_flags_register_static (g_intern_static_string ("SoupMessageFlags"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +soup_message_priority_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { SOUP_MESSAGE_PRIORITY_VERY_LOW, "SOUP_MESSAGE_PRIORITY_VERY_LOW", "very-low" }, + { SOUP_MESSAGE_PRIORITY_LOW, "SOUP_MESSAGE_PRIORITY_LOW", "low" }, + { SOUP_MESSAGE_PRIORITY_NORMAL, "SOUP_MESSAGE_PRIORITY_NORMAL", "normal" }, + { SOUP_MESSAGE_PRIORITY_HIGH, "SOUP_MESSAGE_PRIORITY_HIGH", "high" }, + { SOUP_MESSAGE_PRIORITY_VERY_HIGH, "SOUP_MESSAGE_PRIORITY_VERY_HIGH", "very-high" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("SoupMessagePriority"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +soup_connection_state_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { SOUP_CONNECTION_NEW, "SOUP_CONNECTION_NEW", "new" }, + { SOUP_CONNECTION_CONNECTING, "SOUP_CONNECTION_CONNECTING", "connecting" }, + { SOUP_CONNECTION_IDLE, "SOUP_CONNECTION_IDLE", "idle" }, + { SOUP_CONNECTION_IN_USE, "SOUP_CONNECTION_IN_USE", "in-use" }, + { SOUP_CONNECTION_REMOTE_DISCONNECTED, "SOUP_CONNECTION_REMOTE_DISCONNECTED", "remote-disconnected" }, + { SOUP_CONNECTION_DISCONNECTED, "SOUP_CONNECTION_DISCONNECTED", "disconnected" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("SoupConnectionState"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +soup_requester_error_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { SOUP_REQUESTER_ERROR_BAD_URI, "SOUP_REQUESTER_ERROR_BAD_URI", "bad-uri" }, + { SOUP_REQUESTER_ERROR_UNSUPPORTED_URI_SCHEME, "SOUP_REQUESTER_ERROR_UNSUPPORTED_URI_SCHEME", "unsupported-uri-scheme" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("SoupRequesterError"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +soup_server_listen_options_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GFlagsValue values[] = { + { SOUP_SERVER_LISTEN_HTTPS, "SOUP_SERVER_LISTEN_HTTPS", "https" }, + { SOUP_SERVER_LISTEN_IPV4_ONLY, "SOUP_SERVER_LISTEN_IPV4_ONLY", "ipv4-only" }, + { SOUP_SERVER_LISTEN_IPV6_ONLY, "SOUP_SERVER_LISTEN_IPV6_ONLY", "ipv6-only" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_flags_register_static (g_intern_static_string ("SoupServerListenOptions"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +soup_request_error_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { SOUP_REQUEST_ERROR_BAD_URI, "SOUP_REQUEST_ERROR_BAD_URI", "bad-uri" }, + { SOUP_REQUEST_ERROR_UNSUPPORTED_URI_SCHEME, "SOUP_REQUEST_ERROR_UNSUPPORTED_URI_SCHEME", "unsupported-uri-scheme" }, + { SOUP_REQUEST_ERROR_PARSING, "SOUP_REQUEST_ERROR_PARSING", "parsing" }, + { SOUP_REQUEST_ERROR_ENCODING, "SOUP_REQUEST_ERROR_ENCODING", "encoding" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("SoupRequestError"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +soup_socket_io_status_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { SOUP_SOCKET_OK, "SOUP_SOCKET_OK", "ok" }, + { SOUP_SOCKET_WOULD_BLOCK, "SOUP_SOCKET_WOULD_BLOCK", "would-block" }, + { SOUP_SOCKET_EOF, "SOUP_SOCKET_EOF", "eof" }, + { SOUP_SOCKET_ERROR, "SOUP_SOCKET_ERROR", "error" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("SoupSocketIOStatus"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +soup_status_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { SOUP_STATUS_NONE, "SOUP_STATUS_NONE", "none" }, + { SOUP_STATUS_CANCELLED, "SOUP_STATUS_CANCELLED", "cancelled" }, + { SOUP_STATUS_CANT_RESOLVE, "SOUP_STATUS_CANT_RESOLVE", "cant-resolve" }, + { SOUP_STATUS_CANT_RESOLVE_PROXY, "SOUP_STATUS_CANT_RESOLVE_PROXY", "cant-resolve-proxy" }, + { SOUP_STATUS_CANT_CONNECT, "SOUP_STATUS_CANT_CONNECT", "cant-connect" }, + { SOUP_STATUS_CANT_CONNECT_PROXY, "SOUP_STATUS_CANT_CONNECT_PROXY", "cant-connect-proxy" }, + { SOUP_STATUS_SSL_FAILED, "SOUP_STATUS_SSL_FAILED", "ssl-failed" }, + { SOUP_STATUS_IO_ERROR, "SOUP_STATUS_IO_ERROR", "io-error" }, + { SOUP_STATUS_MALFORMED, "SOUP_STATUS_MALFORMED", "malformed" }, + { SOUP_STATUS_TRY_AGAIN, "SOUP_STATUS_TRY_AGAIN", "try-again" }, + { SOUP_STATUS_TOO_MANY_REDIRECTS, "SOUP_STATUS_TOO_MANY_REDIRECTS", "too-many-redirects" }, + { SOUP_STATUS_TLS_FAILED, "SOUP_STATUS_TLS_FAILED", "tls-failed" }, + { SOUP_STATUS_CONTINUE, "SOUP_STATUS_CONTINUE", "continue" }, + { SOUP_STATUS_SWITCHING_PROTOCOLS, "SOUP_STATUS_SWITCHING_PROTOCOLS", "switching-protocols" }, + { SOUP_STATUS_PROCESSING, "SOUP_STATUS_PROCESSING", "processing" }, + { SOUP_STATUS_OK, "SOUP_STATUS_OK", "ok" }, + { SOUP_STATUS_CREATED, "SOUP_STATUS_CREATED", "created" }, + { SOUP_STATUS_ACCEPTED, "SOUP_STATUS_ACCEPTED", "accepted" }, + { SOUP_STATUS_NON_AUTHORITATIVE, "SOUP_STATUS_NON_AUTHORITATIVE", "non-authoritative" }, + { SOUP_STATUS_NO_CONTENT, "SOUP_STATUS_NO_CONTENT", "no-content" }, + { SOUP_STATUS_RESET_CONTENT, "SOUP_STATUS_RESET_CONTENT", "reset-content" }, + { SOUP_STATUS_PARTIAL_CONTENT, "SOUP_STATUS_PARTIAL_CONTENT", "partial-content" }, + { SOUP_STATUS_MULTI_STATUS, "SOUP_STATUS_MULTI_STATUS", "multi-status" }, + { SOUP_STATUS_MULTIPLE_CHOICES, "SOUP_STATUS_MULTIPLE_CHOICES", "multiple-choices" }, + { SOUP_STATUS_MOVED_PERMANENTLY, "SOUP_STATUS_MOVED_PERMANENTLY", "moved-permanently" }, + { SOUP_STATUS_FOUND, "SOUP_STATUS_FOUND", "found" }, + { SOUP_STATUS_MOVED_TEMPORARILY, "SOUP_STATUS_MOVED_TEMPORARILY", "moved-temporarily" }, + { SOUP_STATUS_SEE_OTHER, "SOUP_STATUS_SEE_OTHER", "see-other" }, + { SOUP_STATUS_NOT_MODIFIED, "SOUP_STATUS_NOT_MODIFIED", "not-modified" }, + { SOUP_STATUS_USE_PROXY, "SOUP_STATUS_USE_PROXY", "use-proxy" }, + { SOUP_STATUS_NOT_APPEARING_IN_THIS_PROTOCOL, "SOUP_STATUS_NOT_APPEARING_IN_THIS_PROTOCOL", "not-appearing-in-this-protocol" }, + { SOUP_STATUS_TEMPORARY_REDIRECT, "SOUP_STATUS_TEMPORARY_REDIRECT", "temporary-redirect" }, + { SOUP_STATUS_BAD_REQUEST, "SOUP_STATUS_BAD_REQUEST", "bad-request" }, + { SOUP_STATUS_UNAUTHORIZED, "SOUP_STATUS_UNAUTHORIZED", "unauthorized" }, + { SOUP_STATUS_PAYMENT_REQUIRED, "SOUP_STATUS_PAYMENT_REQUIRED", "payment-required" }, + { SOUP_STATUS_FORBIDDEN, "SOUP_STATUS_FORBIDDEN", "forbidden" }, + { SOUP_STATUS_NOT_FOUND, "SOUP_STATUS_NOT_FOUND", "not-found" }, + { SOUP_STATUS_METHOD_NOT_ALLOWED, "SOUP_STATUS_METHOD_NOT_ALLOWED", "method-not-allowed" }, + { SOUP_STATUS_NOT_ACCEPTABLE, "SOUP_STATUS_NOT_ACCEPTABLE", "not-acceptable" }, + { SOUP_STATUS_PROXY_AUTHENTICATION_REQUIRED, "SOUP_STATUS_PROXY_AUTHENTICATION_REQUIRED", "proxy-authentication-required" }, + { SOUP_STATUS_PROXY_UNAUTHORIZED, "SOUP_STATUS_PROXY_UNAUTHORIZED", "proxy-unauthorized" }, + { SOUP_STATUS_REQUEST_TIMEOUT, "SOUP_STATUS_REQUEST_TIMEOUT", "request-timeout" }, + { SOUP_STATUS_CONFLICT, "SOUP_STATUS_CONFLICT", "conflict" }, + { SOUP_STATUS_GONE, "SOUP_STATUS_GONE", "gone" }, + { SOUP_STATUS_LENGTH_REQUIRED, "SOUP_STATUS_LENGTH_REQUIRED", "length-required" }, + { SOUP_STATUS_PRECONDITION_FAILED, "SOUP_STATUS_PRECONDITION_FAILED", "precondition-failed" }, + { SOUP_STATUS_REQUEST_ENTITY_TOO_LARGE, "SOUP_STATUS_REQUEST_ENTITY_TOO_LARGE", "request-entity-too-large" }, + { SOUP_STATUS_REQUEST_URI_TOO_LONG, "SOUP_STATUS_REQUEST_URI_TOO_LONG", "request-uri-too-long" }, + { SOUP_STATUS_UNSUPPORTED_MEDIA_TYPE, "SOUP_STATUS_UNSUPPORTED_MEDIA_TYPE", "unsupported-media-type" }, + { SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE, "SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE", "requested-range-not-satisfiable" }, + { SOUP_STATUS_INVALID_RANGE, "SOUP_STATUS_INVALID_RANGE", "invalid-range" }, + { SOUP_STATUS_EXPECTATION_FAILED, "SOUP_STATUS_EXPECTATION_FAILED", "expectation-failed" }, + { SOUP_STATUS_UNPROCESSABLE_ENTITY, "SOUP_STATUS_UNPROCESSABLE_ENTITY", "unprocessable-entity" }, + { SOUP_STATUS_LOCKED, "SOUP_STATUS_LOCKED", "locked" }, + { SOUP_STATUS_FAILED_DEPENDENCY, "SOUP_STATUS_FAILED_DEPENDENCY", "failed-dependency" }, + { SOUP_STATUS_INTERNAL_SERVER_ERROR, "SOUP_STATUS_INTERNAL_SERVER_ERROR", "internal-server-error" }, + { SOUP_STATUS_NOT_IMPLEMENTED, "SOUP_STATUS_NOT_IMPLEMENTED", "not-implemented" }, + { SOUP_STATUS_BAD_GATEWAY, "SOUP_STATUS_BAD_GATEWAY", "bad-gateway" }, + { SOUP_STATUS_SERVICE_UNAVAILABLE, "SOUP_STATUS_SERVICE_UNAVAILABLE", "service-unavailable" }, + { SOUP_STATUS_GATEWAY_TIMEOUT, "SOUP_STATUS_GATEWAY_TIMEOUT", "gateway-timeout" }, + { SOUP_STATUS_HTTP_VERSION_NOT_SUPPORTED, "SOUP_STATUS_HTTP_VERSION_NOT_SUPPORTED", "http-version-not-supported" }, + { SOUP_STATUS_INSUFFICIENT_STORAGE, "SOUP_STATUS_INSUFFICIENT_STORAGE", "insufficient-storage" }, + { SOUP_STATUS_NOT_EXTENDED, "SOUP_STATUS_NOT_EXTENDED", "not-extended" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("SoupStatus"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +soup_known_status_code_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { SOUP_KNOWN_STATUS_CODE_NONE, "SOUP_KNOWN_STATUS_CODE_NONE", "none" }, + { SOUP_KNOWN_STATUS_CODE_CANCELLED, "SOUP_KNOWN_STATUS_CODE_CANCELLED", "cancelled" }, + { SOUP_KNOWN_STATUS_CODE_CANT_RESOLVE, "SOUP_KNOWN_STATUS_CODE_CANT_RESOLVE", "cant-resolve" }, + { SOUP_KNOWN_STATUS_CODE_CANT_RESOLVE_PROXY, "SOUP_KNOWN_STATUS_CODE_CANT_RESOLVE_PROXY", "cant-resolve-proxy" }, + { SOUP_KNOWN_STATUS_CODE_CANT_CONNECT, "SOUP_KNOWN_STATUS_CODE_CANT_CONNECT", "cant-connect" }, + { SOUP_KNOWN_STATUS_CODE_CANT_CONNECT_PROXY, "SOUP_KNOWN_STATUS_CODE_CANT_CONNECT_PROXY", "cant-connect-proxy" }, + { SOUP_KNOWN_STATUS_CODE_SSL_FAILED, "SOUP_KNOWN_STATUS_CODE_SSL_FAILED", "ssl-failed" }, + { SOUP_KNOWN_STATUS_CODE_IO_ERROR, "SOUP_KNOWN_STATUS_CODE_IO_ERROR", "io-error" }, + { SOUP_KNOWN_STATUS_CODE_MALFORMED, "SOUP_KNOWN_STATUS_CODE_MALFORMED", "malformed" }, + { SOUP_KNOWN_STATUS_CODE_TRY_AGAIN, "SOUP_KNOWN_STATUS_CODE_TRY_AGAIN", "try-again" }, + { SOUP_KNOWN_STATUS_CODE_TOO_MANY_REDIRECTS, "SOUP_KNOWN_STATUS_CODE_TOO_MANY_REDIRECTS", "too-many-redirects" }, + { SOUP_KNOWN_STATUS_CODE_TLS_FAILED, "SOUP_KNOWN_STATUS_CODE_TLS_FAILED", "tls-failed" }, + { SOUP_KNOWN_STATUS_CODE_CONTINUE, "SOUP_KNOWN_STATUS_CODE_CONTINUE", "continue" }, + { SOUP_KNOWN_STATUS_CODE_SWITCHING_PROTOCOLS, "SOUP_KNOWN_STATUS_CODE_SWITCHING_PROTOCOLS", "switching-protocols" }, + { SOUP_KNOWN_STATUS_CODE_PROCESSING, "SOUP_KNOWN_STATUS_CODE_PROCESSING", "processing" }, + { SOUP_KNOWN_STATUS_CODE_OK, "SOUP_KNOWN_STATUS_CODE_OK", "ok" }, + { SOUP_KNOWN_STATUS_CODE_CREATED, "SOUP_KNOWN_STATUS_CODE_CREATED", "created" }, + { SOUP_KNOWN_STATUS_CODE_ACCEPTED, "SOUP_KNOWN_STATUS_CODE_ACCEPTED", "accepted" }, + { SOUP_KNOWN_STATUS_CODE_NON_AUTHORITATIVE, "SOUP_KNOWN_STATUS_CODE_NON_AUTHORITATIVE", "non-authoritative" }, + { SOUP_KNOWN_STATUS_CODE_NO_CONTENT, "SOUP_KNOWN_STATUS_CODE_NO_CONTENT", "no-content" }, + { SOUP_KNOWN_STATUS_CODE_RESET_CONTENT, "SOUP_KNOWN_STATUS_CODE_RESET_CONTENT", "reset-content" }, + { SOUP_KNOWN_STATUS_CODE_PARTIAL_CONTENT, "SOUP_KNOWN_STATUS_CODE_PARTIAL_CONTENT", "partial-content" }, + { SOUP_KNOWN_STATUS_CODE_MULTI_STATUS, "SOUP_KNOWN_STATUS_CODE_MULTI_STATUS", "multi-status" }, + { SOUP_KNOWN_STATUS_CODE_MULTIPLE_CHOICES, "SOUP_KNOWN_STATUS_CODE_MULTIPLE_CHOICES", "multiple-choices" }, + { SOUP_KNOWN_STATUS_CODE_MOVED_PERMANENTLY, "SOUP_KNOWN_STATUS_CODE_MOVED_PERMANENTLY", "moved-permanently" }, + { SOUP_KNOWN_STATUS_CODE_FOUND, "SOUP_KNOWN_STATUS_CODE_FOUND", "found" }, + { SOUP_KNOWN_STATUS_CODE_MOVED_TEMPORARILY, "SOUP_KNOWN_STATUS_CODE_MOVED_TEMPORARILY", "moved-temporarily" }, + { SOUP_KNOWN_STATUS_CODE_SEE_OTHER, "SOUP_KNOWN_STATUS_CODE_SEE_OTHER", "see-other" }, + { SOUP_KNOWN_STATUS_CODE_NOT_MODIFIED, "SOUP_KNOWN_STATUS_CODE_NOT_MODIFIED", "not-modified" }, + { SOUP_KNOWN_STATUS_CODE_USE_PROXY, "SOUP_KNOWN_STATUS_CODE_USE_PROXY", "use-proxy" }, + { SOUP_KNOWN_STATUS_CODE_NOT_APPEARING_IN_THIS_PROTOCOL, "SOUP_KNOWN_STATUS_CODE_NOT_APPEARING_IN_THIS_PROTOCOL", "not-appearing-in-this-protocol" }, + { SOUP_KNOWN_STATUS_CODE_TEMPORARY_REDIRECT, "SOUP_KNOWN_STATUS_CODE_TEMPORARY_REDIRECT", "temporary-redirect" }, + { SOUP_KNOWN_STATUS_CODE_BAD_REQUEST, "SOUP_KNOWN_STATUS_CODE_BAD_REQUEST", "bad-request" }, + { SOUP_KNOWN_STATUS_CODE_UNAUTHORIZED, "SOUP_KNOWN_STATUS_CODE_UNAUTHORIZED", "unauthorized" }, + { SOUP_KNOWN_STATUS_CODE_PAYMENT_REQUIRED, "SOUP_KNOWN_STATUS_CODE_PAYMENT_REQUIRED", "payment-required" }, + { SOUP_KNOWN_STATUS_CODE_FORBIDDEN, "SOUP_KNOWN_STATUS_CODE_FORBIDDEN", "forbidden" }, + { SOUP_KNOWN_STATUS_CODE_NOT_FOUND, "SOUP_KNOWN_STATUS_CODE_NOT_FOUND", "not-found" }, + { SOUP_KNOWN_STATUS_CODE_METHOD_NOT_ALLOWED, "SOUP_KNOWN_STATUS_CODE_METHOD_NOT_ALLOWED", "method-not-allowed" }, + { SOUP_KNOWN_STATUS_CODE_NOT_ACCEPTABLE, "SOUP_KNOWN_STATUS_CODE_NOT_ACCEPTABLE", "not-acceptable" }, + { SOUP_KNOWN_STATUS_CODE_PROXY_AUTHENTICATION_REQUIRED, "SOUP_KNOWN_STATUS_CODE_PROXY_AUTHENTICATION_REQUIRED", "proxy-authentication-required" }, + { SOUP_KNOWN_STATUS_CODE_PROXY_UNAUTHORIZED, "SOUP_KNOWN_STATUS_CODE_PROXY_UNAUTHORIZED", "proxy-unauthorized" }, + { SOUP_KNOWN_STATUS_CODE_REQUEST_TIMEOUT, "SOUP_KNOWN_STATUS_CODE_REQUEST_TIMEOUT", "request-timeout" }, + { SOUP_KNOWN_STATUS_CODE_CONFLICT, "SOUP_KNOWN_STATUS_CODE_CONFLICT", "conflict" }, + { SOUP_KNOWN_STATUS_CODE_GONE, "SOUP_KNOWN_STATUS_CODE_GONE", "gone" }, + { SOUP_KNOWN_STATUS_CODE_LENGTH_REQUIRED, "SOUP_KNOWN_STATUS_CODE_LENGTH_REQUIRED", "length-required" }, + { SOUP_KNOWN_STATUS_CODE_PRECONDITION_FAILED, "SOUP_KNOWN_STATUS_CODE_PRECONDITION_FAILED", "precondition-failed" }, + { SOUP_KNOWN_STATUS_CODE_REQUEST_ENTITY_TOO_LARGE, "SOUP_KNOWN_STATUS_CODE_REQUEST_ENTITY_TOO_LARGE", "request-entity-too-large" }, + { SOUP_KNOWN_STATUS_CODE_REQUEST_URI_TOO_LONG, "SOUP_KNOWN_STATUS_CODE_REQUEST_URI_TOO_LONG", "request-uri-too-long" }, + { SOUP_KNOWN_STATUS_CODE_UNSUPPORTED_MEDIA_TYPE, "SOUP_KNOWN_STATUS_CODE_UNSUPPORTED_MEDIA_TYPE", "unsupported-media-type" }, + { SOUP_KNOWN_STATUS_CODE_REQUESTED_RANGE_NOT_SATISFIABLE, "SOUP_KNOWN_STATUS_CODE_REQUESTED_RANGE_NOT_SATISFIABLE", "requested-range-not-satisfiable" }, + { SOUP_KNOWN_STATUS_CODE_INVALID_RANGE, "SOUP_KNOWN_STATUS_CODE_INVALID_RANGE", "invalid-range" }, + { SOUP_KNOWN_STATUS_CODE_EXPECTATION_FAILED, "SOUP_KNOWN_STATUS_CODE_EXPECTATION_FAILED", "expectation-failed" }, + { SOUP_KNOWN_STATUS_CODE_UNPROCESSABLE_ENTITY, "SOUP_KNOWN_STATUS_CODE_UNPROCESSABLE_ENTITY", "unprocessable-entity" }, + { SOUP_KNOWN_STATUS_CODE_LOCKED, "SOUP_KNOWN_STATUS_CODE_LOCKED", "locked" }, + { SOUP_KNOWN_STATUS_CODE_FAILED_DEPENDENCY, "SOUP_KNOWN_STATUS_CODE_FAILED_DEPENDENCY", "failed-dependency" }, + { SOUP_KNOWN_STATUS_CODE_INTERNAL_SERVER_ERROR, "SOUP_KNOWN_STATUS_CODE_INTERNAL_SERVER_ERROR", "internal-server-error" }, + { SOUP_KNOWN_STATUS_CODE_NOT_IMPLEMENTED, "SOUP_KNOWN_STATUS_CODE_NOT_IMPLEMENTED", "not-implemented" }, + { SOUP_KNOWN_STATUS_CODE_BAD_GATEWAY, "SOUP_KNOWN_STATUS_CODE_BAD_GATEWAY", "bad-gateway" }, + { SOUP_KNOWN_STATUS_CODE_SERVICE_UNAVAILABLE, "SOUP_KNOWN_STATUS_CODE_SERVICE_UNAVAILABLE", "service-unavailable" }, + { SOUP_KNOWN_STATUS_CODE_GATEWAY_TIMEOUT, "SOUP_KNOWN_STATUS_CODE_GATEWAY_TIMEOUT", "gateway-timeout" }, + { SOUP_KNOWN_STATUS_CODE_HTTP_VERSION_NOT_SUPPORTED, "SOUP_KNOWN_STATUS_CODE_HTTP_VERSION_NOT_SUPPORTED", "http-version-not-supported" }, + { SOUP_KNOWN_STATUS_CODE_INSUFFICIENT_STORAGE, "SOUP_KNOWN_STATUS_CODE_INSUFFICIENT_STORAGE", "insufficient-storage" }, + { SOUP_KNOWN_STATUS_CODE_NOT_EXTENDED, "SOUP_KNOWN_STATUS_CODE_NOT_EXTENDED", "not-extended" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("SoupKnownStatusCode"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +soup_tld_error_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { SOUP_TLD_ERROR_INVALID_HOSTNAME, "SOUP_TLD_ERROR_INVALID_HOSTNAME", "invalid-hostname" }, + { SOUP_TLD_ERROR_IS_IP_ADDRESS, "SOUP_TLD_ERROR_IS_IP_ADDRESS", "is-ip-address" }, + { SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS, "SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS", "not-enough-domains" }, + { SOUP_TLD_ERROR_NO_BASE_DOMAIN, "SOUP_TLD_ERROR_NO_BASE_DOMAIN", "no-base-domain" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("SoupTLDError"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +soup_websocket_error_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { SOUP_WEBSOCKET_ERROR_FAILED, "SOUP_WEBSOCKET_ERROR_FAILED", "failed" }, + { SOUP_WEBSOCKET_ERROR_NOT_WEBSOCKET, "SOUP_WEBSOCKET_ERROR_NOT_WEBSOCKET", "not-websocket" }, + { SOUP_WEBSOCKET_ERROR_BAD_HANDSHAKE, "SOUP_WEBSOCKET_ERROR_BAD_HANDSHAKE", "bad-handshake" }, + { SOUP_WEBSOCKET_ERROR_BAD_ORIGIN, "SOUP_WEBSOCKET_ERROR_BAD_ORIGIN", "bad-origin" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("SoupWebsocketError"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +soup_websocket_connection_type_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { SOUP_WEBSOCKET_CONNECTION_UNKNOWN, "SOUP_WEBSOCKET_CONNECTION_UNKNOWN", "unknown" }, + { SOUP_WEBSOCKET_CONNECTION_CLIENT, "SOUP_WEBSOCKET_CONNECTION_CLIENT", "client" }, + { SOUP_WEBSOCKET_CONNECTION_SERVER, "SOUP_WEBSOCKET_CONNECTION_SERVER", "server" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("SoupWebsocketConnectionType"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +soup_websocket_data_type_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { SOUP_WEBSOCKET_DATA_TEXT, "SOUP_WEBSOCKET_DATA_TEXT", "text" }, + { SOUP_WEBSOCKET_DATA_BINARY, "SOUP_WEBSOCKET_DATA_BINARY", "binary" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("SoupWebsocketDataType"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +soup_websocket_close_code_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { SOUP_WEBSOCKET_CLOSE_NORMAL, "SOUP_WEBSOCKET_CLOSE_NORMAL", "normal" }, + { SOUP_WEBSOCKET_CLOSE_GOING_AWAY, "SOUP_WEBSOCKET_CLOSE_GOING_AWAY", "going-away" }, + { SOUP_WEBSOCKET_CLOSE_PROTOCOL_ERROR, "SOUP_WEBSOCKET_CLOSE_PROTOCOL_ERROR", "protocol-error" }, + { SOUP_WEBSOCKET_CLOSE_UNSUPPORTED_DATA, "SOUP_WEBSOCKET_CLOSE_UNSUPPORTED_DATA", "unsupported-data" }, + { SOUP_WEBSOCKET_CLOSE_NO_STATUS, "SOUP_WEBSOCKET_CLOSE_NO_STATUS", "no-status" }, + { SOUP_WEBSOCKET_CLOSE_ABNORMAL, "SOUP_WEBSOCKET_CLOSE_ABNORMAL", "abnormal" }, + { SOUP_WEBSOCKET_CLOSE_BAD_DATA, "SOUP_WEBSOCKET_CLOSE_BAD_DATA", "bad-data" }, + { SOUP_WEBSOCKET_CLOSE_POLICY_VIOLATION, "SOUP_WEBSOCKET_CLOSE_POLICY_VIOLATION", "policy-violation" }, + { SOUP_WEBSOCKET_CLOSE_TOO_BIG, "SOUP_WEBSOCKET_CLOSE_TOO_BIG", "too-big" }, + { SOUP_WEBSOCKET_CLOSE_NO_EXTENSION, "SOUP_WEBSOCKET_CLOSE_NO_EXTENSION", "no-extension" }, + { SOUP_WEBSOCKET_CLOSE_SERVER_ERROR, "SOUP_WEBSOCKET_CLOSE_SERVER_ERROR", "server-error" }, + { SOUP_WEBSOCKET_CLOSE_TLS_HANDSHAKE, "SOUP_WEBSOCKET_CLOSE_TLS_HANDSHAKE", "tls-handshake" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("SoupWebsocketCloseCode"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +soup_websocket_state_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { SOUP_WEBSOCKET_STATE_OPEN, "SOUP_WEBSOCKET_STATE_OPEN", "open" }, + { SOUP_WEBSOCKET_STATE_CLOSING, "SOUP_WEBSOCKET_STATE_CLOSING", "closing" }, + { SOUP_WEBSOCKET_STATE_CLOSED, "SOUP_WEBSOCKET_STATE_CLOSED", "closed" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("SoupWebsocketState"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +soup_xmlrpc_error_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { SOUP_XMLRPC_ERROR_ARGUMENTS, "SOUP_XMLRPC_ERROR_ARGUMENTS", "arguments" }, + { SOUP_XMLRPC_ERROR_RETVAL, "SOUP_XMLRPC_ERROR_RETVAL", "retval" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("SoupXMLRPCError"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +soup_xmlrpc_fault_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { SOUP_XMLRPC_FAULT_PARSE_ERROR_NOT_WELL_FORMED, "SOUP_XMLRPC_FAULT_PARSE_ERROR_NOT_WELL_FORMED", "parse-error-not-well-formed" }, + { SOUP_XMLRPC_FAULT_PARSE_ERROR_UNSUPPORTED_ENCODING, "SOUP_XMLRPC_FAULT_PARSE_ERROR_UNSUPPORTED_ENCODING", "parse-error-unsupported-encoding" }, + { SOUP_XMLRPC_FAULT_PARSE_ERROR_INVALID_CHARACTER_FOR_ENCODING, "SOUP_XMLRPC_FAULT_PARSE_ERROR_INVALID_CHARACTER_FOR_ENCODING", "parse-error-invalid-character-for-encoding" }, + { SOUP_XMLRPC_FAULT_SERVER_ERROR_INVALID_XML_RPC, "SOUP_XMLRPC_FAULT_SERVER_ERROR_INVALID_XML_RPC", "server-error-invalid-xml-rpc" }, + { SOUP_XMLRPC_FAULT_SERVER_ERROR_REQUESTED_METHOD_NOT_FOUND, "SOUP_XMLRPC_FAULT_SERVER_ERROR_REQUESTED_METHOD_NOT_FOUND", "server-error-requested-method-not-found" }, + { SOUP_XMLRPC_FAULT_SERVER_ERROR_INVALID_METHOD_PARAMETERS, "SOUP_XMLRPC_FAULT_SERVER_ERROR_INVALID_METHOD_PARAMETERS", "server-error-invalid-method-parameters" }, + { SOUP_XMLRPC_FAULT_SERVER_ERROR_INTERNAL_XML_RPC_ERROR, "SOUP_XMLRPC_FAULT_SERVER_ERROR_INTERNAL_XML_RPC_ERROR", "server-error-internal-xml-rpc-error" }, + { SOUP_XMLRPC_FAULT_APPLICATION_ERROR, "SOUP_XMLRPC_FAULT_APPLICATION_ERROR", "application-error" }, + { SOUP_XMLRPC_FAULT_SYSTEM_ERROR, "SOUP_XMLRPC_FAULT_SYSTEM_ERROR", "system-error" }, + { SOUP_XMLRPC_FAULT_TRANSPORT_ERROR, "SOUP_XMLRPC_FAULT_TRANSPORT_ERROR", "transport-error" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("SoupXMLRPCFault"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} + +/* Generated data ends here */ + diff --git a/libsoup/soup-enum-types.h b/libsoup/soup-enum-types.h new file mode 100644 index 0000000..ccef30b --- /dev/null +++ b/libsoup/soup-enum-types.h @@ -0,0 +1,80 @@ + +/* This file is generated by glib-mkenums, do not modify it. This code is licensed under the same license as the containing project. Note that it links to GLib, so must comply with the LGPL linking clauses. */ + +/* Generated by glib-mkenums. Do not edit */ + +#ifndef __SOUP_ENUM_TYPES_H__ +#define __SOUP_ENUM_TYPES_H__ + +#include +#define GLIB_MKENUMS_EXTERN _SOUP_EXTERN +#include + +G_BEGIN_DECLS +#ifndef GLIB_MKENUMS_EXTERN +#define GLIB_MKENUMS_EXTERN +#endif +GLIB_MKENUMS_EXTERN GType soup_address_family_get_type (void) G_GNUC_CONST; +#define SOUP_TYPE_ADDRESS_FAMILY (soup_address_family_get_type ()) +GLIB_MKENUMS_EXTERN GType soup_cacheability_get_type (void) G_GNUC_CONST; +#define SOUP_TYPE_CACHEABILITY (soup_cacheability_get_type ()) +GLIB_MKENUMS_EXTERN GType soup_cache_response_get_type (void) G_GNUC_CONST; +#define SOUP_TYPE_CACHE_RESPONSE (soup_cache_response_get_type ()) +GLIB_MKENUMS_EXTERN GType soup_cache_type_get_type (void) G_GNUC_CONST; +#define SOUP_TYPE_CACHE_TYPE (soup_cache_type_get_type ()) +GLIB_MKENUMS_EXTERN GType soup_cookie_jar_accept_policy_get_type (void) G_GNUC_CONST; +#define SOUP_TYPE_COOKIE_JAR_ACCEPT_POLICY (soup_cookie_jar_accept_policy_get_type ()) +GLIB_MKENUMS_EXTERN GType soup_date_format_get_type (void) G_GNUC_CONST; +#define SOUP_TYPE_DATE_FORMAT (soup_date_format_get_type ()) +GLIB_MKENUMS_EXTERN GType soup_logger_log_level_get_type (void) G_GNUC_CONST; +#define SOUP_TYPE_LOGGER_LOG_LEVEL (soup_logger_log_level_get_type ()) +GLIB_MKENUMS_EXTERN GType soup_memory_use_get_type (void) G_GNUC_CONST; +#define SOUP_TYPE_MEMORY_USE (soup_memory_use_get_type ()) +GLIB_MKENUMS_EXTERN GType soup_message_headers_type_get_type (void) G_GNUC_CONST; +#define SOUP_TYPE_MESSAGE_HEADERS_TYPE (soup_message_headers_type_get_type ()) +GLIB_MKENUMS_EXTERN GType soup_encoding_get_type (void) G_GNUC_CONST; +#define SOUP_TYPE_ENCODING (soup_encoding_get_type ()) +GLIB_MKENUMS_EXTERN GType soup_expectation_get_type (void) G_GNUC_CONST; +#define SOUP_TYPE_EXPECTATION (soup_expectation_get_type ()) +GLIB_MKENUMS_EXTERN GType soup_http_version_get_type (void) G_GNUC_CONST; +#define SOUP_TYPE_HTTP_VERSION (soup_http_version_get_type ()) +GLIB_MKENUMS_EXTERN GType soup_message_flags_get_type (void) G_GNUC_CONST; +#define SOUP_TYPE_MESSAGE_FLAGS (soup_message_flags_get_type ()) +GLIB_MKENUMS_EXTERN GType soup_message_priority_get_type (void) G_GNUC_CONST; +#define SOUP_TYPE_MESSAGE_PRIORITY (soup_message_priority_get_type ()) +GLIB_MKENUMS_EXTERN GType soup_connection_state_get_type (void) G_GNUC_CONST; +#define SOUP_TYPE_CONNECTION_STATE (soup_connection_state_get_type ()) +GLIB_MKENUMS_EXTERN GType soup_requester_error_get_type (void) G_GNUC_CONST; +#define SOUP_TYPE_REQUESTER_ERROR (soup_requester_error_get_type ()) +GLIB_MKENUMS_EXTERN GType soup_server_listen_options_get_type (void) G_GNUC_CONST; +#define SOUP_TYPE_SERVER_LISTEN_OPTIONS (soup_server_listen_options_get_type ()) +GLIB_MKENUMS_EXTERN GType soup_request_error_get_type (void) G_GNUC_CONST; +#define SOUP_TYPE_REQUEST_ERROR (soup_request_error_get_type ()) +GLIB_MKENUMS_EXTERN GType soup_socket_io_status_get_type (void) G_GNUC_CONST; +#define SOUP_TYPE_SOCKET_IO_STATUS (soup_socket_io_status_get_type ()) +GLIB_MKENUMS_EXTERN GType soup_status_get_type (void) G_GNUC_CONST; +#define SOUP_TYPE_STATUS (soup_status_get_type ()) +GLIB_MKENUMS_EXTERN GType soup_known_status_code_get_type (void) G_GNUC_CONST; +#define SOUP_TYPE_KNOWN_STATUS_CODE (soup_known_status_code_get_type ()) +GLIB_MKENUMS_EXTERN GType soup_tld_error_get_type (void) G_GNUC_CONST; +#define SOUP_TYPE_TLD_ERROR (soup_tld_error_get_type ()) +GLIB_MKENUMS_EXTERN GType soup_websocket_error_get_type (void) G_GNUC_CONST; +#define SOUP_TYPE_WEBSOCKET_ERROR (soup_websocket_error_get_type ()) +GLIB_MKENUMS_EXTERN GType soup_websocket_connection_type_get_type (void) G_GNUC_CONST; +#define SOUP_TYPE_WEBSOCKET_CONNECTION_TYPE (soup_websocket_connection_type_get_type ()) +GLIB_MKENUMS_EXTERN GType soup_websocket_data_type_get_type (void) G_GNUC_CONST; +#define SOUP_TYPE_WEBSOCKET_DATA_TYPE (soup_websocket_data_type_get_type ()) +GLIB_MKENUMS_EXTERN GType soup_websocket_close_code_get_type (void) G_GNUC_CONST; +#define SOUP_TYPE_WEBSOCKET_CLOSE_CODE (soup_websocket_close_code_get_type ()) +GLIB_MKENUMS_EXTERN GType soup_websocket_state_get_type (void) G_GNUC_CONST; +#define SOUP_TYPE_WEBSOCKET_STATE (soup_websocket_state_get_type ()) +GLIB_MKENUMS_EXTERN GType soup_xmlrpc_error_get_type (void) G_GNUC_CONST; +#define SOUP_TYPE_XMLRPC_ERROR (soup_xmlrpc_error_get_type ()) +GLIB_MKENUMS_EXTERN GType soup_xmlrpc_fault_get_type (void) G_GNUC_CONST; +#define SOUP_TYPE_XMLRPC_FAULT (soup_xmlrpc_fault_get_type ()) +G_END_DECLS + +#endif /* __SOUP_ENUM_TYPES_H__ */ + +/* Generated data ends here */ + diff --git a/libsoup/soup-filter-input-stream.c b/libsoup/soup-filter-input-stream.c new file mode 100644 index 0000000..2c30bf9 --- /dev/null +++ b/libsoup/soup-filter-input-stream.c @@ -0,0 +1,277 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-filter-input-stream.c + * + * Copyright 2012 Red Hat, Inc. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "soup-filter-input-stream.h" +#include "soup.h" + +/* This is essentially a subset of GDataInputStream, except that we + * can do the equivalent of "fill_nonblocking()" on it. (We could use + * an actual GDataInputStream, and implement the nonblocking semantics + * via fill_async(), but that would be more work...) + */ + +struct _SoupFilterInputStreamPrivate { + GByteArray *buf; + gboolean need_more; + gboolean in_read_until; +}; + +static void soup_filter_input_stream_pollable_init (GPollableInputStreamInterface *pollable_interface, gpointer interface_data); + +G_DEFINE_TYPE_WITH_CODE (SoupFilterInputStream, soup_filter_input_stream, G_TYPE_FILTER_INPUT_STREAM, + G_ADD_PRIVATE (SoupFilterInputStream) + G_IMPLEMENT_INTERFACE (G_TYPE_POLLABLE_INPUT_STREAM, + soup_filter_input_stream_pollable_init)) + +static void +soup_filter_input_stream_init (SoupFilterInputStream *stream) +{ + stream->priv = soup_filter_input_stream_get_instance_private (stream); +} + +static void +soup_filter_input_stream_finalize (GObject *object) +{ + SoupFilterInputStream *fstream = SOUP_FILTER_INPUT_STREAM (object); + + g_clear_pointer (&fstream->priv->buf, g_byte_array_unref); + + G_OBJECT_CLASS (soup_filter_input_stream_parent_class)->finalize (object); +} + +static gssize +read_from_buf (SoupFilterInputStream *fstream, gpointer buffer, gsize count) +{ + GByteArray *buf = fstream->priv->buf; + + if (buf->len < count) + count = buf->len; + memcpy (buffer, buf->data, count); + + if (count == buf->len) { + g_byte_array_free (buf, TRUE); + fstream->priv->buf = NULL; + } else { + memmove (buf->data, buf->data + count, + buf->len - count); + g_byte_array_set_size (buf, buf->len - count); + } + + return count; +} + +static gssize +soup_filter_input_stream_read_fn (GInputStream *stream, + void *buffer, + gsize count, + GCancellable *cancellable, + GError **error) +{ + SoupFilterInputStream *fstream = SOUP_FILTER_INPUT_STREAM (stream); + + if (!fstream->priv->in_read_until) + fstream->priv->need_more = FALSE; + + if (fstream->priv->buf && !fstream->priv->in_read_until) { + return read_from_buf (fstream, buffer, count); + } else { + return g_pollable_stream_read (G_FILTER_INPUT_STREAM (fstream)->base_stream, + buffer, count, + TRUE, cancellable, error); + } +} + +static gboolean +soup_filter_input_stream_is_readable (GPollableInputStream *stream) +{ + SoupFilterInputStream *fstream = SOUP_FILTER_INPUT_STREAM (stream); + + if (fstream->priv->buf && !fstream->priv->need_more) + return TRUE; + else + return g_pollable_input_stream_is_readable (G_POLLABLE_INPUT_STREAM (G_FILTER_INPUT_STREAM (fstream)->base_stream)); +} + +static gssize +soup_filter_input_stream_read_nonblocking (GPollableInputStream *stream, + void *buffer, + gsize count, + GError **error) +{ + SoupFilterInputStream *fstream = SOUP_FILTER_INPUT_STREAM (stream); + + if (!fstream->priv->in_read_until) + fstream->priv->need_more = FALSE; + + if (fstream->priv->buf && !fstream->priv->in_read_until) { + return read_from_buf (fstream, buffer, count); + } else { + return g_pollable_stream_read (G_FILTER_INPUT_STREAM (fstream)->base_stream, + buffer, count, + FALSE, NULL, error); + } +} + +static GSource * +soup_filter_input_stream_create_source (GPollableInputStream *stream, + GCancellable *cancellable) +{ + SoupFilterInputStream *fstream = SOUP_FILTER_INPUT_STREAM (stream); + GSource *base_source, *pollable_source; + + if (fstream->priv->buf && !fstream->priv->need_more) + base_source = g_timeout_source_new (0); + else + base_source = g_pollable_input_stream_create_source (G_POLLABLE_INPUT_STREAM (G_FILTER_INPUT_STREAM (fstream)->base_stream), cancellable); + + g_source_set_dummy_callback (base_source); + pollable_source = g_pollable_source_new (G_OBJECT (stream)); + g_source_add_child_source (pollable_source, base_source); + g_source_unref (base_source); + + return pollable_source; +} + +static void +soup_filter_input_stream_class_init (SoupFilterInputStreamClass *stream_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (stream_class); + GInputStreamClass *input_stream_class = G_INPUT_STREAM_CLASS (stream_class); + + object_class->finalize = soup_filter_input_stream_finalize; + + input_stream_class->read_fn = soup_filter_input_stream_read_fn; +} + +static void +soup_filter_input_stream_pollable_init (GPollableInputStreamInterface *pollable_interface, + gpointer interface_data) +{ + pollable_interface->is_readable = soup_filter_input_stream_is_readable; + pollable_interface->read_nonblocking = soup_filter_input_stream_read_nonblocking; + pollable_interface->create_source = soup_filter_input_stream_create_source; +} + +GInputStream * +soup_filter_input_stream_new (GInputStream *base_stream) +{ + return g_object_new (SOUP_TYPE_FILTER_INPUT_STREAM, + "base-stream", base_stream, + "close-base-stream", FALSE, + NULL); +} + +gssize +soup_filter_input_stream_read_line (SoupFilterInputStream *fstream, + void *buffer, + gsize length, + gboolean blocking, + gboolean *got_line, + GCancellable *cancellable, + GError **error) +{ + return soup_filter_input_stream_read_until (fstream, buffer, length, + "\n", 1, blocking, + TRUE, got_line, + cancellable, error); +} + +gssize +soup_filter_input_stream_read_until (SoupFilterInputStream *fstream, + void *buffer, + gsize length, + const void *boundary, + gsize boundary_length, + gboolean blocking, + gboolean include_boundary, + gboolean *got_boundary, + GCancellable *cancellable, + GError **error) +{ + gssize nread, read_length; + guint8 *p, *buf, *end; + gboolean eof = FALSE; + GError *my_error = NULL; + + g_return_val_if_fail (SOUP_IS_FILTER_INPUT_STREAM (fstream), -1); + g_return_val_if_fail (!include_boundary || (boundary_length < length), -1); + + *got_boundary = FALSE; + fstream->priv->need_more = FALSE; + + if (!fstream->priv->buf || fstream->priv->buf->len < boundary_length) { + guint prev_len; + + fill_buffer: + if (!fstream->priv->buf) + fstream->priv->buf = g_byte_array_new (); + prev_len = fstream->priv->buf->len; + g_byte_array_set_size (fstream->priv->buf, length); + buf = fstream->priv->buf->data; + + fstream->priv->in_read_until = TRUE; + nread = g_pollable_stream_read (G_INPUT_STREAM (fstream), + buf + prev_len, length - prev_len, + blocking, + cancellable, &my_error); + fstream->priv->in_read_until = FALSE; + if (nread <= 0) { + if (prev_len) + fstream->priv->buf->len = prev_len; + else { + g_byte_array_free (fstream->priv->buf, TRUE); + fstream->priv->buf = NULL; + } + + if (nread == 0 && prev_len) + eof = TRUE; + else { + if (g_error_matches (my_error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) + fstream->priv->need_more = TRUE; + if (my_error) + g_propagate_error (error, my_error); + + return nread; + } + + if (my_error) + g_propagate_error (error, my_error); + } else + fstream->priv->buf->len = prev_len + nread; + } else + buf = fstream->priv->buf->data; + + /* Scan for the boundary within the range we can possibly return. */ + if (include_boundary) + end = buf + MIN (fstream->priv->buf->len, length) - boundary_length; + else + end = buf + MIN (fstream->priv->buf->len - boundary_length, length); + for (p = buf; p <= end; p++) { + if (*p == *(guint8*)boundary && + !memcmp (p, boundary, boundary_length)) { + if (include_boundary) + p += boundary_length; + *got_boundary = TRUE; + break; + } + } + + if (!*got_boundary && fstream->priv->buf->len < length && !eof) + goto fill_buffer; + + if (eof && !*got_boundary) + read_length = MIN (fstream->priv->buf->len, length); + else + read_length = p - buf; + return read_from_buf (fstream, buffer, read_length); +} diff --git a/libsoup/soup-filter-input-stream.h b/libsoup/soup-filter-input-stream.h new file mode 100644 index 0000000..276b60f --- /dev/null +++ b/libsoup/soup-filter-input-stream.h @@ -0,0 +1,57 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright 2012 Red Hat, Inc. + */ + +#ifndef SOUP_FILTER_INPUT_STREAM_H +#define SOUP_FILTER_INPUT_STREAM_H 1 + +#include + +G_BEGIN_DECLS + +#define SOUP_TYPE_FILTER_INPUT_STREAM (soup_filter_input_stream_get_type ()) +#define SOUP_FILTER_INPUT_STREAM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SOUP_TYPE_FILTER_INPUT_STREAM, SoupFilterInputStream)) +#define SOUP_FILTER_INPUT_STREAM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_FILTER_INPUT_STREAM, SoupFilterInputStreamClass)) +#define SOUP_IS_FILTER_INPUT_STREAM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SOUP_TYPE_FILTER_INPUT_STREAM)) +#define SOUP_IS_FILTER_INPUT_STREAM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), SOUP_TYPE_FILTER_INPUT_STREAM)) +#define SOUP_FILTER_INPUT_STREAM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_FILTER_INPUT_STREAM, SoupFilterInputStreamClass)) + +typedef struct _SoupFilterInputStreamPrivate SoupFilterInputStreamPrivate; + +typedef struct { + GFilterInputStream parent; + + SoupFilterInputStreamPrivate *priv; +} SoupFilterInputStream; + +typedef struct { + GFilterInputStreamClass parent_class; + +} SoupFilterInputStreamClass; + +GType soup_filter_input_stream_get_type (void); + +GInputStream *soup_filter_input_stream_new (GInputStream *base_stream); + +gssize soup_filter_input_stream_read_line (SoupFilterInputStream *fstream, + void *buffer, + gsize length, + gboolean blocking, + gboolean *got_line, + GCancellable *cancellable, + GError **error); +gssize soup_filter_input_stream_read_until (SoupFilterInputStream *fstream, + void *buffer, + gsize length, + const void *boundary, + gsize boundary_len, + gboolean blocking, + gboolean include_boundary, + gboolean *got_boundary, + GCancellable *cancellable, + GError **error); + +G_END_DECLS + +#endif /* SOUP_FILTER_INPUT_STREAM_H */ diff --git a/libsoup/soup-form.c b/libsoup/soup-form.c new file mode 100644 index 0000000..aa0974f --- /dev/null +++ b/libsoup/soup-form.c @@ -0,0 +1,491 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* soup-form.c : utility functions for HTML forms */ + +/* + * Copyright 2008 Red Hat, Inc. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "soup-form.h" +#include "soup.h" + +/** + * SECTION:soup-form + * @short_description: HTML form handling + * @see_also: #SoupMultipart + * + * libsoup contains several help methods for processing HTML forms as + * defined by the + * HTML 4.01 specification. + **/ + +/** + * SOUP_FORM_MIME_TYPE_URLENCODED: + * + * A macro containing the value + * "application/x-www-form-urlencoded"; the default + * MIME type for POSTing HTML form data. + * + * Since: 2.26 + **/ + +/** + * SOUP_FORM_MIME_TYPE_MULTIPART: + * + * A macro containing the value + * "multipart/form-data"; the MIME type used for + * posting form data that contains files to be uploaded. + * + * Since: 2.26 + **/ + +#define XDIGIT(c) ((c) <= '9' ? (c) - '0' : ((c) & 0x4F) - 'A' + 10) +#define HEXCHAR(s) ((XDIGIT (s[1]) << 4) + XDIGIT (s[2])) + +static gboolean +form_decode (char *part) +{ + unsigned char *s, *d; + + s = d = (unsigned char *)part; + do { + if (*s == '%') { + if (!g_ascii_isxdigit (s[1]) || + !g_ascii_isxdigit (s[2])) + return FALSE; + *d++ = HEXCHAR (s); + s += 2; + } else if (*s == '+') + *d++ = ' '; + else + *d++ = *s; + } while (*s++); + + return TRUE; +} + +/** + * soup_form_decode: + * @encoded_form: data of type "application/x-www-form-urlencoded" + * + * Decodes @form, which is an urlencoded dataset as defined in the + * HTML 4.01 spec. + * + * Return value: (element-type utf8 utf8) (transfer container): a hash + * table containing the name/value pairs from @encoded_form, which you + * can free with g_hash_table_destroy(). + **/ +GHashTable * +soup_form_decode (const char *encoded_form) +{ + GHashTable *form_data_set; + char **pairs, *eq, *name, *value; + int i; + + form_data_set = g_hash_table_new_full (g_str_hash, g_str_equal, + g_free, NULL); + pairs = g_strsplit (encoded_form, "&", -1); + for (i = 0; pairs[i]; i++) { + name = pairs[i]; + eq = strchr (name, '='); + if (eq) { + *eq = '\0'; + value = eq + 1; + } else + value = NULL; + if (!value || !form_decode (name) || !form_decode (value)) { + g_free (name); + continue; + } + + g_hash_table_replace (form_data_set, name, value); + } + g_free (pairs); + + return form_data_set; +} + +/** + * soup_form_decode_multipart: + * @msg: a #SoupMessage containing a "multipart/form-data" request body + * @file_control_name: (allow-none): the name of the HTML file upload control, or %NULL + * @filename: (out) (allow-none): return location for the name of the uploaded file, or %NULL + * @content_type: (out) (allow-none): return location for the MIME type of the uploaded file, or %NULL + * @file: (out) (allow-none): return location for the uploaded file data, or %NULL + * + * Decodes the "multipart/form-data" request in @msg; this is a + * convenience method for the case when you have a single file upload + * control in a form. (Or when you don't have any file upload + * controls, but are still using "multipart/form-data" anyway.) Pass + * the name of the file upload control in @file_control_name, and + * soup_form_decode_multipart() will extract the uploaded file data + * into @filename, @content_type, and @file. All of the other form + * control data will be returned (as strings, as with + * soup_form_decode()) in the returned #GHashTable. + * + * You may pass %NULL for @filename, @content_type and/or @file if you do not + * care about those fields. soup_form_decode_multipart() may also + * return %NULL in those fields if the client did not provide that + * information. You must free the returned filename and content-type + * with g_free(), and the returned file data with soup_buffer_free(). + * + * If you have a form with more than one file upload control, you will + * need to decode it manually, using soup_multipart_new_from_message() + * and soup_multipart_get_part(). + * + * Return value: (nullable) (element-type utf8 utf8) (transfer container): + * a hash table containing the name/value pairs (other than + * @file_control_name) from @msg, which you can free with + * g_hash_table_destroy(). On error, it will return %NULL. + * + * Since: 2.26 + **/ +GHashTable * +soup_form_decode_multipart (SoupMessage *msg, const char *file_control_name, + char **filename, char **content_type, + SoupBuffer **file) +{ + SoupMultipart *multipart; + GHashTable *form_data_set, *params; + SoupMessageHeaders *part_headers; + SoupBuffer *part_body; + char *disposition, *name; + int i; + + g_return_val_if_fail (SOUP_IS_MESSAGE (msg), NULL); + + multipart = soup_multipart_new_from_message (msg->request_headers, + msg->request_body); + if (!multipart) + return NULL; + + if (filename) + *filename = NULL; + if (content_type) + *content_type = NULL; + if (file) + *file = NULL; + + form_data_set = g_hash_table_new_full (g_str_hash, g_str_equal, + g_free, g_free); + for (i = 0; i < soup_multipart_get_length (multipart); i++) { + soup_multipart_get_part (multipart, i, &part_headers, &part_body); + if (!soup_message_headers_get_content_disposition ( + part_headers, &disposition, ¶ms)) + continue; + name = g_hash_table_lookup (params, "name"); + if (g_ascii_strcasecmp (disposition, "form-data") != 0 || + !name) { + g_free (disposition); + g_hash_table_destroy (params); + continue; + } + + if (file_control_name && !strcmp (name, file_control_name)) { + if (filename) + *filename = g_strdup (g_hash_table_lookup (params, "filename")); + if (content_type) + *content_type = g_strdup (soup_message_headers_get_content_type (part_headers, NULL)); + if (file) + *file = soup_buffer_copy (part_body); + } else { + g_hash_table_insert (form_data_set, + g_strdup (name), + g_strndup (part_body->data, + part_body->length)); + } + + g_free (disposition); + g_hash_table_destroy (params); + } + + soup_multipart_free (multipart); + return form_data_set; +} + +static void +append_form_encoded (GString *str, const char *in) +{ + const unsigned char *s = (const unsigned char *)in; + + while (*s) { + if (*s == ' ') { + g_string_append_c (str, '+'); + s++; + } else if (!g_ascii_isalnum (*s) && (*s != '-') && (*s != '_') + && (*s != '.')) + g_string_append_printf (str, "%%%02X", (int)*s++); + else + g_string_append_c (str, *s++); + } +} + +static void +encode_pair (GString *str, const char *name, const char *value) +{ + g_return_if_fail (name != NULL); + g_return_if_fail (value != NULL); + + if (str->len) + g_string_append_c (str, '&'); + append_form_encoded (str, name); + g_string_append_c (str, '='); + append_form_encoded (str, value); +} + +/** + * soup_form_encode: + * @first_field: name of the first form field + * @...: value of @first_field, followed by additional field names + * and values, terminated by %NULL. + * + * Encodes the given field names and values into a value of type + * "application/x-www-form-urlencoded", as defined in the HTML 4.01 + * spec. + * + * This method requires you to know the names of the form fields (or + * at the very least, the total number of fields) at compile time; for + * working with dynamic forms, use soup_form_encode_hash() or + * soup_form_encode_datalist(). + * + * Return value: the encoded form + **/ +char * +soup_form_encode (const char *first_field, ...) +{ + va_list args; + char *encoded; + + va_start (args, first_field); + encoded = soup_form_encode_valist (first_field, args); + va_end (args); + + return encoded; +} + +/** + * soup_form_encode_hash: + * @form_data_set: (element-type utf8 utf8): a hash table containing + * name/value pairs (as strings) + * + * Encodes @form_data_set into a value of type + * "application/x-www-form-urlencoded", as defined in the HTML 4.01 + * spec. + * + * Note that the HTML spec states that "The control names/values are + * listed in the order they appear in the document." Since this method + * takes a hash table, it cannot enforce that; if you care about the + * ordering of the form fields, use soup_form_encode_datalist(). + * + * Return value: the encoded form + **/ +char * +soup_form_encode_hash (GHashTable *form_data_set) +{ + GString *str = g_string_new (NULL); + GHashTableIter iter; + gpointer name, value; + + g_hash_table_iter_init (&iter, form_data_set); + while (g_hash_table_iter_next (&iter, &name, &value)) + encode_pair (str, name, value); + return g_string_free (str, FALSE); +} + +static void +datalist_encode_foreach (GQuark key_id, gpointer value, gpointer str) +{ + encode_pair (str, g_quark_to_string (key_id), value); +} + +/** + * soup_form_encode_datalist: + * @form_data_set: a datalist containing name/value pairs + * + * Encodes @form_data_set into a value of type + * "application/x-www-form-urlencoded", as defined in the HTML 4.01 + * spec. Unlike soup_form_encode_hash(), this preserves the ordering + * of the form elements, which may be required in some situations. + * + * Return value: the encoded form + **/ +char * +soup_form_encode_datalist (GData **form_data_set) +{ + GString *str = g_string_new (NULL); + + g_datalist_foreach (form_data_set, datalist_encode_foreach, str); + return g_string_free (str, FALSE); +} + +/** + * soup_form_encode_valist: + * @first_field: name of the first form field + * @args: pointer to additional values, as in soup_form_encode() + * + * See soup_form_encode(). This is mostly an internal method, used by + * various other methods such as soup_uri_set_query_from_fields() and + * soup_form_request_new(). + * + * Return value: the encoded form + **/ +char * +soup_form_encode_valist (const char *first_field, va_list args) +{ + GString *str = g_string_new (NULL); + const char *name, *value; + + name = first_field; + value = va_arg (args, const char *); + while (name && value) { + encode_pair (str, name, value); + + name = va_arg (args, const char *); + if (name) + value = va_arg (args, const char *); + } + + return g_string_free (str, FALSE); +} + +static SoupMessage * +soup_form_request_for_data (const char *method, const char *uri_string, + char *form_data) +{ + SoupMessage *msg; + SoupURI *uri; + + uri = soup_uri_new (uri_string); + if (!uri) + return NULL; + + if (!strcmp (method, "GET")) { + g_free (uri->query); + uri->query = form_data; + + msg = soup_message_new_from_uri (method, uri); + } else if (!strcmp (method, "POST") || !strcmp (method, "PUT")) { + msg = soup_message_new_from_uri (method, uri); + + soup_message_set_request ( + msg, SOUP_FORM_MIME_TYPE_URLENCODED, + SOUP_MEMORY_TAKE, + form_data, strlen (form_data)); + } else { + g_warning ("invalid method passed to soup_form_request_new"); + g_free (form_data); + + /* Don't crash */ + msg = soup_message_new_from_uri (method, uri); + } + soup_uri_free (uri); + + return msg; +} + +/** + * soup_form_request_new: + * @method: the HTTP method, either "GET" or "POST" + * @uri: the URI to send the form data to + * @first_field: name of the first form field + * @...: value of @first_field, followed by additional field names + * and values, terminated by %NULL. + * + * Creates a new %SoupMessage and sets it up to send the given data + * to @uri via @method. (That is, if @method is "GET", it will encode + * the form data into @uri's query field, and if @method is "POST", it + * will encode it into the %SoupMessage's request_body.) + * + * Return value: (transfer full): the new %SoupMessage + **/ +SoupMessage * +soup_form_request_new (const char *method, const char *uri, + const char *first_field, ...) +{ + va_list args; + char *form_data; + + va_start (args, first_field); + form_data = soup_form_encode_valist (first_field, args); + va_end (args); + + return soup_form_request_for_data (method, uri, form_data); +} + +/** + * soup_form_request_new_from_hash: + * @method: the HTTP method, either "GET" or "POST" + * @uri: the URI to send the form data to + * @form_data_set: (element-type utf8 utf8): the data to send to @uri + * + * Creates a new %SoupMessage and sets it up to send @form_data_set to + * @uri via @method, as with soup_form_request_new(). + * + * Return value: (transfer full): the new %SoupMessage + **/ +SoupMessage * +soup_form_request_new_from_hash (const char *method, const char *uri, + GHashTable *form_data_set) +{ + return soup_form_request_for_data ( + method, uri, soup_form_encode_hash (form_data_set)); +} + +/** + * soup_form_request_new_from_datalist: + * @method: the HTTP method, either "GET" or "POST" + * @uri: the URI to send the form data to + * @form_data_set: the data to send to @uri + * + * Creates a new %SoupMessage and sets it up to send @form_data_set to + * @uri via @method, as with soup_form_request_new(). + * + * Return value: (transfer full): the new %SoupMessage + **/ +SoupMessage * +soup_form_request_new_from_datalist (const char *method, const char *uri, + GData **form_data_set) +{ + return soup_form_request_for_data ( + method, uri, soup_form_encode_datalist (form_data_set)); +} + +/** + * soup_form_request_new_from_multipart: + * @uri: the URI to send the form data to + * @multipart: a "multipart/form-data" #SoupMultipart + * + * Creates a new %SoupMessage and sets it up to send @multipart to + * @uri via POST. + * + * To send a "multipart/form-data" POST, first + * create a #SoupMultipart, using %SOUP_FORM_MIME_TYPE_MULTIPART as + * the MIME type. Then use soup_multipart_append_form_string() and + * soup_multipart_append_form_file() to add the value of each form + * control to the multipart. (These are just convenience methods, and + * you can use soup_multipart_append_part() if you need greater + * control over the part headers.) Finally, call + * soup_form_request_new_from_multipart() to serialize the multipart + * structure and create a #SoupMessage. + * + * Return value: (transfer full): the new %SoupMessage + * + * Since: 2.26 + **/ +SoupMessage * +soup_form_request_new_from_multipart (const char *uri, + SoupMultipart *multipart) +{ + SoupMessage *msg; + + msg = soup_message_new ("POST", uri); + soup_multipart_to_message (multipart, msg->request_headers, + msg->request_body); + return msg; +} diff --git a/libsoup/soup-form.h b/libsoup/soup-form.h new file mode 100644 index 0000000..a0df034 --- /dev/null +++ b/libsoup/soup-form.h @@ -0,0 +1,63 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright 2008 Red Hat, Inc. + */ + +#ifndef SOUP_FORM_H +#define SOUP_FORM_H 1 + +#include +#include + +G_BEGIN_DECLS + +#define SOUP_FORM_MIME_TYPE_URLENCODED "application/x-www-form-urlencoded" +#define SOUP_FORM_MIME_TYPE_MULTIPART "multipart/form-data" + +SOUP_AVAILABLE_IN_2_4 +GHashTable *soup_form_decode (const char *encoded_form); +SOUP_AVAILABLE_IN_2_26 +GHashTable *soup_form_decode_multipart (SoupMessage *msg, + const char *file_control_name, + char **filename, + char **content_type, + SoupBuffer **file); + +SOUP_AVAILABLE_IN_2_4 +char *soup_form_encode (const char *first_field, + ...) G_GNUC_NULL_TERMINATED; +SOUP_AVAILABLE_IN_2_4 +char *soup_form_encode_hash (GHashTable *form_data_set); +SOUP_AVAILABLE_IN_2_4 +char *soup_form_encode_datalist (GData **form_data_set); +SOUP_AVAILABLE_IN_2_4 +char *soup_form_encode_valist (const char *first_field, + va_list args); + +#ifndef SOUP_DISABLE_DEPRECATED +/* Compatibility with libsoup 2.3.0 */ +#define soup_form_decode_urlencoded soup_form_decode +#define soup_form_encode_urlencoded soup_form_encode_hash +#define soup_form_encode_urlencoded_list soup_form_encode_datalist +#endif + +SOUP_AVAILABLE_IN_2_4 +SoupMessage *soup_form_request_new (const char *method, + const char *uri, + const char *first_field, + ...) G_GNUC_NULL_TERMINATED; +SOUP_AVAILABLE_IN_2_4 +SoupMessage *soup_form_request_new_from_hash (const char *method, + const char *uri, + GHashTable *form_data_set); +SOUP_AVAILABLE_IN_2_4 +SoupMessage *soup_form_request_new_from_datalist (const char *method, + const char *uri, + GData **form_data_set); +SOUP_AVAILABLE_IN_2_26 +SoupMessage *soup_form_request_new_from_multipart (const char *uri, + SoupMultipart *multipart); + +G_END_DECLS + +#endif /* SOUP_FORM_H */ diff --git a/libsoup/soup-gnome-features.c b/libsoup/soup-gnome-features.c new file mode 100644 index 0000000..4b40f34 --- /dev/null +++ b/libsoup/soup-gnome-features.c @@ -0,0 +1,21 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-gnome-features.c: GNOME-specific features + * + * Copyright (C) 2008 Red Hat, Inc. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "soup-gnome-features.h" + +GType +soup_gnome_features_2_26_get_type (void) +{ + G_GNUC_BEGIN_IGNORE_DEPRECATIONS; + return SOUP_TYPE_PROXY_RESOLVER_GNOME; + G_GNUC_END_IGNORE_DEPRECATIONS; +} + diff --git a/libsoup/soup-gnome-features.h b/libsoup/soup-gnome-features.h new file mode 100644 index 0000000..18f37de --- /dev/null +++ b/libsoup/soup-gnome-features.h @@ -0,0 +1,30 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2008 Red Hat, Inc. + */ + +#ifndef SOUP_GNOME_FEATURES_H +#define SOUP_GNOME_FEATURES_H 1 + +#include + +G_BEGIN_DECLS + +SOUP_AVAILABLE_IN_2_26 +SOUP_DEPRECATED_IN_2_42_FOR(SoupSession:proxy-resolver) +GType soup_proxy_resolver_gnome_get_type (void); +#define SOUP_TYPE_PROXY_RESOLVER_GNOME (soup_proxy_resolver_gnome_get_type ()) + +SOUP_AVAILABLE_IN_2_26 +SOUP_DEPRECATED_IN_2_42 +GType soup_gnome_features_2_26_get_type (void); +#define SOUP_TYPE_GNOME_FEATURES_2_26 (soup_gnome_features_2_26_get_type ()) + +SOUP_AVAILABLE_IN_2_28 +SOUP_DEPRECATED_IN_2_28 +GType soup_password_manager_gnome_get_type (void); +#define SOUP_TYPE_PASSWORD_MANAGER_GNOME (soup_password_manager_gnome_get_type ()) + +G_END_DECLS + +#endif /* SOUP_GNOME_FEATURES_H */ diff --git a/libsoup/soup-gnome.h b/libsoup/soup-gnome.h new file mode 100644 index 0000000..a2134a4 --- /dev/null +++ b/libsoup/soup-gnome.h @@ -0,0 +1,14 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2008 Red Hat, Inc. + */ + +#ifndef SOUP_GNOME_H +#define SOUP_GNOME_H 1 + +#include + +#include +#include + +#endif /* SOUP_GNOME_H */ diff --git a/libsoup/soup-headers.c b/libsoup/soup-headers.c new file mode 100644 index 0000000..271d2a6 --- /dev/null +++ b/libsoup/soup-headers.c @@ -0,0 +1,958 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-headers.c: HTTP message header parsing + * + * Copyright (C) 2001-2003, Ximian, Inc. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include "soup-headers.h" +#include "soup.h" + +/** + * soup_headers_parse: + * @str: the header string (including the Request-Line or Status-Line, + * but not the trailing blank line) + * @len: length of @str + * @dest: #SoupMessageHeaders to store the header values in + * + * Parses the headers of an HTTP request or response in @str and + * stores the results in @dest. Beware that @dest may be modified even + * on failure. + * + * This is a low-level method; normally you would use + * soup_headers_parse_request() or soup_headers_parse_response(). + * + * Return value: success or failure + * + * Since: 2.26 + **/ +gboolean +soup_headers_parse (const char *str, int len, SoupMessageHeaders *dest) +{ + const char *headers_start; + char *headers_copy, *name, *name_end, *value, *value_end; + char *eol, *sol, *p; + gsize copy_len; + gboolean success = FALSE; + + g_return_val_if_fail (str != NULL, FALSE); + g_return_val_if_fail (dest != NULL, FALSE); + + /* As per RFC 2616 section 19.3, we treat '\n' as the + * line terminator, and '\r', if it appears, merely as + * ignorable trailing whitespace. + */ + + /* Skip over the Request-Line / Status-Line */ + headers_start = memchr (str, '\n', len); + if (!headers_start) + return FALSE; + /* No '\0's in the Request-Line / Status-Line */ + if (memchr (str, '\0', headers_start - str)) + return FALSE; + + /* We work on a copy of the headers, which we can write '\0's + * into, so that we don't have to individually g_strndup and + * then g_free each header name and value. + */ + copy_len = len - (headers_start - str); + headers_copy = g_malloc (copy_len + 1); + memcpy (headers_copy, headers_start, copy_len); + headers_copy[copy_len] = '\0'; + value_end = headers_copy; + + /* There shouldn't be any '\0's in the headers already, but + * this is the web we're talking about. + */ + while ((p = memchr (headers_copy, '\0', copy_len))) { + memmove (p, p + 1, copy_len - (p - headers_copy)); + copy_len--; + } + + while (*(value_end + 1)) { + name = value_end + 1; + name_end = strchr (name, ':'); + + /* Reject if there is no ':', or the header name is + * empty, or it contains whitespace. + */ + if (!name_end || + name_end == name || + name + strcspn (name, " \t\r\n") < name_end) { + /* Ignore this line. Note that if it has + * continuation lines, we'll end up ignoring + * them too since they'll start with spaces. + */ + value_end = strchr (name, '\n'); + if (!value_end) + goto done; + continue; + } + + /* Find the end of the value; ie, an end-of-line that + * isn't followed by a continuation line. + */ + value = name_end + 1; + value_end = strchr (name, '\n'); + if (!value_end) + goto done; + while (*(value_end + 1) == ' ' || *(value_end + 1) == '\t') { + value_end = strchr (value_end + 1, '\n'); + if (!value_end) + goto done; + } + + *name_end = '\0'; + *value_end = '\0'; + + /* Skip leading whitespace */ + while (value < value_end && + (*value == ' ' || *value == '\t' || + *value == '\r' || *value == '\n')) + value++; + + /* Collapse continuation lines */ + while ((eol = strchr (value, '\n'))) { + /* find start of next line */ + sol = eol + 1; + while (*sol == ' ' || *sol == '\t') + sol++; + + /* back up over trailing whitespace on current line */ + while (eol[-1] == ' ' || eol[-1] == '\t' || eol[-1] == '\r') + eol--; + + /* Delete all but one SP */ + *eol = ' '; + g_memmove (eol + 1, sol, strlen (sol) + 1); + } + + /* clip trailing whitespace */ + eol = strchr (value, '\0'); + while (eol > value && + (eol[-1] == ' ' || eol[-1] == '\t' || eol[-1] == '\r')) + eol--; + *eol = '\0'; + + /* convert (illegal) '\r's to spaces */ + for (p = strchr (value, '\r'); p; p = strchr (p, '\r')) + *p = ' '; + + soup_message_headers_append (dest, name, value); + } + success = TRUE; + +done: + g_free (headers_copy); + return success; +} + +/** + * soup_headers_parse_request: + * @str: the headers (up to, but not including, the trailing blank line) + * @len: length of @str + * @req_headers: #SoupMessageHeaders to store the header values in + * @req_method: (out) (allow-none): if non-%NULL, will be filled in with the + * request method + * @req_path: (out) (allow-none): if non-%NULL, will be filled in with the + * request path + * @ver: (out) (allow-none): if non-%NULL, will be filled in with the HTTP + * version + * + * Parses the headers of an HTTP request in @str and stores the + * results in @req_method, @req_path, @ver, and @req_headers. + * + * Beware that @req_headers may be modified even on failure. + * + * Return value: %SOUP_STATUS_OK if the headers could be parsed, or an + * HTTP error to be returned to the client if they could not be. + **/ +guint +soup_headers_parse_request (const char *str, + int len, + SoupMessageHeaders *req_headers, + char **req_method, + char **req_path, + SoupHTTPVersion *ver) +{ + const char *method, *method_end, *path, *path_end; + const char *version, *version_end, *headers; + unsigned long major_version, minor_version; + char *p; + + g_return_val_if_fail (str != NULL, SOUP_STATUS_MALFORMED); + + /* RFC 2616 4.1 "servers SHOULD ignore any empty line(s) + * received where a Request-Line is expected." + */ + while ((*str == '\r' || *str == '\n') && len > 0) { + str++; + len--; + } + if (!len) + return SOUP_STATUS_BAD_REQUEST; + + /* RFC 2616 19.3 "[servers] SHOULD accept any amount of SP or + * HT characters between [Request-Line] fields" + */ + + method = method_end = str; + while (method_end < str + len && *method_end != ' ' && *method_end != '\t') + method_end++; + if (method_end >= str + len) + return SOUP_STATUS_BAD_REQUEST; + + path = method_end; + while (path < str + len && (*path == ' ' || *path == '\t')) + path++; + if (path >= str + len) + return SOUP_STATUS_BAD_REQUEST; + + path_end = path; + while (path_end < str + len && *path_end != ' ' && *path_end != '\t') + path_end++; + if (path_end >= str + len) + return SOUP_STATUS_BAD_REQUEST; + + version = path_end; + while (version < str + len && (*version == ' ' || *version == '\t')) + version++; + if (version + 8 >= str + len) + return SOUP_STATUS_BAD_REQUEST; + + if (strncmp (version, "HTTP/", 5) != 0 || + !g_ascii_isdigit (version[5])) + return SOUP_STATUS_BAD_REQUEST; + major_version = strtoul (version + 5, &p, 10); + if (*p != '.' || !g_ascii_isdigit (p[1])) + return SOUP_STATUS_BAD_REQUEST; + minor_version = strtoul (p + 1, &p, 10); + version_end = p; + if (major_version != 1) + return SOUP_STATUS_HTTP_VERSION_NOT_SUPPORTED; + if (minor_version > 1) + return SOUP_STATUS_HTTP_VERSION_NOT_SUPPORTED; + + headers = version_end; + while (headers < str + len && (*headers == '\r' || *headers == ' ')) + headers++; + if (headers >= str + len || *headers != '\n') + return SOUP_STATUS_BAD_REQUEST; + + if (!soup_headers_parse (str, len, req_headers)) + return SOUP_STATUS_BAD_REQUEST; + + if (soup_message_headers_get_expectations (req_headers) & + SOUP_EXPECTATION_UNRECOGNIZED) + return SOUP_STATUS_EXPECTATION_FAILED; + /* RFC 2616 14.10 */ + if (minor_version == 0) + soup_message_headers_clean_connection_headers (req_headers); + + if (req_method) + *req_method = g_strndup (method, method_end - method); + if (req_path) + *req_path = g_strndup (path, path_end - path); + if (ver) + *ver = (minor_version == 0) ? SOUP_HTTP_1_0 : SOUP_HTTP_1_1; + + return SOUP_STATUS_OK; +} + +/** + * soup_headers_parse_status_line: + * @status_line: an HTTP Status-Line + * @ver: (out) (allow-none): if non-%NULL, will be filled in with the HTTP + * version + * @status_code: (out) (allow-none): if non-%NULL, will be filled in with + * the status code + * @reason_phrase: (out) (allow-none): if non-%NULL, will be filled in with + * the reason phrase + * + * Parses the HTTP Status-Line string in @status_line into @ver, + * @status_code, and @reason_phrase. @status_line must be terminated by + * either "\0" or "\r\n". + * + * Return value: %TRUE if @status_line was parsed successfully. + **/ +gboolean +soup_headers_parse_status_line (const char *status_line, + SoupHTTPVersion *ver, + guint *status_code, + char **reason_phrase) +{ + unsigned long major_version, minor_version, code; + const char *code_start, *code_end, *phrase_start, *phrase_end; + char *p; + + g_return_val_if_fail (status_line != NULL, FALSE); + + if (strncmp (status_line, "HTTP/", 5) == 0 && + g_ascii_isdigit (status_line[5])) { + major_version = strtoul (status_line + 5, &p, 10); + if (*p != '.' || !g_ascii_isdigit (p[1])) + return FALSE; + minor_version = strtoul (p + 1, &p, 10); + if (major_version != 1) + return FALSE; + if (minor_version > 1) + return FALSE; + if (ver) + *ver = (minor_version == 0) ? SOUP_HTTP_1_0 : SOUP_HTTP_1_1; + } else if (!strncmp (status_line, "ICY", 3)) { + /* Shoutcast not-quite-HTTP format */ + if (ver) + *ver = SOUP_HTTP_1_0; + p = (char *)status_line + 3; + } else + return FALSE; + + code_start = p; + while (*code_start == ' ' || *code_start == '\t') + code_start++; + code_end = code_start; + while (*code_end >= '0' && *code_end <= '9') + code_end++; + if (code_end != code_start + 3) + return FALSE; + code = atoi (code_start); + if (code < 100 || code > 999) + return FALSE; + if (status_code) + *status_code = code; + + phrase_start = code_end; + while (*phrase_start == ' ' || *phrase_start == '\t') + phrase_start++; + phrase_end = phrase_start + strcspn (phrase_start, "\n"); + while (phrase_end > phrase_start && + (phrase_end[-1] == '\r' || phrase_end[-1] == ' ' || phrase_end[-1] == '\t')) + phrase_end--; + if (reason_phrase) + *reason_phrase = g_strndup (phrase_start, phrase_end - phrase_start); + + return TRUE; +} + +/** + * soup_headers_parse_response: + * @str: the headers (up to, but not including, the trailing blank line) + * @len: length of @str + * @headers: #SoupMessageHeaders to store the header values in + * @ver: (out) (allow-none): if non-%NULL, will be filled in with the HTTP + * version + * @status_code: (out) (allow-none): if non-%NULL, will be filled in with + * the status code + * @reason_phrase: (out) (allow-none): if non-%NULL, will be filled in with + * the reason phrase + * + * Parses the headers of an HTTP response in @str and stores the + * results in @ver, @status_code, @reason_phrase, and @headers. + * + * Beware that @headers may be modified even on failure. + * + * Return value: success or failure. + **/ +gboolean +soup_headers_parse_response (const char *str, + int len, + SoupMessageHeaders *headers, + SoupHTTPVersion *ver, + guint *status_code, + char **reason_phrase) +{ + SoupHTTPVersion version; + + g_return_val_if_fail (str != NULL, FALSE); + + /* Workaround for broken servers that send extra line breaks + * after a response, which we then see prepended to the next + * response on that connection. + */ + while ((*str == '\r' || *str == '\n') && len > 0) { + str++; + len--; + } + if (!len) + return FALSE; + + if (!soup_headers_parse (str, len, headers)) + return FALSE; + + if (!soup_headers_parse_status_line (str, + &version, + status_code, + reason_phrase)) + return FALSE; + if (ver) + *ver = version; + + /* RFC 2616 14.10 */ + if (version == SOUP_HTTP_1_0) + soup_message_headers_clean_connection_headers (headers); + + return TRUE; +} + + +/* + * Parsing of specific HTTP header types + */ + +static const char * +skip_lws (const char *s) +{ + while (g_ascii_isspace (*s)) + s++; + return s; +} + +static const char * +unskip_lws (const char *s, const char *start) +{ + while (s > start && g_ascii_isspace (*(s - 1))) + s--; + return s; +} + +static const char * +skip_delims (const char *s, char delim) +{ + /* The grammar allows for multiple delimiters */ + while (g_ascii_isspace (*s) || *s == delim) + s++; + return s; +} + +static const char * +skip_item (const char *s, char delim) +{ + gboolean quoted = FALSE; + const char *start = s; + + /* A list item ends at the last non-whitespace character + * before a delimiter which is not inside a quoted-string. Or + * at the end of the string. + */ + + while (*s) { + if (*s == '"') + quoted = !quoted; + else if (quoted) { + if (*s == '\\' && *(s + 1)) + s++; + } else { + if (*s == delim) + break; + } + s++; + } + + return unskip_lws (s, start); +} + +static GSList * +parse_list (const char *header, char delim) +{ + GSList *list = NULL; + const char *end; + + header = skip_delims (header, delim); + while (*header) { + end = skip_item (header, delim); + list = g_slist_prepend (list, g_strndup (header, end - header)); + header = skip_delims (end, delim); + } + + return g_slist_reverse (list); +} + +/** + * soup_header_parse_list: + * @header: a header value + * + * Parses a header whose content is described by RFC2616 as + * "#something", where "something" does not itself contain commas, + * except as part of quoted-strings. + * + * Return value: (transfer full) (element-type utf8): a #GSList of + * list elements, as allocated strings + **/ +GSList * +soup_header_parse_list (const char *header) +{ + g_return_val_if_fail (header != NULL, NULL); + + return parse_list (header, ','); +} + +typedef struct { + char *item; + double qval; +} QualityItem; + +static int +sort_by_qval (const void *a, const void *b) +{ + QualityItem *qia = (QualityItem *)a; + QualityItem *qib = (QualityItem *)b; + + if (qia->qval == qib->qval) + return 0; + else if (qia->qval < qib->qval) + return 1; + else + return -1; +} + +/** + * soup_header_parse_quality_list: + * @header: a header value + * @unacceptable: (out) (allow-none) (transfer full) (element-type utf8): on + * return, will contain a list of unacceptable values + * + * Parses a header whose content is a list of items with optional + * "qvalue"s (eg, Accept, Accept-Charset, Accept-Encoding, + * Accept-Language, TE). + * + * If @unacceptable is not %NULL, then on return, it will contain the + * items with qvalue 0. Either way, those items will be removed from + * the main list. + * + * Return value: (transfer full) (element-type utf8): a #GSList of + * acceptable values (as allocated strings), highest-qvalue first. + **/ +GSList * +soup_header_parse_quality_list (const char *header, GSList **unacceptable) +{ + GSList *unsorted; + QualityItem *array; + GSList *sorted, *iter; + char *item, *semi; + const char *param, *equal, *value; + double qval; + int n; + + g_return_val_if_fail (header != NULL, NULL); + + if (unacceptable) + *unacceptable = NULL; + + unsorted = soup_header_parse_list (header); + array = g_new0 (QualityItem, g_slist_length (unsorted)); + for (iter = unsorted, n = 0; iter; iter = iter->next) { + item = iter->data; + qval = 1.0; + for (semi = strchr (item, ';'); semi; semi = strchr (semi + 1, ';')) { + param = skip_lws (semi + 1); + if (*param != 'q') + continue; + equal = skip_lws (param + 1); + if (!equal || *equal != '=') + continue; + value = skip_lws (equal + 1); + if (!value) + continue; + + if (value[0] != '0' && value[0] != '1') + continue; + qval = (double)(value[0] - '0'); + if (value[0] == '0' && value[1] == '.') { + if (g_ascii_isdigit (value[2])) { + qval += (double)(value[2] - '0') / 10; + if (g_ascii_isdigit (value[3])) { + qval += (double)(value[3] - '0') / 100; + if (g_ascii_isdigit (value[4])) + qval += (double)(value[4] - '0') / 1000; + } + } + } + + *semi = '\0'; + break; + } + + if (qval == 0.0) { + if (unacceptable) { + *unacceptable = g_slist_prepend (*unacceptable, + item); + } + } else { + array[n].item = item; + array[n].qval = qval; + n++; + } + } + g_slist_free (unsorted); + + qsort (array, n, sizeof (QualityItem), sort_by_qval); + sorted = NULL; + while (n--) + sorted = g_slist_prepend (sorted, array[n].item); + g_free (array); + + return sorted; +} + +/** + * soup_header_free_list: (skip) + * @list: a #GSList returned from soup_header_parse_list() or + * soup_header_parse_quality_list() + * + * Frees @list. + **/ +void +soup_header_free_list (GSList *list) +{ + g_slist_free_full (list, g_free); +} + +/** + * soup_header_contains: + * @header: An HTTP header suitable for parsing with + * soup_header_parse_list() + * @token: a token + * + * Parses @header to see if it contains the token @token (matched + * case-insensitively). Note that this can't be used with lists + * that have qvalues. + * + * Return value: whether or not @header contains @token + **/ +gboolean +soup_header_contains (const char *header, const char *token) +{ + const char *end; + guint len; + + g_return_val_if_fail (header != NULL, FALSE); + g_return_val_if_fail (token != NULL, FALSE); + + len = strlen (token); + + header = skip_delims (header, ','); + while (*header) { + end = skip_item (header, ','); + if (end - header == len && + !g_ascii_strncasecmp (header, token, len)) + return TRUE; + header = skip_delims (end, ','); + } + + return FALSE; +} + +static void +decode_quoted_string (char *quoted_string) +{ + char *src, *dst; + + src = quoted_string + 1; + dst = quoted_string; + while (*src && *src != '"') { + if (*src == '\\' && *(src + 1)) + src++; + *dst++ = *src++; + } + *dst = '\0'; +} + +static gboolean +decode_rfc5987 (char *encoded_string) +{ + char *q, *decoded; + gboolean iso_8859_1 = FALSE; + + q = strchr (encoded_string, '\''); + if (!q) + return FALSE; + if (g_ascii_strncasecmp (encoded_string, "UTF-8", + q - encoded_string) == 0) + ; + else if (g_ascii_strncasecmp (encoded_string, "iso-8859-1", + q - encoded_string) == 0) + iso_8859_1 = TRUE; + else + return FALSE; + + q = strchr (q + 1, '\''); + if (!q) + return FALSE; + + decoded = soup_uri_decode (q + 1); + if (iso_8859_1) { + char *utf8 = g_convert_with_fallback (decoded, -1, "UTF-8", + "iso-8859-1", "_", + NULL, NULL, NULL); + g_free (decoded); + if (!utf8) + return FALSE; + decoded = utf8; + } + + /* If encoded_string was UTF-8, then each 3-character %-escape + * will be converted to a single byte, and so decoded is + * shorter than encoded_string. If encoded_string was + * iso-8859-1, then each 3-character %-escape will be + * converted into at most 2 bytes in UTF-8, and so it's still + * shorter. + */ + strcpy (encoded_string, decoded); + g_free (decoded); + return TRUE; +} + +static GHashTable * +parse_param_list (const char *header, char delim) +{ + GHashTable *params; + GSList *list, *iter; + char *item, *eq, *name_end, *value; + gboolean override; + + params = g_hash_table_new_full (soup_str_case_hash, + soup_str_case_equal, + g_free, NULL); + + list = parse_list (header, delim); + for (iter = list; iter; iter = iter->next) { + item = iter->data; + override = FALSE; + + eq = strchr (item, '='); + if (eq) { + name_end = (char *)unskip_lws (eq, item); + if (name_end == item) { + /* That's no good... */ + g_free (item); + continue; + } + + *name_end = '\0'; + + value = (char *)skip_lws (eq + 1); + + if (name_end[-1] == '*' && name_end > item + 1) { + name_end[-1] = '\0'; + if (!decode_rfc5987 (value)) { + g_free (item); + continue; + } + override = TRUE; + } else if (*value == '"') + decode_quoted_string (value); + } else + value = NULL; + + if (override || !g_hash_table_lookup (params, item)) + g_hash_table_replace (params, item, value); + else + g_free (item); + } + + g_slist_free (list); + return params; +} + +/** + * soup_header_parse_param_list: + * @header: a header value + * + * Parses a header which is a comma-delimited list of something like: + * token [ "=" ( token | quoted-string ) ]. + * + * Tokens that don't have an associated value will still be added to + * the resulting hash table, but with a %NULL value. + * + * This also handles RFC5987 encoding (which in HTTP is mostly used + * for giving UTF8-encoded filenames in the Content-Disposition + * header). + * + * Return value: (element-type utf8 utf8) (transfer full): a + * #GHashTable of list elements, which can be freed with + * soup_header_free_param_list(). + **/ +GHashTable * +soup_header_parse_param_list (const char *header) +{ + g_return_val_if_fail (header != NULL, NULL); + + return parse_param_list (header, ','); +} + +/** + * soup_header_parse_semi_param_list: + * @header: a header value + * + * Parses a header which is a semicolon-delimited list of something + * like: token [ "=" ( token | quoted-string ) ]. + * + * Tokens that don't have an associated value will still be added to + * the resulting hash table, but with a %NULL value. + * + * This also handles RFC5987 encoding (which in HTTP is mostly used + * for giving UTF8-encoded filenames in the Content-Disposition + * header). + * + * Return value: (element-type utf8 utf8) (transfer full): a + * #GHashTable of list elements, which can be freed with + * soup_header_free_param_list(). + * + * Since: 2.24 + **/ +GHashTable * +soup_header_parse_semi_param_list (const char *header) +{ + g_return_val_if_fail (header != NULL, NULL); + + return parse_param_list (header, ';'); +} + +/** + * soup_header_free_param_list: + * @param_list: (element-type utf8 utf8): a #GHashTable returned from soup_header_parse_param_list() + * or soup_header_parse_semi_param_list() + * + * Frees @param_list. + **/ +void +soup_header_free_param_list (GHashTable *param_list) +{ + g_return_if_fail (param_list != NULL); + + g_hash_table_destroy (param_list); +} + +static void +append_param_rfc5987 (GString *string, + const char *name, + const char *value) +{ + char *encoded; + + g_string_append (string, name); + g_string_append (string, "*=UTF-8''"); + encoded = soup_uri_encode (value, " *'%()<>@,;:\\\"/[]?="); + g_string_append (string, encoded); + g_free (encoded); +} + +static void +append_param_quoted (GString *string, + const char *name, + const char *value) +{ + int len; + + g_string_append (string, name); + g_string_append (string, "=\""); + while (*value) { + while (*value == '\\' || *value == '"') { + g_string_append_c (string, '\\'); + g_string_append_c (string, *value++); + } + len = strcspn (value, "\\\""); + g_string_append_len (string, value, len); + value += len; + } + g_string_append_c (string, '"'); +} + +static void +append_param_internal (GString *string, + const char *name, + const char *value, + gboolean allow_token) +{ + const char *v; + gboolean use_token = allow_token; + + for (v = value; *v; v++) { + if (*v & 0x80) { + if (g_utf8_validate (value, -1, NULL)) { + append_param_rfc5987 (string, name, value); + return; + } else { + use_token = FALSE; + break; + } + } else if (!soup_char_is_token (*v)) + use_token = FALSE; + } + + if (use_token) { + g_string_append (string, name); + g_string_append_c (string, '='); + g_string_append (string, value); + } else + append_param_quoted (string, name, value); +} + +/** + * soup_header_g_string_append_param_quoted: + * @string: a #GString being used to construct an HTTP header value + * @name: a parameter name + * @value: a parameter value + * + * Appends something like @name="@value" to + * @string, taking care to escape any quotes or backslashes in @value. + * + * If @value is (non-ASCII) UTF-8, this will instead use RFC 5987 + * encoding, just like soup_header_g_string_append_param(). + * + * Since: 2.30 + **/ +void +soup_header_g_string_append_param_quoted (GString *string, + const char *name, + const char *value) +{ + g_return_if_fail (string != NULL); + g_return_if_fail (name != NULL); + g_return_if_fail (value != NULL); + + append_param_internal (string, name, value, FALSE); +} + +/** + * soup_header_g_string_append_param: + * @string: a #GString being used to construct an HTTP header value + * @name: a parameter name + * @value: a parameter value, or %NULL + * + * Appends something like @name=@value to @string, + * taking care to quote @value if needed, and if so, to escape any + * quotes or backslashes in @value. + * + * Alternatively, if @value is a non-ASCII UTF-8 string, it will be + * appended using RFC5987 syntax. Although in theory this is supposed + * to work anywhere in HTTP that uses this style of parameter, in + * reality, it can only be used portably with the Content-Disposition + * "filename" parameter. + * + * If @value is %NULL, this will just append @name to @string. + * + * Since: 2.26 + **/ +void +soup_header_g_string_append_param (GString *string, + const char *name, + const char *value) +{ + g_return_if_fail (string != NULL); + g_return_if_fail (name != NULL); + + if (!value) { + g_string_append (string, name); + return; + } + + append_param_internal (string, name, value, TRUE); +} diff --git a/libsoup/soup-headers.h b/libsoup/soup-headers.h new file mode 100644 index 0000000..d1f3461 --- /dev/null +++ b/libsoup/soup-headers.h @@ -0,0 +1,74 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2001-2003, Ximian, Inc. + */ + +#ifndef SOUP_HEADERS_H +#define SOUP_HEADERS_H 1 + +#include +#include + +G_BEGIN_DECLS + +/* HTTP Header Parsing */ + +SOUP_AVAILABLE_IN_2_26 +gboolean soup_headers_parse (const char *str, + int len, + SoupMessageHeaders *dest); + +SOUP_AVAILABLE_IN_2_4 +guint soup_headers_parse_request (const char *str, + int len, + SoupMessageHeaders *req_headers, + char **req_method, + char **req_path, + SoupHTTPVersion *ver); + +SOUP_AVAILABLE_IN_2_4 +gboolean soup_headers_parse_status_line (const char *status_line, + SoupHTTPVersion *ver, + guint *status_code, + char **reason_phrase); + +SOUP_AVAILABLE_IN_2_4 +gboolean soup_headers_parse_response (const char *str, + int len, + SoupMessageHeaders *headers, + SoupHTTPVersion *ver, + guint *status_code, + char **reason_phrase); + +/* Individual header parsing */ +SOUP_AVAILABLE_IN_2_4 +GSList *soup_header_parse_list (const char *header); +SOUP_AVAILABLE_IN_2_4 +GSList *soup_header_parse_quality_list (const char *header, + GSList **unacceptable); +SOUP_AVAILABLE_IN_2_4 +void soup_header_free_list (GSList *list); + +SOUP_AVAILABLE_IN_2_4 +gboolean soup_header_contains (const char *header, + const char *token); + +SOUP_AVAILABLE_IN_2_4 +GHashTable *soup_header_parse_param_list (const char *header); +SOUP_AVAILABLE_IN_2_24 +GHashTable *soup_header_parse_semi_param_list (const char *header); +SOUP_AVAILABLE_IN_2_4 +void soup_header_free_param_list (GHashTable *param_list); + +SOUP_AVAILABLE_IN_2_26 +void soup_header_g_string_append_param (GString *string, + const char *name, + const char *value); +SOUP_AVAILABLE_IN_2_30 +void soup_header_g_string_append_param_quoted (GString *string, + const char *name, + const char *value); + +G_END_DECLS + +#endif /*SOUP_HEADERS_H*/ diff --git a/libsoup/soup-init.c b/libsoup/soup-init.c new file mode 100644 index 0000000..c4950ce --- /dev/null +++ b/libsoup/soup-init.c @@ -0,0 +1,82 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-session.c + * + * Copyright (C) 2000-2003, Ximian, Inc. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include "gconstructor.h" + +#ifdef G_OS_WIN32 +#define WIN32_LEAN_AND_MEAN +#include + +HMODULE soup_dll; +#endif + +static void +soup_init (void) +{ +#ifdef G_OS_WIN32 + char *basedir = g_win32_get_package_installation_directory_of_module (soup_dll); + char *localedir = g_build_filename (basedir, "share", "locale", NULL); + bindtextdomain (GETTEXT_PACKAGE, localedir); + g_free (localedir); + g_free (basedir); +#else + bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); +#endif +#ifdef HAVE_BIND_TEXTDOMAIN_CODESET + bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); +#endif +} + +#if defined (G_OS_WIN32) + +BOOL WINAPI DllMain (HINSTANCE hinstDLL, + DWORD fdwReason, + LPVOID lpvReserved); + +BOOL WINAPI +DllMain (HINSTANCE hinstDLL, + DWORD fdwReason, + LPVOID lpvReserved) +{ + switch (fdwReason) { + case DLL_PROCESS_ATTACH: + soup_dll = hinstDLL; + + soup_init (); + break; + + case DLL_THREAD_DETACH: + + default: + /* do nothing */ + ; + } + + return TRUE; +} + +#elif defined (G_HAS_CONSTRUCTORS) + +#ifdef G_DEFINE_CONSTRUCTOR_NEEDS_PRAGMA +#pragma G_DEFINE_CONSTRUCTOR_PRAGMA_ARGS(soup_init_ctor) +#endif +G_DEFINE_CONSTRUCTOR(soup_init_ctor) + +static void +soup_init_ctor (void) +{ + soup_init (); +} + +#else +# error Your platform/compiler is missing constructor support +#endif diff --git a/libsoup/soup-io-stream.c b/libsoup/soup-io-stream.c new file mode 100644 index 0000000..9c77b26 --- /dev/null +++ b/libsoup/soup-io-stream.c @@ -0,0 +1,219 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-io-stream.c + * + * Copyright 2012 Red Hat, Inc. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "soup-io-stream.h" +#include "soup.h" +#include "soup-filter-input-stream.h" + +struct _SoupIOStreamPrivate { + GIOStream *base_iostream; + gboolean close_on_dispose; + + GInputStream *istream; + GOutputStream *ostream; + gboolean disposing; +}; + +enum { + PROP_0, + + PROP_BASE_IOSTREAM, + PROP_CLOSE_ON_DISPOSE +}; + +G_DEFINE_TYPE_WITH_PRIVATE (SoupIOStream, soup_io_stream, G_TYPE_IO_STREAM) + +static void +soup_io_stream_init (SoupIOStream *stream) +{ + stream->priv = soup_io_stream_get_instance_private (stream); +} + +static void +soup_io_stream_set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + SoupIOStream *siostream = SOUP_IO_STREAM (object); + GIOStream *io; + + switch (prop_id) { + case PROP_BASE_IOSTREAM: + io = siostream->priv->base_iostream = g_value_dup_object (value); + if (io) { + siostream->priv->istream = + soup_filter_input_stream_new (g_io_stream_get_input_stream (io)); + siostream->priv->ostream = + g_object_ref (g_io_stream_get_output_stream (io)); + } else { + g_clear_object (&siostream->priv->istream); + g_clear_object (&siostream->priv->ostream); + } + break; + case PROP_CLOSE_ON_DISPOSE: + siostream->priv->close_on_dispose = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +soup_io_stream_get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + SoupIOStream *siostream = SOUP_IO_STREAM (object); + + switch (prop_id) { + case PROP_BASE_IOSTREAM: + g_value_set_object (value, siostream->priv->base_iostream); + break; + case PROP_CLOSE_ON_DISPOSE: + g_value_set_boolean (value, siostream->priv->close_on_dispose); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +soup_io_stream_dispose (GObject *object) +{ + SoupIOStream *siostream = SOUP_IO_STREAM (object); + + siostream->priv->disposing = TRUE; + + G_OBJECT_CLASS (soup_io_stream_parent_class)->dispose (object); +} + +static void +soup_io_stream_finalize (GObject *object) +{ + SoupIOStream *siostream = SOUP_IO_STREAM (object); + + g_clear_object (&siostream->priv->base_iostream); + g_clear_object (&siostream->priv->istream); + g_clear_object (&siostream->priv->ostream); + + G_OBJECT_CLASS (soup_io_stream_parent_class)->finalize (object); +} + +static GInputStream * +soup_io_stream_get_input_stream (GIOStream *stream) +{ + return SOUP_IO_STREAM (stream)->priv->istream; +} + +static GOutputStream * +soup_io_stream_get_output_stream (GIOStream *stream) +{ + return SOUP_IO_STREAM (stream)->priv->ostream; +} + + +static gboolean +soup_io_stream_close (GIOStream *stream, + GCancellable *cancellable, + GError **error) +{ + SoupIOStream *siostream = SOUP_IO_STREAM (stream); + + if (siostream->priv->disposing && + !siostream->priv->close_on_dispose) + return TRUE; + + return g_io_stream_close (siostream->priv->base_iostream, + cancellable, error); +} + +static void +close_async_complete (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + GTask *task = user_data; + GError *error = NULL; + + if (g_io_stream_close_finish (G_IO_STREAM (object), result, &error)) + g_task_return_boolean (task, TRUE); + else + g_task_return_error (task, error); + g_object_unref (task); +} + +static void +soup_io_stream_close_async (GIOStream *stream, + int io_priority, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GTask *task; + + task = g_task_new (stream, cancellable, callback, user_data); + g_io_stream_close_async (SOUP_IO_STREAM (stream)->priv->base_iostream, + io_priority, cancellable, + close_async_complete, task); +} + +static gboolean +soup_io_stream_close_finish (GIOStream *stream, + GAsyncResult *result, + GError **error) +{ + return g_task_propagate_boolean (G_TASK (result), error); +} + +static void +soup_io_stream_class_init (SoupIOStreamClass *stream_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (stream_class); + GIOStreamClass *io_stream_class = G_IO_STREAM_CLASS (stream_class); + + object_class->set_property = soup_io_stream_set_property; + object_class->get_property = soup_io_stream_get_property; + object_class->dispose = soup_io_stream_dispose; + object_class->finalize = soup_io_stream_finalize; + + io_stream_class->get_input_stream = soup_io_stream_get_input_stream; + io_stream_class->get_output_stream = soup_io_stream_get_output_stream; + io_stream_class->close_fn = soup_io_stream_close; + io_stream_class->close_async = soup_io_stream_close_async; + io_stream_class->close_finish = soup_io_stream_close_finish; + + g_object_class_install_property ( + object_class, PROP_BASE_IOSTREAM, + g_param_spec_object ("base-iostream", + "Base IOStream", + "Base GIOStream", + G_TYPE_IO_STREAM, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); + g_object_class_install_property ( + object_class, PROP_CLOSE_ON_DISPOSE, + g_param_spec_boolean ("close-on-dispose", + "Close base stream", + "Close base GIOStream when closing", + TRUE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); +} + +GIOStream * +soup_io_stream_new (GIOStream *base_iostream, + gboolean close_on_dispose) +{ + return g_object_new (SOUP_TYPE_IO_STREAM, + "base-iostream", base_iostream, + "close-on-dispose", close_on_dispose, + NULL); +} diff --git a/libsoup/soup-io-stream.h b/libsoup/soup-io-stream.h new file mode 100644 index 0000000..92c24c3 --- /dev/null +++ b/libsoup/soup-io-stream.h @@ -0,0 +1,40 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright 2012 Red Hat, Inc. + */ + +#ifndef __SOUP_IO_STREAM_H__ +#define __SOUP_IO_STREAM_H__ 1 + +#include + +G_BEGIN_DECLS + +#define SOUP_TYPE_IO_STREAM (soup_io_stream_get_type ()) +#define SOUP_IO_STREAM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SOUP_TYPE_IO_STREAM, SoupIOStream)) +#define SOUP_IO_STREAM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_IO_STREAM, SoupIOStreamClass)) +#define SOUP_IS_IO_STREAM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SOUP_TYPE_IO_STREAM)) +#define SOUP_IS_IO_STREAM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), SOUP_TYPE_IO_STREAM)) +#define SOUP_IO_STREAM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_IO_STREAM, SoupIOStreamClass)) + +typedef struct _SoupIOStreamPrivate SoupIOStreamPrivate; + +typedef struct { + GIOStream parent; + + SoupIOStreamPrivate *priv; +} SoupIOStream; + +typedef struct { + GIOStreamClass parent_class; + +} SoupIOStreamClass; + +GType soup_io_stream_get_type (void); + +GIOStream *soup_io_stream_new (GIOStream *base_iostream, + gboolean close_on_dispose); + +G_END_DECLS + +#endif /* __SOUP_IO_STREAM_H__ */ diff --git a/libsoup/soup-logger.c b/libsoup/soup-logger.c new file mode 100644 index 0000000..261ec8d --- /dev/null +++ b/libsoup/soup-logger.c @@ -0,0 +1,842 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-logger.c + * + * Copyright (C) 2001-2004 Novell, Inc. + * Copyright (C) 2008 Red Hat, Inc. + * Copyright (C) 2013 Igalia, S.L. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include "soup-logger.h" +#include "soup-connection.h" +#include "soup-message-private.h" +#include "soup.h" + +/** + * SECTION:soup-logger + * @short_description: Debug logging support + * + * #SoupLogger watches a #SoupSession and logs the HTTP traffic that + * it generates, for debugging purposes. Many applications use an + * environment variable to determine whether or not to use + * #SoupLogger, and to determine the amount of debugging output. + * + * To use #SoupLogger, first create a logger with soup_logger_new(), + * optionally configure it with soup_logger_set_request_filter(), + * soup_logger_set_response_filter(), and soup_logger_set_printer(), + * and then attach it to a session (or multiple sessions) with + * soup_session_add_feature(). + * + * By default, the debugging output is sent to + * stdout, and looks something like: + * + * + * > POST /unauth HTTP/1.1 + * > Soup-Debug-Timestamp: 1200171744 + * > Soup-Debug: SoupSessionAsync 1 (0x612190), SoupMessage 1 (0x617000), SoupSocket 1 (0x612220) + * > Host: localhost + * > Content-Type: text/plain + * > Connection: close + * > + * > This is a test. + * + * < HTTP/1.1 201 Created + * < Soup-Debug-Timestamp: 1200171744 + * < Soup-Debug: SoupMessage 1 (0x617000) + * < Date: Sun, 12 Jan 2008 21:02:24 GMT + * < Content-Length: 0 + * + * + * The Soup-Debug-Timestamp line gives the time (as + * a time_t) when the request was sent, or the response fully + * received. + * + * The Soup-Debug line gives further debugging + * information about the #SoupSession, #SoupMessage, and #SoupSocket + * involved; the hex numbers are the addresses of the objects in + * question (which may be useful if you are running in a debugger). + * The decimal IDs are simply counters that uniquely identify objects + * across the lifetime of the #SoupLogger. In particular, this can be + * used to identify when multiple messages are sent across the same + * connection. + * + * Currently, the request half of the message is logged just before + * the first byte of the request gets written to the network (from the + * #SoupMessage::starting signal), which means that if you have + * not made the complete request body available at that point, it will + * not be logged. + * + * The response is logged just after the last byte of the response + * body is read from the network (from the #SoupMessage::got_body or + * #SoupMessage::got_informational signal), which means that the + * #SoupMessage::got_headers signal, and anything triggered off it + * (such as #SoupSession::authenticate) will be emitted + * before the response headers are actually + * logged. + * + * If the response doesn't happen to trigger the + * #SoupMessage::got_body nor #SoupMessage::got_informational signals + * due to, for example, a cancellation before receiving the last byte + * of the response body, the response will still be logged on the + * event of the #SoupMessage::finished signal. + **/ + +typedef struct { + /* We use a mutex so that if requests are being run in + * multiple threads, we don't mix up the output. + */ + GMutex lock; + + GQuark tag; + GHashTable *ids; + + SoupSession *session; + SoupLoggerLogLevel level; + int max_body_size; + + SoupLoggerFilter request_filter; + gpointer request_filter_data; + GDestroyNotify request_filter_dnotify; + + SoupLoggerFilter response_filter; + gpointer response_filter_data; + GDestroyNotify response_filter_dnotify; + + SoupLoggerPrinter printer; + gpointer printer_data; + GDestroyNotify printer_dnotify; +} SoupLoggerPrivate; + +enum { + PROP_0, + + PROP_LEVEL, + PROP_MAX_BODY_SIZE, + + LAST_PROP +}; + +static SoupSessionFeatureInterface *soup_logger_default_feature_interface; +static void soup_logger_session_feature_init (SoupSessionFeatureInterface *feature_interface, gpointer interface_data); + +G_DEFINE_TYPE_WITH_CODE (SoupLogger, soup_logger, G_TYPE_OBJECT, + G_ADD_PRIVATE (SoupLogger) + G_IMPLEMENT_INTERFACE (SOUP_TYPE_SESSION_FEATURE, + soup_logger_session_feature_init)) + +static void +soup_logger_init (SoupLogger *logger) +{ + SoupLoggerPrivate *priv = soup_logger_get_instance_private (logger); + + g_mutex_init (&priv->lock); + priv->tag = g_quark_from_static_string (g_strdup_printf ("SoupLogger-%p", logger)); + priv->ids = g_hash_table_new (NULL, NULL); +} + +static void +soup_logger_finalize (GObject *object) +{ + SoupLogger *logger = SOUP_LOGGER (object); + SoupLoggerPrivate *priv = soup_logger_get_instance_private (logger); + + g_hash_table_destroy (priv->ids); + + if (priv->request_filter_dnotify) + priv->request_filter_dnotify (priv->request_filter_data); + if (priv->response_filter_dnotify) + priv->response_filter_dnotify (priv->response_filter_data); + if (priv->printer_dnotify) + priv->printer_dnotify (priv->printer_data); + + g_mutex_clear (&priv->lock); + + G_OBJECT_CLASS (soup_logger_parent_class)->finalize (object); +} + +static void +soup_logger_set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + SoupLogger *logger = SOUP_LOGGER (object); + SoupLoggerPrivate *priv = soup_logger_get_instance_private (logger); + + switch (prop_id) { + case PROP_LEVEL: + priv->level = g_value_get_enum (value); + break; + case PROP_MAX_BODY_SIZE: + priv->max_body_size = g_value_get_int (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +soup_logger_get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + SoupLogger *logger = SOUP_LOGGER (object); + SoupLoggerPrivate *priv = soup_logger_get_instance_private (logger); + + switch (prop_id) { + case PROP_LEVEL: + g_value_set_enum (value, priv->level); + break; + case PROP_MAX_BODY_SIZE: + g_value_set_int (value, priv->max_body_size); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +soup_logger_class_init (SoupLoggerClass *logger_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (logger_class); + + object_class->finalize = soup_logger_finalize; + object_class->set_property = soup_logger_set_property; + object_class->get_property = soup_logger_get_property; + + /* properties */ + /** + * SoupLogger:level: + * + * The level of logging output + * + * Since: 2.56 + */ + /** + * SOUP_LOGGER_LEVEL: + * + * Alias for the #SoupLogger:level property, qv. + * + * Since: 2.56 + **/ + g_object_class_install_property ( + object_class, PROP_LEVEL, + g_param_spec_enum (SOUP_LOGGER_LEVEL, + "Level", + "The level of logging output", + SOUP_TYPE_LOGGER_LOG_LEVEL, + SOUP_LOGGER_LOG_MINIMAL, + G_PARAM_READWRITE)); + + /** + * SoupLogger:max-body-size: + * + * If #SoupLogger:level is %SOUP_LOGGER_LOG_BODY, this gives + * the maximum number of bytes of the body that will be logged. + * (-1 means "no limit".) + * + * Since: 2.56 + */ + /** + * SOUP_LOGGER_MAX_BODY_SIZE: + * + * Alias for the #SoupLogger:max-body-size property, qv. + * + * Since: 2.56 + **/ + g_object_class_install_property ( + object_class, PROP_MAX_BODY_SIZE, + g_param_spec_int (SOUP_LOGGER_MAX_BODY_SIZE, + "Max Body Size", + "The maximum body size to output", + -1, + G_MAXINT, + -1, + G_PARAM_READWRITE)); +} + +/** + * SoupLoggerLogLevel: + * @SOUP_LOGGER_LOG_NONE: No logging + * @SOUP_LOGGER_LOG_MINIMAL: Log the Request-Line or Status-Line and + * the Soup-Debug pseudo-headers + * @SOUP_LOGGER_LOG_HEADERS: Log the full request/response headers + * @SOUP_LOGGER_LOG_BODY: Log the full headers and request/response + * bodies. + * + * Describes the level of logging output to provide. + **/ + +/** + * soup_logger_new: + * @level: the debug level + * @max_body_size: the maximum body size to output, or -1 + * + * Creates a new #SoupLogger with the given debug level. If @level is + * %SOUP_LOGGER_LOG_BODY, @max_body_size gives the maximum number of + * bytes of the body that will be logged. (-1 means "no limit".) + * + * If you need finer control over what message parts are and aren't + * logged, use soup_logger_set_request_filter() and + * soup_logger_set_response_filter(). + * + * Returns: a new #SoupLogger + **/ +SoupLogger * +soup_logger_new (SoupLoggerLogLevel level, int max_body_size) +{ + return g_object_new (SOUP_TYPE_LOGGER, + SOUP_LOGGER_LEVEL, level, + SOUP_LOGGER_MAX_BODY_SIZE, max_body_size, + NULL); +} + +/** + * SoupLoggerFilter: + * @logger: the #SoupLogger + * @msg: the message being logged + * @user_data: the data passed to soup_logger_set_request_filter() + * or soup_logger_set_response_filter() + * + * The prototype for a logging filter. The filter callback will be + * invoked for each request or response, and should analyze it and + * return a #SoupLoggerLogLevel value indicating how much of the + * message to log. Eg, it might choose between %SOUP_LOGGER_LOG_BODY + * and %SOUP_LOGGER_LOG_HEADERS depending on the Content-Type. + * + * Return value: a #SoupLoggerLogLevel value indicating how much of + * the message to log + **/ + +/** + * soup_logger_set_request_filter: + * @logger: a #SoupLogger + * @request_filter: the callback for request debugging + * @filter_data: data to pass to the callback + * @destroy: a #GDestroyNotify to free @filter_data + * + * Sets up a filter to determine the log level for a given request. + * For each HTTP request @logger will invoke @request_filter to + * determine how much (if any) of that request to log. (If you do not + * set a request filter, @logger will just always log requests at the + * level passed to soup_logger_new().) + **/ +void +soup_logger_set_request_filter (SoupLogger *logger, + SoupLoggerFilter request_filter, + gpointer filter_data, + GDestroyNotify destroy) +{ + SoupLoggerPrivate *priv = soup_logger_get_instance_private (logger); + + priv->request_filter = request_filter; + priv->request_filter_data = filter_data; + priv->request_filter_dnotify = destroy; +} + +/** + * soup_logger_set_response_filter: + * @logger: a #SoupLogger + * @response_filter: the callback for response debugging + * @filter_data: data to pass to the callback + * @destroy: a #GDestroyNotify to free @filter_data + * + * Sets up a filter to determine the log level for a given response. + * For each HTTP response @logger will invoke @response_filter to + * determine how much (if any) of that response to log. (If you do not + * set a response filter, @logger will just always log responses at + * the level passed to soup_logger_new().) + **/ +void +soup_logger_set_response_filter (SoupLogger *logger, + SoupLoggerFilter response_filter, + gpointer filter_data, + GDestroyNotify destroy) +{ + SoupLoggerPrivate *priv = soup_logger_get_instance_private (logger); + + priv->response_filter = response_filter; + priv->response_filter_data = filter_data; + priv->response_filter_dnotify = destroy; +} + +/** + * SoupLoggerPrinter: + * @logger: the #SoupLogger + * @level: the level of the information being printed. + * @direction: a single-character prefix to @data + * @data: data to print + * @user_data: the data passed to soup_logger_set_printer() + * + * The prototype for a custom printing callback. + * + * @level indicates what kind of information is being printed. Eg, it + * will be %SOUP_LOGGER_LOG_HEADERS if @data is header data. + * + * @direction is either '<', '>', or ' ', and @data is the single line + * to print; the printer is expected to add a terminating newline. + * + * To get the effect of the default printer, you would do: + * + * + * printf ("%c %s\n", direction, data); + * + **/ + +/** + * soup_logger_set_printer: + * @logger: a #SoupLogger + * @printer: the callback for printing logging output + * @printer_data: data to pass to the callback + * @destroy: a #GDestroyNotify to free @printer_data + * + * Sets up an alternate log printing routine, if you don't want + * the log to go to stdout. + **/ +void +soup_logger_set_printer (SoupLogger *logger, + SoupLoggerPrinter printer, + gpointer printer_data, + GDestroyNotify destroy) +{ + SoupLoggerPrivate *priv = soup_logger_get_instance_private (logger); + + priv->printer = printer; + priv->printer_data = printer_data; + priv->printer_dnotify = destroy; +} + +static guint +soup_logger_get_id (SoupLogger *logger, gpointer object) +{ + SoupLoggerPrivate *priv = soup_logger_get_instance_private (logger); + + return GPOINTER_TO_UINT (g_object_get_qdata (object, priv->tag)); +} + +static guint +soup_logger_set_id (SoupLogger *logger, gpointer object) +{ + SoupLoggerPrivate *priv = soup_logger_get_instance_private (logger); + gpointer klass = G_OBJECT_GET_CLASS (object); + gpointer id; + + id = g_hash_table_lookup (priv->ids, klass); + id = (char *)id + 1; + g_hash_table_insert (priv->ids, klass, id); + + g_object_set_qdata (object, priv->tag, id); + return GPOINTER_TO_UINT (id); +} + +/** + * soup_logger_attach: + * @logger: a #SoupLogger + * @session: a #SoupSession + * + * Sets @logger to watch @session and print debug information for + * its messages. + * + * (The session will take a reference on @logger, which will be + * removed when you call soup_logger_detach(), or when the session is + * destroyed.) + * + * Deprecated: Use soup_session_add_feature() instead. + **/ +void +soup_logger_attach (SoupLogger *logger, + SoupSession *session) +{ + soup_session_add_feature (session, SOUP_SESSION_FEATURE (logger)); +} + +/** + * soup_logger_detach: + * @logger: a #SoupLogger + * @session: a #SoupSession + * + * Stops @logger from watching @session. + * + * Deprecated: Use soup_session_remove_feature() instead. + **/ +void +soup_logger_detach (SoupLogger *logger, + SoupSession *session) +{ + soup_session_remove_feature (session, SOUP_SESSION_FEATURE (logger)); +} + +static void soup_logger_print (SoupLogger *logger, SoupLoggerLogLevel level, + char direction, const char *format, ...) G_GNUC_PRINTF (4, 5); + +static void +soup_logger_print (SoupLogger *logger, SoupLoggerLogLevel level, + char direction, const char *format, ...) +{ + SoupLoggerPrivate *priv = soup_logger_get_instance_private (logger); + va_list args; + char *data, *line, *end; + + va_start (args, format); + data = g_strdup_vprintf (format, args); + va_end (args); + + if (level == SOUP_LOGGER_LOG_BODY && priv->max_body_size > 0) { + if (strlen (data) > priv->max_body_size + 6) + strcpy (data + priv->max_body_size, "\n[...]"); + } + + line = data; + do { + end = strchr (line, '\n'); + if (end) + *end = '\0'; + if (priv->printer) { + priv->printer (logger, level, direction, + line, priv->printer_data); + } else + printf ("%c %s\n", direction, line); + + line = end + 1; + } while (end && *line); + + g_free (data); +} + +static void +soup_logger_print_basic_auth (SoupLogger *logger, const char *value) +{ + char *decoded, *decoded_utf8, *p; + gsize len; + + decoded = (char *)g_base64_decode (value + 6, &len); + if (decoded && !g_utf8_validate (decoded, -1, NULL)) { + decoded_utf8 = g_convert_with_fallback (decoded, -1, + "UTF-8", "ISO-8859-1", + NULL, NULL, &len, + NULL); + if (decoded_utf8) { + g_free (decoded); + decoded = decoded_utf8; + } + } + + if (!decoded) + decoded = g_strdup (value); + p = strchr (decoded, ':'); + if (p) { + while (++p < decoded + len) + *p = '*'; + } + soup_logger_print (logger, SOUP_LOGGER_LOG_HEADERS, '>', + "Authorization: Basic [%.*s]", (int)len, decoded); + g_free (decoded); +} + +static void +print_request (SoupLogger *logger, SoupMessage *msg, + SoupSocket *socket, gboolean restarted) +{ + SoupLoggerPrivate *priv = soup_logger_get_instance_private (logger); + SoupLoggerLogLevel log_level; + SoupMessageHeadersIter iter; + const char *name, *value; + char *socket_dbg; + SoupURI *uri; + + if (priv->request_filter) { + log_level = priv->request_filter (logger, msg, + priv->request_filter_data); + } else + log_level = priv->level; + + if (log_level == SOUP_LOGGER_LOG_NONE) + return; + + uri = soup_message_get_uri (msg); + if (msg->method == SOUP_METHOD_CONNECT) { + soup_logger_print (logger, SOUP_LOGGER_LOG_MINIMAL, '>', + "CONNECT %s:%u HTTP/1.%d", + uri->host, uri->port, + soup_message_get_http_version (msg)); + } else { + soup_logger_print (logger, SOUP_LOGGER_LOG_MINIMAL, '>', + "%s %s%s%s HTTP/1.%d", + msg->method, uri->path, + uri->query ? "?" : "", + uri->query ? uri->query : "", + soup_message_get_http_version (msg)); + } + + soup_logger_print (logger, SOUP_LOGGER_LOG_MINIMAL, '>', + "Soup-Debug-Timestamp: %lu", + (unsigned long)time (0)); + + socket_dbg = socket ? + g_strdup_printf ("%s %u (%p)", + g_type_name_from_instance ((GTypeInstance *)socket), + soup_logger_get_id (logger, socket), socket) + : NULL; + + soup_logger_print (logger, SOUP_LOGGER_LOG_MINIMAL, '>', + "Soup-Debug: %s %u (%p), %s %u (%p), %s%s", + g_type_name_from_instance ((GTypeInstance *)priv->session), + soup_logger_get_id (logger, priv->session), priv->session, + g_type_name_from_instance ((GTypeInstance *)msg), + soup_logger_get_id (logger, msg), msg, + socket_dbg ? socket_dbg : "cached", + restarted ? ", restarted" : ""); + g_free (socket_dbg); + + if (log_level == SOUP_LOGGER_LOG_MINIMAL) + return; + + if (!soup_message_headers_get_one (msg->request_headers, "Host")) { + char *uri_host; + + if (strchr (uri->host, ':')) + uri_host = g_strdup_printf ("[%s]", uri->host); + else if (g_hostname_is_non_ascii (uri->host)) + uri_host = g_hostname_to_ascii (uri->host); + else + uri_host = uri->host; + + soup_logger_print (logger, SOUP_LOGGER_LOG_HEADERS, '>', + "Host: %s%c%u", uri_host, + soup_uri_uses_default_port (uri) ? '\0' : ':', + uri->port); + + if (uri_host != uri->host) + g_free (uri_host); + } + soup_message_headers_iter_init (&iter, msg->request_headers); + while (soup_message_headers_iter_next (&iter, &name, &value)) { + if (!g_ascii_strcasecmp (name, "Authorization") && + !g_ascii_strncasecmp (value, "Basic ", 6)) + soup_logger_print_basic_auth (logger, value); + else { + soup_logger_print (logger, SOUP_LOGGER_LOG_HEADERS, '>', + "%s: %s", name, value); + } + } + if (log_level == SOUP_LOGGER_LOG_HEADERS) + return; + + if (msg->request_body->length && + soup_message_body_get_accumulate (msg->request_body)) { + SoupBuffer *request; + + request = soup_message_body_flatten (msg->request_body); + g_return_if_fail (request != NULL); + soup_buffer_free (request); + + if (soup_message_headers_get_expectations (msg->request_headers) != SOUP_EXPECTATION_CONTINUE) { + soup_logger_print (logger, SOUP_LOGGER_LOG_BODY, '>', + "\n%s", msg->request_body->data); + } + } +} + +static void +print_response (SoupLogger *logger, SoupMessage *msg) +{ + SoupLoggerPrivate *priv = soup_logger_get_instance_private (logger); + SoupLoggerLogLevel log_level; + SoupMessageHeadersIter iter; + const char *name, *value; + + if (priv->response_filter) { + log_level = priv->response_filter (logger, msg, + priv->response_filter_data); + } else + log_level = priv->level; + + if (log_level == SOUP_LOGGER_LOG_NONE) + return; + + soup_logger_print (logger, SOUP_LOGGER_LOG_MINIMAL, '<', + "HTTP/1.%d %u %s\n", + soup_message_get_http_version (msg), + msg->status_code, msg->reason_phrase); + + soup_logger_print (logger, SOUP_LOGGER_LOG_MINIMAL, '<', + "Soup-Debug-Timestamp: %lu", + (unsigned long)time (0)); + soup_logger_print (logger, SOUP_LOGGER_LOG_MINIMAL, '<', + "Soup-Debug: %s %u (%p)", + g_type_name_from_instance ((GTypeInstance *)msg), + soup_logger_get_id (logger, msg), msg); + + if (log_level == SOUP_LOGGER_LOG_MINIMAL) + return; + + soup_message_headers_iter_init (&iter, msg->response_headers); + while (soup_message_headers_iter_next (&iter, &name, &value)) { + soup_logger_print (logger, SOUP_LOGGER_LOG_HEADERS, '<', + "%s: %s", name, value); + } + if (log_level == SOUP_LOGGER_LOG_HEADERS) + return; + + if (msg->response_body->data) { + soup_logger_print (logger, SOUP_LOGGER_LOG_BODY, '<', + "\n%s", msg->response_body->data); + } +} + +static void +finished (SoupMessage *msg, gpointer user_data) +{ + SoupLogger *logger = user_data; + SoupLoggerPrivate *priv = soup_logger_get_instance_private (logger); + + g_mutex_lock (&priv->lock); + + print_response (logger, msg); + soup_logger_print (logger, SOUP_LOGGER_LOG_MINIMAL, ' ', "\n"); + + g_mutex_unlock (&priv->lock); +} + +static void +got_informational (SoupMessage *msg, gpointer user_data) +{ + SoupLogger *logger = user_data; + SoupLoggerPrivate *priv = soup_logger_get_instance_private (logger); + + g_mutex_lock (&priv->lock); + + g_signal_handlers_disconnect_by_func (msg, finished, logger); + print_response (logger, msg); + soup_logger_print (logger, SOUP_LOGGER_LOG_MINIMAL, ' ', "\n"); + + if (msg->status_code == SOUP_STATUS_CONTINUE && msg->request_body->data) { + SoupLoggerLogLevel log_level; + + soup_logger_print (logger, SOUP_LOGGER_LOG_MINIMAL, '>', + "[Now sending request body...]"); + + if (priv->request_filter) { + log_level = priv->request_filter (logger, msg, + priv->request_filter_data); + } else + log_level = priv->level; + + if (log_level == SOUP_LOGGER_LOG_BODY) { + soup_logger_print (logger, SOUP_LOGGER_LOG_BODY, '>', + "%s", msg->request_body->data); + } + + soup_logger_print (logger, SOUP_LOGGER_LOG_MINIMAL, ' ', "\n"); + } + + g_mutex_unlock (&priv->lock); +} + +static void +got_body (SoupMessage *msg, gpointer user_data) +{ + SoupLogger *logger = user_data; + SoupLoggerPrivate *priv = soup_logger_get_instance_private (logger); + + g_mutex_lock (&priv->lock); + + g_signal_handlers_disconnect_by_func (msg, finished, logger); + print_response (logger, msg); + soup_logger_print (logger, SOUP_LOGGER_LOG_MINIMAL, ' ', "\n"); + + g_mutex_unlock (&priv->lock); +} + +static void +starting (SoupMessage *msg, gpointer user_data) +{ + SoupLogger *logger = SOUP_LOGGER (user_data); + SoupLoggerPrivate *priv = soup_logger_get_instance_private (logger); + gboolean restarted; + guint msg_id; + SoupConnection *conn; + SoupSocket *socket; + + msg_id = soup_logger_get_id (logger, msg); + if (msg_id) + restarted = TRUE; + else { + soup_logger_set_id (logger, msg); + restarted = FALSE; + } + + if (!soup_logger_get_id (logger, priv->session)) + soup_logger_set_id (logger, priv->session); + + conn = soup_message_get_connection (msg); + socket = conn ? soup_connection_get_socket (conn) : NULL; + if (socket && !soup_logger_get_id (logger, socket)) + soup_logger_set_id (logger, socket); + + print_request (logger, msg, socket, restarted); + soup_logger_print (logger, SOUP_LOGGER_LOG_MINIMAL, ' ', "\n"); +} + +static void +soup_logger_request_queued (SoupSessionFeature *logger, + SoupSession *session, + SoupMessage *msg) +{ + g_return_if_fail (SOUP_IS_MESSAGE (msg)); + + g_signal_connect (msg, "starting", + G_CALLBACK (starting), + logger); + g_signal_connect (msg, "got-informational", + G_CALLBACK (got_informational), + logger); + g_signal_connect (msg, "got-body", + G_CALLBACK (got_body), + logger); + g_signal_connect (msg, "finished", + G_CALLBACK (finished), + logger); +} + +static void +soup_logger_request_unqueued (SoupSessionFeature *logger, + SoupSession *session, + SoupMessage *msg) +{ + g_return_if_fail (SOUP_IS_MESSAGE (msg)); + + g_signal_handlers_disconnect_by_func (msg, starting, logger); + g_signal_handlers_disconnect_by_func (msg, got_informational, logger); + g_signal_handlers_disconnect_by_func (msg, got_body, logger); + g_signal_handlers_disconnect_by_func (msg, finished, logger); +} + +static void +soup_logger_feature_attach (SoupSessionFeature *feature, + SoupSession *session) +{ + SoupLoggerPrivate *priv = soup_logger_get_instance_private (SOUP_LOGGER (feature)); + + priv->session = session; + + soup_logger_default_feature_interface->attach (feature, session); +} + +static void +soup_logger_session_feature_init (SoupSessionFeatureInterface *feature_interface, + gpointer interface_data) +{ + soup_logger_default_feature_interface = + g_type_default_interface_peek (SOUP_TYPE_SESSION_FEATURE); + + feature_interface->attach = soup_logger_feature_attach; + feature_interface->request_queued = soup_logger_request_queued; + feature_interface->request_unqueued = soup_logger_request_unqueued; +} diff --git a/libsoup/soup-logger.h b/libsoup/soup-logger.h new file mode 100644 index 0000000..df4a347 --- /dev/null +++ b/libsoup/soup-logger.h @@ -0,0 +1,92 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2008 Red Hat, Inc. + */ + +#ifndef SOUP_LOGGER_H +#define SOUP_LOGGER_H 1 + +#include + +G_BEGIN_DECLS + +#define SOUP_TYPE_LOGGER (soup_logger_get_type ()) +#define SOUP_LOGGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SOUP_TYPE_LOGGER, SoupLogger)) +#define SOUP_LOGGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_LOGGER, SoupLoggerClass)) +#define SOUP_IS_LOGGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SOUP_TYPE_LOGGER)) +#define SOUP_IS_LOGGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), SOUP_TYPE_LOGGER)) +#define SOUP_LOGGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_LOGGER, SoupLoggerClass)) + +typedef enum { + SOUP_LOGGER_LOG_NONE, + SOUP_LOGGER_LOG_MINIMAL, + SOUP_LOGGER_LOG_HEADERS, + SOUP_LOGGER_LOG_BODY +} SoupLoggerLogLevel; + +typedef struct { + GObject parent; + +} SoupLogger; + +typedef struct { + GObjectClass parent_class; + + /* Padding for future expansion */ + void (*_libsoup_reserved1) (void); + void (*_libsoup_reserved2) (void); + void (*_libsoup_reserved3) (void); + void (*_libsoup_reserved4) (void); +} SoupLoggerClass; + +typedef SoupLoggerLogLevel (*SoupLoggerFilter) (SoupLogger *logger, + SoupMessage *msg, + gpointer user_data); + +typedef void (*SoupLoggerPrinter) (SoupLogger *logger, + SoupLoggerLogLevel level, + char direction, + const char *data, + gpointer user_data); + +SOUP_AVAILABLE_IN_2_4 +GType soup_logger_get_type (void); + +#define SOUP_LOGGER_LEVEL "level" +#define SOUP_LOGGER_MAX_BODY_SIZE "max-body-size" + +SOUP_AVAILABLE_IN_2_4 +SoupLogger *soup_logger_new (SoupLoggerLogLevel level, + int max_body_size); + +#ifndef SOUP_DISABLE_DEPRECATED +SOUP_AVAILABLE_IN_2_4 +SOUP_DEPRECATED_IN_2_24_FOR(soup_session_add_feature) +void soup_logger_attach (SoupLogger *logger, + SoupSession *session); +SOUP_AVAILABLE_IN_2_4 +SOUP_DEPRECATED_IN_2_24_FOR(soup_session_remove_feature) +void soup_logger_detach (SoupLogger *logger, + SoupSession *session); +#endif + +SOUP_AVAILABLE_IN_2_4 +void soup_logger_set_request_filter (SoupLogger *logger, + SoupLoggerFilter request_filter, + gpointer filter_data, + GDestroyNotify destroy); +SOUP_AVAILABLE_IN_2_4 +void soup_logger_set_response_filter (SoupLogger *logger, + SoupLoggerFilter response_filter, + gpointer filter_data, + GDestroyNotify destroy); + +SOUP_AVAILABLE_IN_2_4 +void soup_logger_set_printer (SoupLogger *logger, + SoupLoggerPrinter printer, + gpointer printer_data, + GDestroyNotify destroy); + +G_END_DECLS + +#endif /* SOUP_LOGGER_H */ diff --git a/libsoup/soup-message-body.c b/libsoup/soup-message-body.c new file mode 100644 index 0000000..0c45e18 --- /dev/null +++ b/libsoup/soup-message-body.c @@ -0,0 +1,752 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-message-body.c: SoupMessage request/response bodies + * + * Copyright (C) 2000-2003, Ximian, Inc. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "soup-message-body.h" +#include "soup.h" + +/** + * SECTION:soup-message-body + * @short_description: HTTP message body + * @see_also: #SoupMessage + * + * #SoupMessageBody represents the request or response body of a + * #SoupMessage. + * + * In addition to #SoupMessageBody, libsoup also defines a "smaller" + * data buffer type, #SoupBuffer, which is primarily used as a + * component of #SoupMessageBody. In particular, when using chunked + * encoding to transmit or receive a message, each chunk is + * represented as a #SoupBuffer. + **/ + +/** + * SoupMemoryUse: + * @SOUP_MEMORY_STATIC: The memory is statically allocated and + * constant; libsoup can use the passed-in buffer directly and not + * need to worry about it being modified or freed. + * @SOUP_MEMORY_TAKE: The caller has allocated the memory for the + * #SoupBuffer's use; libsoup will assume ownership of it and free it + * (with g_free()) when it is done with it. + * @SOUP_MEMORY_COPY: The passed-in data belongs to the caller; the + * #SoupBuffer will copy it into new memory, leaving the caller free + * to reuse the original memory. + * @SOUP_MEMORY_TEMPORARY: The passed-in data belongs to the caller, + * but will remain valid for the lifetime of the #SoupBuffer. The + * difference between this and @SOUP_MEMORY_STATIC is that if you copy + * a @SOUP_MEMORY_TEMPORARY buffer, it will make a copy of the memory + * as well, rather than reusing the original memory. + * + * Describes how #SoupBuffer should use the data passed in by the + * caller. + * + * See also soup_buffer_new_with_owner(), which allows to you create a + * buffer containing data which is owned by another object. + **/ + +/* Internal SoupMemoryUse values */ +enum { + SOUP_MEMORY_SUBBUFFER = SOUP_MEMORY_TEMPORARY + 1, + SOUP_MEMORY_OWNED +}; + +/** + * SoupBuffer: + * @data: (type gpointer): the data + * @length: length of @data + * + * A data buffer, generally used to represent a chunk of a + * #SoupMessageBody. + * + * @data is a #char because that's generally convenient; in some + * situations you may need to cast it to #guchar or another type. + **/ + +typedef struct { + SoupBuffer buffer; + SoupMemoryUse use; + guint refcount; + + gpointer owner; + GDestroyNotify owner_dnotify; +} SoupBufferPrivate; + +/** + * soup_buffer_new: + * @use: how @data is to be used by the buffer + * @data: (array length=length) (element-type guint8): data + * @length: length of @data + * + * Creates a new #SoupBuffer containing @length bytes from @data. + * + * Return value: the new #SoupBuffer. + **/ +SoupBuffer * +soup_buffer_new (SoupMemoryUse use, gconstpointer data, gsize length) +{ + SoupBufferPrivate *priv = g_slice_new0 (SoupBufferPrivate); + + if (use == SOUP_MEMORY_COPY) { + data = g_memdup (data, length); + use = SOUP_MEMORY_TAKE; + } + + priv->buffer.data = data; + priv->buffer.length = length; + priv->use = use; + priv->refcount = 1; + + if (use == SOUP_MEMORY_TAKE) { + priv->owner = (gpointer)data; + priv->owner_dnotify = g_free; + } + + return (SoupBuffer *)priv; +} + +/** + * soup_buffer_new_take: (rename-to soup_buffer_new) + * @data: (array length=length) (transfer full): data + * @length: length of @data + * + * Creates a new #SoupBuffer containing @length bytes from @data. + * + * This function is exactly equivalent to soup_buffer_new() with + * %SOUP_MEMORY_TAKE as first argument; it exists mainly for + * convenience and simplifying language bindings. + * + * Return value: the new #SoupBuffer. + * + * Since: 2.32 + **/ +SoupBuffer * +soup_buffer_new_take (guchar *data, gsize length) +{ + return soup_buffer_new (SOUP_MEMORY_TAKE, data, length); +} + +/** + * soup_buffer_new_subbuffer: + * @parent: the parent #SoupBuffer + * @offset: offset within @parent to start at + * @length: number of bytes to copy from @parent + * + * Creates a new #SoupBuffer containing @length bytes "copied" from + * @parent starting at @offset. (Normally this will not actually copy + * any data, but will instead simply reference the same data as + * @parent does.) + * + * Return value: the new #SoupBuffer. + **/ +SoupBuffer * +soup_buffer_new_subbuffer (SoupBuffer *parent, gsize offset, gsize length) +{ + SoupBufferPrivate *priv; + + /* Normally this is just a ref, but if @parent is TEMPORARY, + * it will do an actual copy. + */ + parent = soup_buffer_copy (parent); + + priv = g_slice_new0 (SoupBufferPrivate); + priv->buffer.data = parent->data + offset; + priv->buffer.length = length; + priv->use = SOUP_MEMORY_SUBBUFFER; + priv->owner = parent; + priv->owner_dnotify = (GDestroyNotify)soup_buffer_free; + priv->refcount = 1; + + return (SoupBuffer *)priv; +} + +/** + * soup_buffer_new_with_owner: + * @data: (array length=length) (element-type guint8): data + * @length: length of @data + * @owner: pointer to an object that owns @data + * @owner_dnotify: (allow-none): a function to free/unref @owner when + * the buffer is freed + * + * Creates a new #SoupBuffer containing @length bytes from @data. When + * the #SoupBuffer is freed, it will call @owner_dnotify, passing + * @owner to it. You must ensure that @data will remain valid until + * @owner_dnotify is called. + * + * For example, you could use this to create a buffer containing data + * returned from libxml without needing to do an extra copy: + * + * + * xmlDocDumpMemory (doc, &xmlbody, &len); + * return soup_buffer_new_with_owner (xmlbody, len, xmlbody, + * (GDestroyNotify)xmlFree); + * + * + * In this example, @data and @owner are the same, but in other cases + * they would be different (eg, @owner would be a object, and @data + * would be a pointer to one of the object's fields). + * + * Return value: the new #SoupBuffer. + **/ +SoupBuffer * +soup_buffer_new_with_owner (gconstpointer data, gsize length, + gpointer owner, GDestroyNotify owner_dnotify) +{ + SoupBufferPrivate *priv = g_slice_new0 (SoupBufferPrivate); + + priv->buffer.data = data; + priv->buffer.length = length; + priv->use = SOUP_MEMORY_OWNED; + priv->owner = owner; + priv->owner_dnotify = owner_dnotify; + priv->refcount = 1; + + return (SoupBuffer *)priv; +} + +/** + * soup_buffer_get_owner: + * @buffer: a #SoupBuffer created with soup_buffer_new_with_owner() + * + * Gets the "owner" object for a buffer created with + * soup_buffer_new_with_owner(). + * + * Return value: (transfer none): the owner pointer + **/ +gpointer +soup_buffer_get_owner (SoupBuffer *buffer) +{ + SoupBufferPrivate *priv = (SoupBufferPrivate *)buffer; + + g_return_val_if_fail ((int)priv->use == (int)SOUP_MEMORY_OWNED, NULL); + return priv->owner; +} + +/** + * soup_buffer_get_data: + * @buffer: a #SoupBuffer + * @data: (out) (array length=length) (transfer none): the pointer + * to the buffer data is stored here + * @length: (out): the length of the buffer data is stored here + * + * This function exists for use by language bindings, because it's not + * currently possible to get the right effect by annotating the fields + * of #SoupBuffer. + * + * Since: 2.32 + */ +void +soup_buffer_get_data (SoupBuffer *buffer, + const guint8 **data, + gsize *length) +{ + *data = (const guint8 *)buffer->data; + *length = buffer->length; +} + +/** + * soup_buffer_copy: + * @buffer: a #SoupBuffer + * + * Makes a copy of @buffer. In reality, #SoupBuffer is a refcounted + * type, and calling soup_buffer_copy() will normally just increment + * the refcount on @buffer and return it. However, if @buffer was + * created with #SOUP_MEMORY_TEMPORARY memory, then soup_buffer_copy() + * will actually return a copy of it, so that the data in the copy + * will remain valid after the temporary buffer is freed. + * + * Return value: the new (or newly-reffed) buffer + **/ +SoupBuffer * +soup_buffer_copy (SoupBuffer *buffer) +{ + SoupBufferPrivate *priv = (SoupBufferPrivate *)buffer; + + /* For non-TEMPORARY buffers, this is just a ref */ + if (priv->use != SOUP_MEMORY_TEMPORARY) { + g_atomic_int_inc (&priv->refcount); + return buffer; + } + + /* For TEMPORARY buffers, we need to do a real copy the first + * time, and then after that, we just keep returning the copy. + * We store the copy in priv->owner, which is technically + * backwards, but it saves us from having to keep an extra + * pointer in SoupBufferPrivate. + */ + + if (!priv->owner) { + priv->owner = soup_buffer_new (SOUP_MEMORY_COPY, + buffer->data, + buffer->length); + priv->owner_dnotify = (GDestroyNotify)soup_buffer_free; + } + return soup_buffer_copy (priv->owner); +} + +/** + * soup_buffer_free: + * @buffer: a #SoupBuffer + * + * Frees @buffer. (In reality, as described in the documentation for + * soup_buffer_copy(), this is actually an "unref" operation, and may + * or may not actually free @buffer.) + **/ +void +soup_buffer_free (SoupBuffer *buffer) +{ + SoupBufferPrivate *priv = (SoupBufferPrivate *)buffer; + + if (!g_atomic_int_dec_and_test (&priv->refcount)) + return; + + if (priv->owner_dnotify) + priv->owner_dnotify (priv->owner); + g_slice_free (SoupBufferPrivate, priv); +} + +/** + * soup_buffer_get_as_bytes: + * @buffer: a #SoupBuffer + * + * Creates a #GBytes pointing to the same memory as @buffer. The + * #GBytes will hold a reference on @buffer to ensure that it is not + * freed while the #GBytes is still valid. + * + * Returns: (transfer full): a new #GBytes which has the same content + * as the #SoupBuffer. + * + * Since: 2.40 + */ +GBytes * +soup_buffer_get_as_bytes (SoupBuffer *buffer) +{ + SoupBuffer *copy; + + copy = soup_buffer_copy (buffer); + return g_bytes_new_with_free_func (copy->data, copy->length, + (GDestroyNotify)soup_buffer_free, + copy); +} + +G_DEFINE_BOXED_TYPE (SoupBuffer, soup_buffer, soup_buffer_copy, soup_buffer_free) + + +/** + * SoupMessageBody: + * @data: the data + * @length: length of @data + * + * A #SoupMessage request or response body. + * + * Note that while @length always reflects the full length of the + * message body, @data is normally %NULL, and will only be filled in + * after soup_message_body_flatten() is called. For client-side + * messages, this automatically happens for the response body after it + * has been fully read, unless you set the + * %SOUP_MESSAGE_OVERWRITE_CHUNKS flags. Likewise, for server-side + * messages, the request body is automatically filled in after being + * read. + * + * As an added bonus, when @data is filled in, it is always terminated + * with a '\0' byte (which is not reflected in @length). + **/ + +typedef struct { + SoupMessageBody body; + GSList *chunks, *last; + SoupBuffer *flattened; + gboolean accumulate; + goffset base_offset; + int ref_count; +} SoupMessageBodyPrivate; + +/** + * soup_message_body_new: + * + * Creates a new #SoupMessageBody. #SoupMessage uses this internally; you + * will not normally need to call it yourself. + * + * Return value: a new #SoupMessageBody. + **/ +SoupMessageBody * +soup_message_body_new (void) +{ + SoupMessageBodyPrivate *priv; + + priv = g_slice_new0 (SoupMessageBodyPrivate); + priv->accumulate = TRUE; + priv->ref_count = 1; + + return (SoupMessageBody *)priv; +} + +/** + * soup_message_body_set_accumulate: + * @body: a #SoupMessageBody + * @accumulate: whether or not to accumulate body chunks in @body + * + * Sets or clears the accumulate flag on @body. (The default value is + * %TRUE.) If set to %FALSE, @body's %data field will not be filled in + * after the body is fully sent/received, and the chunks that make up + * @body may be discarded when they are no longer needed. + * + * In particular, if you set this flag to %FALSE on an "incoming" + * message body (that is, the #SoupMessage:response_body of a + * client-side message, or #SoupMessage:request_body of a server-side + * message), this will cause each chunk of the body to be discarded + * after its corresponding #SoupMessage::got_chunk signal is emitted. + * (This is equivalent to setting the deprecated + * %SOUP_MESSAGE_OVERWRITE_CHUNKS flag on the message.) + * + * If you set this flag to %FALSE on the #SoupMessage:response_body of + * a server-side message, it will cause each chunk of the body to be + * discarded after its corresponding #SoupMessage::wrote_chunk signal + * is emitted. + * + * If you set the flag to %FALSE on the #SoupMessage:request_body of a + * client-side message, it will block the accumulation of chunks into + * @body's %data field, but it will not normally cause the chunks to + * be discarded after being written like in the server-side + * #SoupMessage:response_body case, because the request body needs to + * be kept around in case the request needs to be sent a second time + * due to redirection or authentication. However, if you set the + * %SOUP_MESSAGE_CAN_REBUILD flag on the message, then the chunks will + * be discarded, and you will be responsible for recreating the + * request body after the #SoupMessage::restarted signal is emitted. + * + * Since: 2.24 + **/ +void +soup_message_body_set_accumulate (SoupMessageBody *body, + gboolean accumulate) +{ + SoupMessageBodyPrivate *priv = (SoupMessageBodyPrivate *)body; + + priv->accumulate = accumulate; +} + +/** + * soup_message_body_get_accumulate: + * @body: a #SoupMessageBody + * + * Gets the accumulate flag on @body; see + * soup_message_body_set_accumulate() for details. + * + * Return value: the accumulate flag for @body. + * + * Since: 2.24 + **/ +gboolean +soup_message_body_get_accumulate (SoupMessageBody *body) +{ + SoupMessageBodyPrivate *priv = (SoupMessageBodyPrivate *)body; + + return priv->accumulate; +} + +static void +append_buffer (SoupMessageBody *body, SoupBuffer *buffer) +{ + SoupMessageBodyPrivate *priv = (SoupMessageBodyPrivate *)body; + + if (priv->last) { + priv->last = g_slist_append (priv->last, buffer); + priv->last = priv->last->next; + } else + priv->chunks = priv->last = g_slist_append (NULL, buffer); + + if (priv->flattened) { + soup_buffer_free (priv->flattened); + priv->flattened = NULL; + body->data = NULL; + } + body->length += buffer->length; +} + +/** + * soup_message_body_append: + * @body: a #SoupMessageBody + * @use: how to use @data + * @data: (array length=length) (element-type guint8): data to append + * @length: length of @data + * + * Appends @length bytes from @data to @body according to @use. + **/ +void +soup_message_body_append (SoupMessageBody *body, SoupMemoryUse use, + gconstpointer data, gsize length) +{ + if (length > 0) + append_buffer (body, soup_buffer_new (use, data, length)); + else if (use == SOUP_MEMORY_TAKE) + g_free ((gpointer)data); +} + +/** + * soup_message_body_append_take: (rename-to soup_message_body_append) + * @body: a #SoupMessageBody + * @data: (array length=length) (transfer full): data to append + * @length: length of @data + * + * Appends @length bytes from @data to @body. + * + * This function is exactly equivalent to soup_message_body_append() + * with %SOUP_MEMORY_TAKE as second argument; it exists mainly for + * convenience and simplifying language bindings. + * + * Since: 2.32 + **/ +void +soup_message_body_append_take (SoupMessageBody *body, + guchar *data, gsize length) +{ + soup_message_body_append(body, SOUP_MEMORY_TAKE, data, length); +} + +/** + * soup_message_body_append_buffer: + * @body: a #SoupMessageBody + * @buffer: a #SoupBuffer + * + * Appends the data from @buffer to @body. (#SoupMessageBody uses + * #SoupBuffers internally, so this is normally a constant-time + * operation that doesn't actually require copying the data in + * @buffer.) + **/ +void +soup_message_body_append_buffer (SoupMessageBody *body, SoupBuffer *buffer) +{ + g_return_if_fail (buffer->length > 0); + append_buffer (body, soup_buffer_copy (buffer)); +} + +/** + * soup_message_body_truncate: + * @body: a #SoupMessageBody + * + * Deletes all of the data in @body. + **/ +void +soup_message_body_truncate (SoupMessageBody *body) +{ + SoupMessageBodyPrivate *priv = (SoupMessageBodyPrivate *)body; + + g_slist_free_full (priv->chunks, (GDestroyNotify)soup_buffer_free); + priv->chunks = priv->last = NULL; + priv->base_offset = 0; + + if (priv->flattened) { + soup_buffer_free (priv->flattened); + priv->flattened = NULL; + body->data = NULL; + } + body->length = 0; +} + +/** + * soup_message_body_complete: + * @body: a #SoupMessageBody + * + * Tags @body as being complete; Call this when using chunked encoding + * after you have appended the last chunk. + **/ +void +soup_message_body_complete (SoupMessageBody *body) +{ + append_buffer (body, soup_buffer_new (SOUP_MEMORY_STATIC, NULL, 0)); +} + +/** + * soup_message_body_flatten: + * @body: a #SoupMessageBody + * + * Fills in @body's data field with a buffer containing all of the + * data in @body (plus an additional '\0' byte not counted by @body's + * length field). + * + * Return value: a #SoupBuffer containing the same data as @body. + * (You must free this buffer if you do not want it.) + **/ +SoupBuffer * +soup_message_body_flatten (SoupMessageBody *body) +{ + SoupMessageBodyPrivate *priv = (SoupMessageBodyPrivate *)body; + char *buf, *ptr; + GSList *iter; + SoupBuffer *chunk; + + g_return_val_if_fail (priv->accumulate == TRUE, NULL); + + if (!priv->flattened) { +#if GLIB_SIZEOF_SIZE_T < 8 + g_return_val_if_fail (body->length < G_MAXSIZE, NULL); +#endif + + buf = ptr = g_malloc (body->length + 1); + for (iter = priv->chunks; iter; iter = iter->next) { + chunk = iter->data; + memcpy (ptr, chunk->data, chunk->length); + ptr += chunk->length; + } + *ptr = '\0'; + + priv->flattened = soup_buffer_new (SOUP_MEMORY_TAKE, + buf, body->length); + body->data = priv->flattened->data; + } + + return soup_buffer_copy (priv->flattened); +} + +/** + * soup_message_body_get_chunk: + * @body: a #SoupMessageBody + * @offset: an offset + * + * Gets a #SoupBuffer containing data from @body starting at @offset. + * The size of the returned chunk is unspecified. You can iterate + * through the entire body by first calling + * soup_message_body_get_chunk() with an offset of 0, and then on each + * successive call, increment the offset by the length of the + * previously-returned chunk. + * + * If @offset is greater than or equal to the total length of @body, + * then the return value depends on whether or not + * soup_message_body_complete() has been called or not; if it has, + * then soup_message_body_get_chunk() will return a 0-length chunk + * (indicating the end of @body). If it has not, then + * soup_message_body_get_chunk() will return %NULL (indicating that + * @body may still potentially have more data, but that data is not + * currently available). + * + * Return value: (nullable): a #SoupBuffer, or %NULL. + **/ +SoupBuffer * +soup_message_body_get_chunk (SoupMessageBody *body, goffset offset) +{ + SoupMessageBodyPrivate *priv = (SoupMessageBodyPrivate *)body; + GSList *iter; + SoupBuffer *chunk = NULL; + + offset -= priv->base_offset; + for (iter = priv->chunks; iter; iter = iter->next) { + chunk = iter->data; + + if (offset < chunk->length || offset == 0) + break; + + offset -= chunk->length; + } + + if (!iter) + return NULL; + + if (offset == 0) + return soup_buffer_copy (chunk); + else { + return soup_buffer_new_subbuffer (chunk, offset, + chunk->length - offset); + } +} + +/** + * soup_message_body_got_chunk: + * @body: a #SoupMessageBody + * @chunk: a #SoupBuffer received from the network + * + * Handles the #SoupMessageBody part of receiving a chunk of data from + * the network. Normally this means appending @chunk to @body, exactly + * as with soup_message_body_append_buffer(), but if you have set + * @body's accumulate flag to %FALSE, then that will not happen. + * + * This is a low-level method which you should not normally need to + * use. + * + * Since: 2.24 + **/ +void +soup_message_body_got_chunk (SoupMessageBody *body, SoupBuffer *chunk) +{ + SoupMessageBodyPrivate *priv = (SoupMessageBodyPrivate *)body; + + if (!priv->accumulate) + return; + + soup_message_body_append_buffer (body, chunk); +} + +/** + * soup_message_body_wrote_chunk: + * @body: a #SoupMessageBody + * @chunk: a #SoupBuffer returned from soup_message_body_get_chunk() + * + * Handles the #SoupMessageBody part of writing a chunk of data to the + * network. Normally this is a no-op, but if you have set @body's + * accumulate flag to %FALSE, then this will cause @chunk to be + * discarded to free up memory. + * + * This is a low-level method which you should not need to use, and + * there are further restrictions on its proper use which are not + * documented here. + * + * Since: 2.24 + **/ +void +soup_message_body_wrote_chunk (SoupMessageBody *body, SoupBuffer *chunk) +{ + SoupMessageBodyPrivate *priv = (SoupMessageBodyPrivate *)body; + SoupBuffer *chunk2; + + if (priv->accumulate) + return; + + chunk2 = priv->chunks->data; + g_return_if_fail (chunk->length == chunk2->length); + g_return_if_fail (chunk == chunk2 || ((SoupBufferPrivate *)chunk2)->use == SOUP_MEMORY_TEMPORARY); + + priv->chunks = g_slist_remove (priv->chunks, chunk2); + if (!priv->chunks) + priv->last = NULL; + + priv->base_offset += chunk2->length; + soup_buffer_free (chunk2); +} + +static SoupMessageBody * +soup_message_body_copy (SoupMessageBody *body) +{ + SoupMessageBodyPrivate *priv = (SoupMessageBodyPrivate *)body; + + g_atomic_int_inc (&priv->ref_count); + return body; +} + +/** + * soup_message_body_free: + * @body: a #SoupMessageBody + * + * Frees @body. You will not normally need to use this, as + * #SoupMessage frees its associated message bodies automatically. + **/ +void +soup_message_body_free (SoupMessageBody *body) +{ + SoupMessageBodyPrivate *priv = (SoupMessageBodyPrivate *)body; + + if (!g_atomic_int_dec_and_test (&priv->ref_count)) + return; + + soup_message_body_truncate (body); + g_slice_free (SoupMessageBodyPrivate, priv); +} + +G_DEFINE_BOXED_TYPE (SoupMessageBody, soup_message_body, soup_message_body_copy, soup_message_body_free) diff --git a/libsoup/soup-message-body.h b/libsoup/soup-message-body.h new file mode 100644 index 0000000..fc6c200 --- /dev/null +++ b/libsoup/soup-message-body.h @@ -0,0 +1,114 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2000-2003, Ximian, Inc. + */ + +#ifndef SOUP_MESSAGE_BODY_H +#define SOUP_MESSAGE_BODY_H 1 + +#include + +G_BEGIN_DECLS + +typedef enum { + SOUP_MEMORY_STATIC, + SOUP_MEMORY_TAKE, + SOUP_MEMORY_COPY, + SOUP_MEMORY_TEMPORARY +} SoupMemoryUse; + +typedef struct { + const char *data; + gsize length; +} SoupBuffer; + +SOUP_AVAILABLE_IN_2_4 +GType soup_buffer_get_type (void); +#define SOUP_TYPE_BUFFER (soup_buffer_get_type ()) + +SOUP_AVAILABLE_IN_2_4 +SoupBuffer *soup_buffer_new (SoupMemoryUse use, + gconstpointer data, + gsize length); +SOUP_AVAILABLE_IN_2_32 +SoupBuffer *soup_buffer_new_take (guchar *data, + gsize length); +SOUP_AVAILABLE_IN_2_4 +SoupBuffer *soup_buffer_new_subbuffer (SoupBuffer *parent, + gsize offset, + gsize length); + +SOUP_AVAILABLE_IN_2_4 +SoupBuffer *soup_buffer_new_with_owner (gconstpointer data, + gsize length, + gpointer owner, + GDestroyNotify owner_dnotify); +SOUP_AVAILABLE_IN_2_4 +gpointer soup_buffer_get_owner (SoupBuffer *buffer); +SOUP_AVAILABLE_IN_2_32 +void soup_buffer_get_data (SoupBuffer *buffer, + const guint8 **data, + gsize *length); +SOUP_AVAILABLE_IN_2_40 +GBytes *soup_buffer_get_as_bytes (SoupBuffer *buffer); + +SOUP_AVAILABLE_IN_2_4 +SoupBuffer *soup_buffer_copy (SoupBuffer *buffer); +SOUP_AVAILABLE_IN_2_4 +void soup_buffer_free (SoupBuffer *buffer); + +typedef struct { + const char *data; + goffset length; +} SoupMessageBody; + +SOUP_AVAILABLE_IN_2_4 +GType soup_message_body_get_type (void); +#define SOUP_TYPE_MESSAGE_BODY (soup_message_body_get_type ()) + +SOUP_AVAILABLE_IN_2_4 +SoupMessageBody *soup_message_body_new (void); + +SOUP_AVAILABLE_IN_2_24 +void soup_message_body_set_accumulate(SoupMessageBody *body, + gboolean accumulate); +SOUP_AVAILABLE_IN_2_24 +gboolean soup_message_body_get_accumulate(SoupMessageBody *body); + +SOUP_AVAILABLE_IN_2_4 +void soup_message_body_append (SoupMessageBody *body, + SoupMemoryUse use, + gconstpointer data, + gsize length); +SOUP_AVAILABLE_IN_2_32 +void soup_message_body_append_take (SoupMessageBody *body, + guchar *data, + gsize length); +SOUP_AVAILABLE_IN_2_4 +void soup_message_body_append_buffer (SoupMessageBody *body, + SoupBuffer *buffer); +SOUP_AVAILABLE_IN_2_4 +void soup_message_body_truncate (SoupMessageBody *body); +SOUP_AVAILABLE_IN_2_4 +void soup_message_body_complete (SoupMessageBody *body); + +SOUP_AVAILABLE_IN_2_4 +SoupBuffer *soup_message_body_flatten (SoupMessageBody *body); + +SOUP_AVAILABLE_IN_2_4 +SoupBuffer *soup_message_body_get_chunk (SoupMessageBody *body, + goffset offset); + +SOUP_AVAILABLE_IN_2_24 +void soup_message_body_got_chunk (SoupMessageBody *body, + SoupBuffer *chunk); +SOUP_AVAILABLE_IN_2_24 +void soup_message_body_wrote_chunk (SoupMessageBody *body, + SoupBuffer *chunk); + +SOUP_AVAILABLE_IN_2_4 +void soup_message_body_free (SoupMessageBody *body); + +G_END_DECLS + +#endif /* SOUP_MESSAGE_BODY_H */ diff --git a/libsoup/soup-message-client-io.c b/libsoup/soup-message-client-io.c new file mode 100644 index 0000000..f571ef7 --- /dev/null +++ b/libsoup/soup-message-client-io.c @@ -0,0 +1,166 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-message-client-io.c: client-side request/response + * + * Copyright (C) 2000-2003, Ximian, Inc. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include + +#include "soup.h" +#include "soup-connection.h" +#include "soup-message-private.h" +#include "soup-message-queue.h" +#include "soup-socket-private.h" + +static guint +parse_response_headers (SoupMessage *msg, + char *headers, guint headers_len, + SoupEncoding *encoding, + gpointer user_data, + GError **error) +{ + SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); + SoupHTTPVersion version; + + g_free(msg->reason_phrase); + msg->reason_phrase = NULL; + if (!soup_headers_parse_response (headers, headers_len, + msg->response_headers, + &version, + &msg->status_code, + &msg->reason_phrase)) { + g_set_error_literal (error, SOUP_REQUEST_ERROR, + SOUP_REQUEST_ERROR_PARSING, + _("Could not parse HTTP response")); + return SOUP_STATUS_MALFORMED; + } + + g_object_notify (G_OBJECT (msg), SOUP_MESSAGE_STATUS_CODE); + g_object_notify (G_OBJECT (msg), SOUP_MESSAGE_REASON_PHRASE); + + if (version < priv->http_version) { + priv->http_version = version; + g_object_notify (G_OBJECT (msg), SOUP_MESSAGE_HTTP_VERSION); + } + + if ((msg->method == SOUP_METHOD_HEAD || + msg->status_code == SOUP_STATUS_NO_CONTENT || + msg->status_code == SOUP_STATUS_NOT_MODIFIED || + SOUP_STATUS_IS_INFORMATIONAL (msg->status_code)) || + (msg->method == SOUP_METHOD_CONNECT && + SOUP_STATUS_IS_SUCCESSFUL (msg->status_code))) + *encoding = SOUP_ENCODING_NONE; + else + *encoding = soup_message_headers_get_encoding (msg->response_headers); + + if (*encoding == SOUP_ENCODING_UNRECOGNIZED) { + g_set_error_literal (error, SOUP_REQUEST_ERROR, + SOUP_REQUEST_ERROR_ENCODING, + _("Unrecognized HTTP response encoding")); + return SOUP_STATUS_MALFORMED; + } + + return SOUP_STATUS_OK; +} + +static void +get_request_headers (SoupMessage *msg, GString *header, + SoupEncoding *encoding, gpointer user_data) +{ + SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); + SoupMessageQueueItem *item = user_data; + SoupURI *uri = soup_message_get_uri (msg); + char *uri_host; + char *uri_string; + SoupMessageHeadersIter iter; + const char *name, *value; + + if (strchr (uri->host, ':')) + uri_host = g_strdup_printf ("[%.*s]", (int) strcspn (uri->host, "%"), uri->host); + else if (g_hostname_is_non_ascii (uri->host)) + uri_host = g_hostname_to_ascii (uri->host); + else + uri_host = uri->host; + + if (msg->method == SOUP_METHOD_CONNECT) { + /* CONNECT URI is hostname:port for tunnel destination */ + uri_string = g_strdup_printf ("%s:%d", uri_host, uri->port); + } else { + gboolean proxy = soup_connection_is_via_proxy (item->conn); + + /* Proxy expects full URI to destination. Otherwise + * just the path. + */ + uri_string = soup_uri_to_string (uri, !proxy); + + if (proxy && uri->fragment) { + /* Strip fragment */ + char *fragment = strchr (uri_string, '#'); + if (fragment) + *fragment = '\0'; + } + } + + g_string_append_printf (header, "%s %s HTTP/1.%d\r\n", + msg->method, uri_string, + (priv->http_version == SOUP_HTTP_1_0) ? 0 : 1); + + if (!soup_message_headers_get_one (msg->request_headers, "Host")) { + if (soup_uri_uses_default_port (uri)) { + g_string_append_printf (header, "Host: %s\r\n", + uri_host); + } else { + g_string_append_printf (header, "Host: %s:%d\r\n", + uri_host, uri->port); + } + } + g_free (uri_string); + if (uri_host != uri->host) + g_free (uri_host); + + *encoding = soup_message_headers_get_encoding (msg->request_headers); + if ((*encoding == SOUP_ENCODING_CONTENT_LENGTH || + *encoding == SOUP_ENCODING_NONE) && + (msg->request_body->length > 0 || + soup_message_headers_get_one (msg->request_headers, "Content-Type")) && + !soup_message_headers_get_content_length (msg->request_headers)) { + *encoding = SOUP_ENCODING_CONTENT_LENGTH; + soup_message_headers_set_content_length (msg->request_headers, + msg->request_body->length); + } + + soup_message_headers_iter_init (&iter, msg->request_headers); + while (soup_message_headers_iter_next (&iter, &name, &value)) + g_string_append_printf (header, "%s: %s\r\n", name, value); + g_string_append (header, "\r\n"); +} + +void +soup_message_send_request (SoupMessageQueueItem *item, + SoupMessageCompletionFn completion_cb, + gpointer user_data) +{ + GMainContext *async_context; + GIOStream *iostream; + + if (!SOUP_IS_SESSION_SYNC (item->session)) { + async_context = soup_session_get_async_context (item->session); + if (!async_context) + async_context = g_main_context_default (); + } else + async_context = NULL; + iostream = soup_socket_get_iostream (soup_connection_get_socket (item->conn)); + + soup_message_io_client (item, iostream, async_context, + get_request_headers, + parse_response_headers, + item, + completion_cb, user_data); +} diff --git a/libsoup/soup-message-headers.c b/libsoup/soup-message-headers.c new file mode 100644 index 0000000..16e487a --- /dev/null +++ b/libsoup/soup-message-headers.c @@ -0,0 +1,1468 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-message-headers.c: HTTP message header arrays + * + * Copyright (C) 2007, 2008 Red Hat, Inc. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "soup-message-headers.h" +#include "soup.h" +#include "soup-misc-private.h" + +/** + * SECTION:soup-message-headers + * @short_description: HTTP message headers + * @see_also: #SoupMessage + * + * #SoupMessageHeaders represents the HTTP message headers associated + * with a request or response. + **/ + +/** + * SoupMessageHeaders: + * + * The HTTP message headers associated with a request or response. + */ + +/** + * SoupMessageHeadersType: + * @SOUP_MESSAGE_HEADERS_REQUEST: request headers + * @SOUP_MESSAGE_HEADERS_RESPONSE: response headers + * @SOUP_MESSAGE_HEADERS_MULTIPART: multipart body part headers + * + * Value passed to soup_message_headers_new() to set certain default + * behaviors. + **/ + +typedef void (*SoupHeaderSetter) (SoupMessageHeaders *, const char *); +static const char *intern_header_name (const char *name, SoupHeaderSetter *setter); +static void clear_special_headers (SoupMessageHeaders *hdrs); + +typedef struct { + const char *name; + char *value; +} SoupHeader; + +struct SoupMessageHeaders { + GArray *array; + GHashTable *concat; + SoupMessageHeadersType type; + + SoupEncoding encoding; + goffset content_length; + SoupExpectation expectations; + char *content_type; + + int ref_count; +}; + +/** + * soup_message_headers_new: + * @type: the type of headers + * + * Creates a #SoupMessageHeaders. (#SoupMessage does this + * automatically for its own headers. You would only need to use this + * method if you are manually parsing or generating message headers.) + * + * Return value: a new #SoupMessageHeaders + **/ +SoupMessageHeaders * +soup_message_headers_new (SoupMessageHeadersType type) +{ + SoupMessageHeaders *hdrs; + + hdrs = g_slice_new0 (SoupMessageHeaders); + /* FIXME: is "5" a good default? */ + hdrs->array = g_array_sized_new (TRUE, FALSE, sizeof (SoupHeader), 5); + hdrs->type = type; + hdrs->encoding = -1; + hdrs->ref_count = 1; + + return hdrs; +} + +static SoupMessageHeaders * +soup_message_headers_copy (SoupMessageHeaders *hdrs) +{ + g_atomic_int_inc (&hdrs->ref_count); + return hdrs; +} + +/** + * soup_message_headers_free: + * @hdrs: a #SoupMessageHeaders + * + * Frees @hdrs. + **/ +void +soup_message_headers_free (SoupMessageHeaders *hdrs) +{ + if (!g_atomic_int_dec_and_test (&hdrs->ref_count)) + return; + + soup_message_headers_clear (hdrs); + g_array_free (hdrs->array, TRUE); + g_clear_pointer (&hdrs->concat, g_hash_table_destroy); + g_slice_free (SoupMessageHeaders, hdrs); +} + +G_DEFINE_BOXED_TYPE (SoupMessageHeaders, soup_message_headers, soup_message_headers_copy, soup_message_headers_free) + +/** + * soup_message_headers_get_headers_type: + * @hdrs: a #SoupMessageHeaders + * + * Gets the type of headers. + * + * Return value: the header's type. + * + * Since: 2.50 + **/ +SoupMessageHeadersType +soup_message_headers_get_headers_type (SoupMessageHeaders *hdrs) +{ + return hdrs->type; +} + +/** + * soup_message_headers_clear: + * @hdrs: a #SoupMessageHeaders + * + * Clears @hdrs. + **/ +void +soup_message_headers_clear (SoupMessageHeaders *hdrs) +{ + SoupHeader *hdr_array = (SoupHeader *)hdrs->array->data; + guint i; + + for (i = 0; i < hdrs->array->len; i++) + g_free (hdr_array[i].value); + g_array_set_size (hdrs->array, 0); + + if (hdrs->concat) + g_hash_table_remove_all (hdrs->concat); + + clear_special_headers (hdrs); +} + +/** + * soup_message_headers_clean_connection_headers: + * @hdrs: a #SoupMessageHeaders + * + * Removes all the headers listed in the Connection header. + * + * Since: 2.36 + */ +void +soup_message_headers_clean_connection_headers (SoupMessageHeaders *hdrs) +{ + /* RFC 2616 14.10 */ + const char *connection; + GSList *tokens, *t; + + connection = soup_message_headers_get_list (hdrs, "Connection"); + if (!connection) + return; + + tokens = soup_header_parse_list (connection); + for (t = tokens; t; t = t->next) + soup_message_headers_remove (hdrs, t->data); + soup_header_free_list (tokens); +} + +/** + * soup_message_headers_append: + * @hdrs: a #SoupMessageHeaders + * @name: the header name to add + * @value: the new value of @name + * + * Appends a new header with name @name and value @value to @hdrs. (If + * there is an existing header with name @name, then this creates a + * second one, which is only allowed for list-valued headers; see also + * soup_message_headers_replace().) + * + * The caller is expected to make sure that @name and @value are + * syntactically correct. + **/ +void +soup_message_headers_append (SoupMessageHeaders *hdrs, + const char *name, const char *value) +{ + SoupHeader header; + SoupHeaderSetter setter; + + g_return_if_fail (name != NULL); + g_return_if_fail (value != NULL); + + /* Setting a syntactically invalid header name or value is + * considered to be a programming error. However, it can also + * be a security hole, so we want to fail here even if + * compiled with G_DISABLE_CHECKS. + */ +#ifndef G_DISABLE_CHECKS + g_return_if_fail (*name && strpbrk (name, " \t\r\n:") == NULL); + g_return_if_fail (strpbrk (value, "\r\n") == NULL); +#else + if (*name && strpbrk (name, " \t\r\n:")) { + g_warning ("soup_message_headers_append: Ignoring bad name '%s'", name); + return; + } + if (strpbrk (value, "\r\n")) { + g_warning ("soup_message_headers_append: Ignoring bad value '%s'", value); + return; + } +#endif + + header.name = intern_header_name (name, &setter); + header.value = g_strdup (value); + g_array_append_val (hdrs->array, header); + if (hdrs->concat) + g_hash_table_remove (hdrs->concat, header.name); + if (setter) + setter (hdrs, header.value); +} + +/** + * soup_message_headers_replace: + * @hdrs: a #SoupMessageHeaders + * @name: the header name to replace + * @value: the new value of @name + * + * Replaces the value of the header @name in @hdrs with @value. (See + * also soup_message_headers_append().) + * + * The caller is expected to make sure that @name and @value are + * syntactically correct. + **/ +void +soup_message_headers_replace (SoupMessageHeaders *hdrs, + const char *name, const char *value) +{ + soup_message_headers_remove (hdrs, name); + soup_message_headers_append (hdrs, name, value); +} + +static int +find_header (SoupHeader *hdr_array, const char *interned_name, int nth) +{ + int i; + + for (i = 0; hdr_array[i].name; i++) { + if (hdr_array[i].name == interned_name) { + if (nth-- == 0) + return i; + } + } + return -1; +} + +static int +find_last_header (SoupHeader *hdr_array, guint length, const char *interned_name, int nth) +{ + int i; + + for (i = length; i >= 0; i--) { + if (hdr_array[i].name == interned_name) { + if (nth-- == 0) + return i; + } + } + return -1; +} + +/** + * soup_message_headers_remove: + * @hdrs: a #SoupMessageHeaders + * @name: the header name to remove + * + * Removes @name from @hdrs. If there are multiple values for @name, + * they are all removed. + **/ +void +soup_message_headers_remove (SoupMessageHeaders *hdrs, const char *name) +{ + SoupHeader *hdr_array = (SoupHeader *)(hdrs->array->data); + SoupHeaderSetter setter; + int index; + + g_return_if_fail (name != NULL); + + name = intern_header_name (name, &setter); + while ((index = find_header (hdr_array, name, 0)) != -1) { + g_free (hdr_array[index].value); + g_array_remove_index (hdrs->array, index); + } + if (hdrs->concat) + g_hash_table_remove (hdrs->concat, name); + if (setter) + setter (hdrs, NULL); +} + +/** + * soup_message_headers_get_one: + * @hdrs: a #SoupMessageHeaders + * @name: header name + * + * Gets the value of header @name in @hdrs. Use this for headers whose + * values are not comma-delimited lists, and + * which therefore can only appear at most once in the headers. For + * list-valued headers, use soup_message_headers_get_list(). + * + * If @hdrs does erroneously contain multiple copies of the header, it + * is not defined which one will be returned. (Ideally, it will return + * whichever one makes libsoup most compatible with other HTTP + * implementations.) + * + * Return value: (nullable): the header's value or %NULL if not found. + * + * Since: 2.28 + **/ +const char * +soup_message_headers_get_one (SoupMessageHeaders *hdrs, const char *name) +{ + SoupHeader *hdr_array = (SoupHeader *)(hdrs->array->data); + guint hdr_length = hdrs->array->len; + int index; + + g_return_val_if_fail (name != NULL, NULL); + + name = intern_header_name (name, NULL); + + index = find_last_header (hdr_array, hdr_length, name, 0); + + return (index == -1) ? NULL : hdr_array[index].value; +} + +/** + * soup_message_headers_header_contains: + * @hdrs: a #SoupMessageHeaders + * @name: header name + * @token: token to look for + * + * Checks whether the list-valued header @name is present in @hdrs, + * and contains a case-insensitive match for @token. + * + * (If @name is present in @hdrs, then this is equivalent to calling + * soup_header_contains() on its value.) + * + * Return value: %TRUE if the header is present and contains @token, + * %FALSE otherwise. + * + * Since: 2.50 + **/ +gboolean +soup_message_headers_header_contains (SoupMessageHeaders *hdrs, const char *name, const char *token) +{ + const char *value; + + value = soup_message_headers_get_list (hdrs, name); + if (!value) + return FALSE; + return soup_header_contains (value, token); +} + +/** + * soup_message_headers_header_equals: + * @hdrs: a #SoupMessageHeaders + * @name: header name + * @value: expected value + * + * Checks whether the header @name is present in @hdrs and is + * (case-insensitively) equal to @value. + * + * Return value: %TRUE if the header is present and its value is + * @value, %FALSE otherwise. + * + * Since: 2.50 + **/ +gboolean +soup_message_headers_header_equals (SoupMessageHeaders *hdrs, const char *name, const char *value) +{ + const char *internal_value; + + internal_value = soup_message_headers_get_list (hdrs, name); + if (!internal_value) + return FALSE; + return !g_ascii_strcasecmp (internal_value, value); +} + +/** + * soup_message_headers_get_list: + * @hdrs: a #SoupMessageHeaders + * @name: header name + * + * Gets the value of header @name in @hdrs. Use this for headers whose + * values are comma-delimited lists, and which are therefore allowed + * to appear multiple times in the headers. For non-list-valued + * headers, use soup_message_headers_get_one(). + * + * If @name appears multiple times in @hdrs, + * soup_message_headers_get_list() will concatenate all of the values + * together, separated by commas. This is sometimes awkward to parse + * (eg, WWW-Authenticate, Set-Cookie), but you have to be able to deal + * with it anyway, because the HTTP spec explicitly states that this + * transformation is allowed, and so an upstream proxy could do the + * same thing. + * + * Return value: (nullable): the header's value or %NULL if not found. + * + * Since: 2.28 + **/ +const char * +soup_message_headers_get_list (SoupMessageHeaders *hdrs, const char *name) +{ + SoupHeader *hdr_array = (SoupHeader *)(hdrs->array->data); + GString *concat; + char *value; + int index, i; + + g_return_val_if_fail (name != NULL, NULL); + + name = intern_header_name (name, NULL); + if (hdrs->concat) { + value = g_hash_table_lookup (hdrs->concat, name); + if (value) + return value; + } + + index = find_header (hdr_array, name, 0); + if (index == -1) + return NULL; + else if (find_header (hdr_array, name, 1) == -1) + return hdr_array[index].value; + + concat = g_string_new (NULL); + for (i = 0; (index = find_header (hdr_array, name, i)) != -1; i++) { + if (i != 0) + g_string_append (concat, ", "); + g_string_append (concat, hdr_array[index].value); + } + value = g_string_free (concat, FALSE); + + if (!hdrs->concat) + hdrs->concat = g_hash_table_new_full (NULL, NULL, NULL, g_free); + g_hash_table_insert (hdrs->concat, (gpointer)name, value); + return value; +} + +/** + * soup_message_headers_get: + * @hdrs: a #SoupMessageHeaders + * @name: header name + * + * Gets the value of header @name in @hdrs. + * + * This method was supposed to work correctly for both single-valued + * and list-valued headers, but because some HTTP clients/servers + * mistakenly send multiple copies of headers that are supposed to be + * single-valued, it sometimes returns incorrect results. To fix this, + * the methods soup_message_headers_get_one() and + * soup_message_headers_get_list() were introduced, so callers can + * explicitly state which behavior they are expecting. + * + * Return value: (nullable): as with soup_message_headers_get_list(). + * + * Deprecated: Use soup_message_headers_get_one() or + * soup_message_headers_get_list() instead. + **/ +const char * +soup_message_headers_get (SoupMessageHeaders *hdrs, const char *name) +{ + return soup_message_headers_get_list (hdrs, name); +} + +/** + * SoupMessageHeadersIter: + * + * An opaque type used to iterate over a %SoupMessageHeaders + * structure. + * + * After intializing the iterator with + * soup_message_headers_iter_init(), call + * soup_message_headers_iter_next() to fetch data from it. + * + * You may not modify the headers while iterating over them. + **/ + +typedef struct { + SoupMessageHeaders *hdrs; + int index; +} SoupMessageHeadersIterReal; + +/** + * soup_message_headers_iter_init: + * @iter: (out) (transfer none): a pointer to a %SoupMessageHeadersIter + * structure + * @hdrs: a %SoupMessageHeaders + * + * Initializes @iter for iterating @hdrs. + **/ +void +soup_message_headers_iter_init (SoupMessageHeadersIter *iter, + SoupMessageHeaders *hdrs) +{ + SoupMessageHeadersIterReal *real = (SoupMessageHeadersIterReal *)iter; + + real->hdrs = hdrs; + real->index = 0; +} + +/** + * soup_message_headers_iter_next: + * @iter: (inout) (transfer none): a %SoupMessageHeadersIter + * @name: (out) (transfer none): pointer to a variable to return + * the header name in + * @value: (out) (transfer none): pointer to a variable to return + * the header value in + * + * Yields the next name/value pair in the %SoupMessageHeaders being + * iterated by @iter. If @iter has already yielded the last header, + * then soup_message_headers_iter_next() will return %FALSE and @name + * and @value will be unchanged. + * + * Return value: %TRUE if another name and value were returned, %FALSE + * if the end of the headers has been reached. + **/ +gboolean +soup_message_headers_iter_next (SoupMessageHeadersIter *iter, + const char **name, const char **value) +{ + SoupMessageHeadersIterReal *real = (SoupMessageHeadersIterReal *)iter; + SoupHeader *hdr_array = (SoupHeader *)real->hdrs->array->data; + + if (real->index >= real->hdrs->array->len) + return FALSE; + + *name = hdr_array[real->index].name; + *value = hdr_array[real->index].value; + real->index++; + return TRUE; +} + +/** + * SoupMessageHeadersForeachFunc: + * @name: the header name + * @value: the header value + * @user_data: the data passed to soup_message_headers_foreach() + * + * The callback passed to soup_message_headers_foreach(). + **/ + +/** + * soup_message_headers_foreach: + * @hdrs: a #SoupMessageHeaders + * @func: (scope call): callback function to run for each header + * @user_data: data to pass to @func + * + * Calls @func once for each header value in @hdrs. + * + * Beware that unlike soup_message_headers_get(), this processes the + * headers in exactly the way they were added, rather than + * concatenating multiple same-named headers into a single value. + * (This is intentional; it ensures that if you call + * soup_message_headers_append() multiple times with the same name, + * then the I/O code will output multiple copies of the header when + * sending the message to the remote implementation, which may be + * required for interoperability in some cases.) + * + * You may not modify the headers from @func. + **/ +void +soup_message_headers_foreach (SoupMessageHeaders *hdrs, + SoupMessageHeadersForeachFunc func, + gpointer user_data) +{ + SoupHeader *hdr_array = (SoupHeader *)hdrs->array->data; + guint i; + + for (i = 0; i < hdrs->array->len; i++) + func (hdr_array[i].name, hdr_array[i].value, user_data); +} + + +G_LOCK_DEFINE_STATIC (header_pool); +static GHashTable *header_pool, *header_setters; + +static void transfer_encoding_setter (SoupMessageHeaders *, const char *); +static void content_length_setter (SoupMessageHeaders *, const char *); +static void expectation_setter (SoupMessageHeaders *, const char *); +static void content_type_setter (SoupMessageHeaders *, const char *); + +static char * +intern_header_locked (const char *name) +{ + char *interned; + + interned = g_hash_table_lookup (header_pool, name); + if (!interned) { + char *dup = g_strdup (name); + g_hash_table_insert (header_pool, dup, dup); + interned = dup; + } + return interned; +} + +static const char * +intern_header_name (const char *name, SoupHeaderSetter *setter) +{ + const char *interned; + + G_LOCK (header_pool); + + if (!header_pool) { + header_pool = g_hash_table_new (soup_str_case_hash, soup_str_case_equal); + header_setters = g_hash_table_new (NULL, NULL); + g_hash_table_insert (header_setters, + intern_header_locked ("Transfer-Encoding"), + transfer_encoding_setter); + g_hash_table_insert (header_setters, + intern_header_locked ("Content-Length"), + content_length_setter); + g_hash_table_insert (header_setters, + intern_header_locked ("Expect"), + expectation_setter); + g_hash_table_insert (header_setters, + intern_header_locked ("Content-Type"), + content_type_setter); + } + + interned = intern_header_locked (name); + if (setter) + *setter = g_hash_table_lookup (header_setters, interned); + + G_UNLOCK (header_pool); + return interned; +} + +static void +clear_special_headers (SoupMessageHeaders *hdrs) +{ + SoupHeaderSetter setter; + GHashTableIter iter; + gpointer key, value; + + /* Make sure header_setters has been initialized */ + intern_header_name ("", NULL); + + g_hash_table_iter_init (&iter, header_setters); + while (g_hash_table_iter_next (&iter, &key, &value)) { + setter = value; + setter (hdrs, NULL); + } +} + +/* Specific headers */ + +static void +transfer_encoding_setter (SoupMessageHeaders *hdrs, const char *value) +{ + if (value) { + if (g_ascii_strcasecmp (value, "chunked") == 0) + hdrs->encoding = SOUP_ENCODING_CHUNKED; + else + hdrs->encoding = SOUP_ENCODING_UNRECOGNIZED; + } else + hdrs->encoding = -1; +} + +static void +content_length_setter (SoupMessageHeaders *hdrs, const char *value) +{ + /* Transfer-Encoding trumps Content-Length */ + if (hdrs->encoding == SOUP_ENCODING_CHUNKED) + return; + + if (value) { + char *end; + + hdrs->content_length = g_ascii_strtoull (value, &end, 10); + if (*end) + hdrs->encoding = SOUP_ENCODING_UNRECOGNIZED; + else + hdrs->encoding = SOUP_ENCODING_CONTENT_LENGTH; + } else + hdrs->encoding = -1; +} + +/** + * SoupEncoding: + * @SOUP_ENCODING_UNRECOGNIZED: unknown / error + * @SOUP_ENCODING_NONE: no body is present (which is not the same as a + * 0-length body, and only occurs in certain places) + * @SOUP_ENCODING_CONTENT_LENGTH: Content-Length encoding + * @SOUP_ENCODING_EOF: Response body ends when the connection is closed + * @SOUP_ENCODING_CHUNKED: chunked encoding (currently only supported + * for response) + * @SOUP_ENCODING_BYTERANGES: multipart/byteranges (Reserved for future + * use: NOT CURRENTLY IMPLEMENTED) + * + * How a message body is encoded for transport + **/ + +/** + * soup_message_headers_get_encoding: + * @hdrs: a #SoupMessageHeaders + * + * Gets the message body encoding that @hdrs declare. This may not + * always correspond to the encoding used on the wire; eg, a HEAD + * response may declare a Content-Length or Transfer-Encoding, but + * it will never actually include a body. + * + * Return value: the encoding declared by @hdrs. + **/ +SoupEncoding +soup_message_headers_get_encoding (SoupMessageHeaders *hdrs) +{ + const char *header; + + if (hdrs->encoding != -1) + return hdrs->encoding; + + /* If Transfer-Encoding was set, hdrs->encoding would already + * be set. So we don't need to check that possibility. + */ + header = soup_message_headers_get_one (hdrs, "Content-Length"); + if (header) { + content_length_setter (hdrs, header); + if (hdrs->encoding != -1) + return hdrs->encoding; + } + + /* Per RFC 2616 4.4, a response body that doesn't indicate its + * encoding otherwise is terminated by connection close, and a + * request that doesn't indicate otherwise has no body. Note + * that SoupMessage calls soup_message_headers_set_encoding() + * to override the response body default for our own + * server-side messages. + */ + hdrs->encoding = (hdrs->type == SOUP_MESSAGE_HEADERS_RESPONSE) ? + SOUP_ENCODING_EOF : SOUP_ENCODING_NONE; + return hdrs->encoding; +} + +/** + * soup_message_headers_set_encoding: + * @hdrs: a #SoupMessageHeaders + * @encoding: a #SoupEncoding + * + * Sets the message body encoding that @hdrs will declare. In particular, + * you should use this if you are going to send a request or response in + * chunked encoding. + **/ +void +soup_message_headers_set_encoding (SoupMessageHeaders *hdrs, + SoupEncoding encoding) +{ + if (encoding == hdrs->encoding) + return; + + switch (encoding) { + case SOUP_ENCODING_NONE: + case SOUP_ENCODING_EOF: + soup_message_headers_remove (hdrs, "Transfer-Encoding"); + soup_message_headers_remove (hdrs, "Content-Length"); + break; + + case SOUP_ENCODING_CONTENT_LENGTH: + soup_message_headers_remove (hdrs, "Transfer-Encoding"); + break; + + case SOUP_ENCODING_CHUNKED: + soup_message_headers_remove (hdrs, "Content-Length"); + soup_message_headers_replace (hdrs, "Transfer-Encoding", "chunked"); + break; + + default: + g_return_if_reached (); + } + + hdrs->encoding = encoding; +} + +/** + * soup_message_headers_get_content_length: + * @hdrs: a #SoupMessageHeaders + * + * Gets the message body length that @hdrs declare. This will only + * be non-0 if soup_message_headers_get_encoding() returns + * %SOUP_ENCODING_CONTENT_LENGTH. + * + * Return value: the message body length declared by @hdrs. + **/ +goffset +soup_message_headers_get_content_length (SoupMessageHeaders *hdrs) +{ + SoupEncoding encoding; + + encoding = soup_message_headers_get_encoding (hdrs); + if (encoding == SOUP_ENCODING_CONTENT_LENGTH) + return hdrs->content_length; + else + return 0; +} + +/** + * soup_message_headers_set_content_length: + * @hdrs: a #SoupMessageHeaders + * @content_length: the message body length + * + * Sets the message body length that @hdrs will declare, and sets + * @hdrs's encoding to %SOUP_ENCODING_CONTENT_LENGTH. + * + * You do not normally need to call this; if @hdrs is set to use + * Content-Length encoding, libsoup will automatically set its + * Content-Length header for you immediately before sending the + * headers. One situation in which this method is useful is when + * generating the response to a HEAD request; Calling + * soup_message_headers_set_content_length() allows you to put the + * correct content length into the response without needing to waste + * memory by filling in a response body which won't actually be sent. + **/ +void +soup_message_headers_set_content_length (SoupMessageHeaders *hdrs, + goffset content_length) +{ + char length[128]; + + g_snprintf (length, sizeof (length), "%" G_GUINT64_FORMAT, + content_length); + soup_message_headers_remove (hdrs, "Transfer-Encoding"); + soup_message_headers_replace (hdrs, "Content-Length", length); +} + +static void +expectation_setter (SoupMessageHeaders *hdrs, const char *value) +{ + if (value) { + if (!g_ascii_strcasecmp (value, "100-continue")) + hdrs->expectations = SOUP_EXPECTATION_CONTINUE; + else + hdrs->expectations = SOUP_EXPECTATION_UNRECOGNIZED; + } else + hdrs->expectations = 0; +} + +/** + * SoupExpectation: + * @SOUP_EXPECTATION_CONTINUE: "100-continue" + * @SOUP_EXPECTATION_UNRECOGNIZED: any unrecognized expectation + * + * Represents the parsed value of the "Expect" header. + **/ + +/** + * soup_message_headers_get_expectations: + * @hdrs: a #SoupMessageHeaders + * + * Gets the expectations declared by @hdrs's "Expect" header. + * Currently this will either be %SOUP_EXPECTATION_CONTINUE or + * %SOUP_EXPECTATION_UNRECOGNIZED. + * + * Return value: the contents of @hdrs's "Expect" header + **/ +SoupExpectation +soup_message_headers_get_expectations (SoupMessageHeaders *hdrs) +{ + return hdrs->expectations; +} + +/** + * soup_message_headers_set_expectations: + * @hdrs: a #SoupMessageHeaders + * @expectations: the expectations to set + * + * Sets @hdrs's "Expect" header according to @expectations. + * + * Currently %SOUP_EXPECTATION_CONTINUE is the only known expectation + * value. You should set this value on a request if you are sending a + * large message body (eg, via POST or PUT), and want to give the + * server a chance to reject the request after seeing just the headers + * (eg, because it will require authentication before allowing you to + * post, or because you're POSTing to a URL that doesn't exist). This + * saves you from having to transmit the large request body when the + * server is just going to ignore it anyway. + **/ +void +soup_message_headers_set_expectations (SoupMessageHeaders *hdrs, + SoupExpectation expectations) +{ + g_return_if_fail ((expectations & ~SOUP_EXPECTATION_CONTINUE) == 0); + + if (expectations & SOUP_EXPECTATION_CONTINUE) + soup_message_headers_replace (hdrs, "Expect", "100-continue"); + else + soup_message_headers_remove (hdrs, "Expect"); +} + +/** + * SoupRange: + * @start: the start of the range + * @end: the end of the range + * + * Represents a byte range as used in the Range header. + * + * If @end is non-negative, then @start and @end represent the bounds + * of of the range, counting from 0. (Eg, the first 500 bytes would be + * represented as @start = 0 and @end = 499.) + * + * If @end is -1 and @start is non-negative, then this represents a + * range starting at @start and ending with the last byte of the + * requested resource body. (Eg, all but the first 500 bytes would be + * @start = 500, and @end = -1.) + * + * If @end is -1 and @start is negative, then it represents a "suffix + * range", referring to the last -@start bytes of the resource body. + * (Eg, the last 500 bytes would be @start = -500 and @end = -1.) + * + * Since: 2.26 + **/ + +static int +sort_ranges (gconstpointer a, gconstpointer b) +{ + SoupRange *ra = (SoupRange *)a; + SoupRange *rb = (SoupRange *)b; + + return ra->start - rb->start; +} + +/* like soup_message_headers_get_ranges(), except it returns: + * SOUP_STATUS_OK if there is no Range or it should be ignored. + * SOUP_STATUS_PARTIAL_CONTENT if there is at least one satisfiable range. + * SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE if @check_satisfiable + * is %TRUE and the request is not satisfiable given @total_length. + */ +guint +soup_message_headers_get_ranges_internal (SoupMessageHeaders *hdrs, + goffset total_length, + gboolean check_satisfiable, + SoupRange **ranges, + int *length) +{ + const char *range = soup_message_headers_get_one (hdrs, "Range"); + GSList *range_list, *r; + GArray *array; + char *spec, *end; + guint status = SOUP_STATUS_OK; + + if (!range || strncmp (range, "bytes", 5) != 0) + return status; + + range += 5; + while (g_ascii_isspace (*range)) + range++; + if (*range++ != '=') + return status; + while (g_ascii_isspace (*range)) + range++; + + range_list = soup_header_parse_list (range); + if (!range_list) + return status; + + array = g_array_new (FALSE, FALSE, sizeof (SoupRange)); + for (r = range_list; r; r = r->next) { + SoupRange cur; + + spec = r->data; + if (*spec == '-') { + cur.start = g_ascii_strtoll (spec, &end, 10) + total_length; + cur.end = total_length - 1; + } else { + cur.start = g_ascii_strtoull (spec, &end, 10); + if (*end == '-') + end++; + if (*end) { + cur.end = g_ascii_strtoull (end, &end, 10); + if (cur.end < cur.start) { + status = SOUP_STATUS_OK; + break; + } + } else + cur.end = total_length - 1; + } + if (*end) { + status = SOUP_STATUS_OK; + break; + } else if (check_satisfiable && cur.start >= total_length) { + if (status == SOUP_STATUS_OK) + status = SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE; + continue; + } + + g_array_append_val (array, cur); + status = SOUP_STATUS_PARTIAL_CONTENT; + } + soup_header_free_list (range_list); + + if (status != SOUP_STATUS_PARTIAL_CONTENT) { + g_array_free (array, TRUE); + return status; + } + + if (total_length) { + guint i; + + g_array_sort (array, sort_ranges); + for (i = 1; i < array->len; i++) { + SoupRange *cur = &((SoupRange *)array->data)[i]; + SoupRange *prev = &((SoupRange *)array->data)[i - 1]; + + if (cur->start <= prev->end) { + prev->end = MAX (prev->end, cur->end); + g_array_remove_index (array, i); + } + } + } + + *ranges = (SoupRange *)array->data; + *length = array->len; + + g_array_free (array, FALSE); + return SOUP_STATUS_PARTIAL_CONTENT; +} + +/** + * soup_message_headers_get_ranges: + * @hdrs: a #SoupMessageHeaders + * @total_length: the total_length of the response body + * @ranges: (out) (array length=length): return location for an array + * of #SoupRange + * @length: the length of the returned array + * + * Parses @hdrs's Range header and returns an array of the requested + * byte ranges. The returned array must be freed with + * soup_message_headers_free_ranges(). + * + * If @total_length is non-0, its value will be used to adjust the + * returned ranges to have explicit start and end values, and the + * returned ranges will be sorted and non-overlapping. If + * @total_length is 0, then some ranges may have an end value of -1, + * as described under #SoupRange, and some of the ranges may be + * redundant. + * + * Beware that even if given a @total_length, this function does not + * check that the ranges are satisfiable. + * + * + * #SoupServer has built-in handling for range requests. If your + * server handler returns a %SOUP_STATUS_OK response containing the + * complete response body (rather than pausing the message and + * returning some of the response body later), and there is a Range + * header in the request, then libsoup will automatically convert the + * response to a %SOUP_STATUS_PARTIAL_CONTENT response containing only + * the range(s) requested by the client. + * + * The only time you need to process the Range header yourself is if + * either you need to stream the response body rather than returning + * it all at once, or you do not already have the complete response + * body available, and only want to generate the parts that were + * actually requested by the client. + * + * + * Return value: %TRUE if @hdrs contained a syntactically-valid + * "Range" header, %FALSE otherwise (in which case @range and @length + * will not be set). + * + * Since: 2.26 + **/ +gboolean +soup_message_headers_get_ranges (SoupMessageHeaders *hdrs, + goffset total_length, + SoupRange **ranges, + int *length) +{ + guint status; + + status = soup_message_headers_get_ranges_internal (hdrs, total_length, FALSE, ranges, length); + return status == SOUP_STATUS_PARTIAL_CONTENT; +} + +/** + * soup_message_headers_free_ranges: + * @hdrs: a #SoupMessageHeaders + * @ranges: an array of #SoupRange + * + * Frees the array of ranges returned from soup_message_headers_get_ranges(). + * + * Since: 2.26 + **/ +void +soup_message_headers_free_ranges (SoupMessageHeaders *hdrs, + SoupRange *ranges) +{ + g_free (ranges); +} + +/** + * soup_message_headers_set_ranges: + * @hdrs: a #SoupMessageHeaders + * @ranges: an array of #SoupRange + * @length: the length of @range + * + * Sets @hdrs's Range header to request the indicated ranges. (If you + * only want to request a single range, you can use + * soup_message_headers_set_range().) + * + * Since: 2.26 + **/ +void +soup_message_headers_set_ranges (SoupMessageHeaders *hdrs, + SoupRange *ranges, + int length) +{ + GString *header; + int i; + + header = g_string_new ("bytes="); + for (i = 0; i < length; i++) { + if (i > 0) + g_string_append_c (header, ','); + if (ranges[i].end >= 0) { + g_string_append_printf (header, "%" G_GINT64_FORMAT "-%" G_GINT64_FORMAT, + ranges[i].start, ranges[i].end); + } else if (ranges[i].start >= 0) { + g_string_append_printf (header,"%" G_GINT64_FORMAT "-", + ranges[i].start); + } else { + g_string_append_printf (header, "%" G_GINT64_FORMAT, + ranges[i].start); + } + } + + soup_message_headers_replace (hdrs, "Range", header->str); + g_string_free (header, TRUE); +} + +/** + * soup_message_headers_set_range: + * @hdrs: a #SoupMessageHeaders + * @start: the start of the range to request + * @end: the end of the range to request + * + * Sets @hdrs's Range header to request the indicated range. + * @start and @end are interpreted as in a #SoupRange. + * + * If you need to request multiple ranges, use + * soup_message_headers_set_ranges(). + * + * Since: 2.26 + **/ +void +soup_message_headers_set_range (SoupMessageHeaders *hdrs, + goffset start, + goffset end) +{ + SoupRange range; + + range.start = start; + range.end = end; + soup_message_headers_set_ranges (hdrs, &range, 1); +} + +/** + * soup_message_headers_get_content_range: + * @hdrs: a #SoupMessageHeaders + * @start: (out): return value for the start of the range + * @end: (out): return value for the end of the range + * @total_length: (out) (optional): return value for the total length of the + * resource, or %NULL if you don't care. + * + * Parses @hdrs's Content-Range header and returns it in @start, + * @end, and @total_length. If the total length field in the header + * was specified as "*", then @total_length will be set to -1. + * + * Return value: %TRUE if @hdrs contained a "Content-Range" header + * containing a byte range which could be parsed, %FALSE otherwise. + * + * Since: 2.26 + **/ +gboolean +soup_message_headers_get_content_range (SoupMessageHeaders *hdrs, + goffset *start, + goffset *end, + goffset *total_length) +{ + const char *header = soup_message_headers_get_one (hdrs, "Content-Range"); + goffset length; + char *p; + + if (!header || strncmp (header, "bytes ", 6) != 0) + return FALSE; + + header += 6; + while (g_ascii_isspace (*header)) + header++; + if (!g_ascii_isdigit (*header)) + return FALSE; + + *start = g_ascii_strtoull (header, &p, 10); + if (*p != '-') + return FALSE; + *end = g_ascii_strtoull (p + 1, &p, 10); + if (*p != '/') + return FALSE; + p++; + if (*p == '*') { + length = -1; + p++; + } else + length = g_ascii_strtoull (p, &p, 10); + + if (total_length) + *total_length = length; + return *p == '\0'; +} + +/** + * soup_message_headers_set_content_range: + * @hdrs: a #SoupMessageHeaders + * @start: the start of the range + * @end: the end of the range + * @total_length: the total length of the resource, or -1 if unknown + * + * Sets @hdrs's Content-Range header according to the given values. + * (Note that @total_length is the total length of the entire resource + * that this is a range of, not simply @end - @start + 1.) + * + * + * #SoupServer has built-in handling for range requests, and you do + * not normally need to call this function youself. See + * soup_message_headers_get_ranges() for more details. + * + * + * Since: 2.26 + **/ +void +soup_message_headers_set_content_range (SoupMessageHeaders *hdrs, + goffset start, + goffset end, + goffset total_length) +{ + char *header; + + if (total_length >= 0) { + header = g_strdup_printf ("bytes %" G_GINT64_FORMAT "-%" + G_GINT64_FORMAT "/%" G_GINT64_FORMAT, + start, end, total_length); + } else { + header = g_strdup_printf ("bytes %" G_GINT64_FORMAT "-%" + G_GINT64_FORMAT "/*", start, end); + } + soup_message_headers_replace (hdrs, "Content-Range", header); + g_free (header); +} + +static gboolean +parse_content_foo (SoupMessageHeaders *hdrs, const char *header_name, + char **foo, GHashTable **params) +{ + const char *header; + char *semi; + + header = soup_message_headers_get_one (hdrs, header_name); + if (!header) + return FALSE; + + if (foo) { + *foo = g_strdup (header); + semi = strchr (*foo, ';'); + if (semi) { + char *p = semi; + + *semi++ = '\0'; + while (p - 1 > *foo && g_ascii_isspace(p[-1])) + *(--p) = '\0'; + } + } else { + semi = strchr (header, ';'); + if (semi) + semi++; + } + + if (!params) + return TRUE; + + if (!semi) { + *params = soup_header_parse_semi_param_list (""); + return TRUE; + } + + *params = soup_header_parse_semi_param_list (semi); + return TRUE; +} + +static void +set_content_foo (SoupMessageHeaders *hdrs, const char *header_name, + const char *foo, GHashTable *params) +{ + GString *str; + GHashTableIter iter; + gpointer key, value; + + str = g_string_new (foo); + if (params) { + g_hash_table_iter_init (&iter, params); + while (g_hash_table_iter_next (&iter, &key, &value)) { + g_string_append (str, "; "); + soup_header_g_string_append_param (str, key, value); + } + } + + soup_message_headers_replace (hdrs, header_name, str->str); + g_string_free (str, TRUE); +} + +static void +content_type_setter (SoupMessageHeaders *hdrs, const char *value) +{ + g_free (hdrs->content_type); + if (value) { + char *content_type, *p; + + parse_content_foo (hdrs, "Content-Type", &content_type, NULL); + p = strpbrk (content_type, " /"); + if (!p || *p != '/' || strpbrk (p + 1, " /")) { + g_free (content_type); + hdrs->content_type = NULL; + } else + hdrs->content_type = content_type; + } else + hdrs->content_type = NULL; +} + +/** + * soup_message_headers_get_content_type: + * @hdrs: a #SoupMessageHeaders + * @params: (out) (element-type utf8 utf8) (allow-none) (transfer full): + * return location for the Content-Type parameters (eg, "charset"), or + * %NULL + * + * Looks up the "Content-Type" header in @hdrs, parses it, and returns + * its value in *@content_type and *@params. @params can be %NULL if you + * are only interested in the content type itself. + * + * Return value: (nullable): a string with the value of the + * "Content-Type" header or %NULL if @hdrs does not contain that + * header or it cannot be parsed (in which case *@params will be + * unchanged). + * + * Since: 2.26 + **/ +const char * +soup_message_headers_get_content_type (SoupMessageHeaders *hdrs, + GHashTable **params) +{ + if (!hdrs->content_type) + return NULL; + + if (params) + parse_content_foo (hdrs, "Content-Type", NULL, params); + return hdrs->content_type; +} + +/** + * soup_message_headers_set_content_type: + * @hdrs: a #SoupMessageHeaders + * @content_type: the MIME type + * @params: (allow-none) (element-type utf8 utf8): additional + * parameters, or %NULL + * + * Sets the "Content-Type" header in @hdrs to @content_type, + * optionally with additional parameters specified in @params. + * + * Since: 2.26 + **/ +void +soup_message_headers_set_content_type (SoupMessageHeaders *hdrs, + const char *content_type, + GHashTable *params) +{ + set_content_foo (hdrs, "Content-Type", content_type, params); +} + +/** + * soup_message_headers_get_content_disposition: + * @hdrs: a #SoupMessageHeaders + * @disposition: (out) (transfer full): return location for the + * disposition-type, or %NULL + * @params: (out) (transfer full) (element-type utf8 utf8): return + * location for the Content-Disposition parameters, or %NULL + * + * Looks up the "Content-Disposition" header in @hdrs, parses it, and + * returns its value in *@disposition and *@params. @params can be + * %NULL if you are only interested in the disposition-type. + * + * In HTTP, the most common use of this header is to set a + * disposition-type of "attachment", to suggest to the browser that a + * response should be saved to disk rather than displayed in the + * browser. If @params contains a "filename" parameter, this is a + * suggestion of a filename to use. (If the parameter value in the + * header contains an absolute or relative path, libsoup will truncate + * it down to just the final path component, so you do not need to + * test this yourself.) + * + * Content-Disposition is also used in "multipart/form-data", however + * this is handled automatically by #SoupMultipart and the associated + * form methods. + * + * Return value: %TRUE if @hdrs contains a "Content-Disposition" + * header, %FALSE if not (in which case *@disposition and *@params + * will be unchanged). + * + * Since: 2.26 + **/ +gboolean +soup_message_headers_get_content_disposition (SoupMessageHeaders *hdrs, + char **disposition, + GHashTable **params) +{ + gpointer orig_key, orig_value; + + if (!parse_content_foo (hdrs, "Content-Disposition", + disposition, params)) + return FALSE; + + /* If there is a filename parameter, make sure it contains + * only a single path component + */ + if (params && g_hash_table_lookup_extended (*params, "filename", + &orig_key, &orig_value)) { + char *filename = strrchr (orig_value, '/'); + + if (filename) + g_hash_table_insert (*params, g_strdup (orig_key), filename + 1); + } + return TRUE; +} + +/** + * soup_message_headers_set_content_disposition: + * @hdrs: a #SoupMessageHeaders + * @disposition: the disposition-type + * @params: (allow-none) (element-type utf8 utf8): additional + * parameters, or %NULL + * + * Sets the "Content-Disposition" header in @hdrs to @disposition, + * optionally with additional parameters specified in @params. + * + * See soup_message_headers_get_content_disposition() for a discussion + * of how Content-Disposition is used in HTTP. + * + * Since: 2.26 + **/ +void +soup_message_headers_set_content_disposition (SoupMessageHeaders *hdrs, + const char *disposition, + GHashTable *params) +{ + set_content_foo (hdrs, "Content-Disposition", disposition, params); +} + diff --git a/libsoup/soup-message-headers.h b/libsoup/soup-message-headers.h new file mode 100644 index 0000000..829e352 --- /dev/null +++ b/libsoup/soup-message-headers.h @@ -0,0 +1,181 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2005 Novell, Inc. + */ + +#ifndef SOUP_MESSAGE_HEADERS_H +#define SOUP_MESSAGE_HEADERS_H 1 + +#include + +G_BEGIN_DECLS + +typedef struct SoupMessageHeaders SoupMessageHeaders; +SOUP_AVAILABLE_IN_2_4 +GType soup_message_headers_get_type (void); +#define SOUP_TYPE_MESSAGE_HEADERS (soup_message_headers_get_type ()) + +typedef enum { + SOUP_MESSAGE_HEADERS_REQUEST, + SOUP_MESSAGE_HEADERS_RESPONSE, + SOUP_MESSAGE_HEADERS_MULTIPART +} SoupMessageHeadersType; + +SOUP_AVAILABLE_IN_2_4 +SoupMessageHeaders *soup_message_headers_new (SoupMessageHeadersType type); + +SOUP_AVAILABLE_IN_2_4 +void soup_message_headers_free (SoupMessageHeaders *hdrs); + +SOUP_AVAILABLE_IN_2_4 +void soup_message_headers_append (SoupMessageHeaders *hdrs, + const char *name, + const char *value); +SOUP_AVAILABLE_IN_2_4 +void soup_message_headers_replace (SoupMessageHeaders *hdrs, + const char *name, + const char *value); + +SOUP_AVAILABLE_IN_2_4 +void soup_message_headers_remove (SoupMessageHeaders *hdrs, + const char *name); +SOUP_AVAILABLE_IN_2_4 +void soup_message_headers_clear (SoupMessageHeaders *hdrs); + +SOUP_AVAILABLE_IN_2_36 +void soup_message_headers_clean_connection_headers (SoupMessageHeaders *hdrs); + +#ifndef SOUP_DISABLE_DEPRECATED +SOUP_AVAILABLE_IN_2_4 +SOUP_DEPRECATED_IN_2_28_FOR ("soup_message_headers_get_one or soup_message_headers_get_list") +const char *soup_message_headers_get (SoupMessageHeaders *hdrs, + const char *name); +#endif +SOUP_AVAILABLE_IN_2_28 +const char *soup_message_headers_get_one (SoupMessageHeaders *hdrs, + const char *name); +SOUP_AVAILABLE_IN_2_28 +const char *soup_message_headers_get_list (SoupMessageHeaders *hdrs, + const char *name); +SOUP_AVAILABLE_IN_2_50 +gboolean soup_message_headers_header_contains (SoupMessageHeaders *hdrs, + const char *name, + const char *token); +SOUP_AVAILABLE_IN_2_50 +gboolean soup_message_headers_header_equals (SoupMessageHeaders *hdrs, + const char *name, + const char *value); + +typedef void (*SoupMessageHeadersForeachFunc)(const char *name, + const char *value, + gpointer user_data); + +SOUP_AVAILABLE_IN_2_4 +void soup_message_headers_foreach (SoupMessageHeaders *hdrs, + SoupMessageHeadersForeachFunc func, + gpointer user_data); + +SOUP_AVAILABLE_IN_2_50 +SoupMessageHeadersType soup_message_headers_get_headers_type (SoupMessageHeaders *hdrs); + +typedef struct { + /*< private >*/ + gpointer dummy[3]; +} SoupMessageHeadersIter; + +SOUP_AVAILABLE_IN_2_4 +void soup_message_headers_iter_init (SoupMessageHeadersIter *iter, + SoupMessageHeaders *hdrs); +SOUP_AVAILABLE_IN_2_4 +gboolean soup_message_headers_iter_next (SoupMessageHeadersIter *iter, + const char **name, + const char **value); + +/* Specific headers */ + +typedef enum { + SOUP_ENCODING_UNRECOGNIZED, + SOUP_ENCODING_NONE, + SOUP_ENCODING_CONTENT_LENGTH, + SOUP_ENCODING_EOF, + SOUP_ENCODING_CHUNKED, + SOUP_ENCODING_BYTERANGES +} SoupEncoding; + +SOUP_AVAILABLE_IN_2_4 +SoupEncoding soup_message_headers_get_encoding (SoupMessageHeaders *hdrs); +SOUP_AVAILABLE_IN_2_4 +void soup_message_headers_set_encoding (SoupMessageHeaders *hdrs, + SoupEncoding encoding); + +SOUP_AVAILABLE_IN_2_4 +goffset soup_message_headers_get_content_length (SoupMessageHeaders *hdrs); +SOUP_AVAILABLE_IN_2_4 +void soup_message_headers_set_content_length (SoupMessageHeaders *hdrs, + goffset content_length); + +typedef enum { + SOUP_EXPECTATION_UNRECOGNIZED = (1 << 0), + SOUP_EXPECTATION_CONTINUE = (1 << 1) +} SoupExpectation; + +SOUP_AVAILABLE_IN_2_4 +SoupExpectation soup_message_headers_get_expectations (SoupMessageHeaders *hdrs); +SOUP_AVAILABLE_IN_2_4 +void soup_message_headers_set_expectations (SoupMessageHeaders *hdrs, + SoupExpectation expectations); + +typedef struct { + goffset start; + goffset end; +} SoupRange; + +SOUP_AVAILABLE_IN_2_26 +gboolean soup_message_headers_get_ranges (SoupMessageHeaders *hdrs, + goffset total_length, + SoupRange **ranges, + int *length); +SOUP_AVAILABLE_IN_2_26 +void soup_message_headers_free_ranges (SoupMessageHeaders *hdrs, + SoupRange *ranges); +SOUP_AVAILABLE_IN_2_26 +void soup_message_headers_set_ranges (SoupMessageHeaders *hdrs, + SoupRange *ranges, + int length); +SOUP_AVAILABLE_IN_2_26 +void soup_message_headers_set_range (SoupMessageHeaders *hdrs, + goffset start, + goffset end); + +SOUP_AVAILABLE_IN_2_26 +gboolean soup_message_headers_get_content_range (SoupMessageHeaders *hdrs, + goffset *start, + goffset *end, + goffset *total_length); +SOUP_AVAILABLE_IN_2_26 +void soup_message_headers_set_content_range (SoupMessageHeaders *hdrs, + goffset start, + goffset end, + goffset total_length); + + +SOUP_AVAILABLE_IN_2_26 +const char *soup_message_headers_get_content_type (SoupMessageHeaders *hdrs, + GHashTable **params); +SOUP_AVAILABLE_IN_2_26 +void soup_message_headers_set_content_type (SoupMessageHeaders *hdrs, + const char *content_type, + GHashTable *params); + +SOUP_AVAILABLE_IN_2_26 +gboolean soup_message_headers_get_content_disposition (SoupMessageHeaders *hdrs, + char **disposition, + GHashTable **params); +SOUP_AVAILABLE_IN_2_26 +void soup_message_headers_set_content_disposition (SoupMessageHeaders *hdrs, + const char *disposition, + GHashTable *params); + +G_END_DECLS + +#endif /* SOUP_MESSAGE_HEADERS_H */ diff --git a/libsoup/soup-message-io.c b/libsoup/soup-message-io.c new file mode 100644 index 0000000..3a7d735 --- /dev/null +++ b/libsoup/soup-message-io.c @@ -0,0 +1,1342 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-message-io.c: HTTP message I/O + * + * Copyright (C) 2000-2003, Ximian, Inc. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include "soup.h" +#include "soup-body-input-stream.h" +#include "soup-body-output-stream.h" +#include "soup-client-input-stream.h" +#include "soup-connection.h" +#include "soup-content-processor.h" +#include "soup-content-sniffer-stream.h" +#include "soup-filter-input-stream.h" +#include "soup-message-private.h" +#include "soup-message-queue.h" +#include "soup-misc-private.h" + +typedef enum { + SOUP_MESSAGE_IO_CLIENT, + SOUP_MESSAGE_IO_SERVER +} SoupMessageIOMode; + +typedef enum { + SOUP_MESSAGE_IO_STATE_NOT_STARTED, + SOUP_MESSAGE_IO_STATE_ANY = SOUP_MESSAGE_IO_STATE_NOT_STARTED, + SOUP_MESSAGE_IO_STATE_HEADERS, + SOUP_MESSAGE_IO_STATE_BLOCKING, + SOUP_MESSAGE_IO_STATE_BODY_START, + SOUP_MESSAGE_IO_STATE_BODY, + SOUP_MESSAGE_IO_STATE_BODY_DATA, + SOUP_MESSAGE_IO_STATE_BODY_FLUSH, + SOUP_MESSAGE_IO_STATE_BODY_DONE, + SOUP_MESSAGE_IO_STATE_FINISHING, + SOUP_MESSAGE_IO_STATE_DONE +} SoupMessageIOState; + +#define SOUP_MESSAGE_IO_STATE_ACTIVE(state) \ + (state != SOUP_MESSAGE_IO_STATE_NOT_STARTED && \ + state != SOUP_MESSAGE_IO_STATE_BLOCKING && \ + state != SOUP_MESSAGE_IO_STATE_DONE) +#define SOUP_MESSAGE_IO_STATE_POLLABLE(state) \ + (SOUP_MESSAGE_IO_STATE_ACTIVE (state) && \ + state != SOUP_MESSAGE_IO_STATE_BODY_DONE) + +typedef struct { + SoupMessageQueueItem *item; + SoupMessageIOMode mode; + GCancellable *cancellable; + + GIOStream *iostream; + SoupFilterInputStream *istream; + GInputStream *body_istream; + GOutputStream *ostream; + GOutputStream *body_ostream; + GMainContext *async_context; + + SoupMessageIOState read_state; + SoupEncoding read_encoding; + GByteArray *read_header_buf; + SoupMessageBody *read_body; + goffset read_length; + + SoupMessageIOState write_state; + SoupEncoding write_encoding; + GString *write_buf; + SoupMessageBody *write_body; + SoupBuffer *write_chunk; + goffset write_body_offset; + goffset write_length; + goffset written; + + GSource *io_source; + GSource *unpause_source; + gboolean paused; + + GCancellable *async_close_wait; + GError *async_close_error; + + SoupMessageGetHeadersFn get_headers_cb; + SoupMessageParseHeadersFn parse_headers_cb; + gpointer header_data; + SoupMessageCompletionFn completion_cb; + gpointer completion_data; +} SoupMessageIOData; + +static void io_run (SoupMessage *msg, gboolean blocking); + +#define RESPONSE_BLOCK_SIZE 8192 +#define HEADER_SIZE_LIMIT (64 * 1024) + +void +soup_message_io_cleanup (SoupMessage *msg) +{ + SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); + SoupMessageIOData *io; + + soup_message_io_stop (msg); + + io = priv->io_data; + if (!io) + return; + priv->io_data = NULL; + + if (io->iostream) + g_object_unref (io->iostream); + if (io->body_istream) + g_object_unref (io->body_istream); + if (io->body_ostream) + g_object_unref (io->body_ostream); + if (io->async_context) + g_main_context_unref (io->async_context); + if (io->item) + soup_message_queue_item_unref (io->item); + + g_byte_array_free (io->read_header_buf, TRUE); + + g_string_free (io->write_buf, TRUE); + if (io->write_chunk) + soup_buffer_free (io->write_chunk); + + if (io->async_close_wait) { + g_cancellable_cancel (io->async_close_wait); + g_clear_object (&io->async_close_wait); + } + g_clear_error (&io->async_close_error); + + g_slice_free (SoupMessageIOData, io); +} + +void +soup_message_io_stop (SoupMessage *msg) +{ + SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); + SoupMessageIOData *io = priv->io_data; + + if (!io) + return; + + if (io->io_source) { + g_source_destroy (io->io_source); + g_source_unref (io->io_source); + io->io_source = NULL; + } + + if (io->unpause_source) { + g_source_destroy (io->unpause_source); + g_source_unref (io->unpause_source); + io->unpause_source = NULL; + } +} + +void +soup_message_io_finished (SoupMessage *msg) +{ + SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); + SoupMessageIOData *io = priv->io_data; + SoupMessageCompletionFn completion_cb; + gpointer completion_data; + SoupMessageIOCompletion completion; + + if (!io) + return; + + completion_cb = io->completion_cb; + completion_data = io->completion_data; + + if ((io->read_state >= SOUP_MESSAGE_IO_STATE_FINISHING && + io->write_state >= SOUP_MESSAGE_IO_STATE_FINISHING)) + completion = SOUP_MESSAGE_IO_COMPLETE; + else + completion = SOUP_MESSAGE_IO_INTERRUPTED; + + g_object_ref (msg); + soup_message_io_cleanup (msg); + if (completion_cb) + completion_cb (msg, completion, completion_data); + g_object_unref (msg); +} + +GIOStream * +soup_message_io_steal (SoupMessage *msg) +{ + SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); + SoupMessageIOData *io = priv->io_data; + SoupMessageCompletionFn completion_cb; + gpointer completion_data; + GIOStream *iostream; + + if (!io || !io->iostream) + return NULL; + + iostream = g_object_ref (io->iostream); + completion_cb = io->completion_cb; + completion_data = io->completion_data; + + g_object_ref (msg); + soup_message_io_cleanup (msg); + if (completion_cb) + completion_cb (msg, SOUP_MESSAGE_IO_STOLEN, completion_data); + g_object_unref (msg); + + return iostream; +} + +static gboolean +read_headers (SoupMessage *msg, gboolean blocking, + GCancellable *cancellable, GError **error) +{ + SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); + SoupMessageIOData *io = priv->io_data; + gssize nread, old_len; + gboolean got_lf; + + while (1) { + old_len = io->read_header_buf->len; + g_byte_array_set_size (io->read_header_buf, old_len + RESPONSE_BLOCK_SIZE); + nread = soup_filter_input_stream_read_line (io->istream, + io->read_header_buf->data + old_len, + RESPONSE_BLOCK_SIZE, + blocking, + &got_lf, + cancellable, error); + io->read_header_buf->len = old_len + MAX (nread, 0); + if (nread == 0) { + if (io->read_header_buf->len > 0) + break; + soup_message_set_status (msg, SOUP_STATUS_MALFORMED); + g_set_error_literal (error, G_IO_ERROR, + G_IO_ERROR_PARTIAL_INPUT, + _("Connection terminated unexpectedly")); + } + if (nread <= 0) + return FALSE; + + if (got_lf) { + if (nread == 1 && old_len >= 2 && + !strncmp ((char *)io->read_header_buf->data + + io->read_header_buf->len - 2, + "\n\n", 2)) { + io->read_header_buf->len--; + break; + } else if (nread == 2 && old_len >= 3 && + !strncmp ((char *)io->read_header_buf->data + + io->read_header_buf->len - 3, + "\n\r\n", 3)) { + io->read_header_buf->len -= 2; + break; + } + } + + if (io->read_header_buf->len > HEADER_SIZE_LIMIT) { + soup_message_set_status (msg, SOUP_STATUS_MALFORMED); + g_set_error_literal (error, G_IO_ERROR, + G_IO_ERROR_PARTIAL_INPUT, + _("Header too big")); + return FALSE; + } + } + + io->read_header_buf->data[io->read_header_buf->len] = '\0'; + return TRUE; +} + +static gint +processing_stage_cmp (gconstpointer a, + gconstpointer b) +{ + SoupProcessingStage stage_a = soup_content_processor_get_processing_stage (SOUP_CONTENT_PROCESSOR (a)); + SoupProcessingStage stage_b = soup_content_processor_get_processing_stage (SOUP_CONTENT_PROCESSOR (b)); + + if (stage_a > stage_b) + return 1; + if (stage_a == stage_b) + return 0; + return -1; +} + +GInputStream * +soup_message_setup_body_istream (GInputStream *body_stream, + SoupMessage *msg, + SoupSession *session, + SoupProcessingStage start_at_stage) +{ + GInputStream *istream; + GSList *p, *processors; + + istream = g_object_ref (body_stream); + + processors = soup_session_get_features (session, SOUP_TYPE_CONTENT_PROCESSOR); + processors = g_slist_sort (processors, processing_stage_cmp); + + for (p = processors; p; p = p->next) { + GInputStream *wrapper; + SoupContentProcessor *processor; + + processor = SOUP_CONTENT_PROCESSOR (p->data); + if (soup_message_disables_feature (msg, p->data) || + soup_content_processor_get_processing_stage (processor) < start_at_stage) + continue; + + wrapper = soup_content_processor_wrap_input (processor, istream, msg, NULL); + if (wrapper) { + g_object_unref (istream); + istream = wrapper; + } + } + + g_slist_free (processors); + + return istream; +} + +static void +closed_async (GObject *source, + GAsyncResult *result, + gpointer user_data) +{ + GOutputStream *body_ostream = G_OUTPUT_STREAM (source); + SoupMessage *msg = user_data; + SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); + SoupMessageIOData *io = priv->io_data; + GCancellable *async_close_wait; + + if (!io || !io->async_close_wait || io->body_ostream != body_ostream) { + g_object_unref (msg); + return; + } + + g_output_stream_close_finish (body_ostream, result, &io->async_close_error); + g_clear_object (&io->body_ostream); + + async_close_wait = io->async_close_wait; + io->async_close_wait = NULL; + g_cancellable_cancel (async_close_wait); + g_object_unref (async_close_wait); + + g_object_unref (msg); +} + +/* + * There are two request/response formats: the basic request/response, + * possibly with one or more unsolicited informational responses (such + * as the WebDAV "102 Processing" response): + * + * Client Server + * W:HEADERS / R:NOT_STARTED -> R:HEADERS / W:NOT_STARTED + * W:BODY / R:NOT_STARTED -> R:BODY / W:NOT_STARTED + * [W:DONE / R:HEADERS (1xx) <- R:DONE / W:HEADERS (1xx) ...] + * W:DONE / R:HEADERS <- R:DONE / W:HEADERS + * W:DONE / R:BODY <- R:DONE / W:BODY + * W:DONE / R:DONE R:DONE / W:DONE + * + * and the "Expect: 100-continue" request/response, with the client + * blocking halfway through its request, and then either continuing or + * aborting, depending on the server response: + * + * Client Server + * W:HEADERS / R:NOT_STARTED -> R:HEADERS / W:NOT_STARTED + * W:BLOCKING / R:HEADERS <- R:BLOCKING / W:HEADERS + * [W:BODY / R:BLOCKING -> R:BODY / W:BLOCKING] + * [W:DONE / R:HEADERS <- R:DONE / W:HEADERS] + * W:DONE / R:BODY <- R:DONE / W:BODY + * W:DONE / R:DONE R:DONE / W:DONE + */ + +/* Attempts to push forward the writing side of @msg's I/O. Returns + * %TRUE if it manages to make some progress, and it is likely that + * further progress can be made. Returns %FALSE if it has reached a + * stopping point of some sort (need input from the application, + * socket not writable, write is complete, etc). + */ +static gboolean +io_write (SoupMessage *msg, gboolean blocking, + GCancellable *cancellable, GError **error) +{ + SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); + SoupMessageIOData *io = priv->io_data; + SoupBuffer *chunk; + gssize nwrote; + + if (io->async_close_error) { + g_propagate_error (error, io->async_close_error); + io->async_close_error = NULL; + return FALSE; + } else if (io->async_close_wait) { + g_set_error_literal (error, G_IO_ERROR, + G_IO_ERROR_WOULD_BLOCK, + _("Operation would block")); + return FALSE; + } + + switch (io->write_state) { + case SOUP_MESSAGE_IO_STATE_HEADERS: + if (io->mode == SOUP_MESSAGE_IO_SERVER && + io->read_state == SOUP_MESSAGE_IO_STATE_BLOCKING && + msg->status_code == 0) { + /* Client requested "Expect: 100-continue", and + * server did not set an error. + */ + soup_message_set_status (msg, SOUP_STATUS_CONTINUE); + } + + if (!io->write_buf->len) { + io->get_headers_cb (msg, io->write_buf, + &io->write_encoding, + io->header_data); + } + + while (io->written < io->write_buf->len) { + nwrote = g_pollable_stream_write (io->ostream, + io->write_buf->str + io->written, + io->write_buf->len - io->written, + blocking, + cancellable, error); + if (nwrote == -1) + return FALSE; + io->written += nwrote; + } + + io->written = 0; + g_string_truncate (io->write_buf, 0); + + if (io->mode == SOUP_MESSAGE_IO_SERVER && + SOUP_STATUS_IS_INFORMATIONAL (msg->status_code)) { + if (msg->status_code == SOUP_STATUS_CONTINUE) { + /* Stop and wait for the body now */ + io->write_state = + SOUP_MESSAGE_IO_STATE_BLOCKING; + io->read_state = SOUP_MESSAGE_IO_STATE_BODY_START; + } else { + /* We just wrote a 1xx response + * header, so stay in STATE_HEADERS. + * (The caller will pause us from the + * wrote_informational callback if he + * is not ready to send the final + * response.) + */ + } + + soup_message_wrote_informational (msg); + + /* If this was "101 Switching Protocols", then + * the server probably stole the connection... + */ + if (io != priv->io_data) + return FALSE; + + soup_message_cleanup_response (msg); + break; + } + + if (io->write_encoding == SOUP_ENCODING_CONTENT_LENGTH) { + SoupMessageHeaders *hdrs = + (io->mode == SOUP_MESSAGE_IO_CLIENT) ? + msg->request_headers : msg->response_headers; + io->write_length = soup_message_headers_get_content_length (hdrs); + } + + if (io->mode == SOUP_MESSAGE_IO_CLIENT && + soup_message_headers_get_expectations (msg->request_headers) & SOUP_EXPECTATION_CONTINUE) { + /* Need to wait for the Continue response */ + io->write_state = SOUP_MESSAGE_IO_STATE_BLOCKING; + io->read_state = SOUP_MESSAGE_IO_STATE_HEADERS; + } else { + io->write_state = SOUP_MESSAGE_IO_STATE_BODY_START; + + /* If the client was waiting for a Continue + * but we sent something else, then they're + * now done writing. + */ + if (io->mode == SOUP_MESSAGE_IO_SERVER && + io->read_state == SOUP_MESSAGE_IO_STATE_BLOCKING) + io->read_state = SOUP_MESSAGE_IO_STATE_DONE; + } + + soup_message_wrote_headers (msg); + break; + + + case SOUP_MESSAGE_IO_STATE_BODY_START: + io->body_ostream = soup_body_output_stream_new (io->ostream, + io->write_encoding, + io->write_length); + io->write_state = SOUP_MESSAGE_IO_STATE_BODY; + break; + + + case SOUP_MESSAGE_IO_STATE_BODY: + if (!io->write_length && + io->write_encoding != SOUP_ENCODING_EOF && + io->write_encoding != SOUP_ENCODING_CHUNKED) { + io->write_state = SOUP_MESSAGE_IO_STATE_BODY_FLUSH; + break; + } + + if (!io->write_chunk) { + io->write_chunk = soup_message_body_get_chunk (io->write_body, io->write_body_offset); + if (!io->write_chunk) { + g_return_val_if_fail (!io->item || !io->item->new_api, FALSE); + soup_message_io_pause (msg); + return FALSE; + } + if (!io->write_chunk->length) { + io->write_state = SOUP_MESSAGE_IO_STATE_BODY_FLUSH; + break; + } + } + + nwrote = g_pollable_stream_write (io->body_ostream, + io->write_chunk->data + io->written, + io->write_chunk->length - io->written, + blocking, + cancellable, error); + if (nwrote == -1) + return FALSE; + + chunk = soup_buffer_new_subbuffer (io->write_chunk, + io->written, nwrote); + io->written += nwrote; + if (io->write_length) + io->write_length -= nwrote; + + if (io->written == io->write_chunk->length) + io->write_state = SOUP_MESSAGE_IO_STATE_BODY_DATA; + + soup_message_wrote_body_data (msg, chunk); + soup_buffer_free (chunk); + break; + + + case SOUP_MESSAGE_IO_STATE_BODY_DATA: + io->written = 0; + if (io->write_chunk->length == 0) { + io->write_state = SOUP_MESSAGE_IO_STATE_BODY_FLUSH; + break; + } + + if (io->mode == SOUP_MESSAGE_IO_SERVER || + priv->msg_flags & SOUP_MESSAGE_CAN_REBUILD) + soup_message_body_wrote_chunk (io->write_body, io->write_chunk); + io->write_body_offset += io->write_chunk->length; + soup_buffer_free (io->write_chunk); + io->write_chunk = NULL; + + io->write_state = SOUP_MESSAGE_IO_STATE_BODY; + soup_message_wrote_chunk (msg); + break; + + + case SOUP_MESSAGE_IO_STATE_BODY_FLUSH: + if (io->body_ostream) { + if (blocking || io->write_encoding != SOUP_ENCODING_CHUNKED) { + if (!g_output_stream_close (io->body_ostream, cancellable, error)) + return FALSE; + g_clear_object (&io->body_ostream); + } else { + io->async_close_wait = g_cancellable_new (); + if (io->async_context) + g_main_context_push_thread_default (io->async_context); + g_output_stream_close_async (io->body_ostream, + G_PRIORITY_DEFAULT, cancellable, + closed_async, g_object_ref (msg)); + if (io->async_context) + g_main_context_pop_thread_default (io->async_context); + } + } + + io->write_state = SOUP_MESSAGE_IO_STATE_BODY_DONE; + break; + + + case SOUP_MESSAGE_IO_STATE_BODY_DONE: + io->write_state = SOUP_MESSAGE_IO_STATE_FINISHING; + soup_message_wrote_body (msg); + break; + + + case SOUP_MESSAGE_IO_STATE_FINISHING: + io->write_state = SOUP_MESSAGE_IO_STATE_DONE; + + if (io->mode == SOUP_MESSAGE_IO_CLIENT) + io->read_state = SOUP_MESSAGE_IO_STATE_HEADERS; + break; + + + default: + g_return_val_if_reached (FALSE); + } + + return TRUE; +} + +/* Attempts to push forward the reading side of @msg's I/O. Returns + * %TRUE if it manages to make some progress, and it is likely that + * further progress can be made. Returns %FALSE if it has reached a + * stopping point of some sort (need input from the application, + * socket not readable, read is complete, etc). + */ +static gboolean +io_read (SoupMessage *msg, gboolean blocking, + GCancellable *cancellable, GError **error) +{ + SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); + SoupMessageIOData *io = priv->io_data; + guchar *stack_buf = NULL; + gssize nread; + SoupBuffer *buffer; + guint status; + + switch (io->read_state) { + case SOUP_MESSAGE_IO_STATE_HEADERS: + if (!read_headers (msg, blocking, cancellable, error)) + return FALSE; + + status = io->parse_headers_cb (msg, (char *)io->read_header_buf->data, + io->read_header_buf->len, + &io->read_encoding, + io->header_data, error); + g_byte_array_set_size (io->read_header_buf, 0); + + if (status != SOUP_STATUS_OK) { + /* Either we couldn't parse the headers, or they + * indicated something that would mean we wouldn't + * be able to parse the body. (Eg, unknown + * Transfer-Encoding.). Skip the rest of the + * reading, and make sure the connection gets + * closed when we're done. + */ + soup_message_set_status (msg, status); + soup_message_headers_append (msg->request_headers, + "Connection", "close"); + io->read_state = SOUP_MESSAGE_IO_STATE_FINISHING; + break; + } + + if (io->mode == SOUP_MESSAGE_IO_CLIENT && + SOUP_STATUS_IS_INFORMATIONAL (msg->status_code)) { + if (msg->status_code == SOUP_STATUS_CONTINUE && + io->write_state == SOUP_MESSAGE_IO_STATE_BLOCKING) { + /* Pause the reader, unpause the writer */ + io->read_state = + SOUP_MESSAGE_IO_STATE_BLOCKING; + io->write_state = + SOUP_MESSAGE_IO_STATE_BODY_START; + } else { + /* Just stay in HEADERS */ + io->read_state = SOUP_MESSAGE_IO_STATE_HEADERS; + } + + /* Informational responses have no bodies, so + * bail out here rather than parsing encoding, etc + */ + soup_message_got_informational (msg); + + /* If this was "101 Switching Protocols", then + * the session may have stolen the connection... + */ + if (io != priv->io_data) + return FALSE; + + soup_message_cleanup_response (msg); + break; + } else if (io->mode == SOUP_MESSAGE_IO_SERVER && + soup_message_headers_get_expectations (msg->request_headers) & SOUP_EXPECTATION_CONTINUE) { + /* We must return a status code and response + * headers to the client; either an error to + * be set by a got-headers handler below, or + * else %SOUP_STATUS_CONTINUE otherwise. + */ + io->write_state = SOUP_MESSAGE_IO_STATE_HEADERS; + io->read_state = SOUP_MESSAGE_IO_STATE_BLOCKING; + } else { + io->read_state = SOUP_MESSAGE_IO_STATE_BODY_START; + + /* If the client was waiting for a Continue + * but got something else, then it's done + * writing. + */ + if (io->mode == SOUP_MESSAGE_IO_CLIENT && + io->write_state == SOUP_MESSAGE_IO_STATE_BLOCKING) + io->write_state = SOUP_MESSAGE_IO_STATE_FINISHING; + } + + if (io->read_encoding == SOUP_ENCODING_CONTENT_LENGTH) { + SoupMessageHeaders *hdrs = + (io->mode == SOUP_MESSAGE_IO_CLIENT) ? + msg->response_headers : msg->request_headers; + io->read_length = soup_message_headers_get_content_length (hdrs); + + if (io->mode == SOUP_MESSAGE_IO_CLIENT && + !soup_message_is_keepalive (msg)) { + /* Some servers suck and send + * incorrect Content-Length values, so + * allow EOF termination in this case + * (iff the message is too short) too. + */ + io->read_encoding = SOUP_ENCODING_EOF; + } + } else + io->read_length = -1; + + soup_message_got_headers (msg); + break; + + + case SOUP_MESSAGE_IO_STATE_BODY_START: + if (!io->body_istream) { + GInputStream *body_istream = soup_body_input_stream_new (G_INPUT_STREAM (io->istream), + io->read_encoding, + io->read_length); + + /* TODO: server-side messages do not have a io->item. This means + * that we cannot use content processors for them right now. + */ + if (io->mode == SOUP_MESSAGE_IO_CLIENT) { + io->body_istream = soup_message_setup_body_istream (body_istream, msg, + io->item->session, + SOUP_STAGE_MESSAGE_BODY); + g_object_unref (body_istream); + } else { + io->body_istream = body_istream; + } + } + + if (priv->sniffer) { + SoupContentSnifferStream *sniffer_stream = SOUP_CONTENT_SNIFFER_STREAM (io->body_istream); + const char *content_type; + GHashTable *params; + + if (!soup_content_sniffer_stream_is_ready (sniffer_stream, blocking, + cancellable, error)) + return FALSE; + + content_type = soup_content_sniffer_stream_sniff (sniffer_stream, ¶ms); + soup_message_content_sniffed (msg, content_type, params); + } + + io->read_state = SOUP_MESSAGE_IO_STATE_BODY; + break; + + + case SOUP_MESSAGE_IO_STATE_BODY: + if (priv->chunk_allocator) { + buffer = priv->chunk_allocator (msg, io->read_length, priv->chunk_allocator_data); + if (!buffer) { + g_return_val_if_fail (!io->item || !io->item->new_api, FALSE); + soup_message_io_pause (msg); + return FALSE; + } + } else { + if (!stack_buf) + stack_buf = alloca (RESPONSE_BLOCK_SIZE); + buffer = soup_buffer_new (SOUP_MEMORY_TEMPORARY, + stack_buf, + RESPONSE_BLOCK_SIZE); + } + + nread = g_pollable_stream_read (io->body_istream, + (guchar *)buffer->data, + buffer->length, + blocking, + cancellable, error); + if (nread > 0) { + buffer->length = nread; + soup_message_body_got_chunk (io->read_body, buffer); + soup_message_got_chunk (msg, buffer); + soup_buffer_free (buffer); + break; + } + + soup_buffer_free (buffer); + if (nread == -1) + return FALSE; + + /* else nread == 0 */ + io->read_state = SOUP_MESSAGE_IO_STATE_BODY_DONE; + break; + + + case SOUP_MESSAGE_IO_STATE_BODY_DONE: + io->read_state = SOUP_MESSAGE_IO_STATE_FINISHING; + soup_message_got_body (msg); + break; + + + case SOUP_MESSAGE_IO_STATE_FINISHING: + io->read_state = SOUP_MESSAGE_IO_STATE_DONE; + + if (io->mode == SOUP_MESSAGE_IO_SERVER) + io->write_state = SOUP_MESSAGE_IO_STATE_HEADERS; + break; + + + default: + g_return_val_if_reached (FALSE); + } + + return TRUE; +} + +typedef struct { + GSource source; + SoupMessage *msg; + gboolean paused; +} SoupMessageSource; + +static gboolean +message_source_check (GSource *source) +{ + SoupMessageSource *message_source = (SoupMessageSource *)source; + + if (message_source->paused) { + SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (message_source->msg); + SoupMessageIOData *io = priv->io_data; + + if (io && io->paused) + return FALSE; + else + return TRUE; + } else + return FALSE; +} + +static gboolean +message_source_prepare (GSource *source, + gint *timeout) +{ + *timeout = -1; + return message_source_check (source); +} + +static gboolean +message_source_dispatch (GSource *source, + GSourceFunc callback, + gpointer user_data) +{ + SoupMessageSourceFunc func = (SoupMessageSourceFunc)callback; + SoupMessageSource *message_source = (SoupMessageSource *)source; + + return (*func) (message_source->msg, user_data); +} + +static void +message_source_finalize (GSource *source) +{ + SoupMessageSource *message_source = (SoupMessageSource *)source; + + g_object_unref (message_source->msg); +} + +static gboolean +message_source_closure_callback (SoupMessage *msg, + gpointer data) +{ + GClosure *closure = data; + GValue param = G_VALUE_INIT; + GValue result_value = G_VALUE_INIT; + gboolean result; + + g_value_init (&result_value, G_TYPE_BOOLEAN); + + g_value_init (¶m, SOUP_TYPE_MESSAGE); + g_value_set_object (¶m, msg); + + g_closure_invoke (closure, &result_value, 1, ¶m, NULL); + + result = g_value_get_boolean (&result_value); + g_value_unset (&result_value); + g_value_unset (¶m); + + return result; +} + +static GSourceFuncs message_source_funcs = +{ + message_source_prepare, + message_source_check, + message_source_dispatch, + message_source_finalize, + (GSourceFunc)message_source_closure_callback, + (GSourceDummyMarshal)g_cclosure_marshal_generic, +}; + +GSource * +soup_message_io_get_source (SoupMessage *msg, GCancellable *cancellable, + SoupMessageSourceFunc callback, gpointer user_data) +{ + SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); + SoupMessageIOData *io = priv->io_data; + GSource *base_source, *source; + SoupMessageSource *message_source; + + if (!io) { + base_source = g_timeout_source_new (0); + } else if (io->paused) { + base_source = NULL; + } else if (io->async_close_wait) { + base_source = g_cancellable_source_new (io->async_close_wait); + } else if (SOUP_MESSAGE_IO_STATE_POLLABLE (io->read_state)) { + GPollableInputStream *istream; + + if (io->body_istream) + istream = G_POLLABLE_INPUT_STREAM (io->body_istream); + else + istream = G_POLLABLE_INPUT_STREAM (io->istream); + base_source = g_pollable_input_stream_create_source (istream, cancellable); + } else if (SOUP_MESSAGE_IO_STATE_POLLABLE (io->write_state)) { + GPollableOutputStream *ostream; + + if (io->body_ostream) + ostream = G_POLLABLE_OUTPUT_STREAM (io->body_ostream); + else + ostream = G_POLLABLE_OUTPUT_STREAM (io->ostream); + base_source = g_pollable_output_stream_create_source (ostream, cancellable); + } else + base_source = g_timeout_source_new (0); + + source = g_source_new (&message_source_funcs, + sizeof (SoupMessageSource)); + g_source_set_name (source, "SoupMessageSource"); + message_source = (SoupMessageSource *)source; + message_source->msg = g_object_ref (msg); + message_source->paused = io && io->paused; + + if (base_source) { + g_source_set_dummy_callback (base_source); + g_source_add_child_source (source, base_source); + g_source_unref (base_source); + } + g_source_set_callback (source, (GSourceFunc) callback, user_data, NULL); + return source; +} + +static gboolean +request_is_restartable (SoupMessage *msg, GError *error) +{ + SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); + SoupMessageIOData *io = priv->io_data; + + if (!io) + return FALSE; + + return (io->mode == SOUP_MESSAGE_IO_CLIENT && + io->read_state <= SOUP_MESSAGE_IO_STATE_HEADERS && + io->read_header_buf->len == 0 && + soup_connection_get_ever_used (io->item->conn) && + !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_TIMED_OUT) && + !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK) && + error->domain != G_TLS_ERROR && + SOUP_METHOD_IS_IDEMPOTENT (msg->method)); +} + +static gboolean +io_run_until (SoupMessage *msg, gboolean blocking, + SoupMessageIOState read_state, SoupMessageIOState write_state, + GCancellable *cancellable, GError **error) +{ + SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); + SoupMessageIOData *io = priv->io_data; + gboolean progress = TRUE, done; + GError *my_error = NULL; + + if (g_cancellable_set_error_if_cancelled (cancellable, error)) + return FALSE; + else if (!io) { + g_set_error_literal (error, G_IO_ERROR, + G_IO_ERROR_CANCELLED, + _("Operation was cancelled")); + return FALSE; + } + + g_object_ref (msg); + + while (progress && priv->io_data == io && !io->paused && !io->async_close_wait && + (io->read_state < read_state || io->write_state < write_state)) { + + if (SOUP_MESSAGE_IO_STATE_ACTIVE (io->read_state)) + progress = io_read (msg, blocking, cancellable, &my_error); + else if (SOUP_MESSAGE_IO_STATE_ACTIVE (io->write_state)) + progress = io_write (msg, blocking, cancellable, &my_error); + else + progress = FALSE; + } + + if (my_error) { + if (request_is_restartable (msg, my_error)) { + /* Connection got closed, but we can safely try again */ + g_error_free (my_error); + g_set_error_literal (error, SOUP_HTTP_ERROR, + SOUP_STATUS_TRY_AGAIN, ""); + g_object_unref (msg); + return FALSE; + } + + g_propagate_error (error, my_error); + g_object_unref (msg); + return FALSE; + } else if (priv->io_data != io) { + g_set_error_literal (error, G_IO_ERROR, + G_IO_ERROR_CANCELLED, + _("Operation was cancelled")); + g_object_unref (msg); + return FALSE; + } else if (!io->async_close_wait && + g_cancellable_set_error_if_cancelled (cancellable, error)) { + g_object_unref (msg); + return FALSE; + } + + done = (io->read_state >= read_state && + io->write_state >= write_state); + + if (!blocking && !done) { + g_set_error_literal (error, G_IO_ERROR, + G_IO_ERROR_WOULD_BLOCK, + _("Operation would block")); + g_object_unref (msg); + return FALSE; + } + + g_object_unref (msg); + return done; +} + +static gboolean +io_run_ready (SoupMessage *msg, gpointer user_data) +{ + io_run (msg, FALSE); + return FALSE; +} + +static void +io_run (SoupMessage *msg, gboolean blocking) +{ + SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); + SoupMessageIOData *io = priv->io_data; + GError *error = NULL; + GCancellable *cancellable; + + if (io->io_source) { + g_source_destroy (io->io_source); + g_source_unref (io->io_source); + io->io_source = NULL; + } + + g_object_ref (msg); + cancellable = io->cancellable ? g_object_ref (io->cancellable) : NULL; + + if (io_run_until (msg, blocking, + SOUP_MESSAGE_IO_STATE_DONE, + SOUP_MESSAGE_IO_STATE_DONE, + cancellable, &error)) { + soup_message_io_finished (msg); + } else if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) { + g_clear_error (&error); + io->io_source = soup_message_io_get_source (msg, NULL, io_run_ready, msg); + g_source_attach (io->io_source, io->async_context); + } else if (error && priv->io_data == io) { + if (g_error_matches (error, SOUP_HTTP_ERROR, SOUP_STATUS_TRY_AGAIN)) + io->item->state = SOUP_MESSAGE_RESTARTING; + else if (error->domain == G_TLS_ERROR) { + soup_message_set_status_full (msg, + SOUP_STATUS_SSL_FAILED, + error->message); + } else if (!SOUP_STATUS_IS_TRANSPORT_ERROR (msg->status_code)) + soup_message_set_status (msg, SOUP_STATUS_IO_ERROR); + + g_error_free (error); + soup_message_io_finished (msg); + } else if (error) + g_error_free (error); + + g_object_unref (msg); + g_clear_object (&cancellable); +} + +gboolean +soup_message_io_run_until_write (SoupMessage *msg, gboolean blocking, + GCancellable *cancellable, GError **error) +{ + return io_run_until (msg, blocking, + SOUP_MESSAGE_IO_STATE_ANY, + SOUP_MESSAGE_IO_STATE_BODY, + cancellable, error); +} + +gboolean +soup_message_io_run_until_read (SoupMessage *msg, gboolean blocking, + GCancellable *cancellable, GError **error) +{ + return io_run_until (msg, blocking, + SOUP_MESSAGE_IO_STATE_BODY, + SOUP_MESSAGE_IO_STATE_ANY, + cancellable, error); +} + +gboolean +soup_message_io_run_until_finish (SoupMessage *msg, + gboolean blocking, + GCancellable *cancellable, + GError **error) +{ + SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); + SoupMessageIOData *io = priv->io_data; + gboolean success; + + g_object_ref (msg); + + if (io) { + g_return_val_if_fail (io->mode == SOUP_MESSAGE_IO_CLIENT, FALSE); + + if (io->read_state < SOUP_MESSAGE_IO_STATE_BODY_DONE) + io->read_state = SOUP_MESSAGE_IO_STATE_FINISHING; + } + + success = io_run_until (msg, blocking, + SOUP_MESSAGE_IO_STATE_DONE, + SOUP_MESSAGE_IO_STATE_DONE, + cancellable, error); + + g_object_unref (msg); + return success; +} + +static void +client_stream_eof (SoupClientInputStream *stream, gpointer user_data) +{ + SoupMessage *msg = user_data; + SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); + SoupMessageIOData *io = priv->io_data; + + if (io && io->read_state == SOUP_MESSAGE_IO_STATE_BODY) + io->read_state = SOUP_MESSAGE_IO_STATE_BODY_DONE; +} + +GInputStream * +soup_message_io_get_response_istream (SoupMessage *msg, + GError **error) +{ + SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); + SoupMessageIOData *io = priv->io_data; + GInputStream *client_stream; + + g_return_val_if_fail (io->mode == SOUP_MESSAGE_IO_CLIENT, NULL); + + if (SOUP_STATUS_IS_TRANSPORT_ERROR (msg->status_code)) { + g_set_error_literal (error, SOUP_HTTP_ERROR, + msg->status_code, msg->reason_phrase); + return NULL; + } + + client_stream = soup_client_input_stream_new (io->body_istream, msg); + g_signal_connect (client_stream, "eof", + G_CALLBACK (client_stream_eof), msg); + + return client_stream; +} + + +static SoupMessageIOData * +new_iostate (SoupMessage *msg, GIOStream *iostream, + GMainContext *async_context, SoupMessageIOMode mode, + SoupMessageGetHeadersFn get_headers_cb, + SoupMessageParseHeadersFn parse_headers_cb, + gpointer header_data, + SoupMessageCompletionFn completion_cb, + gpointer completion_data) +{ + SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); + SoupMessageIOData *io; + + io = g_slice_new0 (SoupMessageIOData); + io->mode = mode; + io->get_headers_cb = get_headers_cb; + io->parse_headers_cb = parse_headers_cb; + io->header_data = header_data; + io->completion_cb = completion_cb; + io->completion_data = completion_data; + + io->iostream = g_object_ref (iostream); + io->istream = SOUP_FILTER_INPUT_STREAM (g_io_stream_get_input_stream (iostream)); + io->ostream = g_io_stream_get_output_stream (iostream); + + if (async_context) + io->async_context = g_main_context_ref (async_context); + + io->read_header_buf = g_byte_array_new (); + io->write_buf = g_string_new (NULL); + + io->read_state = SOUP_MESSAGE_IO_STATE_NOT_STARTED; + io->write_state = SOUP_MESSAGE_IO_STATE_NOT_STARTED; + + if (priv->io_data) + soup_message_io_cleanup (msg); + priv->io_data = io; + return io; +} + +void +soup_message_io_client (SoupMessageQueueItem *item, + GIOStream *iostream, + GMainContext *async_context, + SoupMessageGetHeadersFn get_headers_cb, + SoupMessageParseHeadersFn parse_headers_cb, + gpointer header_data, + SoupMessageCompletionFn completion_cb, + gpointer completion_data) +{ + SoupMessageIOData *io; + + io = new_iostate (item->msg, iostream, async_context, + SOUP_MESSAGE_IO_CLIENT, + get_headers_cb, parse_headers_cb, header_data, + completion_cb, completion_data); + + io->item = item; + soup_message_queue_item_ref (item); + io->cancellable = item->cancellable; + + io->read_body = item->msg->response_body; + io->write_body = item->msg->request_body; + + io->write_state = SOUP_MESSAGE_IO_STATE_HEADERS; + + if (!item->new_api) { + gboolean blocking = + SOUP_IS_SESSION_SYNC (item->session) || + (!SOUP_IS_SESSION_ASYNC (item->session) && !item->async); + io_run (item->msg, blocking); + } +} + +void +soup_message_io_server (SoupMessage *msg, + GIOStream *iostream, GMainContext *async_context, + SoupMessageGetHeadersFn get_headers_cb, + SoupMessageParseHeadersFn parse_headers_cb, + gpointer header_data, + SoupMessageCompletionFn completion_cb, + gpointer completion_data) +{ + SoupMessageIOData *io; + + io = new_iostate (msg, iostream, async_context, + SOUP_MESSAGE_IO_SERVER, + get_headers_cb, parse_headers_cb, header_data, + completion_cb, completion_data); + + io->read_body = msg->request_body; + io->write_body = msg->response_body; + + io->read_state = SOUP_MESSAGE_IO_STATE_HEADERS; + io_run (msg, FALSE); +} + +void +soup_message_io_pause (SoupMessage *msg) +{ + SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); + SoupMessageIOData *io = priv->io_data; + + g_return_if_fail (io != NULL); + + if (io->item && io->item->new_api) + g_return_if_fail (io->read_state < SOUP_MESSAGE_IO_STATE_BODY); + + if (io->io_source) { + g_source_destroy (io->io_source); + g_source_unref (io->io_source); + io->io_source = NULL; + } + + if (io->unpause_source) { + g_source_destroy (io->unpause_source); + g_source_unref (io->unpause_source); + io->unpause_source = NULL; + } + + io->paused = TRUE; +} + +static gboolean +io_unpause_internal (gpointer msg) +{ + SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); + SoupMessageIOData *io = priv->io_data; + + g_return_val_if_fail (io != NULL, FALSE); + + g_clear_pointer (&io->unpause_source, g_source_unref); + io->paused = FALSE; + + if (io->io_source) + return FALSE; + + io_run (msg, FALSE); + return FALSE; +} + +void +soup_message_io_unpause (SoupMessage *msg) +{ + SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); + SoupMessageIOData *io = priv->io_data; + + g_return_if_fail (io != NULL); + + if (io->item && io->item->new_api) { + g_return_if_fail (io->read_state < SOUP_MESSAGE_IO_STATE_BODY); + io->paused = FALSE; + return; + } + + if (!io->unpause_source) { + io->unpause_source = soup_add_completion_reffed (io->async_context, + io_unpause_internal, msg, NULL); + } +} + +/** + * soup_message_io_in_progress: + * @msg: a #SoupMessage + * + * Tests whether or not I/O is currently in progress on @msg. + * + * Return value: whether or not I/O is currently in progress. + **/ +gboolean +soup_message_io_in_progress (SoupMessage *msg) +{ + SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); + + return priv->io_data != NULL; +} diff --git a/libsoup/soup-message-private.h b/libsoup/soup-message-private.h new file mode 100644 index 0000000..71adac7 --- /dev/null +++ b/libsoup/soup-message-private.h @@ -0,0 +1,164 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2000-2003, Ximian, Inc. + */ + +#ifndef SOUP_MESSAGE_PRIVATE_H +#define SOUP_MESSAGE_PRIVATE_H 1 + +#include "soup-message.h" +#include "soup-auth.h" +#include "soup-content-processor.h" +#include "soup-content-sniffer.h" +#include "soup-session.h" + +typedef struct { + gpointer io_data; + + SoupChunkAllocator chunk_allocator; + gpointer chunk_allocator_data; + GDestroyNotify chunk_allocator_dnotify; + + guint msg_flags; + gboolean server_side; + + SoupContentSniffer *sniffer; + gsize bytes_for_sniffing; + + SoupHTTPVersion http_version, orig_http_version; + + SoupURI *uri; + SoupAddress *addr; + + SoupAuth *auth, *proxy_auth; + SoupConnection *connection; + + GSList *disabled_features; + + SoupURI *first_party; + + GTlsCertificate *tls_certificate; + GTlsCertificateFlags tls_errors; + + SoupRequest *request; + + SoupMessagePriority priority; +} SoupMessagePrivate; +#define SOUP_MESSAGE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUP_TYPE_MESSAGE, SoupMessagePrivate)) + +void soup_message_cleanup_response (SoupMessage *msg); + +typedef enum { + SOUP_MESSAGE_IO_COMPLETE, + SOUP_MESSAGE_IO_INTERRUPTED, + SOUP_MESSAGE_IO_STOLEN +} SoupMessageIOCompletion; + +typedef void (*SoupMessageGetHeadersFn) (SoupMessage *msg, + GString *headers, + SoupEncoding *encoding, + gpointer user_data); +typedef guint (*SoupMessageParseHeadersFn)(SoupMessage *msg, + char *headers, + guint header_len, + SoupEncoding *encoding, + gpointer user_data, + GError **error); +typedef void (*SoupMessageCompletionFn) (SoupMessage *msg, + SoupMessageIOCompletion completion, + gpointer user_data); + + +void soup_message_send_request (SoupMessageQueueItem *item, + SoupMessageCompletionFn completion_cb, + gpointer user_data); +void soup_message_read_request (SoupMessage *msg, + SoupSocket *sock, + gboolean use_thread_context, + SoupMessageCompletionFn completion_cb, + gpointer user_data); + +void soup_message_io_client (SoupMessageQueueItem *item, + GIOStream *iostream, + GMainContext *async_context, + SoupMessageGetHeadersFn get_headers_cb, + SoupMessageParseHeadersFn parse_headers_cb, + gpointer headers_data, + SoupMessageCompletionFn completion_cb, + gpointer user_data); +void soup_message_io_server (SoupMessage *msg, + GIOStream *iostream, + GMainContext *async_context, + SoupMessageGetHeadersFn get_headers_cb, + SoupMessageParseHeadersFn parse_headers_cb, + gpointer headers_data, + SoupMessageCompletionFn completion_cb, + gpointer user_data); + +/* Auth handling */ +void soup_message_set_auth (SoupMessage *msg, + SoupAuth *auth); +SoupAuth *soup_message_get_auth (SoupMessage *msg); +void soup_message_set_proxy_auth (SoupMessage *msg, + SoupAuth *auth); +SoupAuth *soup_message_get_proxy_auth (SoupMessage *msg); + +/* I/O */ +void soup_message_io_stop (SoupMessage *msg); +void soup_message_io_finished (SoupMessage *msg); +/* This is supposed to be private, but there are programs that rely on it + * being exported. See bug #687758, #687468. + */ +SOUP_AVAILABLE_IN_2_4 +void soup_message_io_cleanup (SoupMessage *msg); +void soup_message_io_pause (SoupMessage *msg); +void soup_message_io_unpause (SoupMessage *msg); +gboolean soup_message_io_in_progress (SoupMessage *msg); +GIOStream *soup_message_io_steal (SoupMessage *msg); + + +gboolean soup_message_io_run_until_write (SoupMessage *msg, + gboolean blocking, + GCancellable *cancellable, + GError **error); +gboolean soup_message_io_run_until_read (SoupMessage *msg, + gboolean blocking, + GCancellable *cancellable, + GError **error); +gboolean soup_message_io_run_until_finish (SoupMessage *msg, + gboolean blocking, + GCancellable *cancellable, + GError **error); + +typedef gboolean (*SoupMessageSourceFunc) (SoupMessage *, gpointer); +GSource *soup_message_io_get_source (SoupMessage *msg, + GCancellable *cancellable, + SoupMessageSourceFunc callback, + gpointer user_data); + +GInputStream *soup_message_io_get_response_istream (SoupMessage *msg, + GError **error); + +gboolean soup_message_disables_feature (SoupMessage *msg, + gpointer feature); + +void soup_message_set_https_status (SoupMessage *msg, + SoupConnection *conn); + +void soup_message_network_event (SoupMessage *msg, + GSocketClientEvent event, + GIOStream *connection); + +GInputStream *soup_message_setup_body_istream (GInputStream *body_stream, + SoupMessage *msg, + SoupSession *session, + SoupProcessingStage start_at_stage); + +void soup_message_set_soup_request (SoupMessage *msg, + SoupRequest *req); + +SoupConnection *soup_message_get_connection (SoupMessage *msg); +void soup_message_set_connection (SoupMessage *msg, + SoupConnection *conn); + +#endif /* SOUP_MESSAGE_PRIVATE_H */ diff --git a/libsoup/soup-message-queue.c b/libsoup/soup-message-queue.c new file mode 100644 index 0000000..436f3eb --- /dev/null +++ b/libsoup/soup-message-queue.c @@ -0,0 +1,303 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-message-queue.c: Message queue + * + * Copyright (C) 2003 Novell, Inc. + * Copyright (C) 2008 Red Hat, Inc. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "soup-message-queue.h" +#include "soup.h" + +/* This is an internal structure used by #SoupSession and its + * subclasses to keep track of the status of messages currently being + * processed. + * + * The #SoupMessageQueue itself is mostly just a linked list of + * #SoupMessageQueueItem, with some added cleverness to allow the list + * to be walked safely while other threads / re-entrant loops are + * adding items to and removing items from it. In particular, this is + * handled by refcounting items and then keeping "removed" items in + * the list until their ref_count drops to 0, but skipping over the + * "removed" ones when walking the queue. + **/ + +struct _SoupMessageQueue { + SoupSession *session; + + GMutex mutex; + SoupMessageQueueItem *head, *tail; +}; + +SoupMessageQueue * +soup_message_queue_new (SoupSession *session) +{ + SoupMessageQueue *queue; + + queue = g_slice_new0 (SoupMessageQueue); + queue->session = session; + g_mutex_init (&queue->mutex); + return queue; +} + +void +soup_message_queue_destroy (SoupMessageQueue *queue) +{ + g_return_if_fail (queue->head == NULL); + + g_mutex_clear (&queue->mutex); + g_slice_free (SoupMessageQueue, queue); +} + +static void +queue_message_restarted (SoupMessage *msg, gpointer user_data) +{ + SoupMessageQueueItem *item = user_data; + + g_cancellable_reset (item->cancellable); +} + +/** + * soup_message_queue_append: + * @queue: a #SoupMessageQueue + * @msg: a #SoupMessage + * @callback: the callback for @msg + * @user_data: the data to pass to @callback + * + * Creates a new #SoupMessageQueueItem and appends it to @queue. + * + * Return value: the new item, which you must unref with + * soup_message_queue_unref_item() when you are done with. + **/ +SoupMessageQueueItem * +soup_message_queue_append (SoupMessageQueue *queue, SoupMessage *msg, + SoupSessionCallback callback, gpointer user_data) +{ + SoupMessageQueueItem *item; + + item = g_slice_new0 (SoupMessageQueueItem); + item->session = g_object_ref (queue->session); + item->async_context = soup_session_get_async_context (item->session); + if (item->async_context) + g_main_context_ref (item->async_context); + item->queue = queue; + item->msg = g_object_ref (msg); + item->callback = callback; + item->callback_data = user_data; + item->cancellable = g_cancellable_new (); + item->priority = soup_message_get_priority (msg); + + g_signal_connect (msg, "restarted", + G_CALLBACK (queue_message_restarted), item); + + /* Note: the initial ref_count of 1 represents the caller's + * ref; the queue's own ref is indicated by the absence of the + * "removed" flag. + */ + item->ref_count = 1; + + g_mutex_lock (&queue->mutex); + if (queue->head) { + SoupMessageQueueItem *it = queue->head; + + while (it && it->priority >= item->priority) + it = it->next; + + if (!it) { + if (queue->tail) { + queue->tail->next = item; + item->prev = queue->tail; + } else + queue->head = item; + queue->tail = item; + } else { + if (it != queue->head) + it->prev->next = item; + else + queue->head = item; + item->prev = it->prev; + it->prev = item; + item->next = it; + } + } else + queue->head = queue->tail = item; + + g_mutex_unlock (&queue->mutex); + return item; +} + +/** + * soup_message_queue_item_ref: + * @item: a #SoupMessageQueueItem + * + * Refs @item. + **/ +void +soup_message_queue_item_ref (SoupMessageQueueItem *item) +{ + g_mutex_lock (&item->queue->mutex); + item->ref_count++; + g_mutex_unlock (&item->queue->mutex); +} + +/** + * soup_message_queue_item_unref: + * @item: a #SoupMessageQueueItem + * + * Unrefs @item; use this on a #SoupMessageQueueItem that you are done + * with (but that you aren't passing to + * soup_message_queue_item_next()). + **/ +void +soup_message_queue_item_unref (SoupMessageQueueItem *item) +{ + g_mutex_lock (&item->queue->mutex); + + /* Decrement the ref_count; if it's still non-zero OR if the + * item is still in the queue, then return. + */ + if (--item->ref_count || !item->removed) { + g_mutex_unlock (&item->queue->mutex); + return; + } + + g_warn_if_fail (item->conn == NULL); + + /* OK, @item is dead. Rewrite @queue around it */ + if (item->prev) + item->prev->next = item->next; + else + item->queue->head = item->next; + if (item->next) + item->next->prev = item->prev; + else + item->queue->tail = item->prev; + + g_mutex_unlock (&item->queue->mutex); + + /* And free it */ + g_signal_handlers_disconnect_by_func (item->msg, + queue_message_restarted, item); + g_object_unref (item->session); + g_object_unref (item->msg); + g_object_unref (item->cancellable); + g_clear_error (&item->error); + g_clear_object (&item->task); + g_clear_pointer (&item->async_context, g_main_context_unref); + if (item->io_source) { + g_source_destroy (item->io_source); + g_source_unref (item->io_source); + } + g_slice_free (SoupMessageQueueItem, item); +} + +/** + * soup_message_queue_lookup: + * @queue: a #SoupMessageQueue + * @msg: a #SoupMessage + * + * Finds the #SoupMessageQueueItem for @msg in @queue. You must unref + * the item with soup_message_queue_unref_item() when you are done + * with it. + * + * Return value: (nullable): the queue item for @msg, or %NULL + **/ +SoupMessageQueueItem * +soup_message_queue_lookup (SoupMessageQueue *queue, SoupMessage *msg) +{ + SoupMessageQueueItem *item; + + g_mutex_lock (&queue->mutex); + + item = queue->tail; + while (item && (item->removed || item->msg != msg)) + item = item->prev; + + if (item) + item->ref_count++; + + g_mutex_unlock (&queue->mutex); + return item; +} + +/** + * soup_message_queue_first: + * @queue: a #SoupMessageQueue + * + * Gets the first item in @queue. You must unref the item by calling + * soup_message_queue_unref_item() on it when you are done. + * (soup_message_queue_next() does this for you automatically, so you + * only need to unref the item yourself if you are not going to + * finishing walking the queue.) + * + * Return value: the first item in @queue. + **/ +SoupMessageQueueItem * +soup_message_queue_first (SoupMessageQueue *queue) +{ + SoupMessageQueueItem *item; + + g_mutex_lock (&queue->mutex); + + item = queue->head; + while (item && item->removed) + item = item->next; + + if (item) + item->ref_count++; + + g_mutex_unlock (&queue->mutex); + return item; +} + +/** + * soup_message_queue_next: + * @queue: a #SoupMessageQueue + * @item: a #SoupMessageQueueItem + * + * Unrefs @item and gets the next item after it in @queue. As with + * soup_message_queue_first(), you must unref the returned item + * yourself with soup_message_queue_unref_item() if you do not finish + * walking the queue. + * + * Return value: the next item in @queue. + **/ +SoupMessageQueueItem * +soup_message_queue_next (SoupMessageQueue *queue, SoupMessageQueueItem *item) +{ + SoupMessageQueueItem *next; + + g_mutex_lock (&queue->mutex); + + next = item->next; + while (next && next->removed) + next = next->next; + if (next) + next->ref_count++; + + g_mutex_unlock (&queue->mutex); + soup_message_queue_item_unref (item); + return next; +} + +/** + * soup_message_queue_remove: + * @queue: a #SoupMessageQueue + * @item: a #SoupMessageQueueItem + * + * Removes @item from @queue. Note that you probably also need to call + * soup_message_queue_unref_item() after this. + **/ +void +soup_message_queue_remove (SoupMessageQueue *queue, SoupMessageQueueItem *item) +{ + g_return_if_fail (!item->removed); + + g_mutex_lock (&queue->mutex); + item->removed = TRUE; + g_mutex_unlock (&queue->mutex); +} diff --git a/libsoup/soup-message-queue.h b/libsoup/soup-message-queue.h new file mode 100644 index 0000000..275ea38 --- /dev/null +++ b/libsoup/soup-message-queue.h @@ -0,0 +1,89 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2003 Novell, Inc. + * Copyright (C) 2008 Red Hat, Inc. + */ + +#ifndef SOUP_MESSAGE_QUEUE_H +#define SOUP_MESSAGE_QUEUE_H 1 + +#include "soup-connection.h" +#include "soup-message.h" +#include "soup-session.h" + +G_BEGIN_DECLS + +typedef enum { + SOUP_MESSAGE_STARTING, + SOUP_MESSAGE_GOT_CONNECTION, + SOUP_MESSAGE_CONNECTING, + SOUP_MESSAGE_CONNECTED, + SOUP_MESSAGE_TUNNELING, + SOUP_MESSAGE_TUNNELED, + SOUP_MESSAGE_READY, + SOUP_MESSAGE_RUNNING, + SOUP_MESSAGE_CACHED, + SOUP_MESSAGE_RESTARTING, + SOUP_MESSAGE_FINISHING, + SOUP_MESSAGE_FINISHED +} SoupMessageQueueItemState; + +struct _SoupMessageQueueItem { + /*< public >*/ + SoupSession *session; + SoupMessageQueue *queue; + SoupMessage *msg; + SoupSessionCallback callback; + gpointer callback_data; + GMainContext *async_context; + + GCancellable *cancellable; + GError *error; + + SoupConnection *conn; + GTask *task; + GSource *io_source; + + guint paused : 1; + guint new_api : 1; + guint io_started : 1; + guint async : 1; + guint async_pending : 1; + guint conn_is_dedicated : 1; + guint connect_only : 1; + guint priority : 3; + guint resend_count : 5; + + SoupMessageQueueItemState state; + + /*< private >*/ + guint removed : 1; + guint ref_count : 31; + SoupMessageQueueItem *prev, *next; + SoupMessageQueueItem *related; +}; + +SoupMessageQueue *soup_message_queue_new (SoupSession *session); +SoupMessageQueueItem *soup_message_queue_append (SoupMessageQueue *queue, + SoupMessage *msg, + SoupSessionCallback callback, + gpointer user_data); + +SoupMessageQueueItem *soup_message_queue_lookup (SoupMessageQueue *queue, + SoupMessage *msg); + +SoupMessageQueueItem *soup_message_queue_first (SoupMessageQueue *queue); +SoupMessageQueueItem *soup_message_queue_next (SoupMessageQueue *queue, + SoupMessageQueueItem *item); + +void soup_message_queue_remove (SoupMessageQueue *queue, + SoupMessageQueueItem *item); + +void soup_message_queue_destroy (SoupMessageQueue *queue); + +void soup_message_queue_item_ref (SoupMessageQueueItem *item); +void soup_message_queue_item_unref (SoupMessageQueueItem *item); + +G_END_DECLS + +#endif /* SOUP_MESSAGE_QUEUE_H */ diff --git a/libsoup/soup-message-server-io.c b/libsoup/soup-message-server-io.c new file mode 100644 index 0000000..35b544c --- /dev/null +++ b/libsoup/soup-message-server-io.c @@ -0,0 +1,310 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-message-server-io.c: server-side request/response + * + * Copyright (C) 2000-2003, Ximian, Inc. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include + +#include "soup.h" +#include "soup-message-private.h" +#include "soup-misc-private.h" +#include "soup-socket-private.h" + +static SoupURI * +parse_connect_authority (const char *req_path) +{ + SoupURI *uri; + char *fake_uri; + + fake_uri = g_strdup_printf ("http://%s", req_path); + uri = soup_uri_new (fake_uri); + g_free (fake_uri); + + if (uri->user || uri->password || + uri->query || uri->fragment || + !uri->host || + (uri->port == 0) || + (strcmp (uri->path, "/") != 0)) { + soup_uri_free (uri); + return NULL; + } + + return uri; +} + +static guint +parse_request_headers (SoupMessage *msg, char *headers, guint headers_len, + SoupEncoding *encoding, gpointer sock, GError **error) +{ + SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); + char *req_method, *req_path, *url; + SoupHTTPVersion version; + const char *req_host; + guint status; + SoupURI *uri; + + status = soup_headers_parse_request (headers, headers_len, + msg->request_headers, + &req_method, + &req_path, + &version); + if (!SOUP_STATUS_IS_SUCCESSFUL (status)) { + if (status == SOUP_STATUS_MALFORMED) { + g_set_error_literal (error, SOUP_REQUEST_ERROR, + SOUP_REQUEST_ERROR_PARSING, + _("Could not parse HTTP request")); + } + return status; + } + + g_object_set (G_OBJECT (msg), + SOUP_MESSAGE_METHOD, req_method, + SOUP_MESSAGE_HTTP_VERSION, version, + NULL); + g_free (req_method); + + /* Handle request body encoding */ + *encoding = soup_message_headers_get_encoding (msg->request_headers); + if (*encoding == SOUP_ENCODING_UNRECOGNIZED) { + if (soup_message_headers_get_list (msg->request_headers, "Transfer-Encoding")) + return SOUP_STATUS_NOT_IMPLEMENTED; + else + return SOUP_STATUS_BAD_REQUEST; + } + + /* Generate correct context for request */ + req_host = soup_message_headers_get_one (msg->request_headers, "Host"); + if (req_host && strchr (req_host, '/')) { + g_free (req_path); + return SOUP_STATUS_BAD_REQUEST; + } + + if (!strcmp (req_path, "*") && req_host) { + /* Eg, "OPTIONS * HTTP/1.1" */ + url = g_strdup_printf ("%s://%s", + soup_socket_is_ssl (sock) ? "https" : "http", + req_host); + uri = soup_uri_new (url); + if (uri) + soup_uri_set_path (uri, "*"); + g_free (url); + } else if (msg->method == SOUP_METHOD_CONNECT) { + /* Authority */ + uri = parse_connect_authority (req_path); + } else if (*req_path != '/') { + /* Absolute URI */ + uri = soup_uri_new (req_path); + } else if (req_host) { + url = g_strdup_printf ("%s://%s%s", + soup_socket_is_ssl (sock) ? "https" : "http", + req_host, req_path); + uri = soup_uri_new (url); + g_free (url); + } else if (priv->http_version == SOUP_HTTP_1_0) { + /* No Host header, no AbsoluteUri */ + SoupAddress *addr = soup_socket_get_local_address (sock); + + uri = soup_uri_new (NULL); + soup_uri_set_scheme (uri, soup_socket_is_ssl (sock) ? + SOUP_URI_SCHEME_HTTPS : + SOUP_URI_SCHEME_HTTP); + soup_uri_set_host (uri, soup_address_get_physical (addr)); + soup_uri_set_port (uri, soup_address_get_port (addr)); + soup_uri_set_path (uri, req_path); + } else + uri = NULL; + + g_free (req_path); + + if (!uri || !uri->host) { + if (uri) + soup_uri_free (uri); + return SOUP_STATUS_BAD_REQUEST; + } + + soup_message_set_uri (msg, uri); + soup_uri_free (uri); + + return SOUP_STATUS_OK; +} + +static void +handle_partial_get (SoupMessage *msg) +{ + SoupRange *ranges; + int nranges; + SoupBuffer *full_response; + guint status; + + /* Make sure the message is set up right for us to return a + * partial response; it has to be a GET, the status must be + * 200 OK (and in particular, NOT already 206 Partial + * Content), and the SoupServer must have already filled in + * the response body + */ + if (msg->method != SOUP_METHOD_GET || + msg->status_code != SOUP_STATUS_OK || + soup_message_headers_get_encoding (msg->response_headers) != + SOUP_ENCODING_CONTENT_LENGTH || + msg->response_body->length == 0 || + !soup_message_body_get_accumulate (msg->response_body)) + return; + + /* Oh, and there has to have been a valid Range header on the + * request, of course. + */ + status = soup_message_headers_get_ranges_internal (msg->request_headers, + msg->response_body->length, + TRUE, + &ranges, &nranges); + if (status == SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE) { + soup_message_set_status (msg, status); + soup_message_body_truncate (msg->response_body); + return; + } else if (status != SOUP_STATUS_PARTIAL_CONTENT) + return; + + full_response = soup_message_body_flatten (msg->response_body); + if (!full_response) { + soup_message_headers_free_ranges (msg->request_headers, ranges); + return; + } + + soup_message_set_status (msg, SOUP_STATUS_PARTIAL_CONTENT); + soup_message_body_truncate (msg->response_body); + + if (nranges == 1) { + SoupBuffer *range_buf; + + /* Single range, so just set Content-Range and fix the body. */ + + soup_message_headers_set_content_range (msg->response_headers, + ranges[0].start, + ranges[0].end, + full_response->length); + range_buf = soup_buffer_new_subbuffer (full_response, + ranges[0].start, + ranges[0].end - ranges[0].start + 1); + soup_message_body_append_buffer (msg->response_body, range_buf); + soup_buffer_free (range_buf); + } else { + SoupMultipart *multipart; + SoupMessageHeaders *part_headers; + SoupBuffer *part_body; + const char *content_type; + int i; + + /* Multiple ranges, so build a multipart/byteranges response + * to replace msg->response_body with. + */ + + multipart = soup_multipart_new ("multipart/byteranges"); + content_type = soup_message_headers_get_one (msg->response_headers, + "Content-Type"); + for (i = 0; i < nranges; i++) { + part_headers = soup_message_headers_new (SOUP_MESSAGE_HEADERS_MULTIPART); + if (content_type) { + soup_message_headers_append (part_headers, + "Content-Type", + content_type); + } + soup_message_headers_set_content_range (part_headers, + ranges[i].start, + ranges[i].end, + full_response->length); + part_body = soup_buffer_new_subbuffer (full_response, + ranges[i].start, + ranges[i].end - ranges[i].start + 1); + soup_multipart_append_part (multipart, part_headers, + part_body); + soup_message_headers_free (part_headers); + soup_buffer_free (part_body); + } + + soup_multipart_to_message (multipart, msg->response_headers, + msg->response_body); + soup_multipart_free (multipart); + } + + soup_buffer_free (full_response); + soup_message_headers_free_ranges (msg->request_headers, ranges); +} + +static void +get_response_headers (SoupMessage *msg, GString *headers, + SoupEncoding *encoding, gpointer user_data) +{ + SoupEncoding claimed_encoding; + SoupMessageHeadersIter iter; + const char *name, *value; + + if (msg->status_code == 0) + soup_message_set_status (msg, SOUP_STATUS_INTERNAL_SERVER_ERROR); + + handle_partial_get (msg); + + g_string_append_printf (headers, "HTTP/1.%c %d %s\r\n", + soup_message_get_http_version (msg) == SOUP_HTTP_1_0 ? '0' : '1', + msg->status_code, msg->reason_phrase); + + claimed_encoding = soup_message_headers_get_encoding (msg->response_headers); + if ((msg->method == SOUP_METHOD_HEAD || + msg->status_code == SOUP_STATUS_NO_CONTENT || + msg->status_code == SOUP_STATUS_NOT_MODIFIED || + SOUP_STATUS_IS_INFORMATIONAL (msg->status_code)) || + (msg->method == SOUP_METHOD_CONNECT && + SOUP_STATUS_IS_SUCCESSFUL (msg->status_code))) + *encoding = SOUP_ENCODING_NONE; + else + *encoding = claimed_encoding; + + if (claimed_encoding == SOUP_ENCODING_CONTENT_LENGTH && + !soup_message_headers_get_content_length (msg->response_headers)) { + soup_message_headers_set_content_length (msg->response_headers, + msg->response_body->length); + } + + soup_message_headers_iter_init (&iter, msg->response_headers); + while (soup_message_headers_iter_next (&iter, &name, &value)) + g_string_append_printf (headers, "%s: %s\r\n", name, value); + g_string_append (headers, "\r\n"); +} + +void +soup_message_read_request (SoupMessage *msg, + SoupSocket *sock, + gboolean use_thread_context, + SoupMessageCompletionFn completion_cb, + gpointer user_data) +{ + GMainContext *async_context; + GIOStream *iostream; + + if (use_thread_context) + async_context = g_main_context_ref_thread_default (); + else { + g_object_get (sock, + SOUP_SOCKET_ASYNC_CONTEXT, &async_context, + NULL); + if (!async_context) + async_context = g_main_context_ref (g_main_context_default ()); + } + + iostream = soup_socket_get_iostream (sock); + + soup_message_io_server (msg, iostream, async_context, + get_response_headers, + parse_request_headers, + sock, + completion_cb, user_data); + g_main_context_unref (async_context); +} diff --git a/libsoup/soup-message.c b/libsoup/soup-message.c new file mode 100644 index 0000000..e4d7847 --- /dev/null +++ b/libsoup/soup-message.c @@ -0,0 +1,2090 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-message.c: HTTP request/response + * + * Copyright (C) 2000-2003, Ximian, Inc. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "soup-message.h" +#include "soup.h" +#include "soup-connection.h" +#include "soup-message-private.h" + +/** + * SECTION:soup-message + * @short_description: An HTTP request and response. + * @see_also: #SoupMessageHeaders, #SoupMessageBody + * + * A #SoupMessage represents an HTTP message that is being sent or + * received. + * + * For client-side usage, if you are using the traditional + * #SoupSession APIs (soup_session_queue_message() and + * soup_session_send_message()), you would create a #SoupMessage with + * soup_message_new() or soup_message_new_from_uri(), set up its + * fields appropriately, and send it. If you are using the newer + * #SoupRequest API, you would create a request with + * soup_session_request_http() or soup_session_request_http_uri(), and + * the returned #SoupRequestHTTP will already have an associated + * #SoupMessage that you can retrieve via + * soup_request_http_get_message(). + * + * For server-side usage, #SoupServer will create #SoupMessages automatically for incoming requests, which your application + * will receive via handlers. + * + * Note that libsoup's terminology here does not quite match the HTTP + * specification: in RFC 2616, an "HTTP-message" is + * either a Request, or a + * Response. In libsoup, a #SoupMessage combines both the request and + * the response. + **/ + +/** + * SoupMessage: + * @method: the HTTP method + * @status_code: the HTTP status code + * @reason_phrase: the status phrase associated with @status_code + * @request_body: the request body + * @request_headers: the request headers + * @response_body: the response body + * @response_headers: the response headers + * + * Represents an HTTP message being sent or received. + * + * @status_code will normally be a #SoupStatus value, eg, + * %SOUP_STATUS_OK, though of course it might actually be an unknown + * status code. @reason_phrase is the actual text returned from the + * server, which may or may not correspond to the "standard" + * description of @status_code. At any rate, it is almost certainly + * not localized, and not very descriptive even if it is in the user's + * language; you should not use @reason_phrase in user-visible + * messages. Rather, you should look at @status_code, and determine an + * end-user-appropriate message based on that and on what you were + * trying to do. + * + * As described in the #SoupMessageBody documentation, the + * @request_body and @response_body data fields + * will not necessarily be filled in at all times. When the body + * fields are filled in, they will be terminated with a '\0' byte + * (which is not included in the length), so you + * can use them as ordinary C strings (assuming that you know that the + * body doesn't have any other '\0' bytes). + * + * For a client-side #SoupMessage, @request_body's + * data is usually filled in right before libsoup + * writes the request to the network, but you should not count on + * this; use soup_message_body_flatten() if you want to ensure that + * data is filled in. If you are not using + * #SoupRequest to read the response, then @response_body's + * data will be filled in before + * #SoupMessage::finished is emitted. (If you are using #SoupRequest, + * then the message body is not accumulated by default, so + * @response_body's data will always be %NULL.) + * + * For a server-side #SoupMessage, @request_body's %data will be + * filled in before #SoupMessage::got_body is emitted. + * + * To prevent the %data field from being filled in at all (eg, if you + * are handling the data from a #SoupMessage::got_chunk, and so don't + * need to see it all at the end), call + * soup_message_body_set_accumulate() on @response_body or + * @request_body as appropriate, passing %FALSE. + **/ + +G_DEFINE_TYPE (SoupMessage, soup_message, G_TYPE_OBJECT) + +enum { + WROTE_INFORMATIONAL, + WROTE_HEADERS, + WROTE_CHUNK, + WROTE_BODY_DATA, + WROTE_BODY, + + GOT_INFORMATIONAL, + GOT_HEADERS, + GOT_CHUNK, + GOT_BODY, + CONTENT_SNIFFED, + + STARTING, + RESTARTED, + FINISHED, + + NETWORK_EVENT, + + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +enum { + PROP_0, + + PROP_METHOD, + PROP_URI, + PROP_HTTP_VERSION, + PROP_FLAGS, + PROP_SERVER_SIDE, + PROP_STATUS_CODE, + PROP_REASON_PHRASE, + PROP_FIRST_PARTY, + PROP_REQUEST_BODY, + PROP_REQUEST_BODY_DATA, + PROP_REQUEST_HEADERS, + PROP_RESPONSE_BODY, + PROP_RESPONSE_BODY_DATA, + PROP_RESPONSE_HEADERS, + PROP_TLS_CERTIFICATE, + PROP_TLS_ERRORS, + PROP_PRIORITY, + + LAST_PROP +}; + +static void +soup_message_init (SoupMessage *msg) +{ + SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); + + priv->http_version = priv->orig_http_version = SOUP_HTTP_1_1; + priv->priority = SOUP_MESSAGE_PRIORITY_NORMAL; + + msg->request_body = soup_message_body_new (); + msg->request_headers = soup_message_headers_new (SOUP_MESSAGE_HEADERS_REQUEST); + msg->response_body = soup_message_body_new (); + msg->response_headers = soup_message_headers_new (SOUP_MESSAGE_HEADERS_RESPONSE); +} + +static void +soup_message_finalize (GObject *object) +{ + SoupMessage *msg = SOUP_MESSAGE (object); + SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); + + soup_message_io_cleanup (msg); + if (priv->chunk_allocator_dnotify) + priv->chunk_allocator_dnotify (priv->chunk_allocator_data); + + g_clear_pointer (&priv->uri, soup_uri_free); + g_clear_pointer (&priv->first_party, soup_uri_free); + g_clear_object (&priv->addr); + + g_clear_object (&priv->auth); + g_clear_object (&priv->proxy_auth); + + g_slist_free (priv->disabled_features); + + g_clear_object (&priv->tls_certificate); + + soup_message_body_free (msg->request_body); + soup_message_headers_free (msg->request_headers); + soup_message_body_free (msg->response_body); + soup_message_headers_free (msg->response_headers); + + g_free (msg->reason_phrase); + + G_OBJECT_CLASS (soup_message_parent_class)->finalize (object); +} + +static void +soup_message_set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + SoupMessage *msg = SOUP_MESSAGE (object); + SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); + + switch (prop_id) { + case PROP_METHOD: + msg->method = g_intern_string (g_value_get_string (value)); + break; + case PROP_URI: + soup_message_set_uri (msg, g_value_get_boxed (value)); + break; + case PROP_HTTP_VERSION: + soup_message_set_http_version (msg, g_value_get_enum (value)); + break; + case PROP_FLAGS: + soup_message_set_flags (msg, g_value_get_flags (value)); + break; + case PROP_SERVER_SIDE: + priv->server_side = g_value_get_boolean (value); + if (priv->server_side) { + soup_message_headers_set_encoding (msg->response_headers, + SOUP_ENCODING_CONTENT_LENGTH); + } + break; + case PROP_STATUS_CODE: + soup_message_set_status (msg, g_value_get_uint (value)); + break; + case PROP_REASON_PHRASE: + soup_message_set_status_full (msg, msg->status_code, + g_value_get_string (value)); + break; + case PROP_FIRST_PARTY: + soup_message_set_first_party (msg, g_value_get_boxed (value)); + break; + case PROP_TLS_CERTIFICATE: + if (priv->tls_certificate) + g_object_unref (priv->tls_certificate); + priv->tls_certificate = g_value_dup_object (value); + if (priv->tls_errors) + priv->msg_flags &= ~SOUP_MESSAGE_CERTIFICATE_TRUSTED; + else if (priv->tls_certificate) + priv->msg_flags |= SOUP_MESSAGE_CERTIFICATE_TRUSTED; + break; + case PROP_TLS_ERRORS: + priv->tls_errors = g_value_get_flags (value); + if (priv->tls_errors) + priv->msg_flags &= ~SOUP_MESSAGE_CERTIFICATE_TRUSTED; + else if (priv->tls_certificate) + priv->msg_flags |= SOUP_MESSAGE_CERTIFICATE_TRUSTED; + break; + case PROP_PRIORITY: + priv->priority = g_value_get_enum (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +soup_message_get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + SoupMessage *msg = SOUP_MESSAGE (object); + SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); + SoupBuffer *buf; + + switch (prop_id) { + case PROP_METHOD: + g_value_set_string (value, msg->method); + break; + case PROP_URI: + g_value_set_boxed (value, priv->uri); + break; + case PROP_HTTP_VERSION: + g_value_set_enum (value, priv->http_version); + break; + case PROP_FLAGS: + g_value_set_flags (value, priv->msg_flags); + break; + case PROP_SERVER_SIDE: + g_value_set_boolean (value, priv->server_side); + break; + case PROP_STATUS_CODE: + g_value_set_uint (value, msg->status_code); + break; + case PROP_REASON_PHRASE: + g_value_set_string (value, msg->reason_phrase); + break; + case PROP_FIRST_PARTY: + g_value_set_boxed (value, priv->first_party); + break; + case PROP_REQUEST_BODY: + g_value_set_boxed (value, msg->request_body); + break; + case PROP_REQUEST_BODY_DATA: + buf = soup_message_body_flatten (msg->request_body); + g_value_take_boxed (value, soup_buffer_get_as_bytes (buf)); + soup_buffer_free (buf); + break; + case PROP_REQUEST_HEADERS: + g_value_set_boxed (value, msg->request_headers); + break; + case PROP_RESPONSE_BODY: + g_value_set_boxed (value, msg->response_body); + break; + case PROP_RESPONSE_BODY_DATA: + buf = soup_message_body_flatten (msg->response_body); + g_value_take_boxed (value, soup_buffer_get_as_bytes (buf)); + soup_buffer_free (buf); + break; + case PROP_RESPONSE_HEADERS: + g_value_set_boxed (value, msg->response_headers); + break; + case PROP_TLS_CERTIFICATE: + g_value_set_object (value, priv->tls_certificate); + break; + case PROP_TLS_ERRORS: + g_value_set_flags (value, priv->tls_errors); + break; + case PROP_PRIORITY: + g_value_set_enum (value, priv->priority); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +soup_message_real_got_body (SoupMessage *msg) +{ + SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); + SoupMessageBody *body; + + body = priv->server_side ? msg->request_body : msg->response_body; + if (soup_message_body_get_accumulate (body)) { + SoupBuffer *buffer; + + buffer = soup_message_body_flatten (body); + soup_buffer_free (buffer); + } +} + +static void +soup_message_class_init (SoupMessageClass *message_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (message_class); + + g_type_class_add_private (message_class, sizeof (SoupMessagePrivate)); + + /* virtual method definition */ + message_class->got_body = soup_message_real_got_body; + + /* virtual method override */ + object_class->finalize = soup_message_finalize; + object_class->set_property = soup_message_set_property; + object_class->get_property = soup_message_get_property; + + /* signals */ + + /** + * SoupMessage::wrote-informational: + * @msg: the message + * + * Emitted immediately after writing a 1xx (Informational) + * response for a (server-side) message. + **/ + signals[WROTE_INFORMATIONAL] = + g_signal_new ("wrote_informational", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (SoupMessageClass, wrote_informational), + NULL, NULL, + NULL, + G_TYPE_NONE, 0); + + /** + * SoupMessage::wrote-headers: + * @msg: the message + * + * Emitted immediately after writing the headers for a + * message. (For a client-side message, this is after writing + * the request headers; for a server-side message, it is after + * writing the response headers.) + **/ + signals[WROTE_HEADERS] = + g_signal_new ("wrote_headers", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (SoupMessageClass, wrote_headers), + NULL, NULL, + NULL, + G_TYPE_NONE, 0); + + /** + * SoupMessage::wrote-chunk: + * @msg: the message + * + * Emitted immediately after writing a body chunk for a message. + * + * Note that this signal is not parallel to + * #SoupMessage::got_chunk; it is emitted only when a complete + * chunk (added with soup_message_body_append() or + * soup_message_body_append_buffer()) has been written. To get + * more useful continuous progress information, use + * #SoupMessage::wrote_body_data. + **/ + signals[WROTE_CHUNK] = + g_signal_new ("wrote_chunk", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (SoupMessageClass, wrote_chunk), + NULL, NULL, + NULL, + G_TYPE_NONE, 0); + + /** + * SoupMessage::wrote-body-data: + * @msg: the message + * @chunk: the data written + * + * Emitted immediately after writing a portion of the message + * body to the network. + * + * Unlike #SoupMessage::wrote_chunk, this is emitted after + * every successful write() call, not only after finishing a + * complete "chunk". + * + * Since: 2.24 + **/ + signals[WROTE_BODY_DATA] = + g_signal_new ("wrote_body_data", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + 0, /* FIXME after next ABI break */ + NULL, NULL, + NULL, + G_TYPE_NONE, 1, + SOUP_TYPE_BUFFER); + + /** + * SoupMessage::wrote-body: + * @msg: the message + * + * Emitted immediately after writing the complete body for a + * message. (For a client-side message, this means that + * libsoup is done writing and is now waiting for the response + * from the server. For a server-side message, this means that + * libsoup has finished writing the response and is nearly + * done with the message.) + **/ + signals[WROTE_BODY] = + g_signal_new ("wrote_body", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (SoupMessageClass, wrote_body), + NULL, NULL, + NULL, + G_TYPE_NONE, 0); + + /** + * SoupMessage::got-informational: + * @msg: the message + * + * Emitted after receiving a 1xx (Informational) response for + * a (client-side) message. The response_headers will be + * filled in with the headers associated with the + * informational response; however, those header values will + * be erased after this signal is done. + * + * If you cancel or requeue @msg while processing this signal, + * then the current HTTP I/O will be stopped after this signal + * emission finished, and @msg's connection will be closed. + **/ + signals[GOT_INFORMATIONAL] = + g_signal_new ("got_informational", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (SoupMessageClass, got_informational), + NULL, NULL, + NULL, + G_TYPE_NONE, 0); + + /** + * SoupMessage::got-headers: + * @msg: the message + * + * Emitted after receiving all message headers for a message. + * (For a client-side message, this is after receiving the + * Status-Line and response headers; for a server-side + * message, it is after receiving the Request-Line and request + * headers.) + * + * See also soup_message_add_header_handler() and + * soup_message_add_status_code_handler(), which can be used + * to connect to a subset of emissions of this signal. + * + * If you cancel or requeue @msg while processing this signal, + * then the current HTTP I/O will be stopped after this signal + * emission finished, and @msg's connection will be closed. + * (If you need to requeue a message--eg, after handling + * authentication or redirection--it is usually better to + * requeue it from a #SoupMessage::got_body handler rather + * than a #SoupMessage::got_headers handler, so that the + * existing HTTP connection can be reused.) + **/ + signals[GOT_HEADERS] = + g_signal_new ("got_headers", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (SoupMessageClass, got_headers), + NULL, NULL, + NULL, + G_TYPE_NONE, 0); + + /** + * SoupMessage::got-chunk: + * @msg: the message + * @chunk: the just-read chunk + * + * Emitted after receiving a chunk of a message body. Note + * that "chunk" in this context means any subpiece of the + * body, not necessarily the specific HTTP 1.1 chunks sent by + * the other side. + * + * If you cancel or requeue @msg while processing this signal, + * then the current HTTP I/O will be stopped after this signal + * emission finished, and @msg's connection will be closed. + **/ + signals[GOT_CHUNK] = + g_signal_new ("got_chunk", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (SoupMessageClass, got_chunk), + NULL, NULL, + NULL, + G_TYPE_NONE, 1, + /* Use %G_SIGNAL_TYPE_STATIC_SCOPE so that + * the %SOUP_MEMORY_TEMPORARY buffers used + * by soup-message-io.c when emitting this + * signal don't get forcibly copied by + * g_signal_emit(). + */ + SOUP_TYPE_BUFFER | G_SIGNAL_TYPE_STATIC_SCOPE); + + /** + * SoupMessage::got-body: + * @msg: the message + * + * Emitted after receiving the complete message body. (For a + * server-side message, this means it has received the request + * body. For a client-side message, this means it has received + * the response body and is nearly done with the message.) + * + * See also soup_message_add_header_handler() and + * soup_message_add_status_code_handler(), which can be used + * to connect to a subset of emissions of this signal. + **/ + signals[GOT_BODY] = + g_signal_new ("got_body", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (SoupMessageClass, got_body), + NULL, NULL, + NULL, + G_TYPE_NONE, 0); + + /** + * SoupMessage::content-sniffed: + * @msg: the message + * @type: the content type that we got from sniffing + * @params: (element-type utf8 utf8): a #GHashTable with the parameters + * + * This signal is emitted after #SoupMessage::got-headers, and + * before the first #SoupMessage::got-chunk. If content + * sniffing is disabled, or no content sniffing will be + * performed, due to the sniffer deciding to trust the + * Content-Type sent by the server, this signal is emitted + * immediately after #SoupMessage::got-headers, and @type is + * %NULL. + * + * If the #SoupContentSniffer feature is enabled, and the + * sniffer decided to perform sniffing, the first + * #SoupMessage::got-chunk emission may be delayed, so that the + * sniffer has enough data to correctly sniff the content. It + * notified the library user that the content has been + * sniffed, and allows it to change the header contents in the + * message, if desired. + * + * After this signal is emitted, the data that was spooled so + * that sniffing could be done is delivered on the first + * emission of #SoupMessage::got-chunk. + * + * Since: 2.28 + **/ + signals[CONTENT_SNIFFED] = + g_signal_new ("content_sniffed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + 0, + NULL, NULL, + NULL, + G_TYPE_NONE, 2, + G_TYPE_STRING, + G_TYPE_HASH_TABLE); + + /** + * SoupMessage::starting: + * @msg: the message + * + * Emitted just before a message is sent. + * + * Since: 2.50 + */ + signals[STARTING] = + g_signal_new ("starting", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (SoupMessageClass, starting), + NULL, NULL, + NULL, + G_TYPE_NONE, 0); + + /** + * SoupMessage::restarted: + * @msg: the message + * + * Emitted when a request that was already sent once is now + * being sent again (eg, because the first attempt received a + * redirection response, or because we needed to use + * authentication). + **/ + signals[RESTARTED] = + g_signal_new ("restarted", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (SoupMessageClass, restarted), + NULL, NULL, + NULL, + G_TYPE_NONE, 0); + + /** + * SoupMessage::finished: + * @msg: the message + * + * Emitted when all HTTP processing is finished for a message. + * (After #SoupMessage::got_body for client-side messages, or + * after #SoupMessage::wrote_body for server-side messages.) + **/ + signals[FINISHED] = + g_signal_new ("finished", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (SoupMessageClass, finished), + NULL, NULL, + NULL, + G_TYPE_NONE, 0); + + /** + * SoupMessage::network-event: + * @msg: the message + * @event: the network event + * @connection: the current state of the network connection + * + * Emitted to indicate that some network-related event + * related to @msg has occurred. This essentially proxies the + * #GSocketClient::event signal, but only for events that + * occur while @msg "owns" the connection; if @msg is sent on + * an existing persistent connection, then this signal will + * not be emitted. (If you want to force the message to be + * sent on a new connection, set the + * %SOUP_MESSAGE_NEW_CONNECTION flag on it.) + * + * See #GSocketClient::event for more information on what + * the different values of @event correspond to, and what + * @connection will be in each case. + * + * Since: 2.38 + **/ + signals[NETWORK_EVENT] = + g_signal_new ("network_event", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + 0, + NULL, NULL, + NULL, + G_TYPE_NONE, 2, + G_TYPE_SOCKET_CLIENT_EVENT, + G_TYPE_IO_STREAM); + + /* properties */ + /** + * SOUP_MESSAGE_METHOD: + * + * Alias for the #SoupMessage:method property. (The message's + * HTTP method.) + **/ + g_object_class_install_property ( + object_class, PROP_METHOD, + g_param_spec_string (SOUP_MESSAGE_METHOD, + "Method", + "The message's HTTP method", + SOUP_METHOD_GET, + G_PARAM_READWRITE)); + /** + * SOUP_MESSAGE_URI: + * + * Alias for the #SoupMessage:uri property. (The message's + * #SoupURI.) + **/ + g_object_class_install_property ( + object_class, PROP_URI, + g_param_spec_boxed (SOUP_MESSAGE_URI, + "URI", + "The message's Request-URI", + SOUP_TYPE_URI, + G_PARAM_READWRITE)); + /** + * SOUP_MESSAGE_HTTP_VERSION: + * + * Alias for the #SoupMessage:http-version property. (The + * message's #SoupHTTPVersion.) + **/ + g_object_class_install_property ( + object_class, PROP_HTTP_VERSION, + g_param_spec_enum (SOUP_MESSAGE_HTTP_VERSION, + "HTTP Version", + "The HTTP protocol version to use", + SOUP_TYPE_HTTP_VERSION, + SOUP_HTTP_1_1, + G_PARAM_READWRITE)); + /** + * SOUP_MESSAGE_FLAGS: + * + * Alias for the #SoupMessage:flags property. (The message's + * #SoupMessageFlags.) + **/ + g_object_class_install_property ( + object_class, PROP_FLAGS, + g_param_spec_flags (SOUP_MESSAGE_FLAGS, + "Flags", + "Various message options", + SOUP_TYPE_MESSAGE_FLAGS, + 0, + G_PARAM_READWRITE)); + /** + * SOUP_MESSAGE_SERVER_SIDE: + * + * Alias for the #SoupMessage:server-side property. (%TRUE if + * the message was created by #SoupServer.) + **/ + g_object_class_install_property ( + object_class, PROP_SERVER_SIDE, + g_param_spec_boolean (SOUP_MESSAGE_SERVER_SIDE, + "Server-side", + "Whether or not the message is server-side rather than client-side", + FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + /** + * SOUP_MESSAGE_STATUS_CODE: + * + * Alias for the #SoupMessage:status-code property. (The + * message's HTTP response status code.) + **/ + g_object_class_install_property ( + object_class, PROP_STATUS_CODE, + g_param_spec_uint (SOUP_MESSAGE_STATUS_CODE, + "Status code", + "The HTTP response status code", + 0, 999, 0, + G_PARAM_READWRITE)); + /** + * SOUP_MESSAGE_REASON_PHRASE: + * + * Alias for the #SoupMessage:reason-phrase property. (The + * message's HTTP response reason phrase.) + **/ + g_object_class_install_property ( + object_class, PROP_REASON_PHRASE, + g_param_spec_string (SOUP_MESSAGE_REASON_PHRASE, + "Reason phrase", + "The HTTP response reason phrase", + NULL, + G_PARAM_READWRITE)); + /** + * SOUP_MESSAGE_FIRST_PARTY: + * + * Alias for the #SoupMessage:first-party property. (The + * #SoupURI loaded in the application when the message was + * queued.) + * + * Since: 2.30 + **/ + /** + * SoupMessage:first-party: + * + * The #SoupURI loaded in the application when the message was + * queued. + * + * Since: 2.30 + */ + g_object_class_install_property ( + object_class, PROP_FIRST_PARTY, + g_param_spec_boxed (SOUP_MESSAGE_FIRST_PARTY, + "First party", + "The URI loaded in the application when the message was requested.", + SOUP_TYPE_URI, + G_PARAM_READWRITE)); + /** + * SOUP_MESSAGE_REQUEST_BODY: + * + * Alias for the #SoupMessage:request-body property. (The + * message's HTTP request body.) + **/ + g_object_class_install_property ( + object_class, PROP_REQUEST_BODY, + g_param_spec_boxed (SOUP_MESSAGE_REQUEST_BODY, + "Request Body", + "The HTTP request content", + SOUP_TYPE_MESSAGE_BODY, + G_PARAM_READABLE)); + /** + * SOUP_MESSAGE_REQUEST_BODY_DATA: + * + * Alias for the #SoupMessage:request-body-data property. (The + * message's HTTP request body, as a #GBytes.) + * + * Since: 2.46 + **/ + /** + * SoupMessage:request-body-data: + * + * The message's HTTP request body, as a #GBytes. + * + * Since: 2.46 + **/ + g_object_class_install_property ( + object_class, PROP_REQUEST_BODY_DATA, + g_param_spec_boxed (SOUP_MESSAGE_REQUEST_BODY_DATA, + "Request Body Data", + "The HTTP request body", + G_TYPE_BYTES, + G_PARAM_READABLE)); + /** + * SOUP_MESSAGE_REQUEST_HEADERS: + * + * Alias for the #SoupMessage:request-headers property. (The + * message's HTTP request headers.) + **/ + g_object_class_install_property ( + object_class, PROP_REQUEST_HEADERS, + g_param_spec_boxed (SOUP_MESSAGE_REQUEST_HEADERS, + "Request Headers", + "The HTTP request headers", + SOUP_TYPE_MESSAGE_HEADERS, + G_PARAM_READABLE)); + /** + * SOUP_MESSAGE_RESPONSE_BODY: + * + * Alias for the #SoupMessage:response-body property. (The + * message's HTTP response body.) + **/ + g_object_class_install_property ( + object_class, PROP_RESPONSE_BODY, + g_param_spec_boxed (SOUP_MESSAGE_RESPONSE_BODY, + "Response Body", + "The HTTP response content", + SOUP_TYPE_MESSAGE_BODY, + G_PARAM_READABLE)); + /** + * SOUP_MESSAGE_RESPONSE_BODY_DATA: + * + * Alias for the #SoupMessage:response-body-data property. (The + * message's HTTP response body, as a #GBytes.) + * + * Since: 2.46 + **/ + /** + * SoupMessage:response-body-data: + * + * The message's HTTP response body, as a #GBytes. + * + * Since: 2.46 + **/ + g_object_class_install_property ( + object_class, PROP_RESPONSE_BODY_DATA, + g_param_spec_boxed (SOUP_MESSAGE_RESPONSE_BODY_DATA, + "Response Body Data", + "The HTTP response body", + G_TYPE_BYTES, + G_PARAM_READABLE)); + /** + * SOUP_MESSAGE_RESPONSE_HEADERS: + * + * Alias for the #SoupMessage:response-headers property. (The + * message's HTTP response headers.) + **/ + g_object_class_install_property ( + object_class, PROP_RESPONSE_HEADERS, + g_param_spec_boxed (SOUP_MESSAGE_RESPONSE_HEADERS, + "Response Headers", + "The HTTP response headers", + SOUP_TYPE_MESSAGE_HEADERS, + G_PARAM_READABLE)); + /** + * SOUP_MESSAGE_TLS_CERTIFICATE: + * + * Alias for the #SoupMessage:tls-certificate property. (The + * TLS certificate associated with the message, if any.) + * + * Since: 2.34 + **/ + /** + * SoupMessage:tls-certificate: + * + * The #GTlsCertificate associated with the message + * + * Since: 2.34 + */ + g_object_class_install_property ( + object_class, PROP_TLS_CERTIFICATE, + g_param_spec_object (SOUP_MESSAGE_TLS_CERTIFICATE, + "TLS Certificate", + "The TLS certificate associated with the message", + G_TYPE_TLS_CERTIFICATE, + G_PARAM_READWRITE)); + /** + * SOUP_MESSAGE_TLS_ERRORS: + * + * Alias for the #SoupMessage:tls-errors property. (The + * verification errors on #SoupMessage:tls-certificate.) + * + * Since: 2.34 + **/ + /** + * SoupMessage:tls-errors: + * + * The verification errors on #SoupMessage:tls-certificate + * + * Since: 2.34 + */ + g_object_class_install_property ( + object_class, PROP_TLS_ERRORS, + g_param_spec_flags (SOUP_MESSAGE_TLS_ERRORS, + "TLS Errors", + "The verification errors on the message's TLS certificate", + G_TYPE_TLS_CERTIFICATE_FLAGS, 0, + G_PARAM_READWRITE)); + /** + * SOUP_MESSAGE_PRIORITY: + * + * Sets the priority of the #SoupMessage. See + * soup_message_set_priority() for further details. + * + * Since: 2.44 + **/ + g_object_class_install_property ( + object_class, PROP_PRIORITY, + g_param_spec_enum (SOUP_MESSAGE_PRIORITY, + "Priority", + "The priority of the message", + SOUP_TYPE_MESSAGE_PRIORITY, + SOUP_MESSAGE_PRIORITY_NORMAL, + G_PARAM_READWRITE)); +} + + +/** + * soup_message_new: + * @method: the HTTP method for the created request + * @uri_string: the destination endpoint (as a string) + * + * Creates a new empty #SoupMessage, which will connect to @uri + * + * Return value: (nullable): the new #SoupMessage (or %NULL if @uri + * could not be parsed). + */ +SoupMessage * +soup_message_new (const char *method, const char *uri_string) +{ + SoupMessage *msg; + SoupURI *uri; + + g_return_val_if_fail (method != NULL, NULL); + g_return_val_if_fail (uri_string != NULL, NULL); + + uri = soup_uri_new (uri_string); + if (!uri) + return NULL; + if (!uri->host) { + soup_uri_free (uri); + return NULL; + } + + msg = soup_message_new_from_uri (method, uri); + soup_uri_free (uri); + return msg; +} + +/** + * soup_message_new_from_uri: + * @method: the HTTP method for the created request + * @uri: the destination endpoint (as a #SoupURI) + * + * Creates a new empty #SoupMessage, which will connect to @uri + * + * Return value: the new #SoupMessage + */ +SoupMessage * +soup_message_new_from_uri (const char *method, SoupURI *uri) +{ + return g_object_new (SOUP_TYPE_MESSAGE, + SOUP_MESSAGE_METHOD, method, + SOUP_MESSAGE_URI, uri, + NULL); +} + +/** + * soup_message_set_request: + * @msg: the message + * @content_type: (allow-none): MIME Content-Type of the body + * @req_use: a #SoupMemoryUse describing how to handle @req_body + * @req_body: (allow-none) (array length=req_length) (element-type guint8): + * a data buffer containing the body of the message request. + * @req_length: the byte length of @req_body. + * + * Convenience function to set the request body of a #SoupMessage. If + * @content_type is %NULL, the request body must be empty as well. + */ +void +soup_message_set_request (SoupMessage *msg, + const char *content_type, + SoupMemoryUse req_use, + const char *req_body, + gsize req_length) +{ + g_return_if_fail (SOUP_IS_MESSAGE (msg)); + g_return_if_fail (content_type != NULL || req_length == 0); + + if (content_type) { + g_warn_if_fail (strchr (content_type, '/') != NULL); + + soup_message_headers_replace (msg->request_headers, + "Content-Type", content_type); + soup_message_body_append (msg->request_body, req_use, + req_body, req_length); + } else { + soup_message_headers_remove (msg->request_headers, + "Content-Type"); + soup_message_body_truncate (msg->request_body); + } +} + +/** + * soup_message_set_response: + * @msg: the message + * @content_type: (allow-none): MIME Content-Type of the body + * @resp_use: a #SoupMemoryUse describing how to handle @resp_body + * @resp_body: (allow-none) (array length=resp_length) (element-type guint8): + * a data buffer containing the body of the message response. + * @resp_length: the byte length of @resp_body. + * + * Convenience function to set the response body of a #SoupMessage. If + * @content_type is %NULL, the response body must be empty as well. + */ +void +soup_message_set_response (SoupMessage *msg, + const char *content_type, + SoupMemoryUse resp_use, + const char *resp_body, + gsize resp_length) +{ + g_return_if_fail (SOUP_IS_MESSAGE (msg)); + g_return_if_fail (content_type != NULL || resp_length == 0); + + if (content_type) { + g_warn_if_fail (strchr (content_type, '/') != NULL); + + soup_message_headers_replace (msg->response_headers, + "Content-Type", content_type); + soup_message_body_append (msg->response_body, resp_use, + resp_body, resp_length); + } else { + soup_message_headers_remove (msg->response_headers, + "Content-Type"); + soup_message_body_truncate (msg->response_body); + } +} + +void +soup_message_wrote_informational (SoupMessage *msg) +{ + g_signal_emit (msg, signals[WROTE_INFORMATIONAL], 0); +} + +void +soup_message_wrote_headers (SoupMessage *msg) +{ + g_signal_emit (msg, signals[WROTE_HEADERS], 0); +} + +void +soup_message_wrote_chunk (SoupMessage *msg) +{ + g_signal_emit (msg, signals[WROTE_CHUNK], 0); +} + +void +soup_message_wrote_body_data (SoupMessage *msg, SoupBuffer *chunk) +{ + g_signal_emit (msg, signals[WROTE_BODY_DATA], 0, chunk); +} + +void +soup_message_wrote_body (SoupMessage *msg) +{ + g_signal_emit (msg, signals[WROTE_BODY], 0); +} + +void +soup_message_got_informational (SoupMessage *msg) +{ + g_signal_emit (msg, signals[GOT_INFORMATIONAL], 0); +} + +void +soup_message_got_headers (SoupMessage *msg) +{ + g_signal_emit (msg, signals[GOT_HEADERS], 0); +} + +void +soup_message_got_chunk (SoupMessage *msg, SoupBuffer *chunk) +{ + g_signal_emit (msg, signals[GOT_CHUNK], 0, chunk); +} + +void +soup_message_got_body (SoupMessage *msg) +{ + g_signal_emit (msg, signals[GOT_BODY], 0); +} + +void +soup_message_content_sniffed (SoupMessage *msg, const char *content_type, GHashTable *params) +{ + g_signal_emit (msg, signals[CONTENT_SNIFFED], 0, content_type, params); +} + +void +soup_message_starting (SoupMessage *msg) +{ + g_signal_emit (msg, signals[STARTING], 0); +} + +void +soup_message_restarted (SoupMessage *msg) +{ + SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); + + if (priv->msg_flags & SOUP_MESSAGE_CAN_REBUILD) + soup_message_body_truncate (msg->request_body); + + g_signal_emit (msg, signals[RESTARTED], 0); +} + +void +soup_message_finished (SoupMessage *msg) +{ + g_signal_emit (msg, signals[FINISHED], 0); +} + +void +soup_message_network_event (SoupMessage *msg, + GSocketClientEvent event, + GIOStream *connection) +{ + g_signal_emit (msg, signals[NETWORK_EVENT], 0, + event, connection); +} + +static void +header_handler_free (gpointer header_name, GClosure *closure) +{ + g_free (header_name); +} + +static void +header_handler_metamarshal (GClosure *closure, GValue *return_value, + guint n_param_values, const GValue *param_values, + gpointer invocation_hint, gpointer marshal_data) +{ + SoupMessage *msg = g_value_get_object (¶m_values[0]); + SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); + const char *header_name = marshal_data; + SoupMessageHeaders *hdrs; + + hdrs = priv->server_side ? msg->request_headers : msg->response_headers; + if (soup_message_headers_get_one (hdrs, header_name)) { + closure->marshal (closure, return_value, n_param_values, + param_values, invocation_hint, + ((GCClosure *)closure)->callback); + } +} + +/** + * soup_message_add_header_handler: (skip) + * @msg: a #SoupMessage + * @signal: signal to connect the handler to. + * @header: HTTP response header to match against + * @callback: the header handler + * @user_data: data to pass to @handler_cb + * + * Adds a signal handler to @msg for @signal, as with + * g_signal_connect(), but the @callback will only be run if @msg's + * incoming messages headers (that is, the + * request_headers for a client #SoupMessage, or + * the response_headers for a server #SoupMessage) + * contain a header named @header. + * + * Return value: the handler ID from g_signal_connect() + **/ +guint +soup_message_add_header_handler (SoupMessage *msg, + const char *signal, + const char *header, + GCallback callback, + gpointer user_data) +{ + GClosure *closure; + char *header_name; + + g_return_val_if_fail (SOUP_IS_MESSAGE (msg), 0); + g_return_val_if_fail (signal != NULL, 0); + g_return_val_if_fail (header != NULL, 0); + g_return_val_if_fail (callback != NULL, 0); + + closure = g_cclosure_new (callback, user_data, NULL); + + header_name = g_strdup (header); + g_closure_set_meta_marshal (closure, header_name, + header_handler_metamarshal); + g_closure_add_finalize_notifier (closure, header_name, + header_handler_free); + + return g_signal_connect_closure (msg, signal, closure, FALSE); +} + +static void +status_handler_metamarshal (GClosure *closure, GValue *return_value, + guint n_param_values, const GValue *param_values, + gpointer invocation_hint, gpointer marshal_data) +{ + SoupMessage *msg = g_value_get_object (¶m_values[0]); + guint status = GPOINTER_TO_UINT (marshal_data); + + if (msg->status_code == status) { + closure->marshal (closure, return_value, n_param_values, + param_values, invocation_hint, + ((GCClosure *)closure)->callback); + } +} + +/** + * soup_message_add_status_code_handler: (skip) + * @msg: a #SoupMessage + * @signal: signal to connect the handler to. + * @status_code: status code to match against + * @callback: the header handler + * @user_data: data to pass to @handler_cb + * + * Adds a signal handler to @msg for @signal, as with + * g_signal_connect(), but the @callback will only be run if @msg has + * the status @status_code. + * + * @signal must be a signal that will be emitted after @msg's status + * is set. For a client #SoupMessage, this means it can't be a "wrote" + * signal. For a server #SoupMessage, this means it can't be a "got" + * signal. + * + * Return value: the handler ID from g_signal_connect() + **/ +guint +soup_message_add_status_code_handler (SoupMessage *msg, + const char *signal, + guint status_code, + GCallback callback, + gpointer user_data) +{ + GClosure *closure; + + g_return_val_if_fail (SOUP_IS_MESSAGE (msg), 0); + g_return_val_if_fail (signal != NULL, 0); + g_return_val_if_fail (callback != NULL, 0); + + closure = g_cclosure_new (callback, user_data, NULL); + g_closure_set_meta_marshal (closure, GUINT_TO_POINTER (status_code), + status_handler_metamarshal); + + return g_signal_connect_closure (msg, signal, closure, FALSE); +} + + +void +soup_message_set_auth (SoupMessage *msg, SoupAuth *auth) +{ + SoupMessagePrivate *priv; + + g_return_if_fail (SOUP_IS_MESSAGE (msg)); + g_return_if_fail (auth == NULL || SOUP_IS_AUTH (auth)); + + priv = SOUP_MESSAGE_GET_PRIVATE (msg); + + if (priv->auth == auth) + return; + + if (priv->auth) + g_object_unref (priv->auth); + priv->auth = auth ? g_object_ref (auth) : NULL; +} + +SoupAuth * +soup_message_get_auth (SoupMessage *msg) +{ + g_return_val_if_fail (SOUP_IS_MESSAGE (msg), NULL); + + return SOUP_MESSAGE_GET_PRIVATE (msg)->auth; +} + +void +soup_message_set_proxy_auth (SoupMessage *msg, SoupAuth *auth) +{ + SoupMessagePrivate *priv; + + g_return_if_fail (SOUP_IS_MESSAGE (msg)); + g_return_if_fail (auth == NULL || SOUP_IS_AUTH (auth)); + + priv = SOUP_MESSAGE_GET_PRIVATE (msg); + + if (priv->proxy_auth == auth) + return; + + if (priv->proxy_auth) + g_object_unref (priv->proxy_auth); + priv->proxy_auth = auth ? g_object_ref (auth) : NULL; +} + +SoupAuth * +soup_message_get_proxy_auth (SoupMessage *msg) +{ + g_return_val_if_fail (SOUP_IS_MESSAGE (msg), NULL); + + return SOUP_MESSAGE_GET_PRIVATE (msg)->proxy_auth; +} + +SoupConnection * +soup_message_get_connection (SoupMessage *msg) +{ + return SOUP_MESSAGE_GET_PRIVATE (msg)->connection; +} + +void +soup_message_set_connection (SoupMessage *msg, + SoupConnection *conn) +{ + SOUP_MESSAGE_GET_PRIVATE (msg)->connection = conn; +} + +/** + * soup_message_cleanup_response: + * @msg: a #SoupMessage + * + * Cleans up all response data on @msg, so that the request can be sent + * again and receive a new response. (Eg, as a result of a redirect or + * authorization request.) + **/ +void +soup_message_cleanup_response (SoupMessage *msg) +{ + SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); + + soup_message_body_truncate (msg->response_body); + soup_message_headers_clear (msg->response_headers); + if (priv->server_side) { + soup_message_headers_set_encoding (msg->response_headers, + SOUP_ENCODING_CONTENT_LENGTH); + } + + priv->msg_flags &= ~SOUP_MESSAGE_CONTENT_DECODED; + + msg->status_code = SOUP_STATUS_NONE; + if (msg->reason_phrase) { + g_free (msg->reason_phrase); + msg->reason_phrase = NULL; + } + priv->http_version = priv->orig_http_version; + + g_object_notify (G_OBJECT (msg), SOUP_MESSAGE_STATUS_CODE); + g_object_notify (G_OBJECT (msg), SOUP_MESSAGE_REASON_PHRASE); + g_object_notify (G_OBJECT (msg), SOUP_MESSAGE_HTTP_VERSION); + g_object_notify (G_OBJECT (msg), SOUP_MESSAGE_FLAGS); + g_object_notify (G_OBJECT (msg), SOUP_MESSAGE_TLS_CERTIFICATE); + g_object_notify (G_OBJECT (msg), SOUP_MESSAGE_TLS_ERRORS); +} + +/** + * SoupMessageFlags: + * @SOUP_MESSAGE_NO_REDIRECT: The session should not follow redirect + * (3xx) responses received by this message. + * @SOUP_MESSAGE_CAN_REBUILD: The caller will rebuild the request + * body if the message is restarted; see + * soup_message_body_set_accumulate() for more details. + * @SOUP_MESSAGE_OVERWRITE_CHUNKS: Deprecated: equivalent to calling + * soup_message_body_set_accumulate() on the incoming message body + * (ie, #SoupMessage:response_body for a client-side request), + * passing %FALSE. + * @SOUP_MESSAGE_CONTENT_DECODED: Set by #SoupContentDecoder to + * indicate that it has removed the Content-Encoding on a message (and + * so headers such as Content-Length may no longer accurately describe + * the body). + * @SOUP_MESSAGE_CERTIFICATE_TRUSTED: if set after an https response + * has been received, indicates that the server's SSL certificate is + * trusted according to the session's CA. + * @SOUP_MESSAGE_NEW_CONNECTION: Requests that the message should be + * sent on a newly-created connection, not reusing an existing + * persistent connection. Note that messages with non-idempotent + * #SoupMessage:methods behave this way by default, unless + * #SOUP_MESSAGE_IDEMPOTENT is set. + * @SOUP_MESSAGE_IDEMPOTENT: The message is considered idempotent, + * regardless its #SoupMessage:method, and allows reuse of existing + * idle connections, instead of always requiring a new one, unless + * #SOUP_MESSAGE_NEW_CONNECTION is set. + * @SOUP_MESSAGE_IGNORE_CONNECTION_LIMITS: Request that a new connection is + * created for the message if there aren't idle connections available + * and it's not possible to create new connections due to any of the + * connection limits has been reached. If a dedicated connection is + * eventually created for this message, it will be dropped when the + * message finishes. Since 2.50 + * @SOUP_MESSAGE_DO_NOT_USE_AUTH_CACHE: The #SoupAuthManager should not use + * the credentials cache for this message, neither to use cached credentials + * to automatically authenticate this message nor to cache the credentials + * after the message is successfully authenticated. This applies to both server + * and proxy authentication. Note that #SoupSession::authenticate signal will + * be emitted, if you want to disable authentication for a message use + * soup_message_disable_feature() passing #SOUP_TYPE_AUTH_MANAGER instead. Since 2.58 + * + * Various flags that can be set on a #SoupMessage to alter its + * behavior. + **/ + +/** + * soup_message_set_flags: + * @msg: a #SoupMessage + * @flags: a set of #SoupMessageFlags values + * + * Sets the specified flags on @msg. + **/ +void +soup_message_set_flags (SoupMessage *msg, SoupMessageFlags flags) +{ + SoupMessagePrivate *priv; + + g_return_if_fail (SOUP_IS_MESSAGE (msg)); + priv = SOUP_MESSAGE_GET_PRIVATE (msg); + + if ((priv->msg_flags ^ flags) & SOUP_MESSAGE_OVERWRITE_CHUNKS) { + soup_message_body_set_accumulate ( + priv->server_side ? msg->request_body : msg->response_body, + !(flags & SOUP_MESSAGE_OVERWRITE_CHUNKS)); + } + + priv->msg_flags = flags; + g_object_notify (G_OBJECT (msg), SOUP_MESSAGE_FLAGS); +} + +/** + * soup_message_get_flags: + * @msg: a #SoupMessage + * + * Gets the flags on @msg + * + * Return value: the flags + **/ +SoupMessageFlags +soup_message_get_flags (SoupMessage *msg) +{ + g_return_val_if_fail (SOUP_IS_MESSAGE (msg), 0); + + return SOUP_MESSAGE_GET_PRIVATE (msg)->msg_flags; +} + +/** + * SoupHTTPVersion: + * @SOUP_HTTP_1_0: HTTP 1.0 (RFC 1945) + * @SOUP_HTTP_1_1: HTTP 1.1 (RFC 2616) + * + * Indicates the HTTP protocol version being used. + **/ + +/** + * soup_message_set_http_version: + * @msg: a #SoupMessage + * @version: the HTTP version + * + * Sets the HTTP version on @msg. The default version is + * %SOUP_HTTP_1_1. Setting it to %SOUP_HTTP_1_0 will prevent certain + * functionality from being used. + **/ +void +soup_message_set_http_version (SoupMessage *msg, SoupHTTPVersion version) +{ + SoupMessagePrivate *priv; + + g_return_if_fail (SOUP_IS_MESSAGE (msg)); + priv = SOUP_MESSAGE_GET_PRIVATE (msg); + + priv->http_version = version; + if (msg->status_code == SOUP_STATUS_NONE) + priv->orig_http_version = version; + g_object_notify (G_OBJECT (msg), SOUP_MESSAGE_HTTP_VERSION); +} + +/** + * soup_message_get_http_version: + * @msg: a #SoupMessage + * + * Gets the HTTP version of @msg. This is the minimum of the + * version from the request and the version from the response. + * + * Return value: the HTTP version + **/ +SoupHTTPVersion +soup_message_get_http_version (SoupMessage *msg) +{ + g_return_val_if_fail (SOUP_IS_MESSAGE (msg), SOUP_HTTP_1_0); + + return SOUP_MESSAGE_GET_PRIVATE (msg)->http_version; +} + +/** + * soup_message_is_keepalive: + * @msg: a #SoupMessage + * + * Determines whether or not @msg's connection can be kept alive for + * further requests after processing @msg, based on the HTTP version, + * Connection header, etc. + * + * Return value: %TRUE or %FALSE. + **/ +gboolean +soup_message_is_keepalive (SoupMessage *msg) +{ + if (msg->status_code == SOUP_STATUS_OK && + msg->method == SOUP_METHOD_CONNECT) + return TRUE; + + /* Not persistent if the server sent a terminate-by-EOF response */ + if (soup_message_headers_get_encoding (msg->response_headers) == SOUP_ENCODING_EOF) + return FALSE; + + if (SOUP_MESSAGE_GET_PRIVATE (msg)->http_version == SOUP_HTTP_1_0) { + /* In theory, HTTP/1.0 connections are only persistent + * if the client requests it, and the server agrees. + * But some servers do keep-alive even if the client + * doesn't request it. So ignore c_conn. + */ + + if (!soup_message_headers_header_contains (msg->response_headers, + "Connection", "Keep-Alive")) + return FALSE; + } else { + /* Normally persistent unless either side requested otherwise */ + if (soup_message_headers_header_contains (msg->request_headers, + "Connection", "close") || + soup_message_headers_header_contains (msg->response_headers, + "Connection", "close")) + return FALSE; + + return TRUE; + } + + return TRUE; +} + +/** + * soup_message_set_uri: + * @msg: a #SoupMessage + * @uri: the new #SoupURI + * + * Sets @msg's URI to @uri. If @msg has already been sent and you want + * to re-send it with the new URI, you need to call + * soup_session_requeue_message(). + **/ +void +soup_message_set_uri (SoupMessage *msg, SoupURI *uri) +{ + SoupMessagePrivate *priv; + + g_return_if_fail (SOUP_IS_MESSAGE (msg)); + priv = SOUP_MESSAGE_GET_PRIVATE (msg); + + if (priv->uri) + soup_uri_free (priv->uri); + if (priv->addr) { + g_object_unref (priv->addr); + priv->addr = NULL; + } + priv->uri = soup_uri_copy (uri); + + g_object_notify (G_OBJECT (msg), SOUP_MESSAGE_URI); +} + +/** + * soup_message_get_uri: + * @msg: a #SoupMessage + * + * Gets @msg's URI + * + * Return value: (transfer none): the URI @msg is targeted for. + **/ +SoupURI * +soup_message_get_uri (SoupMessage *msg) +{ + g_return_val_if_fail (SOUP_IS_MESSAGE (msg), NULL); + + return SOUP_MESSAGE_GET_PRIVATE (msg)->uri; +} + +/** + * soup_message_get_address: + * @msg: a #SoupMessage + * + * Gets the address @msg's URI points to. After first setting the + * URI on a message, this will be unresolved, although the message's + * session will resolve it before sending the message. + * + * Return value: (transfer none): the address @msg's URI points to + * + * Since: 2.26 + **/ +SoupAddress * +soup_message_get_address (SoupMessage *msg) +{ + SoupMessagePrivate *priv; + + g_return_val_if_fail (SOUP_IS_MESSAGE (msg), NULL); + + priv = SOUP_MESSAGE_GET_PRIVATE (msg); + if (!priv->addr) { + priv->addr = soup_address_new (priv->uri->host, + priv->uri->port); + } + return priv->addr; +} + +/** + * soup_message_set_status: + * @msg: a #SoupMessage + * @status_code: an HTTP status code + * + * Sets @msg's status code to @status_code. If @status_code is a + * known value, it will also set @msg's reason_phrase. + **/ +void +soup_message_set_status (SoupMessage *msg, guint status_code) +{ + g_return_if_fail (SOUP_IS_MESSAGE (msg)); + g_return_if_fail (status_code != 0); + + g_free (msg->reason_phrase); + + msg->status_code = status_code; + msg->reason_phrase = g_strdup (soup_status_get_phrase (status_code)); + g_object_notify (G_OBJECT (msg), SOUP_MESSAGE_STATUS_CODE); + g_object_notify (G_OBJECT (msg), SOUP_MESSAGE_REASON_PHRASE); +} + +/** + * soup_message_set_status_full: + * @msg: a #SoupMessage + * @status_code: an HTTP status code + * @reason_phrase: a description of the status + * + * Sets @msg's status code and reason phrase. + **/ +void +soup_message_set_status_full (SoupMessage *msg, + guint status_code, + const char *reason_phrase) +{ + g_return_if_fail (SOUP_IS_MESSAGE (msg)); + g_return_if_fail (status_code != 0); + g_return_if_fail (reason_phrase != NULL); + + g_free (msg->reason_phrase); + + msg->status_code = status_code; + msg->reason_phrase = g_strdup (reason_phrase); + g_object_notify (G_OBJECT (msg), SOUP_MESSAGE_STATUS_CODE); + g_object_notify (G_OBJECT (msg), SOUP_MESSAGE_REASON_PHRASE); +} + +/** + * SoupChunkAllocator: + * @msg: the #SoupMessage the chunk is being allocated for + * @max_len: the maximum length that will be read, or 0. + * @user_data: the data passed to soup_message_set_chunk_allocator() + * + * The prototype for a chunk allocation callback. This should allocate + * a new #SoupBuffer and return it for the I/O layer to read message + * body data off the network into. + * + * If @max_len is non-0, it indicates the maximum number of bytes that + * could be read, based on what is known about the message size. Note + * that this might be a very large number, and you should not simply + * try to allocate that many bytes blindly. If @max_len is 0, that + * means that libsoup does not know how many bytes remain to be read, + * and the allocator should return a buffer of a size that it finds + * convenient. + * + * If the allocator returns %NULL, the message will be paused. It is + * up to the application to make sure that it gets unpaused when it + * becomes possible to allocate a new buffer. + * + * Return value: (nullable): the new buffer (or %NULL) + * + * Deprecated: Use #SoupRequest if you want to read into your + * own buffers. + **/ + +/** + * soup_message_set_chunk_allocator: + * @msg: a #SoupMessage + * @allocator: the chunk allocator callback + * @user_data: data to pass to @allocator + * @destroy_notify: destroy notifier to free @user_data when @msg is + * destroyed + * + * Sets an alternate chunk-allocation function to use when reading + * @msg's body when using the traditional (ie, + * non-#SoupRequest-based) API. Every time data is available + * to read, libsoup will call @allocator, which should return a + * #SoupBuffer. (See #SoupChunkAllocator for additional details.) + * Libsoup will then read data from the network into that buffer, and + * update the buffer's length to indicate how much + * data it read. + * + * Generally, a custom chunk allocator would be used in conjunction + * with soup_message_body_set_accumulate() %FALSE and + * #SoupMessage::got_chunk, as part of a strategy to avoid unnecessary + * copying of data. However, you cannot assume that every call to the + * allocator will be followed by a call to your + * #SoupMessage::got_chunk handler; if an I/O error occurs, then the + * buffer will be unreffed without ever having been used. If your + * buffer-allocation strategy requires special cleanup, use + * soup_buffer_new_with_owner() rather than doing the cleanup from the + * #SoupMessage::got_chunk handler. + * + * The other thing to remember when using non-accumulating message + * bodies is that the buffer passed to the #SoupMessage::got_chunk + * handler will be unreffed after the handler returns, just as it + * would be in the non-custom-allocated case. If you want to hand the + * chunk data off to some other part of your program to use later, + * you'll need to ref the #SoupBuffer (or its owner, in the + * soup_buffer_new_with_owner() case) to ensure that the data remains + * valid. + * + * Deprecated: #SoupRequest provides a much simpler API that lets you + * read the response directly into your own buffers without needing to + * mess with callbacks, pausing/unpausing, etc. + **/ +void +soup_message_set_chunk_allocator (SoupMessage *msg, + SoupChunkAllocator allocator, + gpointer user_data, + GDestroyNotify destroy_notify) +{ + SoupMessagePrivate *priv; + + g_return_if_fail (SOUP_IS_MESSAGE (msg)); + + priv = SOUP_MESSAGE_GET_PRIVATE (msg); + + if (priv->chunk_allocator_dnotify) + priv->chunk_allocator_dnotify (priv->chunk_allocator_data); + + priv->chunk_allocator = allocator; + priv->chunk_allocator_data = user_data; + priv->chunk_allocator_dnotify = destroy_notify; +} + +/** + * soup_message_disable_feature: + * @msg: a #SoupMessage + * @feature_type: the #GType of a #SoupSessionFeature + * + * This disables the actions of #SoupSessionFeatures with the + * given @feature_type (or a subclass of that type) on @msg, so that + * @msg is processed as though the feature(s) hadn't been added to the + * session. Eg, passing #SOUP_TYPE_CONTENT_SNIFFER for @feature_type + * will disable Content-Type sniffing on the message. + * + * You must call this before queueing @msg on a session; calling it on + * a message that has already been queued is undefined. In particular, + * you cannot call this on a message that is being requeued after a + * redirect or authentication. + * + * Since: 2.28 + **/ +void +soup_message_disable_feature (SoupMessage *msg, GType feature_type) +{ + SoupMessagePrivate *priv; + + g_return_if_fail (SOUP_IS_MESSAGE (msg)); + + priv = SOUP_MESSAGE_GET_PRIVATE (msg); + + priv->disabled_features = g_slist_prepend (priv->disabled_features, + GSIZE_TO_POINTER (feature_type)); +} + +gboolean +soup_message_disables_feature (SoupMessage *msg, gpointer feature) +{ + SoupMessagePrivate *priv; + GSList *f; + + g_return_val_if_fail (SOUP_IS_MESSAGE (msg), FALSE); + + priv = SOUP_MESSAGE_GET_PRIVATE (msg); + + for (f = priv->disabled_features; f; f = f->next) { + if (G_TYPE_CHECK_INSTANCE_TYPE (feature, (GType) GPOINTER_TO_SIZE (f->data))) + return TRUE; + } + return FALSE; +} + +/** + * soup_message_get_first_party: + * @msg: a #SoupMessage + * + * Gets @msg's first-party #SoupURI + * + * Returns: (transfer none): the @msg's first party #SoupURI + * + * Since: 2.30 + **/ +SoupURI * +soup_message_get_first_party (SoupMessage *msg) +{ + SoupMessagePrivate *priv; + + g_return_val_if_fail (SOUP_IS_MESSAGE (msg), NULL); + + priv = SOUP_MESSAGE_GET_PRIVATE (msg); + return priv->first_party; +} + +/** + * soup_message_set_first_party: + * @msg: a #SoupMessage + * @first_party: the #SoupURI for the @msg's first party + * + * Sets @first_party as the main document #SoupURI for @msg. For + * details of when and how this is used refer to the documentation for + * #SoupCookieJarAcceptPolicy. + * + * Since: 2.30 + **/ +void +soup_message_set_first_party (SoupMessage *msg, + SoupURI *first_party) +{ + SoupMessagePrivate *priv; + + g_return_if_fail (SOUP_IS_MESSAGE (msg)); + g_return_if_fail (first_party != NULL); + + priv = SOUP_MESSAGE_GET_PRIVATE (msg); + + if (priv->first_party) { + if (soup_uri_equal (priv->first_party, first_party)) + return; + + soup_uri_free (priv->first_party); + } + + priv->first_party = soup_uri_copy (first_party); + g_object_notify (G_OBJECT (msg), SOUP_MESSAGE_FIRST_PARTY); +} + +void +soup_message_set_https_status (SoupMessage *msg, SoupConnection *conn) +{ + SoupSocket *sock; + + sock = conn ? soup_connection_get_socket (conn) : NULL; + if (sock && soup_socket_is_ssl (sock)) { + GTlsCertificate *certificate; + GTlsCertificateFlags errors; + + g_object_get (sock, + SOUP_SOCKET_TLS_CERTIFICATE, &certificate, + SOUP_SOCKET_TLS_ERRORS, &errors, + NULL); + g_object_set (msg, + SOUP_MESSAGE_TLS_CERTIFICATE, certificate, + SOUP_MESSAGE_TLS_ERRORS, errors, + NULL); + if (certificate) + g_object_unref (certificate); + } else { + g_object_set (msg, + SOUP_MESSAGE_TLS_CERTIFICATE, NULL, + SOUP_MESSAGE_TLS_ERRORS, 0, + NULL); + } +} + +/** + * soup_message_get_https_status: + * @msg: a #SoupMessage + * @certificate: (out) (transfer none): @msg's TLS certificate + * @errors: (out): the verification status of @certificate + * + * If @msg is using https (or attempted to use https but got + * %SOUP_STATUS_SSL_FAILED), this retrieves the #GTlsCertificate + * associated with its connection, and the #GTlsCertificateFlags + * showing what problems, if any, have been found with that + * certificate. + * + * This is only meaningful with messages processed by a #SoupSession and is + * not useful for messages received by a #SoupServer + * + * Return value: %TRUE if @msg used/attempted https, %FALSE if not + * + * Since: 2.34 + */ +gboolean +soup_message_get_https_status (SoupMessage *msg, + GTlsCertificate **certificate, + GTlsCertificateFlags *errors) +{ + SoupMessagePrivate *priv; + + g_return_val_if_fail (SOUP_IS_MESSAGE (msg), FALSE); + + priv = SOUP_MESSAGE_GET_PRIVATE (msg); + + if (certificate) + *certificate = priv->tls_certificate; + if (errors) + *errors = priv->tls_errors; + return priv->tls_certificate != NULL; +} + +/** + * soup_message_set_redirect: + * @msg: a #SoupMessage + * @status_code: a 3xx status code + * @redirect_uri: the URI to redirect @msg to + * + * Sets @msg's status_code to @status_code and adds a Location header + * pointing to @redirect_uri. Use this from a #SoupServer when you + * want to redirect the client to another URI. + * + * @redirect_uri can be a relative URI, in which case it is + * interpreted relative to @msg's current URI. In particular, if + * @redirect_uri is just a path, it will replace the path + * and query of @msg's URI. + * + * Since: 2.38 + */ +void +soup_message_set_redirect (SoupMessage *msg, guint status_code, + const char *redirect_uri) +{ + SoupURI *location; + char *location_str; + + location = soup_uri_new_with_base (soup_message_get_uri (msg), redirect_uri); + g_return_if_fail (location != NULL); + + soup_message_set_status (msg, status_code); + location_str = soup_uri_to_string (location, FALSE); + soup_message_headers_replace (msg->response_headers, "Location", + location_str); + g_free (location_str); + soup_uri_free (location); +} + +void +soup_message_set_soup_request (SoupMessage *msg, + SoupRequest *req) +{ + SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); + + priv->request = req; +} + +/** + * soup_message_get_soup_request: + * @msg: a #SoupMessage + * + * If @msg is associated with a #SoupRequest, this returns that + * request. Otherwise it returns %NULL. + * + * Return value: (transfer none): @msg's associated #SoupRequest + * + * Since: 2.42 + */ +SoupRequest * +soup_message_get_soup_request (SoupMessage *msg) +{ + SoupMessagePrivate *priv; + + g_return_val_if_fail (SOUP_IS_MESSAGE (msg), NULL); + + priv = SOUP_MESSAGE_GET_PRIVATE (msg); + return priv->request; +} + +/** + * SoupMessagePriority: + * @SOUP_MESSAGE_PRIORITY_VERY_LOW: The lowest priority, the messages + * with this priority will be the last ones to be attended. + * @SOUP_MESSAGE_PRIORITY_LOW: Use this for low priority messages, a + * #SoupMessage with the default priority will be processed first. + * @SOUP_MESSAGE_PRIORITY_NORMAL: The default priotity, this is the + * priority assigned to the #SoupMessage by default. + * @SOUP_MESSAGE_PRIORITY_HIGH: High priority, a #SoupMessage with + * this priority will be processed before the ones with the default + * priority. + * @SOUP_MESSAGE_PRIORITY_VERY_HIGH: The highest priority, use this + * for very urgent #SoupMessage as they will be the first ones to be + * attended. + * + * Priorities that can be set on a #SoupMessage to instruct the + * message queue to process it before any other message with lower + * priority. + **/ + +/** + * soup_message_set_priority: + * @msg: a #SoupMessage + * @priority: the #SoupMessagePriority + * + * Sets the priority of a message. Note that this won't have any + * effect unless used before the message is added to the session's + * message processing queue. + * + * The message will be placed just before any other previously added + * message with lower priority (messages with the same priority are + * processed on a FIFO basis). + * + * Setting priorities does not currently work with #SoupSessionSync + * (or with synchronous messages on a plain #SoupSession) because in + * the synchronous/blocking case, priority ends up being determined + * semi-randomly by thread scheduling. + * + * Since: 2.44 + */ +void +soup_message_set_priority (SoupMessage *msg, + SoupMessagePriority priority) +{ + g_return_if_fail (SOUP_IS_MESSAGE (msg)); + + g_object_set (msg, SOUP_MESSAGE_PRIORITY, priority, NULL); +} + +/** + * soup_message_get_priority: + * @msg: a #SoupMessage + * + * Retrieves the #SoupMessagePriority. If not set this value defaults + * to #SOUP_MESSAGE_PRIORITY_NORMAL. + * + * Return value: the priority of the message. + * + * Since: 2.44 + */ +SoupMessagePriority +soup_message_get_priority (SoupMessage *msg) +{ + g_return_val_if_fail (SOUP_IS_MESSAGE (msg), SOUP_MESSAGE_PRIORITY_NORMAL); + + return SOUP_MESSAGE_GET_PRIVATE (msg)->priority; +} diff --git a/libsoup/soup-message.h b/libsoup/soup-message.h new file mode 100644 index 0000000..cab2bad --- /dev/null +++ b/libsoup/soup-message.h @@ -0,0 +1,259 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2000-2003, Ximian, Inc. + */ + +#ifndef SOUP_MESSAGE_H +#define SOUP_MESSAGE_H 1 + +#include +#include +#include +#include + +G_BEGIN_DECLS + +#define SOUP_TYPE_MESSAGE (soup_message_get_type ()) +#define SOUP_MESSAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SOUP_TYPE_MESSAGE, SoupMessage)) +#define SOUP_MESSAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_MESSAGE, SoupMessageClass)) +#define SOUP_IS_MESSAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SOUP_TYPE_MESSAGE)) +#define SOUP_IS_MESSAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), SOUP_TYPE_MESSAGE)) +#define SOUP_MESSAGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_MESSAGE, SoupMessageClass)) + +struct _SoupMessage { + GObject parent; + + /*< public >*/ + const char *method; + + guint status_code; + char *reason_phrase; + + SoupMessageBody *request_body; + SoupMessageHeaders *request_headers; + + SoupMessageBody *response_body; + SoupMessageHeaders *response_headers; +}; + +typedef struct { + GObjectClass parent_class; + + /* signals */ + void (*wrote_informational) (SoupMessage *msg); + void (*wrote_headers) (SoupMessage *msg); + void (*wrote_chunk) (SoupMessage *msg); + void (*wrote_body) (SoupMessage *msg); + void (*got_informational) (SoupMessage *msg); + void (*got_headers) (SoupMessage *msg); + void (*got_chunk) (SoupMessage *msg, SoupBuffer *chunk); + void (*got_body) (SoupMessage *msg); + void (*restarted) (SoupMessage *msg); + void (*finished) (SoupMessage *msg); + void (*starting) (SoupMessage *msg); + + /* Padding for future expansion */ + void (*_libsoup_reserved1) (void); + void (*_libsoup_reserved2) (void); + void (*_libsoup_reserved3) (void); +} SoupMessageClass; + +SOUP_AVAILABLE_IN_2_4 +GType soup_message_get_type (void); + +#define SOUP_MESSAGE_METHOD "method" +#define SOUP_MESSAGE_URI "uri" +#define SOUP_MESSAGE_HTTP_VERSION "http-version" +#define SOUP_MESSAGE_FLAGS "flags" +#define SOUP_MESSAGE_SERVER_SIDE "server-side" +#define SOUP_MESSAGE_STATUS_CODE "status-code" +#define SOUP_MESSAGE_REASON_PHRASE "reason-phrase" +#define SOUP_MESSAGE_FIRST_PARTY "first-party" +#define SOUP_MESSAGE_REQUEST_BODY "request-body" +#define SOUP_MESSAGE_REQUEST_BODY_DATA "request-body-data" +#define SOUP_MESSAGE_REQUEST_HEADERS "request-headers" +#define SOUP_MESSAGE_RESPONSE_BODY "response-body" +#define SOUP_MESSAGE_RESPONSE_BODY_DATA "response-body-data" +#define SOUP_MESSAGE_RESPONSE_HEADERS "response-headers" +#define SOUP_MESSAGE_TLS_CERTIFICATE "tls-certificate" +#define SOUP_MESSAGE_TLS_ERRORS "tls-errors" +#define SOUP_MESSAGE_PRIORITY "priority" + +SOUP_AVAILABLE_IN_2_4 +SoupMessage *soup_message_new (const char *method, + const char *uri_string); +SOUP_AVAILABLE_IN_2_4 +SoupMessage *soup_message_new_from_uri (const char *method, + SoupURI *uri); + +SOUP_AVAILABLE_IN_2_4 +void soup_message_set_request (SoupMessage *msg, + const char *content_type, + SoupMemoryUse req_use, + const char *req_body, + gsize req_length); +SOUP_AVAILABLE_IN_2_4 +void soup_message_set_response (SoupMessage *msg, + const char *content_type, + SoupMemoryUse resp_use, + const char *resp_body, + gsize resp_length); + +typedef enum { + SOUP_HTTP_1_0 = 0, /*< nick=http-1-0 >*/ + SOUP_HTTP_1_1 = 1 /*< nick=http-1-1 >*/ +} SoupHTTPVersion; + +SOUP_AVAILABLE_IN_2_4 +void soup_message_set_http_version (SoupMessage *msg, + SoupHTTPVersion version); +SOUP_AVAILABLE_IN_2_4 +SoupHTTPVersion soup_message_get_http_version (SoupMessage *msg); + +SOUP_AVAILABLE_IN_2_4 +gboolean soup_message_is_keepalive (SoupMessage *msg); + +SOUP_AVAILABLE_IN_2_4 +SoupURI *soup_message_get_uri (SoupMessage *msg); +SOUP_AVAILABLE_IN_2_4 +void soup_message_set_uri (SoupMessage *msg, + SoupURI *uri); +SOUP_AVAILABLE_IN_2_26 +SoupAddress *soup_message_get_address (SoupMessage *msg); + +SOUP_AVAILABLE_IN_2_30 +SoupURI *soup_message_get_first_party (SoupMessage *msg); +SOUP_AVAILABLE_IN_2_30 +void soup_message_set_first_party (SoupMessage *msg, + SoupURI *first_party); + +typedef enum { + SOUP_MESSAGE_NO_REDIRECT = (1 << 1), + SOUP_MESSAGE_CAN_REBUILD = (1 << 2), +#ifndef SOUP_DISABLE_DEPRECATED + SOUP_MESSAGE_OVERWRITE_CHUNKS = (1 << 3), +#endif + SOUP_MESSAGE_CONTENT_DECODED = (1 << 4), + SOUP_MESSAGE_CERTIFICATE_TRUSTED = (1 << 5), + SOUP_MESSAGE_NEW_CONNECTION = (1 << 6), + SOUP_MESSAGE_IDEMPOTENT = (1 << 7), + SOUP_MESSAGE_IGNORE_CONNECTION_LIMITS = (1 << 8), + SOUP_MESSAGE_DO_NOT_USE_AUTH_CACHE = (1 << 9) +} SoupMessageFlags; + +SOUP_AVAILABLE_IN_2_4 +void soup_message_set_flags (SoupMessage *msg, + SoupMessageFlags flags); + +SOUP_AVAILABLE_IN_2_4 +SoupMessageFlags soup_message_get_flags (SoupMessage *msg); + +SOUP_AVAILABLE_IN_2_34 +gboolean soup_message_get_https_status (SoupMessage *msg, + GTlsCertificate **certificate, + GTlsCertificateFlags *errors); + + +/* Specialized signal handlers */ +SOUP_AVAILABLE_IN_2_4 +guint soup_message_add_header_handler (SoupMessage *msg, + const char *signal, + const char *header, + GCallback callback, + gpointer user_data); + +SOUP_AVAILABLE_IN_2_4 +guint soup_message_add_status_code_handler ( + SoupMessage *msg, + const char *signal, + guint status_code, + GCallback callback, + gpointer user_data); + +/* + * Status Setting + */ +SOUP_AVAILABLE_IN_2_4 +void soup_message_set_status (SoupMessage *msg, + guint status_code); + +SOUP_AVAILABLE_IN_2_4 +void soup_message_set_status_full (SoupMessage *msg, + guint status_code, + const char *reason_phrase); + +SOUP_AVAILABLE_IN_2_38 +void soup_message_set_redirect (SoupMessage *msg, + guint status_code, + const char *redirect_uri); + +/* I/O */ +#ifndef SOUP_DISABLE_DEPRECATED +typedef SoupBuffer * (*SoupChunkAllocator) (SoupMessage *msg, + gsize max_len, + gpointer user_data); + +SOUP_AVAILABLE_IN_2_4 +SOUP_DEPRECATED_IN_2_42_FOR(SoupRequest) +void soup_message_set_chunk_allocator (SoupMessage *msg, + SoupChunkAllocator allocator, + gpointer user_data, + GDestroyNotify destroy_notify); +#endif + +SOUP_AVAILABLE_IN_2_28 +void soup_message_disable_feature (SoupMessage *msg, + GType feature_type); + +SOUP_AVAILABLE_IN_2_42 +SoupRequest *soup_message_get_soup_request (SoupMessage *msg); + + +typedef enum { + SOUP_MESSAGE_PRIORITY_VERY_LOW = 0, + SOUP_MESSAGE_PRIORITY_LOW, + SOUP_MESSAGE_PRIORITY_NORMAL, + SOUP_MESSAGE_PRIORITY_HIGH, + SOUP_MESSAGE_PRIORITY_VERY_HIGH +} SoupMessagePriority; + +SOUP_AVAILABLE_IN_2_44 +void soup_message_set_priority (SoupMessage *msg, + SoupMessagePriority priority); + + +SOUP_AVAILABLE_IN_2_44 +SoupMessagePriority soup_message_get_priority (SoupMessage *msg); + +SOUP_AVAILABLE_IN_2_4 +void soup_message_wrote_informational (SoupMessage *msg); +SOUP_AVAILABLE_IN_2_4 +void soup_message_wrote_headers (SoupMessage *msg); +SOUP_AVAILABLE_IN_2_4 +void soup_message_wrote_chunk (SoupMessage *msg); +SOUP_AVAILABLE_IN_2_4 +void soup_message_wrote_body_data (SoupMessage *msg, SoupBuffer *chunk); +SOUP_AVAILABLE_IN_2_4 +void soup_message_wrote_body (SoupMessage *msg); +SOUP_AVAILABLE_IN_2_4 +void soup_message_got_informational (SoupMessage *msg); +SOUP_AVAILABLE_IN_2_4 +void soup_message_got_headers (SoupMessage *msg); +SOUP_AVAILABLE_IN_2_4 +void soup_message_got_chunk (SoupMessage *msg, SoupBuffer *chunk); +SOUP_AVAILABLE_IN_2_4 +void soup_message_got_body (SoupMessage *msg); +SOUP_AVAILABLE_IN_2_4 +void soup_message_content_sniffed (SoupMessage *msg, const char *content_type, GHashTable *params); + +SOUP_AVAILABLE_IN_2_50 +void soup_message_starting (SoupMessage *msg); + +SOUP_AVAILABLE_IN_2_4 +void soup_message_restarted (SoupMessage *msg); +SOUP_AVAILABLE_IN_2_4 +void soup_message_finished (SoupMessage *msg); + +G_END_DECLS + +#endif /*SOUP_MESSAGE_H*/ diff --git a/libsoup/soup-method.c b/libsoup/soup-method.c new file mode 100644 index 0000000..de7d589 --- /dev/null +++ b/libsoup/soup-method.c @@ -0,0 +1,107 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-method.c: declarations of _SOUP_METHOD_* variables + * + * Copyright (C) 2008 Red Hat, Inc. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "soup-method.h" + +/* Explicit assignment to NULL is to help the OS X linker not be + * stupid. #522957 + */ +gpointer _SOUP_METHOD_CONNECT = NULL; +gpointer _SOUP_METHOD_COPY = NULL; +gpointer _SOUP_METHOD_DELETE = NULL; +gpointer _SOUP_METHOD_GET = NULL; +gpointer _SOUP_METHOD_HEAD = NULL; +gpointer _SOUP_METHOD_LOCK = NULL; +gpointer _SOUP_METHOD_MKCOL = NULL; +gpointer _SOUP_METHOD_MOVE = NULL; +gpointer _SOUP_METHOD_OPTIONS = NULL; +gpointer _SOUP_METHOD_POST = NULL; +gpointer _SOUP_METHOD_PROPFIND = NULL; +gpointer _SOUP_METHOD_PROPPATCH = NULL; +gpointer _SOUP_METHOD_PUT = NULL; +gpointer _SOUP_METHOD_TRACE = NULL; +gpointer _SOUP_METHOD_UNLOCK = NULL; + +/** + * SOUP_METHOD_OPTIONS: + * + * "OPTIONS" as an interned string. + **/ +/** + * SOUP_METHOD_GET: + * + * "GET" as an interned string. + **/ +/** + * SOUP_METHOD_HEAD: + * + * "HEAD" as an interned string. + **/ +/** + * SOUP_METHOD_POST: + * + * "POST" as an interned string. + **/ +/** + * SOUP_METHOD_PUT: + * + * "PUT" as an interned string. + **/ +/** + * SOUP_METHOD_DELETE: + * + * "DELETE" as an interned string. + **/ +/** + * SOUP_METHOD_TRACE: + * + * "TRACE" as an interned string. + **/ +/** + * SOUP_METHOD_CONNECT: + * + * "CONNECT" as an interned string. + **/ +/** + * SOUP_METHOD_PROPFIND: + * + * "PROPFIND" as an interned string. + **/ +/** + * SOUP_METHOD_PROPPATCH: + * + * "PROPPATCH" as an interned string. + **/ +/** + * SOUP_METHOD_MKCOL: + * + * "MKCOL" as an interned string. + **/ +/** + * SOUP_METHOD_COPY: + * + * "COPY" as an interned string. + **/ +/** + * SOUP_METHOD_MOVE: + * + * "MOVE" as an interned string. + **/ +/** + * SOUP_METHOD_LOCK: + * + * "LOCK" as an interned string. + **/ +/** + * SOUP_METHOD_UNLOCK: + * + * "UNLOCK" as an interned string. + **/ diff --git a/libsoup/soup-method.h b/libsoup/soup-method.h new file mode 100644 index 0000000..cec59e3 --- /dev/null +++ b/libsoup/soup-method.h @@ -0,0 +1,80 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2008 Red Hat, Inc. + */ + +#ifndef SOUP_METHOD_H +#define SOUP_METHOD_H 1 + +#include +#include + +G_BEGIN_DECLS + +/** + * SECTION:soup-method + * @short_description: HTTP method definitions + * + * soup-method.h contains a number of defines for standard HTTP and + * WebDAV headers. You do not need to use these defines; you can pass + * arbitrary strings to soup_message_new() if you prefer. + * + * The thing that these defines are useful for is + * performing quick comparisons against #SoupMessage's %method field; + * because that field always contains an interned string, and these + * macros return interned strings, you can compare %method directly + * against these macros rather than needing to use strcmp(). This is + * most useful in SoupServer handlers. Eg: + * + * + * if (msg->method != SOUP_METHOD_GET && msg->method != SOUP_METHOD_HEAD) { + * soup_message_set_status (msg, SOUP_METHOD_NOT_IMPLEMENTED); + * return; + * } + * + **/ + +#define _SOUP_INTERN_METHOD(method) (_SOUP_ATOMIC_INTERN_STRING (_SOUP_METHOD_##method, #method)) + +/* HTTP/1.1 methods */ +#define SOUP_METHOD_OPTIONS _SOUP_INTERN_METHOD (OPTIONS) +#define SOUP_METHOD_GET _SOUP_INTERN_METHOD (GET) +#define SOUP_METHOD_HEAD _SOUP_INTERN_METHOD (HEAD) +#define SOUP_METHOD_POST _SOUP_INTERN_METHOD (POST) +#define SOUP_METHOD_PUT _SOUP_INTERN_METHOD (PUT) +#define SOUP_METHOD_DELETE _SOUP_INTERN_METHOD (DELETE) +#define SOUP_METHOD_TRACE _SOUP_INTERN_METHOD (TRACE) +#define SOUP_METHOD_CONNECT _SOUP_INTERN_METHOD (CONNECT) + +/* WebDAV methods */ +#define SOUP_METHOD_PROPFIND _SOUP_INTERN_METHOD (PROPFIND) +#define SOUP_METHOD_PROPPATCH _SOUP_INTERN_METHOD (PROPPATCH) +#define SOUP_METHOD_MKCOL _SOUP_INTERN_METHOD (MKCOL) +#define SOUP_METHOD_COPY _SOUP_INTERN_METHOD (COPY) +#define SOUP_METHOD_MOVE _SOUP_INTERN_METHOD (MOVE) +#define SOUP_METHOD_LOCK _SOUP_INTERN_METHOD (LOCK) +#define SOUP_METHOD_UNLOCK _SOUP_INTERN_METHOD (UNLOCK) + +/* Do not use these variables directly; use the macros above, which + * ensure that they get initialized properly. + */ +SOUP_VAR gpointer _SOUP_METHOD_OPTIONS; +SOUP_VAR gpointer _SOUP_METHOD_GET; +SOUP_VAR gpointer _SOUP_METHOD_HEAD; +SOUP_VAR gpointer _SOUP_METHOD_POST; +SOUP_VAR gpointer _SOUP_METHOD_PUT; +SOUP_VAR gpointer _SOUP_METHOD_DELETE; +SOUP_VAR gpointer _SOUP_METHOD_TRACE; +SOUP_VAR gpointer _SOUP_METHOD_CONNECT; + +SOUP_VAR gpointer _SOUP_METHOD_PROPFIND; +SOUP_VAR gpointer _SOUP_METHOD_PROPPATCH; +SOUP_VAR gpointer _SOUP_METHOD_MKCOL; +SOUP_VAR gpointer _SOUP_METHOD_COPY; +SOUP_VAR gpointer _SOUP_METHOD_MOVE; +SOUP_VAR gpointer _SOUP_METHOD_LOCK; +SOUP_VAR gpointer _SOUP_METHOD_UNLOCK; + +G_END_DECLS + +#endif /* SOUP_METHOD_H */ diff --git a/libsoup/soup-misc-private.h b/libsoup/soup-misc-private.h new file mode 100644 index 0000000..7fe31a1 --- /dev/null +++ b/libsoup/soup-misc-private.h @@ -0,0 +1,49 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright 2011 Igalia, S.L. + * Copyright 2011 Red Hat, Inc. + */ + +#ifndef SOUP_MISC_PRIVATE_H +#define SOUP_MISC_PRIVATE_H 1 + +#include "soup-message-headers.h" + +char *soup_uri_decoded_copy (const char *str, int length, int *decoded_length); +char *soup_uri_to_string_internal (SoupURI *uri, gboolean just_path_and_query, + gboolean include_password, gboolean force_port); +gboolean soup_uri_is_http (SoupURI *uri, char **aliases); +gboolean soup_uri_is_https (SoupURI *uri, char **aliases); + +/* At some point it might be possible to mark additional methods + * safe or idempotent... + */ +#define SOUP_METHOD_IS_SAFE(method) (method == SOUP_METHOD_GET || \ + method == SOUP_METHOD_HEAD || \ + method == SOUP_METHOD_OPTIONS || \ + method == SOUP_METHOD_PROPFIND) + +#define SOUP_METHOD_IS_IDEMPOTENT(method) (method == SOUP_METHOD_GET || \ + method == SOUP_METHOD_HEAD || \ + method == SOUP_METHOD_OPTIONS || \ + method == SOUP_METHOD_PROPFIND || \ + method == SOUP_METHOD_PUT || \ + method == SOUP_METHOD_DELETE) + +GSource *soup_add_completion_reffed (GMainContext *async_context, + GSourceFunc function, + gpointer data, + GDestroyNotify dnotify); + +guint soup_message_headers_get_ranges_internal (SoupMessageHeaders *hdrs, + goffset total_length, + gboolean check_satisfiable, + SoupRange **ranges, + int *length); + +SoupAddress *soup_address_new_from_gsockaddr (GSocketAddress *addr); + +gboolean soup_host_matches_host (const gchar *host, + const gchar *compare_with); + +#endif /* SOUP_MISC_PRIVATE_H */ diff --git a/libsoup/soup-misc.c b/libsoup/soup-misc.c new file mode 100644 index 0000000..c583d90 --- /dev/null +++ b/libsoup/soup-misc.c @@ -0,0 +1,279 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-misc.c: Miscellaneous functions + + * Copyright (C) 2000-2003, Ximian, Inc. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "soup-misc.h" +#include "soup-misc-private.h" + +/** + * SECTION:soup-misc + * @short_description: Miscellaneous functions + * + **/ + +const gboolean soup_ssl_supported = TRUE; + +/** + * soup_str_case_hash: + * @key: ASCII string to hash + * + * Hashes @key in a case-insensitive manner. + * + * Return value: the hash code. + **/ +guint +soup_str_case_hash (gconstpointer key) +{ + const char *p = key; + guint h = g_ascii_toupper(*p); + + if (h) + for (p += 1; *p != '\0'; p++) + h = (h << 5) - h + g_ascii_toupper(*p); + + return h; +} + +/** + * soup_str_case_equal: + * @v1: an ASCII string + * @v2: another ASCII string + * + * Compares @v1 and @v2 in a case-insensitive manner + * + * Return value: %TRUE if they are equal (modulo case) + **/ +gboolean +soup_str_case_equal (gconstpointer v1, + gconstpointer v2) +{ + const char *string1 = v1; + const char *string2 = v2; + + return g_ascii_strcasecmp (string1, string2) == 0; +} + +/** + * soup_add_io_watch: (skip) + * @async_context: (allow-none): the #GMainContext to dispatch the I/O + * watch in, or %NULL for the default context + * @chan: the #GIOChannel to watch + * @condition: the condition to watch for + * @function: the callback to invoke when @condition occurs + * @data: user data to pass to @function + * + * Adds an I/O watch as with g_io_add_watch(), but using the given + * @async_context. + * + * Return value: a #GSource, which can be removed from @async_context + * with g_source_destroy(). + **/ +GSource * +soup_add_io_watch (GMainContext *async_context, + GIOChannel *chan, GIOCondition condition, + GIOFunc function, gpointer data) +{ + GSource *watch = g_io_create_watch (chan, condition); + g_source_set_callback (watch, (GSourceFunc) function, data, NULL); + g_source_attach (watch, async_context); + g_source_unref (watch); + return watch; +} + +/** + * soup_add_idle: (skip) + * @async_context: (allow-none): the #GMainContext to dispatch the I/O + * watch in, or %NULL for the default context + * @function: the callback to invoke at idle time + * @data: user data to pass to @function + * + * Adds an idle event as with g_idle_add(), but using the given + * @async_context. + * + * If you want @function to run "right away", use + * soup_add_completion(), since that sets a higher priority on the + * #GSource than soup_add_idle() does. + * + * Return value: a #GSource, which can be removed from @async_context + * with g_source_destroy(). + **/ +GSource * +soup_add_idle (GMainContext *async_context, + GSourceFunc function, gpointer data) +{ + GSource *source = g_idle_source_new (); + g_source_set_callback (source, function, data, NULL); + g_source_attach (source, async_context); + g_source_unref (source); + return source; +} + +GSource * +soup_add_completion_reffed (GMainContext *async_context, + GSourceFunc function, + gpointer data, + GDestroyNotify dnotify) +{ + GSource *source = g_idle_source_new (); + + g_source_set_priority (source, G_PRIORITY_DEFAULT); + g_source_set_callback (source, function, data, dnotify); + g_source_attach (source, async_context); + return source; +} + +/** + * soup_add_completion: (skip) + * @async_context: (allow-none): the #GMainContext to dispatch the I/O + * watch in, or %NULL for the default context + * @function: the callback to invoke + * @data: user data to pass to @function + * + * Adds @function to be executed from inside @async_context with the + * default priority. Use this when you want to complete an action in + * @async_context's main loop, as soon as possible. + * + * Return value: a #GSource, which can be removed from @async_context + * with g_source_destroy(). + * + * Since: 2.24 + **/ +GSource * +soup_add_completion (GMainContext *async_context, + GSourceFunc function, gpointer data) +{ + GSource *source; + + source = soup_add_completion_reffed (async_context, function, data, NULL); + g_source_unref (source); + return source; +} + +/** + * soup_add_timeout: (skip) + * @async_context: (allow-none): the #GMainContext to dispatch the I/O + * watch in, or %NULL for the default context + * @interval: the timeout interval, in milliseconds + * @function: the callback to invoke at timeout time + * @data: user data to pass to @function + * + * Adds a timeout as with g_timeout_add(), but using the given + * @async_context. + * + * Return value: a #GSource, which can be removed from @async_context + * with g_source_destroy(). + **/ +GSource * +soup_add_timeout (GMainContext *async_context, + guint interval, + GSourceFunc function, gpointer data) +{ + GSource *source = g_timeout_source_new (interval); + g_source_set_callback (source, function, data, NULL); + g_source_attach (source, async_context); + g_source_unref (source); + return source; +} + +/* 00 URI_UNRESERVED + * 01 URI_PCT_ENCODED + * 02 URI_GEN_DELIMS + * 04 URI_SUB_DELIMS + * 08 HTTP_SEPARATOR + * 10 HTTP_CTL + */ +const char soup_char_attributes[] = { + /* 0x00 - 0x07 */ + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + /* 0x08 - 0x0f */ + 0x11, 0x19, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + /* 0x10 - 0x17 */ + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + /* 0x18 - 0x1f */ + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + /* !"#$%&' */ + 0x09, 0x04, 0x09, 0x02, 0x04, 0x01, 0x04, 0x04, + /* ()*+,-./ */ + 0x0c, 0x0c, 0x04, 0x04, 0x0c, 0x00, 0x00, 0x0a, + /* 01234567 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 89:;<=>? */ + 0x00, 0x00, 0x0a, 0x0c, 0x09, 0x0a, 0x09, 0x0a, + /* @ABCDEFG */ + 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* HIJKLMNO */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* PQRSTUVW */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* XYZ[\]^_ */ + 0x00, 0x00, 0x00, 0x0a, 0x09, 0x0a, 0x01, 0x00, + /* `abcdefg */ + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* hijklmno */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* pqrstuvw */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* xyz{|}~ */ + 0x00, 0x00, 0x00, 0x09, 0x01, 0x09, 0x00, 0x11, + /* 0x80 - 0xFF */ + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 +}; + +/** + * soup_host_matches_host + * @host: a URI + * @compare_with: a URI + * + * Checks if the @host and @compare_with exactly match or prefixed with a dot. + * + * Return value: %TRUE if the hosts match, %FALSE otherwise + * + * Since: 2.54 + **/ +gboolean +soup_host_matches_host (const gchar *host, const gchar *compare_with) +{ + char *match; + int dlen; + + g_return_val_if_fail (host != NULL, FALSE); + g_return_val_if_fail (compare_with != NULL, FALSE); + + if (!g_ascii_strcasecmp (host, compare_with)) + return TRUE; + if (*host != '.') + return FALSE; + if (!g_ascii_strcasecmp (host + 1, compare_with)) + return TRUE; + dlen = strlen (host); + while ((match = strstr (compare_with, host))) { + if (!match[dlen]) + return TRUE; + compare_with = match + 1; + } + return FALSE; +} diff --git a/libsoup/soup-misc.h b/libsoup/soup-misc.h new file mode 100644 index 0000000..ecb09a8 --- /dev/null +++ b/libsoup/soup-misc.h @@ -0,0 +1,77 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2000-2003, Ximian, Inc. + */ + +#ifndef SOUP_MISC_H +#define SOUP_MISC_H 1 + +#include + +G_BEGIN_DECLS + +/* Non-default-GMainContext operations */ +SOUP_AVAILABLE_IN_2_4 +GSource *soup_add_io_watch (GMainContext *async_context, + GIOChannel *chan, + GIOCondition condition, + GIOFunc function, + gpointer data); +SOUP_AVAILABLE_IN_2_4 +GSource *soup_add_idle (GMainContext *async_context, + GSourceFunc function, + gpointer data); +SOUP_AVAILABLE_IN_2_24 +GSource *soup_add_completion (GMainContext *async_context, + GSourceFunc function, + gpointer data); +SOUP_AVAILABLE_IN_2_4 +GSource *soup_add_timeout (GMainContext *async_context, + guint interval, + GSourceFunc function, + gpointer data); + +/* Misc utils */ + +SOUP_AVAILABLE_IN_2_4 +guint soup_str_case_hash (gconstpointer key); +SOUP_AVAILABLE_IN_2_4 +gboolean soup_str_case_equal (gconstpointer v1, + gconstpointer v2); + +#define _SOUP_ATOMIC_INTERN_STRING(variable, value) ((const char *)(g_atomic_pointer_get (&(variable)) ? (variable) : (g_atomic_pointer_set (&(variable), (gpointer)g_intern_static_string (value)), (variable)))) + +/* character classes */ + +SOUP_AVAILABLE_IN_2_4 +const char soup_char_attributes[]; +#define SOUP_CHAR_URI_PERCENT_ENCODED 0x01 +#define SOUP_CHAR_URI_GEN_DELIMS 0x02 +#define SOUP_CHAR_URI_SUB_DELIMS 0x04 +#define SOUP_CHAR_HTTP_SEPARATOR 0x08 +#define SOUP_CHAR_HTTP_CTL 0x10 + +#define soup_char_is_uri_percent_encoded(ch) (soup_char_attributes[(guchar)ch] & SOUP_CHAR_URI_PERCENT_ENCODED) +#define soup_char_is_uri_gen_delims(ch) (soup_char_attributes[(guchar)ch] & SOUP_CHAR_URI_GEN_DELIMS) +#define soup_char_is_uri_sub_delims(ch) (soup_char_attributes[(guchar)ch] & SOUP_CHAR_URI_SUB_DELIMS) +#define soup_char_is_uri_unreserved(ch) (!(soup_char_attributes[(guchar)ch] & (SOUP_CHAR_URI_PERCENT_ENCODED | SOUP_CHAR_URI_GEN_DELIMS | SOUP_CHAR_URI_SUB_DELIMS))) +#define soup_char_is_token(ch) (!(soup_char_attributes[(guchar)ch] & (SOUP_CHAR_HTTP_SEPARATOR | SOUP_CHAR_HTTP_CTL))) + +/* SSL stuff */ +SOUP_AVAILABLE_IN_2_4 +const gboolean soup_ssl_supported; + +/* Part of a debugging API */ + +typedef enum { + SOUP_CONNECTION_NEW, + SOUP_CONNECTION_CONNECTING, + SOUP_CONNECTION_IDLE, + SOUP_CONNECTION_IN_USE, + SOUP_CONNECTION_REMOTE_DISCONNECTED, + SOUP_CONNECTION_DISCONNECTED +} SoupConnectionState; + +G_END_DECLS + +#endif /* SOUP_MISC_H */ diff --git a/libsoup/soup-multipart-input-stream.c b/libsoup/soup-multipart-input-stream.c new file mode 100644 index 0000000..d44991c --- /dev/null +++ b/libsoup/soup-multipart-input-stream.c @@ -0,0 +1,590 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-multipart-input-stream.c + * + * Copyright (C) 2012 Collabora Ltd. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "soup-body-input-stream.h" +#include "soup-filter-input-stream.h" +#include "soup-enum-types.h" +#include "soup-message.h" +#include "soup-message-private.h" +#include "soup-multipart-input-stream.h" + +#define RESPONSE_BLOCK_SIZE 8192 + +/** + * SECTION:soup-multipart-input-stream + * @short_description: Multipart input handling stream + * + * This adds support for the multipart responses. For handling the + * multiple parts the user needs to wrap the #GInputStream obtained by + * sending the request with a #SoupMultipartInputStream and use + * soup_multipart_input_stream_next_part() before reading. Responses + * which are not wrapped will be treated like non-multipart responses. + * + * Note that although #SoupMultipartInputStream is a #GInputStream, + * you should not read directly from it, and the results are undefined + * if you do. + * + * Since: 2.40 + **/ + +enum { + PROP_0, + + PROP_MESSAGE, +}; + +struct _SoupMultipartInputStreamPrivate { + SoupMessage *msg; + + gboolean done_with_part; + + GByteArray *meta_buf; + SoupMessageHeaders *current_headers; + + SoupFilterInputStream *base_stream; + + char *boundary; + gsize boundary_size; + + goffset remaining_bytes; +}; + +static void soup_multipart_input_stream_pollable_init (GPollableInputStreamInterface *pollable_interface, gpointer interface_data); + +G_DEFINE_TYPE_WITH_CODE (SoupMultipartInputStream, soup_multipart_input_stream, G_TYPE_FILTER_INPUT_STREAM, + G_ADD_PRIVATE (SoupMultipartInputStream) + G_IMPLEMENT_INTERFACE (G_TYPE_POLLABLE_INPUT_STREAM, + soup_multipart_input_stream_pollable_init)) + +static void +soup_multipart_input_stream_dispose (GObject *object) +{ + SoupMultipartInputStream *multipart = SOUP_MULTIPART_INPUT_STREAM (object); + + g_clear_object (&multipart->priv->msg); + g_clear_object (&multipart->priv->base_stream); + + G_OBJECT_CLASS (soup_multipart_input_stream_parent_class)->dispose (object); +} + +static void +soup_multipart_input_stream_finalize (GObject *object) +{ + SoupMultipartInputStream *multipart = SOUP_MULTIPART_INPUT_STREAM (object); + + g_free (multipart->priv->boundary); + + if (multipart->priv->meta_buf) + g_clear_pointer (&multipart->priv->meta_buf, g_byte_array_unref); + + G_OBJECT_CLASS (soup_multipart_input_stream_parent_class)->finalize (object); +} + +static void +soup_multipart_input_stream_set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + SoupMultipartInputStream *multipart = SOUP_MULTIPART_INPUT_STREAM (object); + + switch (prop_id) { + case PROP_MESSAGE: + multipart->priv->msg = g_value_dup_object (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +soup_multipart_input_stream_get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + SoupMultipartInputStream *multipart = SOUP_MULTIPART_INPUT_STREAM (object); + + switch (prop_id) { + case PROP_MESSAGE: + g_value_set_object (value, multipart->priv->msg); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static gssize +soup_multipart_input_stream_read_real (GInputStream *stream, + void *buffer, + gsize count, + gboolean blocking, + GCancellable *cancellable, + GError **error) +{ + SoupMultipartInputStream *multipart = SOUP_MULTIPART_INPUT_STREAM (stream); + SoupMultipartInputStreamPrivate *priv = multipart->priv; + gboolean got_boundary = FALSE; + gssize nread = 0; + guint8 *buf; + + g_return_val_if_fail (priv->boundary != NULL, -1); + + /* If we have received a Content-Length, and are not yet close to the end of + * the part, let's not look for the boundary for now. This optimization is + * necessary for keeping CPU usage civil. + */ + if (priv->remaining_bytes > priv->boundary_size) { + goffset bytes_to_read = MIN (count, priv->remaining_bytes - priv->boundary_size); + + nread = g_pollable_stream_read (G_INPUT_STREAM (priv->base_stream), + buffer, bytes_to_read, blocking, + cancellable, error); + + if (nread > 0) + priv->remaining_bytes -= nread; + + return nread; + } + + if (priv->done_with_part) + return 0; + + nread = soup_filter_input_stream_read_until (priv->base_stream, buffer, count, + priv->boundary, priv->boundary_size, + blocking, FALSE, &got_boundary, + cancellable, error); + + if (nread <= 0) + return nread; + + if (!got_boundary) + return nread; + + priv->done_with_part = TRUE; + + /* Ignore the newline that preceded the boundary. */ + if (nread == 1) { + buf = ((guint8*)buffer); + if (!memcmp (buf, "\n", 1)) + nread -= 1; + } else { + buf = ((guint8*)buffer) + nread - 2; + if (!memcmp (buf, "\r\n", 2)) + nread -= 2; + else if (!memcmp (buf, "\n", 1)) + nread -= 1; + } + + return nread; +} + +static gssize +soup_multipart_input_stream_read (GInputStream *stream, + void *buffer, + gsize count, + GCancellable *cancellable, + GError **error) +{ + return soup_multipart_input_stream_read_real (stream, buffer, count, + TRUE, cancellable, error); +} + +static void +soup_multipart_input_stream_init (SoupMultipartInputStream *multipart) +{ + SoupMultipartInputStreamPrivate *priv; + priv = multipart->priv = soup_multipart_input_stream_get_instance_private (multipart); + + priv->meta_buf = g_byte_array_sized_new (RESPONSE_BLOCK_SIZE); + priv->done_with_part = FALSE; +} + +static void +soup_multipart_input_stream_constructed (GObject *object) +{ + SoupMultipartInputStream *multipart; + SoupMultipartInputStreamPrivate *priv; + GInputStream *base_stream; + const char* boundary; + GHashTable *params = NULL; + + multipart = SOUP_MULTIPART_INPUT_STREAM (object); + priv = multipart->priv; + + base_stream = G_FILTER_INPUT_STREAM (multipart)->base_stream; + priv->base_stream = SOUP_FILTER_INPUT_STREAM (soup_filter_input_stream_new (base_stream)); + + soup_message_headers_get_content_type (priv->msg->response_headers, + ¶ms); + + boundary = g_hash_table_lookup (params, "boundary"); + if (boundary) { + if (g_str_has_prefix (boundary, "--")) + priv->boundary = g_strdup (boundary); + else + priv->boundary = g_strdup_printf ("--%s", boundary); + + priv->boundary_size = strlen (priv->boundary); + } else { + g_warning ("No boundary found in message tagged as multipart."); + } + + g_hash_table_destroy (params); + + if (G_OBJECT_CLASS (soup_multipart_input_stream_parent_class)->constructed) + G_OBJECT_CLASS (soup_multipart_input_stream_parent_class)->constructed (object); +} + +static gboolean +soup_multipart_input_stream_is_readable (GPollableInputStream *stream) +{ + SoupMultipartInputStream *multipart = SOUP_MULTIPART_INPUT_STREAM (stream); + SoupMultipartInputStreamPrivate *priv = multipart->priv; + + return g_pollable_input_stream_is_readable (G_POLLABLE_INPUT_STREAM (priv->base_stream)); +} + +static gssize +soup_multipart_input_stream_read_nonblocking (GPollableInputStream *stream, + void *buffer, + gsize count, + GError **error) +{ + SoupMultipartInputStream *multipart = SOUP_MULTIPART_INPUT_STREAM (stream); + + return soup_multipart_input_stream_read_real (G_INPUT_STREAM (multipart), + buffer, count, + FALSE, NULL, error); +} + +static GSource * +soup_multipart_input_stream_create_source (GPollableInputStream *stream, + GCancellable *cancellable) +{ + SoupMultipartInputStream *multipart = SOUP_MULTIPART_INPUT_STREAM (stream); + SoupMultipartInputStreamPrivate *priv = multipart->priv; + GSource *base_source, *pollable_source; + + base_source = g_pollable_input_stream_create_source (G_POLLABLE_INPUT_STREAM (priv->base_stream), cancellable); + + pollable_source = g_pollable_source_new_full (stream, base_source, cancellable); + g_source_unref (base_source); + + return pollable_source; +} + +static void +soup_multipart_input_stream_class_init (SoupMultipartInputStreamClass *multipart_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (multipart_class); + GInputStreamClass *input_stream_class = + G_INPUT_STREAM_CLASS (multipart_class); + + object_class->dispose = soup_multipart_input_stream_dispose; + object_class->finalize = soup_multipart_input_stream_finalize; + object_class->constructed = soup_multipart_input_stream_constructed; + object_class->set_property = soup_multipart_input_stream_set_property; + object_class->get_property = soup_multipart_input_stream_get_property; + + input_stream_class->read_fn = soup_multipart_input_stream_read; + + g_object_class_install_property ( + object_class, PROP_MESSAGE, + g_param_spec_object ("message", + "Message", + "The SoupMessage", + SOUP_TYPE_MESSAGE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + +} + +static void +soup_multipart_input_stream_pollable_init (GPollableInputStreamInterface *pollable_interface, + gpointer interface_data) +{ + pollable_interface->is_readable = soup_multipart_input_stream_is_readable; + pollable_interface->read_nonblocking = soup_multipart_input_stream_read_nonblocking; + pollable_interface->create_source = soup_multipart_input_stream_create_source; +} + +static void +soup_multipart_input_stream_parse_headers (SoupMultipartInputStream *multipart) +{ + SoupMultipartInputStreamPrivate *priv = multipart->priv; + gboolean success; + + priv->current_headers = soup_message_headers_new (SOUP_MESSAGE_HEADERS_MULTIPART); + + /* The part lacks headers, but is there. */ + if (!priv->meta_buf->len) + return; + + success = soup_headers_parse ((const char*) priv->meta_buf->data, + (int) priv->meta_buf->len, + priv->current_headers); + + if (success) + priv->remaining_bytes = soup_message_headers_get_content_length (priv->current_headers); + else + g_clear_pointer (&priv->current_headers, soup_message_headers_free); + + g_byte_array_remove_range (priv->meta_buf, 0, priv->meta_buf->len); +} + +static gboolean +soup_multipart_input_stream_read_headers (SoupMultipartInputStream *multipart, + GCancellable *cancellable, + GError **error) +{ + SoupMultipartInputStreamPrivate *priv = multipart->priv; + guchar read_buf[RESPONSE_BLOCK_SIZE]; + guchar *buf; + gboolean got_boundary = FALSE; + gboolean got_lf = FALSE; + gssize nread = 0; + + g_return_val_if_fail (priv->boundary != NULL, TRUE); + + g_clear_pointer (&priv->current_headers, soup_message_headers_free); + + while (1) { + nread = soup_filter_input_stream_read_line (priv->base_stream, read_buf, sizeof (read_buf), + /* blocking */ TRUE, &got_lf, cancellable, error); + + if (nread <= 0) + break; + + g_byte_array_append (priv->meta_buf, read_buf, nread); + + /* Need to do this boundary check before checking for the line feed, since we + * may get the multipart end indicator without getting a new line. + */ + if (!got_boundary && + !strncmp ((char *)priv->meta_buf->data, + priv->boundary, + priv->boundary_size)) { + got_boundary = TRUE; + + /* Now check for possible multipart termination. */ + buf = &read_buf[nread - 4]; + if ((nread >= 4 && !memcmp (buf, "--\r\n", 4)) || + (nread >= 3 && !memcmp (buf + 1, "--\n", 3)) || + (nread >= 3 && !memcmp (buf + 2, "--", 2))) { + g_byte_array_set_size (priv->meta_buf, 0); + return FALSE; + } + } + + g_return_val_if_fail (got_lf, FALSE); + + /* Discard pre-boundary lines. */ + if (!got_boundary) { + g_byte_array_set_size (priv->meta_buf, 0); + continue; + } + + if (nread == 1 && + priv->meta_buf->len >= 2 && + !strncmp ((char *)priv->meta_buf->data + + priv->meta_buf->len - 2, + "\n\n", 2)) + break; + else if (nread == 2 && + priv->meta_buf->len >= 3 && + !strncmp ((char *)priv->meta_buf->data + + priv->meta_buf->len - 3, + "\n\r\n", 3)) + break; + } + + return TRUE; +} + +/* Public APIs */ + +/** + * soup_multipart_input_stream_new: + * @msg: the #SoupMessage the response is related to. + * @base_stream: the #GInputStream returned by sending the request. + * + * Creates a new #SoupMultipartInputStream that wraps the + * #GInputStream obtained by sending the #SoupRequest. Reads should + * not be done directly through this object, use the input streams + * returned by soup_multipart_input_stream_next_part() or its async + * counterpart instead. + * + * Returns: a new #SoupMultipartInputStream + * + * Since: 2.40 + **/ +SoupMultipartInputStream * +soup_multipart_input_stream_new (SoupMessage *msg, + GInputStream *base_stream) +{ + return g_object_new (SOUP_TYPE_MULTIPART_INPUT_STREAM, + "message", msg, + "base-stream", base_stream, + NULL); +} + +/** + * soup_multipart_input_stream_next_part: + * @multipart: the #SoupMultipartInputStream + * @cancellable: a #GCancellable + * @error: a #GError + * + * Obtains an input stream for the next part. When dealing with a + * multipart response the input stream needs to be wrapped in a + * #SoupMultipartInputStream and this function or its async + * counterpart need to be called to obtain the first part for + * reading. + * + * After calling this function, + * soup_multipart_input_stream_get_headers() can be used to obtain the + * headers for the first part. A read of 0 bytes indicates the end of + * the part; a new call to this function should be done at that point, + * to obtain the next part. + * + * Return value: (nullable) (transfer full): a new #GInputStream, or + * %NULL if there are no more parts + * + * Since: 2.40 + */ +GInputStream * +soup_multipart_input_stream_next_part (SoupMultipartInputStream *multipart, + GCancellable *cancellable, + GError **error) +{ + if (!soup_multipart_input_stream_read_headers (multipart, cancellable, error)) + return NULL; + + soup_multipart_input_stream_parse_headers (multipart); + + multipart->priv->done_with_part = FALSE; + + return G_INPUT_STREAM (g_object_new (SOUP_TYPE_BODY_INPUT_STREAM, + "base-stream", G_INPUT_STREAM (multipart), + "close-base-stream", FALSE, + "encoding", SOUP_ENCODING_EOF, + NULL)); + +} + +static void +soup_multipart_input_stream_next_part_thread (GTask *task, + gpointer object, + gpointer task_data, + GCancellable *cancellable) +{ + SoupMultipartInputStream *multipart = SOUP_MULTIPART_INPUT_STREAM (object); + GError *error = NULL; + GInputStream *new_stream; + + new_stream = soup_multipart_input_stream_next_part (multipart, cancellable, &error); + + g_input_stream_clear_pending (G_INPUT_STREAM (multipart)); + + if (error) + g_task_return_error (task, error); + else + g_task_return_pointer (task, new_stream, g_object_unref); +} + +/** + * soup_multipart_input_stream_next_part_async: + * @multipart: the #SoupMultipartInputStream. + * @io_priority: the I/O priority for the request. + * @cancellable: a #GCancellable. + * @callback: callback to call when request is satisfied. + * @data: data for @callback + * + * Obtains a #GInputStream for the next request. See + * soup_multipart_input_stream_next_part() for details on the + * workflow. + * + * Since: 2.40 + */ +void +soup_multipart_input_stream_next_part_async (SoupMultipartInputStream *multipart, + int io_priority, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer data) +{ + GInputStream *stream = G_INPUT_STREAM (multipart); + GTask *task; + GError *error = NULL; + + g_return_if_fail (SOUP_IS_MULTIPART_INPUT_STREAM (multipart)); + + task = g_task_new (multipart, cancellable, callback, data); + g_task_set_priority (task, io_priority); + + if (!g_input_stream_set_pending (stream, &error)) { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + g_task_run_in_thread (task, soup_multipart_input_stream_next_part_thread); + g_object_unref (task); +} + +/** + * soup_multipart_input_stream_next_part_finish: + * @multipart: a #SoupMultipartInputStream. + * @result: a #GAsyncResult. + * @error: a #GError location to store any error, or %NULL to ignore. + * + * Finishes an asynchronous request for the next part. + * + * Return value: (nullable) (transfer full): a newly created + * #GInputStream for reading the next part or %NULL if there are no + * more parts. + * + * Since: 2.40 + */ +GInputStream * +soup_multipart_input_stream_next_part_finish (SoupMultipartInputStream *multipart, + GAsyncResult *result, + GError **error) +{ + g_return_val_if_fail (g_task_is_valid (result, multipart), FALSE); + + return g_task_propagate_pointer (G_TASK (result), error); +} + +/** + * soup_multipart_input_stream_get_headers: + * @multipart: a #SoupMultipartInputStream. + * + * Obtains the headers for the part currently being processed. Note + * that the #SoupMessageHeaders that are returned are owned by the + * #SoupMultipartInputStream and will be replaced when a call is made + * to soup_multipart_input_stream_next_part() or its async + * counterpart, so if keeping the headers is required, a copy must be + * made. + * + * Note that if a part had no headers at all an empty #SoupMessageHeaders + * will be returned. + * + * Return value: (nullable) (transfer none): a #SoupMessageHeaders + * containing the headers for the part currently being processed or + * %NULL if the headers failed to parse. + * + * Since: 2.40 + */ +SoupMessageHeaders * +soup_multipart_input_stream_get_headers (SoupMultipartInputStream *multipart) +{ + return multipart->priv->current_headers; +} diff --git a/libsoup/soup-multipart-input-stream.h b/libsoup/soup-multipart-input-stream.h new file mode 100644 index 0000000..8b73506 --- /dev/null +++ b/libsoup/soup-multipart-input-stream.h @@ -0,0 +1,66 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2012 Collabora Ltd. + */ + +#ifndef SOUP_MULTIPART_INPUT_STREAM_H +#define SOUP_MULTIPART_INPUT_STREAM_H 1 + +#include +#include + +G_BEGIN_DECLS + +#define SOUP_TYPE_MULTIPART_INPUT_STREAM (soup_multipart_input_stream_get_type ()) +#define SOUP_MULTIPART_INPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), SOUP_TYPE_MULTIPART_INPUT_STREAM, SoupMultipartInputStream)) +#define SOUP_MULTIPART_INPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), SOUP_TYPE_MULTIPART_INPUT_STREAM, SoupMultipartInputStreamClass)) +#define SOUP_IS_MULTIPART_INPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), SOUP_TYPE_MULTIPART_INPUT_STREAM)) +#define SOUP_IS_MULTIPART_INPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), SOUP_TYPE_MULTIPART_INPUT_STREAM)) +#define SOUP_MULTIPART_INPUT_STREAM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), SOUP_TYPE_MULTIPART_INPUT_STREAM, SoupMultipartInputStreamClass)) + +typedef struct _SoupMultipartInputStream SoupMultipartInputStream; +typedef struct _SoupMultipartInputStreamPrivate SoupMultipartInputStreamPrivate; +typedef struct _SoupMultipartInputStreamClass SoupMultipartInputStreamClass; + +struct _SoupMultipartInputStream { + GFilterInputStream parent_instance; + + /*< private >*/ + SoupMultipartInputStreamPrivate *priv; +}; + +struct _SoupMultipartInputStreamClass { + GFilterInputStreamClass parent_class; +}; + +SOUP_AVAILABLE_IN_2_40 +GType soup_multipart_input_stream_get_type (void) G_GNUC_CONST; + +SOUP_AVAILABLE_IN_2_40 +SoupMultipartInputStream *soup_multipart_input_stream_new (SoupMessage *msg, + GInputStream *base_stream); + +SOUP_AVAILABLE_IN_2_40 +GInputStream *soup_multipart_input_stream_next_part (SoupMultipartInputStream *multipart, + GCancellable *cancellable, + GError **error); + +SOUP_AVAILABLE_IN_2_40 +void soup_multipart_input_stream_next_part_async (SoupMultipartInputStream *multipart, + int io_priority, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer data); + +SOUP_AVAILABLE_IN_2_40 +GInputStream *soup_multipart_input_stream_next_part_finish (SoupMultipartInputStream *multipart, + GAsyncResult *result, + GError **error); + +SOUP_AVAILABLE_IN_2_40 +SoupMessageHeaders *soup_multipart_input_stream_get_headers (SoupMultipartInputStream *multipart); + + +G_END_DECLS + +#endif /* SOUP_MULTIPART_INPUT_STREAM_H */ diff --git a/libsoup/soup-multipart.c b/libsoup/soup-multipart.c new file mode 100644 index 0000000..242c632 --- /dev/null +++ b/libsoup/soup-multipart.c @@ -0,0 +1,495 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-multipart.c: multipart HTTP message bodies + * + * Copyright (C) 2008 Red Hat, Inc. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "soup-multipart.h" +#include "soup.h" + +/** + * SECTION:soup-multipart + * @short_description: multipart HTTP message bodies + * @see_also: #SoupMessageBody, #SoupMessageHeaders + * + **/ + +/** + * SoupMultipart: + * + * Represents a multipart HTTP message body, parsed according to the + * syntax of RFC 2046. Of particular interest to HTTP are + * multipart/byte-ranges and + * multipart/form-data. + * + * Although the headers of a #SoupMultipart body part will contain the + * full headers from that body part, libsoup does not interpret them + * according to MIME rules. For example, each body part is assumed to + * have "binary" Content-Transfer-Encoding, even if its headers + * explicitly state otherwise. In other words, don't try to use + * #SoupMultipart for handling real MIME multiparts. + * + * Since: 2.26 + **/ + +struct SoupMultipart { + char *mime_type, *boundary; + GPtrArray *headers, *bodies; +}; + +static SoupMultipart * +soup_multipart_new_internal (char *mime_type, char *boundary) +{ + SoupMultipart *multipart; + + multipart = g_slice_new (SoupMultipart); + multipart->mime_type = mime_type; + multipart->boundary = boundary; + multipart->headers = g_ptr_array_new_with_free_func ((GDestroyNotify)soup_message_headers_free); + multipart->bodies = g_ptr_array_new_with_free_func ((GDestroyNotify)soup_buffer_free); + + return multipart; +} + +static char * +generate_boundary (void) +{ + static int counter; + struct { + GTimeVal timeval; + int counter; + } data; + + /* avoid valgrind warning */ + if (sizeof (data) != sizeof (data.timeval) + sizeof (data.counter)) + memset (&data, 0, sizeof (data)); + + g_get_current_time (&data.timeval); + data.counter = counter++; + + /* The maximum boundary string length is 69 characters, and a + * stringified SHA256 checksum is 64 bytes long. + */ + return g_compute_checksum_for_data (G_CHECKSUM_SHA256, + (const guchar *)&data, + sizeof (data)); +} + +/** + * soup_multipart_new: + * @mime_type: the MIME type of the multipart to create. + * + * Creates a new empty #SoupMultipart with a randomly-generated + * boundary string. Note that @mime_type must be the full MIME type, + * including "multipart/". + * + * Return value: a new empty #SoupMultipart of the given @mime_type + * + * Since: 2.26 + **/ +SoupMultipart * +soup_multipart_new (const char *mime_type) +{ + return soup_multipart_new_internal (g_strdup (mime_type), + generate_boundary ()); +} + +static const char * +find_boundary (const char *start, const char *end, + const char *boundary, int boundary_len) +{ + const char *b; + + for (b = memchr (start, '-', end - start); + b && b + boundary_len + 4 < end; + b = memchr (b + 2, '-', end - (b + 2))) { + /* Check for "--boundary" */ + if (b[1] != '-' || + memcmp (b + 2, boundary, boundary_len) != 0) + continue; + + /* Check that it's at start of line */ + if (!(b == start || (b[-1] == '\n' && b[-2] == '\r'))) + continue; + + /* Check for "--" or "\r\n" after boundary */ + if ((b[boundary_len + 2] == '-' && b[boundary_len + 3] == '-') || + (b[boundary_len + 2] == '\r' && b[boundary_len + 3] == '\n')) + return b; + } + return NULL; +} + +/** + * soup_multipart_new_from_message: + * @headers: the headers of the HTTP message to parse + * @body: the body of the HTTP message to parse + * + * Parses @headers and @body to form a new #SoupMultipart + * + * Return value: (nullable): a new #SoupMultipart (or %NULL if the + * message couldn't be parsed or wasn't multipart). + * + * Since: 2.26 + **/ +SoupMultipart * +soup_multipart_new_from_message (SoupMessageHeaders *headers, + SoupMessageBody *body) +{ + SoupMultipart *multipart; + const char *content_type, *boundary; + GHashTable *params; + int boundary_len; + SoupBuffer *flattened; + const char *start, *split, *end, *body_end; + SoupMessageHeaders *part_headers; + SoupBuffer *part_body; + + content_type = soup_message_headers_get_content_type (headers, ¶ms); + if (!content_type) + return NULL; + + boundary = g_hash_table_lookup (params, "boundary"); + if (strncmp (content_type, "multipart/", 10) != 0 || !boundary) { + g_hash_table_destroy (params); + return NULL; + } + + multipart = soup_multipart_new_internal ( + g_strdup (content_type), g_strdup (boundary)); + g_hash_table_destroy (params); + + flattened = soup_message_body_flatten (body); + body_end = flattened->data + flattened->length; + boundary = multipart->boundary; + boundary_len = strlen (boundary); + + /* skip preamble */ + start = find_boundary (flattened->data, body_end, + boundary, boundary_len); + if (!start) { + soup_multipart_free (multipart); + soup_buffer_free (flattened); + return NULL; + } + + while (start[2 + boundary_len] != '-') { + end = find_boundary (start + 2 + boundary_len, body_end, + boundary, boundary_len); + if (!end) { + soup_multipart_free (multipart); + soup_buffer_free (flattened); + return NULL; + } + + split = strstr (start, "\r\n\r\n"); + if (!split || split > end) { + soup_multipart_free (multipart); + soup_buffer_free (flattened); + return NULL; + } + split += 4; + + /* @start points to the start of the boundary line + * preceding this part, and @split points to the end + * of the headers / start of the body. + * + * We tell soup_headers_parse() to start parsing at + * @start, because it skips the first line of the + * input anyway (expecting it to be either a + * Request-Line or Status-Line). + */ + part_headers = soup_message_headers_new (SOUP_MESSAGE_HEADERS_MULTIPART); + g_ptr_array_add (multipart->headers, part_headers); + if (!soup_headers_parse (start, split - 2 - start, + part_headers)) { + soup_multipart_free (multipart); + soup_buffer_free (flattened); + return NULL; + } + + /* @split, as previously mentioned, points to the + * start of the body, and @end points to the start of + * the following boundary line, which is to say 2 bytes + * after the end of the body. + */ + part_body = soup_buffer_new_subbuffer (flattened, + split - flattened->data, + end - 2 - split); + g_ptr_array_add (multipart->bodies, part_body); + + start = end; + } + + soup_buffer_free (flattened); + return multipart; +} + +/** + * soup_multipart_get_length: + * @multipart: a #SoupMultipart + * + * Gets the number of body parts in @multipart + * + * Return value: the number of body parts in @multipart + * + * Since: 2.26 + **/ +int +soup_multipart_get_length (SoupMultipart *multipart) +{ + return multipart->bodies->len; +} + +/** + * soup_multipart_get_part: + * @multipart: a #SoupMultipart + * @part: the part number to get (counting from 0) + * @headers: (out) (transfer none): return location for the MIME part + * headers + * @body: (out) (transfer none): return location for the MIME part + * body + * + * Gets the indicated body part from @multipart. + * + * Return value: %TRUE on success, %FALSE if @part is out of range (in + * which case @headers and @body won't be set) + * + * Since: 2.26 + **/ +gboolean +soup_multipart_get_part (SoupMultipart *multipart, int part, + SoupMessageHeaders **headers, SoupBuffer **body) +{ + if (part < 0 || part >= multipart->bodies->len) + return FALSE; + *headers = multipart->headers->pdata[part]; + *body = multipart->bodies->pdata[part]; + return TRUE; +} + +/** + * soup_multipart_append_part: + * @multipart: a #SoupMultipart + * @headers: the MIME part headers + * @body: the MIME part body + * + * Adds a new MIME part to @multipart with the given headers and body. + * (The multipart will make its own copies of @headers and @body, so + * you should free your copies if you are not using them for anything + * else.) + * + * Since: 2.26 + **/ +void +soup_multipart_append_part (SoupMultipart *multipart, + SoupMessageHeaders *headers, + SoupBuffer *body) +{ + SoupMessageHeaders *headers_copy; + SoupMessageHeadersIter iter; + const char *name, *value; + + /* Copying @headers is annoying, but the alternatives seem + * worse: + * + * 1) We don't want to use g_boxed_copy, because + * SoupMessageHeaders actually implements that as just a + * ref, which would be confusing since SoupMessageHeaders + * is mutable and the caller might modify @headers after + * appending it. + * + * 2) We can't change SoupMessageHeaders to not just do a ref + * from g_boxed_copy, because that would break language + * bindings (which need to be able to hold a ref on + * msg->request_headers, but don't want to duplicate it). + * + * 3) We don't want to steal the reference to @headers, + * because then we'd have to either also steal the + * reference to @body (which would be inconsistent with + * other SoupBuffer methods), or NOT steal the reference to + * @body, in which case there'd be inconsistency just + * between the two arguments of this method! + */ + headers_copy = soup_message_headers_new (SOUP_MESSAGE_HEADERS_MULTIPART); + soup_message_headers_iter_init (&iter, headers); + while (soup_message_headers_iter_next (&iter, &name, &value)) + soup_message_headers_append (headers_copy, name, value); + + g_ptr_array_add (multipart->headers, headers_copy); + g_ptr_array_add (multipart->bodies, soup_buffer_copy (body)); +} + +/** + * soup_multipart_append_form_string: + * @multipart: a multipart (presumably of type "multipart/form-data") + * @control_name: the name of the control associated with @data + * @data: the body data + * + * Adds a new MIME part containing @data to @multipart, using + * "Content-Disposition: form-data", as per the HTML forms + * specification. See soup_form_request_new_from_multipart() for more + * details. + * + * Since: 2.26 + **/ +void +soup_multipart_append_form_string (SoupMultipart *multipart, + const char *control_name, const char *data) +{ + SoupBuffer *body; + + body = soup_buffer_new (SOUP_MEMORY_COPY, data, strlen (data)); + soup_multipart_append_form_file (multipart, control_name, + NULL, NULL, body); + soup_buffer_free (body); +} + +/** + * soup_multipart_append_form_file: + * @multipart: a multipart (presumably of type "multipart/form-data") + * @control_name: the name of the control associated with this file + * @filename: the name of the file, or %NULL if not known + * @content_type: the MIME type of the file, or %NULL if not known + * @body: the file data + * + * Adds a new MIME part containing @body to @multipart, using + * "Content-Disposition: form-data", as per the HTML forms + * specification. See soup_form_request_new_from_multipart() for more + * details. + * + * Since: 2.26 + **/ +void +soup_multipart_append_form_file (SoupMultipart *multipart, + const char *control_name, const char *filename, + const char *content_type, SoupBuffer *body) +{ + SoupMessageHeaders *headers; + GString *disposition; + + headers = soup_message_headers_new (SOUP_MESSAGE_HEADERS_MULTIPART); + disposition = g_string_new ("form-data; "); + soup_header_g_string_append_param_quoted (disposition, "name", control_name); + if (filename) { + g_string_append (disposition, "; "); + soup_header_g_string_append_param_quoted (disposition, "filename", filename); + } + soup_message_headers_append (headers, "Content-Disposition", + disposition->str); + g_string_free (disposition, TRUE); + + if (content_type) { + soup_message_headers_append (headers, "Content-Type", + content_type); + } + + g_ptr_array_add (multipart->headers, headers); + g_ptr_array_add (multipart->bodies, soup_buffer_copy (body)); +} + +/** + * soup_multipart_to_message: + * @multipart: a #SoupMultipart + * @dest_headers: the headers of the HTTP message to serialize @multipart to + * @dest_body: the body of the HTTP message to serialize @multipart to + * + * Serializes @multipart to @dest_headers and @dest_body. + * + * Since: 2.26 + **/ +void +soup_multipart_to_message (SoupMultipart *multipart, + SoupMessageHeaders *dest_headers, + SoupMessageBody *dest_body) +{ + SoupMessageHeaders *part_headers; + SoupBuffer *part_body; + SoupMessageHeadersIter iter; + const char *name, *value; + GString *str; + GHashTable *params; + guint i; + + params = g_hash_table_new (g_str_hash, g_str_equal); + g_hash_table_insert (params, "boundary", multipart->boundary); + soup_message_headers_set_content_type (dest_headers, + multipart->mime_type, + params); + g_hash_table_destroy (params); + + for (i = 0; i < multipart->bodies->len; i++) { + part_headers = multipart->headers->pdata[i]; + part_body = multipart->bodies->pdata[i]; + + str = g_string_new (i == 0 ? NULL : "\r\n"); + g_string_append (str, "--"); + g_string_append (str, multipart->boundary); + g_string_append (str, "\r\n"); + soup_message_headers_iter_init (&iter, part_headers); + while (soup_message_headers_iter_next (&iter, &name, &value)) + g_string_append_printf (str, "%s: %s\r\n", name, value); + g_string_append (str, "\r\n"); + soup_message_body_append (dest_body, SOUP_MEMORY_TAKE, + str->str, str->len); + g_string_free (str, FALSE); + + soup_message_body_append_buffer (dest_body, part_body); + } + + str = g_string_new ("\r\n--"); + g_string_append (str, multipart->boundary); + g_string_append (str, "--\r\n"); + soup_message_body_append (dest_body, SOUP_MEMORY_TAKE, + str->str, str->len); + g_string_free (str, FALSE); + + /* (The "\r\n" after the close-delimiter seems wrong according + * to my reading of RFCs 2046 and 2616, but that's what + * everyone else does.) + */ +} + +/** + * soup_multipart_free: + * @multipart: a #SoupMultipart + * + * Frees @multipart + * + * Since: 2.26 + **/ +void +soup_multipart_free (SoupMultipart *multipart) +{ + g_free (multipart->mime_type); + g_free (multipart->boundary); + g_ptr_array_free (multipart->headers, TRUE); + g_ptr_array_free (multipart->bodies, TRUE); + + g_slice_free (SoupMultipart, multipart); +} + +static SoupMultipart * +soup_multipart_copy (SoupMultipart *multipart) +{ + SoupMultipart *copy; + guint i; + + copy = soup_multipart_new_internal (g_strdup (multipart->mime_type), + g_strdup (multipart->boundary)); + for (i = 0; i < multipart->bodies->len; i++) { + soup_multipart_append_part (copy, + multipart->headers->pdata[i], + multipart->bodies->pdata[i]); + } + return copy; +} + +G_DEFINE_BOXED_TYPE (SoupMultipart, soup_multipart, soup_multipart_copy, soup_multipart_free) diff --git a/libsoup/soup-multipart.h b/libsoup/soup-multipart.h new file mode 100644 index 0000000..ddd1b36 --- /dev/null +++ b/libsoup/soup-multipart.h @@ -0,0 +1,61 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2008 Red Hat, Inc. + */ + +#ifndef SOUP_MULTIPART_H +#define SOUP_MULTIPART_H 1 + +#include +#include +#include + +G_BEGIN_DECLS + +typedef struct SoupMultipart SoupMultipart; + +SOUP_AVAILABLE_IN_2_26 +GType soup_multipart_get_type (void); +#define SOUP_TYPE_MULTIPART (soup_multipart_get_type ()) + +SOUP_AVAILABLE_IN_2_26 +SoupMultipart *soup_multipart_new (const char *mime_type); +SOUP_AVAILABLE_IN_2_26 +SoupMultipart *soup_multipart_new_from_message (SoupMessageHeaders *headers, + SoupMessageBody *body); + +SOUP_AVAILABLE_IN_2_26 +int soup_multipart_get_length (SoupMultipart *multipart); +SOUP_AVAILABLE_IN_2_26 +gboolean soup_multipart_get_part (SoupMultipart *multipart, + int part, + SoupMessageHeaders **headers, + SoupBuffer **body); + +SOUP_AVAILABLE_IN_2_26 +void soup_multipart_append_part (SoupMultipart *multipart, + SoupMessageHeaders *headers, + SoupBuffer *body); + +SOUP_AVAILABLE_IN_2_26 +void soup_multipart_append_form_string (SoupMultipart *multipart, + const char *control_name, + const char *data); +SOUP_AVAILABLE_IN_2_26 +void soup_multipart_append_form_file (SoupMultipart *multipart, + const char *control_name, + const char *filename, + const char *content_type, + SoupBuffer *body); + +SOUP_AVAILABLE_IN_2_26 +void soup_multipart_to_message (SoupMultipart *multipart, + SoupMessageHeaders *dest_headers, + SoupMessageBody *dest_body); + +SOUP_AVAILABLE_IN_2_26 +void soup_multipart_free (SoupMultipart *multipart); + +G_END_DECLS + +#endif /* SOUP_MULTIPART_H */ diff --git a/libsoup/soup-password-manager-gnome.c b/libsoup/soup-password-manager-gnome.c new file mode 100644 index 0000000..8101683 --- /dev/null +++ b/libsoup/soup-password-manager-gnome.c @@ -0,0 +1,28 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-password-manager-gnome.c: GNOME-keyring-based password manager + * + * Copyright (C) 2008 Red Hat, Inc. + */ + +/* This is just a stub now; eventually it will go away completely. */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "soup-password-manager-gnome.h" +#include "soup.h" + +G_DEFINE_TYPE_EXTENDED (SoupPasswordManagerGNOME, soup_password_manager_gnome, G_TYPE_OBJECT, 0, + G_IMPLEMENT_INTERFACE (SOUP_TYPE_SESSION_FEATURE, NULL)) + +static void +soup_password_manager_gnome_init (SoupPasswordManagerGNOME *manager_gnome) +{ +} + +static void +soup_password_manager_gnome_class_init (SoupPasswordManagerGNOMEClass *gnome_class) +{ +} diff --git a/libsoup/soup-password-manager-gnome.h b/libsoup/soup-password-manager-gnome.h new file mode 100644 index 0000000..290e3ec --- /dev/null +++ b/libsoup/soup-password-manager-gnome.h @@ -0,0 +1,28 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2008 Red Hat, Inc. + */ + +#ifndef SOUP_PASSWORD_MANAGER_GNOME_H +#define SOUP_PASSWORD_MANAGER_GNOME_H 1 + +#include "soup-password-manager.h" +#include "soup-gnome-features.h" + +#define SOUP_PASSWORD_MANAGER_GNOME(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), SOUP_TYPE_PASSWORD_MANAGER_GNOME, SoupPasswordManagerGNOME)) +#define SOUP_PASSWORD_MANAGER_GNOME_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_PASSWORD_MANAGER_GNOME, SoupPasswordManagerGNOMEClass)) +#define SOUP_IS_PASSWORD_MANAGER_GNOME(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), SOUP_TYPE_PASSWORD_MANAGER_GNOME)) +#define SOUP_IS_PASSWORD_MANAGER_GNOME_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SOUP_TYPE_PASSWORD_MANAGER_GNOME)) +#define SOUP_PASSWORD_MANAGER_GNOME_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_PASSWORD_MANAGER_GNOME, SoupPasswordManagerGNOMEClass)) + +typedef struct { + GObject parent; + +} SoupPasswordManagerGNOME; + +typedef struct { + GObjectClass parent_class; + +} SoupPasswordManagerGNOMEClass; + +#endif /* SOUP_PASSWORD_MANAGER_GNOME_H */ diff --git a/libsoup/soup-password-manager.c b/libsoup/soup-password-manager.c new file mode 100644 index 0000000..532ff7e --- /dev/null +++ b/libsoup/soup-password-manager.c @@ -0,0 +1,48 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-password-manager.c: HTTP auth password manager interface + * + * Copyright (C) 2008 Red Hat, Inc. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "soup-password-manager.h" +#include "soup.h" + +G_DEFINE_INTERFACE_WITH_CODE (SoupPasswordManager, soup_password_manager, G_TYPE_OBJECT, + g_type_interface_add_prerequisite (g_define_type_id, SOUP_TYPE_SESSION_FEATURE); + ) + +static void +soup_password_manager_default_init (SoupPasswordManagerInterface *iface) +{ +} + +/** + * soup_password_manager_get_passwords_async: + * @callback: (scope async) + */ +void +soup_password_manager_get_passwords_async (SoupPasswordManager *password_manager, + SoupMessage *msg, + SoupAuth *auth, + gboolean retrying, + GMainContext *async_context, + GCancellable *cancellable, + SoupPasswordManagerCallback callback, + gpointer user_data) +{ + g_warn_if_reached (); +} + +void +soup_password_manager_get_passwords_sync (SoupPasswordManager *password_manager, + SoupMessage *msg, + SoupAuth *auth, + GCancellable *cancellable) +{ + g_warn_if_reached (); +} diff --git a/libsoup/soup-password-manager.h b/libsoup/soup-password-manager.h new file mode 100644 index 0000000..aa5faf5 --- /dev/null +++ b/libsoup/soup-password-manager.h @@ -0,0 +1,64 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2008 Red Hat, Inc. + */ + +#ifndef SOUP_PASSWORD_MANAGER_H +#define SOUP_PASSWORD_MANAGER_H 1 + +#include + +#define SOUP_TYPE_PASSWORD_MANAGER (soup_password_manager_get_type ()) +#define SOUP_PASSWORD_MANAGER(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), SOUP_TYPE_PASSWORD_MANAGER, SoupPasswordManager)) +#define SOUP_PASSWORD_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_PASSWORD_MANAGER, SoupPasswordManagerInterface)) +#define SOUP_IS_PASSWORD_MANAGER(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), SOUP_TYPE_PASSWORD_MANAGER)) +#define SOUP_IS_PASSWORD_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SOUP_TYPE_PASSWORD_MANAGER)) +#define SOUP_PASSWORD_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), SOUP_TYPE_PASSWORD_MANAGER, SoupPasswordManagerInterface)) + +typedef struct _SoupPasswordManager SoupPasswordManager; + +typedef void (*SoupPasswordManagerCallback) (SoupPasswordManager *password_manager, + SoupMessage *msg, SoupAuth *auth, + gboolean retrying, + gpointer user_data); + +typedef struct { + GTypeInterface base; + + /* virtual methods */ + void (*get_passwords_async) (SoupPasswordManager *password_manager, + SoupMessage *msg, SoupAuth *auth, + gboolean retrying, + GMainContext *async_context, + GCancellable *cancellable, + SoupPasswordManagerCallback callback, + gpointer user_data); + void (*get_passwords_sync) (SoupPasswordManager *password_manager, + SoupMessage *msg, SoupAuth *auth, + GCancellable *cancellable); + +} SoupPasswordManagerInterface; + +SOUP_AVAILABLE_IN_2_28 +SOUP_DEPRECATED_IN_2_28 +GType soup_password_manager_get_type (void); + +SOUP_AVAILABLE_IN_2_28 +SOUP_DEPRECATED_IN_2_28 +void soup_password_manager_get_passwords_async (SoupPasswordManager *password_manager, + SoupMessage *msg, + SoupAuth *auth, + gboolean retrying, + GMainContext *async_context, + GCancellable *cancellable, + SoupPasswordManagerCallback callback, + gpointer user_data); + +SOUP_AVAILABLE_IN_2_28 +SOUP_DEPRECATED_IN_2_28 +void soup_password_manager_get_passwords_sync (SoupPasswordManager *password_manager, + SoupMessage *msg, + SoupAuth *auth, + GCancellable *cancellable); + +#endif /* SOUP_PASSWORD_MANAGER_H */ diff --git a/libsoup/soup-path-map.c b/libsoup/soup-path-map.c new file mode 100644 index 0000000..6be8eb6 --- /dev/null +++ b/libsoup/soup-path-map.c @@ -0,0 +1,192 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-path-map.c: URI path prefix-matcher + * + * Copyright (C) 2007 Novell, Inc. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "soup-path-map.h" + +/* This could be replaced with something more clever, like a Patricia + * trie, but it's probably not worth it since the total number of + * mappings is likely to always be small. So we keep an array of + * paths, sorted by decreasing length. (The first prefix match will + * therefore be the longest.) + */ + +typedef struct { + char *path; + int len; + gpointer data; +} SoupPathMapping; + +struct SoupPathMap { + GArray *mappings; + GDestroyNotify free_func; +}; + +/** + * soup_path_map_new: + * @data_free_func: function to use to free data added with + * soup_path_map_add(). + * + * Creates a new %SoupPathMap. + * + * Return value: the new %SoupPathMap + **/ +SoupPathMap * +soup_path_map_new (GDestroyNotify data_free_func) +{ + SoupPathMap *map; + + map = g_slice_new0 (SoupPathMap); + map->mappings = g_array_new (FALSE, FALSE, sizeof (SoupPathMapping)); + map->free_func = data_free_func; + + return map; +} + +/** + * soup_path_map_free: + * @map: a %SoupPathMap + * + * Frees @map and all data stored in it. + **/ +void +soup_path_map_free (SoupPathMap *map) +{ + SoupPathMapping *mappings = (SoupPathMapping *)map->mappings->data; + guint i; + + for (i = 0; i < map->mappings->len; i++) { + g_free (mappings[i].path); + if (map->free_func) + map->free_func (mappings[i].data); + } + g_array_free (map->mappings, TRUE); + + g_slice_free (SoupPathMap, map); +} + +/* Scan @map looking for @path or one of its ancestors. + * Sets *@match to the index of a match, or -1 if no match is found. + * Sets *@insert to the index to insert @path at if a new mapping is + * desired. Returns %TRUE if *@match is an exact match. + */ +static gboolean +mapping_lookup (SoupPathMap *map, const char *path, int *match, int *insert) +{ + SoupPathMapping *mappings = (SoupPathMapping *)map->mappings->data; + guint i; + int path_len; + gboolean exact = FALSE; + + *match = -1; + + path_len = strcspn (path, "?"); + for (i = 0; i < map->mappings->len; i++) { + if (mappings[i].len > path_len) + continue; + + if (insert && mappings[i].len < path_len) { + *insert = i; + /* Clear insert so we don't try to set it again */ + insert = NULL; + } + + if (!strncmp (mappings[i].path, path, mappings[i].len)) { + *match = i; + if (path_len == mappings[i].len) + exact = TRUE; + if (!insert) + return exact; + } + } + + if (insert) + *insert = i; + return exact; +} + +/** + * soup_path_map_add: + * @map: a %SoupPathMap + * @path: the path + * @data: the data + * + * Adds @data to @map at @path. If there was already data at @path it + * will be freed. + **/ +void +soup_path_map_add (SoupPathMap *map, const char *path, gpointer data) +{ + SoupPathMapping *mappings = (SoupPathMapping *)map->mappings->data; + int match, insert; + + if (mapping_lookup (map, path, &match, &insert)) { + if (map->free_func) + map->free_func (mappings[match].data); + mappings[match].data = data; + } else { + SoupPathMapping mapping; + + mapping.path = g_strdup (path); + mapping.len = strlen (path); + mapping.data = data; + g_array_insert_val (map->mappings, insert, mapping); + } +} + +/** + * soup_path_map_remove: + * @map: a %SoupPathMap + * @path: the path + * + * Removes @data from @map at @path. (This must be called with the same + * path the data was originally added with, not a subdirectory.) + **/ +void +soup_path_map_remove (SoupPathMap *map, const char *path) +{ + SoupPathMapping *mappings = (SoupPathMapping *)map->mappings->data; + int match; + + if (!mapping_lookup (map, path, &match, NULL)) + return; + + if (map->free_func) + map->free_func (mappings[match].data); + g_free (mappings[match].path); + g_array_remove_index (map->mappings, match); +} + +/** + * soup_path_map_lookup: + * @map: a %SoupPathMap + * @path: the path + * + * Finds the data associated with @path in @map. If there is no data + * specifically associated with @path, it will return the data for the + * closest parent directory of @path that has data associated with it. + * + * Return value: (nullable): the data set with soup_path_map_add(), or + * %NULL if no data could be found for @path or any of its ancestors. + **/ +gpointer +soup_path_map_lookup (SoupPathMap *map, const char *path) +{ + SoupPathMapping *mappings = (SoupPathMapping *)map->mappings->data; + int match; + + mapping_lookup (map, path, &match, NULL); + if (match == -1) + return NULL; + else + return mappings[match].data; +} diff --git a/libsoup/soup-path-map.h b/libsoup/soup-path-map.h new file mode 100644 index 0000000..f5a8ba8 --- /dev/null +++ b/libsoup/soup-path-map.h @@ -0,0 +1,26 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2007 Novell, Inc. + */ + +#ifndef SOUP_PATH_MAP_H +#define SOUP_PATH_MAP_H 1 + +#include + +typedef struct SoupPathMap SoupPathMap; + +SoupPathMap *soup_path_map_new (GDestroyNotify data_free_func); +void soup_path_map_free (SoupPathMap *map); + +void soup_path_map_add (SoupPathMap *map, + const char *path, + gpointer data); +void soup_path_map_remove (SoupPathMap *map, + const char *path); + +gpointer soup_path_map_lookup (SoupPathMap *map, + const char *path); + + +#endif /* SOUP_PATH_MAP_H */ diff --git a/libsoup/soup-portability.h b/libsoup/soup-portability.h new file mode 100644 index 0000000..1814efb --- /dev/null +++ b/libsoup/soup-portability.h @@ -0,0 +1,26 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2005, Novell, Inc. + */ + +#ifndef SOUP_PORTABILITY_H +#define SOUP_PORTABILITY_H + +#include + +#ifdef G_OS_WIN32 + +#include +#include + +#else + +#include +#include +#include +#include +#include + +#endif + +#endif /* SOUP_PORTABILITY_H */ diff --git a/libsoup/soup-proxy-resolver-default.c b/libsoup/soup-proxy-resolver-default.c new file mode 100644 index 0000000..adfc54d --- /dev/null +++ b/libsoup/soup-proxy-resolver-default.c @@ -0,0 +1,260 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-proxy-resolver-default.c: proxy resolution based on GIO's GProxyResolver + * + * Copyright (C) 2011 Collabora Ltd. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#undef SOUP_VERSION_MIN_REQUIRED +#define SOUP_VERSION_MIN_REQUIRED SOUP_VERSION_2_42 + +#include "soup-proxy-resolver-default.h" +#include "soup.h" + +/** + * SECTION:soup-proxy-resolver-default + * @short_description: System proxy configuration integration + * + * #SoupProxyResolverDefault is a SoupProxyURIResolver + * implementation that uses the default gio #GProxyResolver to resolve + * proxies. + * + * In libsoup 2.44 and later, you can set the session's + * #SoupSession:proxy-resolver property to the resolver returned by + * g_proxy_resolver_get_default() to get the same effect. Note that + * for "plain" #SoupSessions (ie, not #SoupSessionAsync or + * #SoupSessionSync), this is done for you automatically. + * + * Since: 2.34 + * + * Deprecated: Use #SoupSession:proxy-resolver + */ + +enum { + PROP_0, + PROP_GPROXY_RESOLVER +}; + +typedef struct { + GProxyResolver *gproxy_resolver; +} SoupProxyResolverDefaultPrivate; + +static void soup_proxy_resolver_default_interface_init (SoupProxyURIResolverInterface *proxy_resolver_interface); + +G_DEFINE_TYPE_EXTENDED (SoupProxyResolverDefault, soup_proxy_resolver_default, G_TYPE_OBJECT, 0, + G_ADD_PRIVATE (SoupProxyResolverDefault) + G_IMPLEMENT_INTERFACE (SOUP_TYPE_SESSION_FEATURE, NULL) + G_IMPLEMENT_INTERFACE (SOUP_TYPE_PROXY_URI_RESOLVER, soup_proxy_resolver_default_interface_init)) + +static void +soup_proxy_resolver_default_init (SoupProxyResolverDefault *resolver) +{ +} + +static void +soup_proxy_resolver_default_set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + SoupProxyResolverDefault *resolver = SOUP_PROXY_RESOLVER_DEFAULT (object); + SoupProxyResolverDefaultPrivate *priv = soup_proxy_resolver_default_get_instance_private (resolver); + + switch (prop_id) { + case PROP_GPROXY_RESOLVER: + if (priv->gproxy_resolver) + g_object_unref (priv->gproxy_resolver); + priv->gproxy_resolver = g_value_dup_object (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +soup_proxy_resolver_default_constructed (GObject *object) +{ + SoupProxyResolverDefault *resolver = SOUP_PROXY_RESOLVER_DEFAULT (object); + SoupProxyResolverDefaultPrivate *priv = soup_proxy_resolver_default_get_instance_private (resolver); + + if (!priv->gproxy_resolver) { + priv->gproxy_resolver = g_proxy_resolver_get_default (); + g_object_ref (priv->gproxy_resolver); + } + + G_OBJECT_CLASS (soup_proxy_resolver_default_parent_class)->constructed (object); +} + +static void +soup_proxy_resolver_default_finalize (GObject *object) +{ + SoupProxyResolverDefault *resolver = SOUP_PROXY_RESOLVER_DEFAULT (object); + SoupProxyResolverDefaultPrivate *priv = soup_proxy_resolver_default_get_instance_private (resolver); + + g_clear_object (&priv->gproxy_resolver); + + G_OBJECT_CLASS (soup_proxy_resolver_default_parent_class)->finalize (object); +} + +static void +soup_proxy_resolver_default_class_init (SoupProxyResolverDefaultClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->set_property = soup_proxy_resolver_default_set_property; + object_class->constructed = soup_proxy_resolver_default_constructed; + object_class->finalize = soup_proxy_resolver_default_finalize; + + g_object_class_install_property ( + object_class, PROP_GPROXY_RESOLVER, + g_param_spec_object ("gproxy-resolver", + "GProxyResolver", + "The underlying GProxyResolver", + G_TYPE_PROXY_RESOLVER, + G_PARAM_WRITABLE)); +} + +typedef struct { + SoupProxyURIResolver *resolver; + GCancellable *cancellable; + SoupProxyURIResolverCallback callback; + gpointer user_data; +} SoupAsyncData; + +static void +resolved_proxy (GObject *object, GAsyncResult *result, gpointer data) +{ + GProxyResolver *proxy_resolver = G_PROXY_RESOLVER (object); + SoupAsyncData *async_data = data; + GError *error = NULL; + char **proxy_uris = NULL; + SoupURI *proxy_uri = NULL; + guint status = SOUP_STATUS_OK; + + proxy_uris = g_proxy_resolver_lookup_finish (proxy_resolver, + result, + &error); + + if (error || proxy_uris == NULL || proxy_uris[0] == NULL) { + status = SOUP_STATUS_CANT_RESOLVE_PROXY; + goto finish; + } + + /* We need to handle direct:// specially, otherwise + * SoupSession will try to resolve it as the proxy address. + */ + if (!g_strcmp0 (proxy_uris[0], "direct://")) + goto finish; + + proxy_uri = soup_uri_new (proxy_uris[0]); + if (proxy_uri == NULL) + status = SOUP_STATUS_CANT_RESOLVE_PROXY; + +finish: + async_data->callback (async_data->resolver, + status, + proxy_uri, + async_data->user_data); + + if (async_data->cancellable) + g_object_unref (async_data->cancellable); + + g_strfreev (proxy_uris); + + if (proxy_uri) + soup_uri_free (proxy_uri); + + g_object_unref (async_data->resolver); + g_slice_free (SoupAsyncData, async_data); +} + +static void +get_proxy_uri_async (SoupProxyURIResolver *resolver, + SoupURI *uri, + GMainContext *async_context, + GCancellable *cancellable, + SoupProxyURIResolverCallback callback, + gpointer user_data) +{ + SoupProxyResolverDefault *resolver_default = SOUP_PROXY_RESOLVER_DEFAULT (resolver); + SoupProxyResolverDefaultPrivate *priv = soup_proxy_resolver_default_get_instance_private (resolver_default); + SoupAsyncData *async_data; + char *uri_string; + + async_data = g_slice_new0 (SoupAsyncData); + async_data->resolver = (SoupProxyURIResolver*) g_object_ref (resolver); + async_data->cancellable = cancellable; + async_data->callback = callback; + async_data->user_data = user_data; + + uri_string = soup_uri_to_string (uri, FALSE); + + if (async_context) + g_main_context_push_thread_default (async_context); + + g_proxy_resolver_lookup_async (priv->gproxy_resolver, + uri_string, + cancellable ? g_object_ref (cancellable) : NULL, + resolved_proxy, + async_data); + + if (async_context) + g_main_context_pop_thread_default (async_context); + + g_free (uri_string); +} + +static guint +get_proxy_uri_sync (SoupProxyURIResolver *resolver, + SoupURI *uri, + GCancellable *cancellable, + SoupURI **proxy_uri) +{ + SoupProxyResolverDefault *resolver_default = SOUP_PROXY_RESOLVER_DEFAULT (resolver); + SoupProxyResolverDefaultPrivate *priv = soup_proxy_resolver_default_get_instance_private (resolver_default); + GError *error = NULL; + char** proxy_uris = NULL; + char *uri_string; + guint status = SOUP_STATUS_OK; + + uri_string = soup_uri_to_string (uri, FALSE); + + proxy_uris = g_proxy_resolver_lookup (priv->gproxy_resolver, + uri_string, + cancellable, + &error); + + g_free (uri_string); + + if (error || proxy_uris == NULL || proxy_uris[0] == NULL) { + status = SOUP_STATUS_CANT_RESOLVE_PROXY; + goto cleanup; + } + + /* We need to handle direct:// specially, otherwise + * SoupSession will try to resolve it as the proxy address. + */ + if (!g_strcmp0 (proxy_uris[0], "direct://")) + goto cleanup; + + *proxy_uri = soup_uri_new (proxy_uris[0]); + + if (!*proxy_uri) + status = SOUP_STATUS_CANT_RESOLVE_PROXY; + +cleanup: + g_strfreev (proxy_uris); + if (error) + g_clear_error (&error); + return status; +} + +static void +soup_proxy_resolver_default_interface_init (SoupProxyURIResolverInterface *iface) +{ + iface->get_proxy_uri_async = get_proxy_uri_async; + iface->get_proxy_uri_sync = get_proxy_uri_sync; +} diff --git a/libsoup/soup-proxy-resolver-default.h b/libsoup/soup-proxy-resolver-default.h new file mode 100644 index 0000000..4bc6c74 --- /dev/null +++ b/libsoup/soup-proxy-resolver-default.h @@ -0,0 +1,31 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2011 Collabora Ltd. + */ + +#ifndef SOUP_PROXY_RESOLVER_DEFAULT_H +#define SOUP_PROXY_RESOLVER_DEFAULT_H 1 + +#include + +#define SOUP_PROXY_RESOLVER_DEFAULT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), SOUP_TYPE_PROXY_RESOLVER_DEFAULT, SoupProxyResolverDefault)) +#define SOUP_PROXY_RESOLVER_DEFAULT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_PROXY_RESOLVER_DEFAULT, SoupProxyResolverDefaultClass)) +#define SOUP_IS_PROXY_RESOLVER_DEFAULT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), SOUP_TYPE_PROXY_RESOLVER_DEFAULT)) +#define SOUP_IS_PROXY_RESOLVER_DEFAULT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SOUP_TYPE_PROXY_RESOLVER_DEFAULT)) +#define SOUP_PROXY_RESOLVER_DEFAULT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_PROXY_RESOLVER_DEFAULT, SoupProxyResolverDefaultClass)) + +typedef struct { + GObject parent; + +} SoupProxyResolverDefault; + +typedef struct { + GObjectClass parent_class; + +} SoupProxyResolverDefaultClass; + +SOUP_AVAILABLE_IN_2_4 +GType soup_proxy_resolver_default_get_type (void); +#define SOUP_TYPE_PROXY_RESOLVER_DEFAULT (soup_proxy_resolver_default_get_type ()) + +#endif /*SOUP_PROXY_RESOLVER_DEFAULT_H*/ diff --git a/libsoup/soup-proxy-resolver-gnome.c b/libsoup/soup-proxy-resolver-gnome.c new file mode 100644 index 0000000..16a3468 --- /dev/null +++ b/libsoup/soup-proxy-resolver-gnome.c @@ -0,0 +1,58 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-proxy-resolver-gnome.c: GNOME proxy resolution + * + * Copyright (C) 2008 Red Hat, Inc. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#undef SOUP_VERSION_MIN_REQUIRED +#define SOUP_VERSION_MIN_REQUIRED SOUP_VERSION_2_40 + +#include + +#include "soup-proxy-resolver-gnome.h" +#include "soup.h" + +G_DEFINE_TYPE (SoupProxyResolverGNOME, soup_proxy_resolver_gnome, SOUP_TYPE_PROXY_RESOLVER_DEFAULT) + +static void +soup_proxy_resolver_gnome_init (SoupProxyResolverGNOME *resolver_gnome) +{ + GProxyResolver *gproxyresolver; + GIOExtensionPoint *ep; + GIOExtension *ext; + GType type; + + /* FIXME: there is no way to force _g_io_modules_ensure_loaded() + * to be run other than by requesting some extension that we + * don't necessarily want. + */ + gproxyresolver = g_proxy_resolver_get_default (); + if (strcmp (G_OBJECT_TYPE_NAME (gproxyresolver), + "GProxyResolverGnome") == 0) + return; + + ep = g_io_extension_point_lookup (G_PROXY_RESOLVER_EXTENSION_POINT_NAME); + if (!ep) + return; + + ext = g_io_extension_point_get_extension_by_name (ep, "gnome"); + if (!ext) + return; + + type = g_io_extension_get_type (ext); + gproxyresolver = g_object_new (type, NULL); + g_object_set (G_OBJECT (resolver_gnome), + "gproxy-resolver", gproxyresolver, + NULL); + g_object_unref (gproxyresolver); +} + +static void +soup_proxy_resolver_gnome_class_init (SoupProxyResolverGNOMEClass *gnome_class) +{ +} diff --git a/libsoup/soup-proxy-resolver-gnome.h b/libsoup/soup-proxy-resolver-gnome.h new file mode 100644 index 0000000..809e9dd --- /dev/null +++ b/libsoup/soup-proxy-resolver-gnome.h @@ -0,0 +1,25 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2008 Red Hat, Inc. + */ + +#ifndef SOUP_PROXY_RESOLVER_GNOME_H +#define SOUP_PROXY_RESOLVER_GNOME_H 1 + +#include "soup-gnome-features.h" +#include "soup-proxy-resolver-default.h" + +/* SOUP_TYPE_PROXY_RESOLVER_GNOME and soup_proxy_resolver_gnome_get_type() + * are declared in soup-gnome-features.h. + */ + +#define SOUP_PROXY_RESOLVER_GNOME(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), SOUP_TYPE_PROXY_RESOLVER_GNOME, SoupProxyResolverGNOME)) +#define SOUP_PROXY_RESOLVER_GNOME_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_PROXY_RESOLVER_GNOME, SoupProxyResolverGNOMEClass)) +#define SOUP_IS_PROXY_RESOLVER_GNOME(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), SOUP_TYPE_PROXY_RESOLVER_GNOME)) +#define SOUP_IS_PROXY_RESOLVER_GNOME_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SOUP_TYPE_PROXY_RESOLVER_GNOME)) +#define SOUP_PROXY_RESOLVER_GNOME_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_PROXY_RESOLVER_GNOME, SoupProxyResolverGNOMEClass)) + +typedef SoupProxyResolverDefault SoupProxyResolverGNOME; +typedef SoupProxyResolverDefaultClass SoupProxyResolverGNOMEClass; + +#endif /*SOUP_PROXY_RESOLVER_GNOME_H*/ diff --git a/libsoup/soup-proxy-resolver-wrapper.c b/libsoup/soup-proxy-resolver-wrapper.c new file mode 100644 index 0000000..e07664c --- /dev/null +++ b/libsoup/soup-proxy-resolver-wrapper.c @@ -0,0 +1,167 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-proxy-resolver-wrapper.c: SoupProxyURIResolver -> GProxyResolver wrapper + * + * Copyright 2013 Red Hat, Inc. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "soup-proxy-resolver-wrapper.h" +#include "soup.h" + +static void soup_proxy_resolver_wrapper_interface_init (GProxyResolverInterface *proxy_resolver_interface); + +G_DEFINE_TYPE_WITH_CODE (SoupProxyResolverWrapper, soup_proxy_resolver_wrapper, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (G_TYPE_PROXY_RESOLVER, soup_proxy_resolver_wrapper_interface_init); + ) + +static void +soup_proxy_resolver_wrapper_init (SoupProxyResolverWrapper *resolver_wrapper) +{ +} + +static void +soup_proxy_resolver_wrapper_finalize (GObject *object) +{ + SoupProxyResolverWrapper *wrapper = + SOUP_PROXY_RESOLVER_WRAPPER (object); + + g_clear_object (&wrapper->soup_resolver); + + G_OBJECT_CLASS (soup_proxy_resolver_wrapper_parent_class)->finalize (object); +} + +static char ** +convert_response (SoupURI *source_uri, guint status, + SoupURI *proxy_uri, GError **error) +{ + char **proxies = NULL; + + if (status == SOUP_STATUS_CANT_RESOLVE_PROXY) { + g_set_error (error, G_RESOLVER_ERROR, G_RESOLVER_ERROR_NOT_FOUND, + "%s (%s)", soup_status_get_phrase (status), + source_uri->host); + } else if (status == SOUP_STATUS_CANT_CONNECT_PROXY) { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_CONNECTION_REFUSED, + "%s (%s)", soup_status_get_phrase (status), + source_uri->host); + } else { + g_return_val_if_fail (status == SOUP_STATUS_OK, NULL); + + proxies = g_new (char *, 2); + proxies[0] = soup_uri_to_string (proxy_uri, FALSE); + proxies[1] = NULL; + + soup_uri_free (proxy_uri); + } + + return proxies; +} + +static void +wrapper_lookup_async_complete (SoupProxyURIResolver *resolver, + guint status, SoupURI *proxy_uri, + gpointer user_data) +{ + GTask *task = user_data; + SoupURI *source_uri = g_task_get_task_data (task); + char **proxies; + GError *error = NULL; + + proxies = convert_response (source_uri, status, proxy_uri, &error); + if (error) + g_task_return_error (task, error); + else + g_task_return_pointer (task, proxies, (GDestroyNotify) g_strfreev); + g_object_unref (task); +} + +static void +soup_proxy_resolver_wrapper_lookup_async (GProxyResolver *resolver, + const gchar *uri, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + SoupProxyResolverWrapper *wrapper = + SOUP_PROXY_RESOLVER_WRAPPER (resolver); + GTask *task; + SoupURI *source_uri; + + task = g_task_new (resolver, cancellable, callback, user_data); + source_uri = soup_uri_new (uri); + g_task_set_task_data (task, source_uri, (GDestroyNotify) soup_uri_free); + + G_GNUC_BEGIN_IGNORE_DEPRECATIONS; + soup_proxy_uri_resolver_get_proxy_uri_async (wrapper->soup_resolver, + source_uri, + g_main_context_get_thread_default (), + cancellable, + wrapper_lookup_async_complete, + task); + G_GNUC_END_IGNORE_DEPRECATIONS; +} + +static char ** +soup_proxy_resolver_wrapper_lookup_finish (GProxyResolver *resolver, + GAsyncResult *result, + GError **error) +{ + return g_task_propagate_pointer (G_TASK (result), error); +} + +static gchar ** +soup_proxy_resolver_wrapper_lookup (GProxyResolver *resolver, + const gchar *uri, + GCancellable *cancellable, + GError **error) +{ + SoupProxyResolverWrapper *wrapper = + SOUP_PROXY_RESOLVER_WRAPPER (resolver); + SoupURI *source_uri, *proxy_uri; + guint status; + gchar **proxies; + + source_uri = soup_uri_new (uri); + G_GNUC_BEGIN_IGNORE_DEPRECATIONS; + status = soup_proxy_uri_resolver_get_proxy_uri_sync (wrapper->soup_resolver, + source_uri, + cancellable, + &proxy_uri); + G_GNUC_END_IGNORE_DEPRECATIONS; + proxies = convert_response (source_uri, status, proxy_uri, error); + soup_uri_free (source_uri); + return proxies; +} + +static void +soup_proxy_resolver_wrapper_class_init (SoupProxyResolverWrapperClass *static_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (static_class); + + object_class->finalize = soup_proxy_resolver_wrapper_finalize; +} + +static void +soup_proxy_resolver_wrapper_interface_init (GProxyResolverInterface *proxy_resolver_interface) +{ + proxy_resolver_interface->lookup = + soup_proxy_resolver_wrapper_lookup; + proxy_resolver_interface->lookup_async = + soup_proxy_resolver_wrapper_lookup_async; + proxy_resolver_interface->lookup_finish = + soup_proxy_resolver_wrapper_lookup_finish; +} + +GProxyResolver * +soup_proxy_resolver_wrapper_new (SoupProxyURIResolver *soup_resolver) +{ + SoupProxyResolverWrapper *wrapper; + + wrapper = g_object_new (SOUP_TYPE_PROXY_RESOLVER_WRAPPER, NULL); + wrapper->soup_resolver = g_object_ref (soup_resolver); + return (GProxyResolver *)wrapper; +} diff --git a/libsoup/soup-proxy-resolver-wrapper.h b/libsoup/soup-proxy-resolver-wrapper.h new file mode 100644 index 0000000..d16b57c --- /dev/null +++ b/libsoup/soup-proxy-resolver-wrapper.h @@ -0,0 +1,34 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2008 Red Hat, Inc. + */ + +#ifndef SOUP_PROXY_RESOLVER_WRAPPER_H +#define SOUP_PROXY_RESOLVER_WRAPPER_H 1 + +#include "soup-proxy-uri-resolver.h" +#include "soup-uri.h" + +#define SOUP_TYPE_PROXY_RESOLVER_WRAPPER (soup_proxy_resolver_wrapper_get_type ()) +#define SOUP_PROXY_RESOLVER_WRAPPER(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), SOUP_TYPE_PROXY_RESOLVER_WRAPPER, SoupProxyResolverWrapper)) +#define SOUP_PROXY_RESOLVER_WRAPPER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_PROXY_RESOLVER_WRAPPER, SoupProxyResolverWrapperClass)) +#define SOUP_IS_PROXY_RESOLVER_WRAPPER(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), SOUP_TYPE_PROXY_RESOLVER_WRAPPER)) +#define SOUP_IS_PROXY_RESOLVER_WRAPPER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SOUP_TYPE_PROXY_RESOLVER_WRAPPER)) +#define SOUP_PROXY_RESOLVER_WRAPPER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_PROXY_RESOLVER_WRAPPER, SoupProxyResolverWrapperClass)) + +typedef struct { + GObject parent; + + SoupProxyURIResolver *soup_resolver; +} SoupProxyResolverWrapper; + +typedef struct { + GObjectClass parent_class; + +} SoupProxyResolverWrapperClass; + +GType soup_proxy_resolver_wrapper_get_type (void); + +GProxyResolver *soup_proxy_resolver_wrapper_new (SoupProxyURIResolver *soup_resolver); + +#endif /* SOUP_PROXY_RESOLVER_WRAPPER_H */ diff --git a/libsoup/soup-proxy-resolver.c b/libsoup/soup-proxy-resolver.c new file mode 100644 index 0000000..8886c68 --- /dev/null +++ b/libsoup/soup-proxy-resolver.c @@ -0,0 +1,58 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-proxy-resolver.c: HTTP proxy resolver interface + * + * Copyright (C) 2008 Red Hat, Inc. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "soup-proxy-resolver.h" +#include "soup.h" + +G_DEFINE_INTERFACE_WITH_CODE (SoupProxyResolver, soup_proxy_resolver, G_TYPE_OBJECT, + g_type_interface_add_prerequisite (g_define_type_id, SOUP_TYPE_SESSION_FEATURE); + ) + +static void +soup_proxy_resolver_default_init (SoupProxyResolverInterface *iface) +{ +} + +void +soup_proxy_resolver_get_proxy_async (SoupProxyResolver *proxy_resolver, + SoupMessage *msg, + GMainContext *async_context, + GCancellable *cancellable, + SoupProxyResolverCallback callback, + gpointer user_data) +{ +#ifdef G_GNUC_BEGIN_IGNORE_DEPRECATIONS +G_GNUC_BEGIN_IGNORE_DEPRECATIONS +#endif + SOUP_PROXY_RESOLVER_GET_CLASS (proxy_resolver)-> + get_proxy_async (proxy_resolver, msg, + async_context, cancellable, + callback, user_data); +#ifdef G_GNUC_END_IGNORE_DEPRECATIONS +G_GNUC_END_IGNORE_DEPRECATIONS +#endif +} + +guint +soup_proxy_resolver_get_proxy_sync (SoupProxyResolver *proxy_resolver, + SoupMessage *msg, + GCancellable *cancellable, + SoupAddress **addr) +{ +#ifdef G_GNUC_BEGIN_IGNORE_DEPRECATIONS +G_GNUC_BEGIN_IGNORE_DEPRECATIONS +#endif + return SOUP_PROXY_RESOLVER_GET_CLASS (proxy_resolver)-> + get_proxy_sync (proxy_resolver, msg, cancellable, addr); +#ifdef G_GNUC_END_IGNORE_DEPRECATIONS +G_GNUC_END_IGNORE_DEPRECATIONS +#endif +} diff --git a/libsoup/soup-proxy-resolver.h b/libsoup/soup-proxy-resolver.h new file mode 100644 index 0000000..755d219 --- /dev/null +++ b/libsoup/soup-proxy-resolver.h @@ -0,0 +1,65 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2008 Red Hat, Inc. + */ + +#ifndef SOUP_PROXY_RESOLVER_H +#define SOUP_PROXY_RESOLVER_H 1 + +#include + +G_BEGIN_DECLS + +#ifndef SOUP_DISABLE_DEPRECATED + +#define SOUP_TYPE_PROXY_RESOLVER (soup_proxy_resolver_get_type ()) +#define SOUP_PROXY_RESOLVER(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), SOUP_TYPE_PROXY_RESOLVER, SoupProxyResolver)) +#define SOUP_PROXY_RESOLVER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_PROXY_RESOLVER, SoupProxyResolverInterface)) +#define SOUP_IS_PROXY_RESOLVER(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), SOUP_TYPE_PROXY_RESOLVER)) +#define SOUP_IS_PROXY_RESOLVER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SOUP_TYPE_PROXY_RESOLVER)) +#define SOUP_PROXY_RESOLVER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), SOUP_TYPE_PROXY_RESOLVER, SoupProxyResolverInterface)) + +typedef struct _SoupProxyResolver SoupProxyResolver; + +typedef void (*SoupProxyResolverCallback) (SoupProxyResolver *, SoupMessage *, + guint, SoupAddress *, gpointer); + +typedef struct { + GTypeInterface base; + + /* virtual methods */ + void (*get_proxy_async) (SoupProxyResolver *proxy_resolver, + SoupMessage *msg, GMainContext *async_context, + GCancellable *cancellable, + SoupProxyResolverCallback callaback, + gpointer user_data); + guint (*get_proxy_sync) (SoupProxyResolver *proxy_resolver, + SoupMessage *msg, GCancellable *cancellable, + SoupAddress **addr); + +} SoupProxyResolverInterface; + +SOUP_AVAILABLE_IN_2_4 +SOUP_DEPRECATED_IN_2_28 +GType soup_proxy_resolver_get_type (void); + +SOUP_AVAILABLE_IN_2_4 +SOUP_DEPRECATED_IN_2_28 +void soup_proxy_resolver_get_proxy_async (SoupProxyResolver *proxy_resolver, + SoupMessage *msg, + GMainContext *async_context, + GCancellable *cancellable, + SoupProxyResolverCallback callback, + gpointer user_data); +SOUP_AVAILABLE_IN_2_4 +SOUP_DEPRECATED_IN_2_28 +guint soup_proxy_resolver_get_proxy_sync (SoupProxyResolver *proxy_resolver, + SoupMessage *msg, + GCancellable *cancellable, + SoupAddress **addr); + +#endif + +G_END_DECLS + +#endif /*SOUP_PROXY_RESOLVER_H*/ diff --git a/libsoup/soup-proxy-uri-resolver.c b/libsoup/soup-proxy-uri-resolver.c new file mode 100644 index 0000000..ddb8bd6 --- /dev/null +++ b/libsoup/soup-proxy-uri-resolver.c @@ -0,0 +1,111 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-proxy-uri-resolver.c: HTTP proxy resolver interface, take 2 + * + * Copyright (C) 2009 Red Hat, Inc. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#undef SOUP_VERSION_MIN_REQUIRED +#define SOUP_VERSION_MIN_REQUIRED SOUP_VERSION_2_42 + +#include "soup-proxy-uri-resolver.h" +#include "soup.h" + +/** + * SECTION:soup-proxy-uri-resolver + * @short_description: Interface for locating HTTP proxies + * + * #SoupProxyURIResolver is an interface for finding appropriate HTTP + * proxies to use. + * + * Deprecated: #SoupSession now has a #SoupSession:proxy-resolver + * property that takes a #GProxyResolver (which is semantically + * identical to #SoupProxyURIResolver). + * + * Even in older releases of libsoup, you are not likely to have to + * implement this interface on your own; instead, you should usually + * just be able to use #SoupProxyResolverDefault. + */ + +G_DEFINE_INTERFACE_WITH_CODE (SoupProxyURIResolver, soup_proxy_uri_resolver, G_TYPE_OBJECT, + g_type_interface_add_prerequisite (g_define_type_id, SOUP_TYPE_SESSION_FEATURE); + ) + +static void +soup_proxy_uri_resolver_default_init (SoupProxyURIResolverInterface *iface) +{ +} + +/** + * SoupProxyURIResolverCallback: + * @resolver: the #SoupProxyURIResolver + * @status: a #SoupStatus + * @proxy_uri: the resolved proxy URI, or %NULL + * @user_data: data passed to soup_proxy_uri_resolver_get_proxy_uri_async() + * + * Callback for soup_proxy_uri_resolver_get_proxy_uri_async() + */ + +/** + * soup_proxy_uri_resolver_get_proxy_uri_async: + * @proxy_uri_resolver: the #SoupProxyURIResolver + * @uri: the #SoupURI you want a proxy for + * @async_context: (allow-none): the #GMainContext to invoke @callback in + * @cancellable: a #GCancellable, or %NULL + * @callback: (scope async): callback to invoke with the proxy address + * @user_data: data for @callback + * + * Asynchronously determines a proxy URI to use for @msg and calls + * @callback. + * + * Since: 2.26.3 + * + * Deprecated: #SoupProxyURIResolver is deprecated in favor of + * #GProxyResolver + */ +void +soup_proxy_uri_resolver_get_proxy_uri_async (SoupProxyURIResolver *proxy_uri_resolver, + SoupURI *uri, + GMainContext *async_context, + GCancellable *cancellable, + SoupProxyURIResolverCallback callback, + gpointer user_data) +{ + SOUP_PROXY_URI_RESOLVER_GET_CLASS (proxy_uri_resolver)-> + get_proxy_uri_async (proxy_uri_resolver, uri, + async_context, cancellable, + callback, user_data); +} + +/** + * soup_proxy_uri_resolver_get_proxy_uri_sync: + * @proxy_uri_resolver: the #SoupProxyURIResolver + * @uri: the #SoupURI you want a proxy for + * @cancellable: a #GCancellable, or %NULL + * @proxy_uri: (out): on return, will contain the proxy URI + * + * Synchronously determines a proxy URI to use for @uri. If @uri + * should be sent via proxy, *@proxy_uri will be set to the URI of the + * proxy, else it will be set to %NULL. + * + * Return value: %SOUP_STATUS_OK if successful, or a transport-level + * error. + * + * Since: 2.26.3 + * + * Deprecated: #SoupProxyURIResolver is deprecated in favor of + * #GProxyResolver + */ +guint +soup_proxy_uri_resolver_get_proxy_uri_sync (SoupProxyURIResolver *proxy_uri_resolver, + SoupURI *uri, + GCancellable *cancellable, + SoupURI **proxy_uri) +{ + return SOUP_PROXY_URI_RESOLVER_GET_CLASS (proxy_uri_resolver)-> + get_proxy_uri_sync (proxy_uri_resolver, uri, cancellable, proxy_uri); +} diff --git a/libsoup/soup-proxy-uri-resolver.h b/libsoup/soup-proxy-uri-resolver.h new file mode 100644 index 0000000..e203125 --- /dev/null +++ b/libsoup/soup-proxy-uri-resolver.h @@ -0,0 +1,67 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2009 Red Hat, Inc. + */ + +#ifndef SOUP_PROXY_URI_RESOLVER_H +#define SOUP_PROXY_URI_RESOLVER_H 1 + +#include + +G_BEGIN_DECLS + +#define SOUP_TYPE_PROXY_URI_RESOLVER (soup_proxy_uri_resolver_get_type ()) +#define SOUP_PROXY_URI_RESOLVER(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), SOUP_TYPE_PROXY_URI_RESOLVER, SoupProxyURIResolver)) +#define SOUP_PROXY_URI_RESOLVER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_PROXY_URI_RESOLVER, SoupProxyURIResolverInterface)) +#define SOUP_IS_PROXY_URI_RESOLVER(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), SOUP_TYPE_PROXY_URI_RESOLVER)) +#define SOUP_IS_PROXY_URI_RESOLVER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SOUP_TYPE_PROXY_URI_RESOLVER)) +#define SOUP_PROXY_URI_RESOLVER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), SOUP_TYPE_PROXY_URI_RESOLVER, SoupProxyURIResolverInterface)) + +typedef struct _SoupProxyURIResolver SoupProxyURIResolver; + +typedef void (*SoupProxyURIResolverCallback) (SoupProxyURIResolver *resolver, + guint status, SoupURI *proxy_uri, + gpointer user_data); + +typedef struct { + GTypeInterface base; + + /* virtual methods */ + void (*get_proxy_uri_async) (SoupProxyURIResolver *proxy_uri_resolver, + SoupURI *uri, GMainContext *async_context, + GCancellable *cancellable, + SoupProxyURIResolverCallback callback, + gpointer user_data); + guint (*get_proxy_uri_sync) (SoupProxyURIResolver *proxy_uri_resolver, + SoupURI *uri, GCancellable *cancellable, + SoupURI **proxy_uri); + + /* Padding for future expansion */ + void (*_libsoup_reserved1) (void); + void (*_libsoup_reserved2) (void); + void (*_libsoup_reserved3) (void); + void (*_libsoup_reserved4) (void); +} SoupProxyURIResolverInterface; + +SOUP_AVAILABLE_IN_2_28 +SOUP_DEPRECATED_IN_2_44 +GType soup_proxy_uri_resolver_get_type (void); + +SOUP_AVAILABLE_IN_2_28 +SOUP_DEPRECATED_IN_2_44 +void soup_proxy_uri_resolver_get_proxy_uri_async (SoupProxyURIResolver *proxy_uri_resolver, + SoupURI *uri, + GMainContext *async_context, + GCancellable *cancellable, + SoupProxyURIResolverCallback callback, + gpointer user_data); +SOUP_AVAILABLE_IN_2_28 +SOUP_DEPRECATED_IN_2_44 +guint soup_proxy_uri_resolver_get_proxy_uri_sync (SoupProxyURIResolver *proxy_uri_resolver, + SoupURI *uri, + GCancellable *cancellable, + SoupURI **proxy_uri); + +G_END_DECLS + +#endif /*SOUP_PROXY_URI_RESOLVER_H*/ diff --git a/libsoup/soup-request-data.c b/libsoup/soup-request-data.c new file mode 100644 index 0000000..3e07507 --- /dev/null +++ b/libsoup/soup-request-data.c @@ -0,0 +1,163 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-request-data.c: data: URI request object + * + * Copyright (C) 2009, 2010 Red Hat, Inc. + * Copyright (C) 2010 Igalia, S.L. + * + * 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, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "soup-request-data.h" +#include "soup.h" +#include "soup-misc-private.h" + +/** + * SECTION:soup-request-data + * @short_description: SoupRequest support for "data" URIs + * + * #SoupRequestData implements #SoupRequest for "data" URIs. + */ + + +struct _SoupRequestDataPrivate { + gsize content_length; + char *content_type; +}; + +G_DEFINE_TYPE_WITH_PRIVATE (SoupRequestData, soup_request_data, SOUP_TYPE_REQUEST) + +static void +soup_request_data_init (SoupRequestData *data) +{ + data->priv = soup_request_data_get_instance_private (data); +} + +static void +soup_request_data_finalize (GObject *object) +{ + SoupRequestData *data = SOUP_REQUEST_DATA (object); + + g_free (data->priv->content_type); + + G_OBJECT_CLASS (soup_request_data_parent_class)->finalize (object); +} + +static gboolean +soup_request_data_check_uri (SoupRequest *request, + SoupURI *uri, + GError **error) +{ + return uri->host == NULL; +} + +#define BASE64_INDICATOR ";base64" +#define BASE64_INDICATOR_LEN (sizeof (";base64") - 1) + +static GInputStream * +soup_request_data_send (SoupRequest *request, + GCancellable *cancellable, + GError **error) +{ + SoupRequestData *data = SOUP_REQUEST_DATA (request); + SoupURI *uri = soup_request_get_uri (request); + GInputStream *memstream; + const char *comma, *start, *end; + gboolean base64 = FALSE; + char *uristr; + + uristr = soup_uri_to_string (uri, FALSE); + start = uristr + 5; + comma = strchr (start, ','); + if (comma && comma != start) { + /* Deal with MIME type / params */ + if (comma >= start + BASE64_INDICATOR_LEN && !g_ascii_strncasecmp (comma - BASE64_INDICATOR_LEN, BASE64_INDICATOR, BASE64_INDICATOR_LEN)) { + end = comma - BASE64_INDICATOR_LEN; + base64 = TRUE; + } else + end = comma; + + if (end != start) + data->priv->content_type = soup_uri_decoded_copy (start, end - start, NULL); + } + + memstream = g_memory_input_stream_new (); + + if (comma) + start = comma + 1; + + if (*start) { + int decoded_length = 0; + guchar *buf = (guchar *) soup_uri_decoded_copy (start, strlen (start), + &decoded_length); + + if (base64) + buf = g_base64_decode_inplace ((gchar*) buf, &data->priv->content_length); + else + data->priv->content_length = decoded_length; + + g_memory_input_stream_add_data (G_MEMORY_INPUT_STREAM (memstream), + buf, data->priv->content_length, + g_free); + } + g_free (uristr); + + return memstream; +} + +static goffset +soup_request_data_get_content_length (SoupRequest *request) +{ + SoupRequestData *data = SOUP_REQUEST_DATA (request); + + return data->priv->content_length; +} + +static const char * +soup_request_data_get_content_type (SoupRequest *request) +{ + SoupRequestData *data = SOUP_REQUEST_DATA (request); + + if (data->priv->content_type) + return data->priv->content_type; + else + return "text/plain;charset=US-ASCII"; +} + +static const char *data_schemes[] = { "data", NULL }; + +static void +soup_request_data_class_init (SoupRequestDataClass *request_data_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (request_data_class); + SoupRequestClass *request_class = + SOUP_REQUEST_CLASS (request_data_class); + + request_class->schemes = data_schemes; + + object_class->finalize = soup_request_data_finalize; + + request_class->check_uri = soup_request_data_check_uri; + request_class->send = soup_request_data_send; + request_class->get_content_length = soup_request_data_get_content_length; + request_class->get_content_type = soup_request_data_get_content_type; +} diff --git a/libsoup/soup-request-data.h b/libsoup/soup-request-data.h new file mode 100644 index 0000000..929c590 --- /dev/null +++ b/libsoup/soup-request-data.h @@ -0,0 +1,53 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2009, 2010 Red Hat, Inc. + * Copyright (C) 2010 Igalia, S.L. + * + * 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, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef SOUP_REQUEST_DATA_H +#define SOUP_REQUEST_DATA_H 1 + +#include "soup-request.h" + +G_BEGIN_DECLS + +#define SOUP_TYPE_REQUEST_DATA (soup_request_data_get_type ()) +#define SOUP_REQUEST_DATA(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), SOUP_TYPE_REQUEST_DATA, SoupRequestData)) +#define SOUP_REQUEST_DATA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_REQUEST_DATA, SoupRequestDataClass)) +#define SOUP_IS_REQUEST_DATA(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), SOUP_TYPE_REQUEST_DATA)) +#define SOUP_IS_REQUEST_DATA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SOUP_TYPE_REQUEST_DATA)) +#define SOUP_REQUEST_DATA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_REQUEST_DATA, SoupRequestDataClass)) + +typedef struct _SoupRequestDataPrivate SoupRequestDataPrivate; + +typedef struct { + SoupRequest parent; + + SoupRequestDataPrivate *priv; +} SoupRequestData; + +typedef struct { + SoupRequestClass parent; +} SoupRequestDataClass; + +SOUP_AVAILABLE_IN_2_34 +GType soup_request_data_get_type (void); + +G_END_DECLS + +#endif /* SOUP_REQUEST_DATA_H */ diff --git a/libsoup/soup-request-file.c b/libsoup/soup-request-file.c new file mode 100644 index 0000000..61fc712 --- /dev/null +++ b/libsoup/soup-request-file.c @@ -0,0 +1,294 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-request-file.c: file: URI request object + * + * Copyright (C) 2009, 2010 Red Hat, Inc. + * Copyright (C) 2010 Igalia, S.L. + * + * 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, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "soup-request-file.h" +#include "soup.h" +#include "soup-directory-input-stream.h" +#include "soup-requester.h" + +/** + * SECTION:soup-request-file + * @short_description: SoupRequest support for "file" and "resource" URIs + * + * #SoupRequestFile implements #SoupRequest for "file" and "resource" + * URIs. + */ + +struct _SoupRequestFilePrivate { + GFile *gfile; + + char *mime_type; + goffset size; +}; + +G_DEFINE_TYPE_WITH_PRIVATE (SoupRequestFile, soup_request_file, SOUP_TYPE_REQUEST) + +static void +soup_request_file_init (SoupRequestFile *file) +{ + file->priv = soup_request_file_get_instance_private (file); + + file->priv->size = -1; +} + +static void +soup_request_file_finalize (GObject *object) +{ + SoupRequestFile *file = SOUP_REQUEST_FILE (object); + + g_clear_object (&file->priv->gfile); + g_free (file->priv->mime_type); + + G_OBJECT_CLASS (soup_request_file_parent_class)->finalize (object); +} + +static gboolean +soup_request_file_check_uri (SoupRequest *request, + SoupURI *uri, + GError **error) +{ + /* "file:/foo" is not valid */ + if (!uri->host) + return FALSE; + + /* but it must be "file:///..." or "file://localhost/..." */ + if (*uri->host && + g_ascii_strcasecmp (uri->host, "localhost") != 0) + return FALSE; + return TRUE; +} + +#ifdef G_OS_WIN32 +static void +windowsify_file_uri_path (char *path) +{ + char *p, *slash; + + /* Copied from g_filename_from_uri(), which we can't use + * directly because it rejects invalid URIs that we need to + * keep. + */ + + /* Turn slashes into backslashes, because that's the canonical spelling */ + p = path; + while ((slash = strchr (p, '/')) != NULL) { + *slash = '\\'; + p = slash + 1; + } + + /* Windows URIs with a drive letter can be like + * "file://host/c:/foo" or "file://host/c|/foo" (some Netscape + * versions). In those cases, start the filename from the + * drive letter. + */ + if (g_ascii_isalpha (path[1])) { + if (path[2] == '|') + path[2] = ':'; + if (path[2] == ':') + memmove (path, path + 1, strlen (path)); + } +} +#endif + +static gboolean +soup_request_file_ensure_file (SoupRequestFile *file, + GCancellable *cancellable, + GError **error) +{ + SoupURI *uri; + char *decoded_path; + + if (file->priv->gfile) + return TRUE; + + uri = soup_request_get_uri (SOUP_REQUEST (file)); + decoded_path = soup_uri_decode (uri->path); + +#ifdef G_OS_WIN32 + windowsify_file_uri_path (decoded_path); +#endif + + if (uri->scheme == SOUP_URI_SCHEME_RESOURCE) { + char *uri_str; + + uri_str = g_strdup_printf ("resource://%s", decoded_path); + file->priv->gfile = g_file_new_for_uri (uri_str); + g_free (uri_str); + } else + file->priv->gfile = g_file_new_for_path (decoded_path); + + g_free (decoded_path); + return TRUE; +} + +static GInputStream * +soup_request_file_send (SoupRequest *request, + GCancellable *cancellable, + GError **error) +{ + SoupRequestFile *file = SOUP_REQUEST_FILE (request); + GInputStream *stream; + GError *my_error = NULL; + + if (!soup_request_file_ensure_file (file, cancellable, error)) + return NULL; + + stream = G_INPUT_STREAM (g_file_read (file->priv->gfile, + cancellable, &my_error)); + if (stream == NULL) { + if (g_error_matches (my_error, G_IO_ERROR, G_IO_ERROR_IS_DIRECTORY)) { + GFileEnumerator *enumerator; + g_clear_error (&my_error); + enumerator = g_file_enumerate_children (file->priv->gfile, + "*", + G_FILE_QUERY_INFO_NONE, + cancellable, + error); + if (enumerator) { + stream = soup_directory_input_stream_new (enumerator, + soup_request_get_uri (request)); + g_object_unref (enumerator); + file->priv->mime_type = g_strdup ("text/html"); + } + } else + g_propagate_error (error, my_error); + } else { + GFileInfo *info = g_file_query_info (file->priv->gfile, + G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE "," + G_FILE_ATTRIBUTE_STANDARD_SIZE, + 0, cancellable, NULL); + if (info) { + const char *content_type; + file->priv->size = g_file_info_get_size (info); + content_type = g_file_info_get_content_type (info); + + if (content_type) + file->priv->mime_type = g_content_type_get_mime_type (content_type); + g_object_unref (info); + } + } + + return stream; +} + +static void +soup_request_file_send_async_thread (GTask *task, + gpointer source_object, + gpointer task_data, + GCancellable *cancellable) +{ + SoupRequest *request = source_object; + GInputStream *stream; + GError *error = NULL; + + stream = soup_request_file_send (request, cancellable, &error); + if (stream == NULL) + g_task_return_error (task, error); + else + g_task_return_pointer (task, stream, g_object_unref); +} + +static void +soup_request_file_send_async (SoupRequest *request, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GTask *task; + + task = g_task_new (request, cancellable, callback, user_data); + g_task_run_in_thread (task, soup_request_file_send_async_thread); + g_object_unref (task); +} + +static GInputStream * +soup_request_file_send_finish (SoupRequest *request, + GAsyncResult *result, + GError **error) +{ + g_return_val_if_fail (g_task_is_valid (result, request), NULL); + + return g_task_propagate_pointer (G_TASK (result), error); +} + +static goffset +soup_request_file_get_content_length (SoupRequest *request) +{ + SoupRequestFile *file = SOUP_REQUEST_FILE (request); + + return file->priv->size; +} + +static const char * +soup_request_file_get_content_type (SoupRequest *request) +{ + SoupRequestFile *file = SOUP_REQUEST_FILE (request); + + if (!file->priv->mime_type) + return "application/octet-stream"; + + return file->priv->mime_type; +} + +static const char *file_schemes[] = { "file", "resource", NULL }; + +static void +soup_request_file_class_init (SoupRequestFileClass *request_file_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (request_file_class); + SoupRequestClass *request_class = + SOUP_REQUEST_CLASS (request_file_class); + + request_class->schemes = file_schemes; + + object_class->finalize = soup_request_file_finalize; + + request_class->check_uri = soup_request_file_check_uri; + request_class->send = soup_request_file_send; + request_class->send_async = soup_request_file_send_async; + request_class->send_finish = soup_request_file_send_finish; + request_class->get_content_length = soup_request_file_get_content_length; + request_class->get_content_type = soup_request_file_get_content_type; +} + +/** + * soup_request_file_get_file: + * @file: a #SoupRequestFile + * + * Gets a #GFile corresponding to @file's URI + * + * Return value: (transfer full): a #GFile corresponding to @file + * + * Since: 2.40 + */ +GFile * +soup_request_file_get_file (SoupRequestFile *file) +{ + return g_object_ref (file->priv->gfile); +} diff --git a/libsoup/soup-request-file.h b/libsoup/soup-request-file.h new file mode 100644 index 0000000..df2cbab --- /dev/null +++ b/libsoup/soup-request-file.h @@ -0,0 +1,56 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2009, 2010 Red Hat, Inc. + * Copyright (C) 2010 Igalia, S.L. + * + * 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, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef SOUP_REQUEST_FILE_H +#define SOUP_REQUEST_FILE_H 1 + +#include "soup-request.h" + +G_BEGIN_DECLS + +#define SOUP_TYPE_REQUEST_FILE (soup_request_file_get_type ()) +#define SOUP_REQUEST_FILE(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), SOUP_TYPE_REQUEST_FILE, SoupRequestFile)) +#define SOUP_REQUEST_FILE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_REQUEST_FILE, SoupRequestFileClass)) +#define SOUP_IS_REQUEST_FILE(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), SOUP_TYPE_REQUEST_FILE)) +#define SOUP_IS_REQUEST_FILE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SOUP_TYPE_REQUEST_FILE)) +#define SOUP_REQUEST_FILE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_REQUEST_FILE, SoupRequestFileClass)) + +typedef struct _SoupRequestFilePrivate SoupRequestFilePrivate; + +typedef struct { + SoupRequest parent; + + SoupRequestFilePrivate *priv; +} SoupRequestFile; + +typedef struct { + SoupRequestClass parent; +} SoupRequestFileClass; + +SOUP_AVAILABLE_IN_2_34 +GType soup_request_file_get_type (void); + +SOUP_AVAILABLE_IN_2_34 +GFile *soup_request_file_get_file (SoupRequestFile *file); + +G_END_DECLS + +#endif /* SOUP_REQUEST_FILE_H */ diff --git a/libsoup/soup-request-http.c b/libsoup/soup-request-http.c new file mode 100644 index 0000000..285f59d --- /dev/null +++ b/libsoup/soup-request-http.c @@ -0,0 +1,234 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-request-http.c: http: URI request object + * + * Copyright (C) 2009, 2010 Red Hat, Inc. + * Copyright (C) 2010 Igalia, S.L. + * + * 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, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "soup-request-http.h" +#include "soup.h" +#include "soup-message-private.h" +#include "soup-session-private.h" + +/** + * SECTION:soup-request-http + * @short_description: SoupRequest support for "http" and "https" URIs + * + * #SoupRequestHTTP implements #SoupRequest for "http" and "https" + * URIs. + * + * To do more complicated HTTP operations using the #SoupRequest APIs, + * call soup_request_http_get_message() to get the request's + * #SoupMessage. + */ + +struct _SoupRequestHTTPPrivate { + SoupMessage *msg; + char *content_type; +}; + +G_DEFINE_TYPE_WITH_PRIVATE (SoupRequestHTTP, soup_request_http, SOUP_TYPE_REQUEST) + +static void content_sniffed (SoupMessage *msg, + const char *content_type, + GHashTable *params, + gpointer user_data); + +static void +soup_request_http_init (SoupRequestHTTP *http) +{ + http->priv = soup_request_http_get_instance_private (http); +} + +static gboolean +soup_request_http_check_uri (SoupRequest *request, + SoupURI *uri, + GError **error) +{ + SoupRequestHTTP *http = SOUP_REQUEST_HTTP (request); + + if (!SOUP_URI_VALID_FOR_HTTP (uri)) + return FALSE; + + http->priv->msg = soup_message_new_from_uri (SOUP_METHOD_GET, uri); + soup_message_set_soup_request (http->priv->msg, request); + + g_signal_connect (http->priv->msg, "content-sniffed", + G_CALLBACK (content_sniffed), http); + return TRUE; +} + +static void +soup_request_http_finalize (GObject *object) +{ + SoupRequestHTTP *http = SOUP_REQUEST_HTTP (object); + + if (http->priv->msg) { + g_signal_handlers_disconnect_by_func (http->priv->msg, + G_CALLBACK (content_sniffed), + http); + g_object_unref (http->priv->msg); + } + + g_free (http->priv->content_type); + + G_OBJECT_CLASS (soup_request_http_parent_class)->finalize (object); +} + +static GInputStream * +soup_request_http_send (SoupRequest *request, + GCancellable *cancellable, + GError **error) +{ + SoupRequestHTTP *http = SOUP_REQUEST_HTTP (request); + SoupSession *session = soup_request_get_session (request); + + g_return_val_if_fail (!SOUP_IS_SESSION_ASYNC (session), NULL); + + return soup_session_send (session, http->priv->msg, + cancellable, error); +} + + +static void +http_input_stream_ready_cb (GObject *source, GAsyncResult *result, gpointer user_data) +{ + GTask *task = user_data; + GError *error = NULL; + GInputStream *stream; + + stream = soup_session_send_finish (SOUP_SESSION (source), result, &error); + if (stream) + g_task_return_pointer (task, stream, g_object_unref); + else + g_task_return_error (task, error); + g_object_unref (task); +} + +static void +soup_request_http_send_async (SoupRequest *request, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + SoupRequestHTTP *http = SOUP_REQUEST_HTTP (request); + SoupSession *session = soup_request_get_session (request); + GTask *task; + + g_return_if_fail (!SOUP_IS_SESSION_SYNC (session)); + + task = g_task_new (request, cancellable, callback, user_data); + soup_session_send_async (session, http->priv->msg, cancellable, + http_input_stream_ready_cb, task); +} + +static GInputStream * +soup_request_http_send_finish (SoupRequest *request, + GAsyncResult *result, + GError **error) +{ + g_return_val_if_fail (g_task_is_valid (result, request), NULL); + + return g_task_propagate_pointer (G_TASK (result), error); +} + +static goffset +soup_request_http_get_content_length (SoupRequest *request) +{ + SoupRequestHTTP *http = SOUP_REQUEST_HTTP (request); + + return soup_message_headers_get_content_length (http->priv->msg->response_headers); +} + +static void +content_sniffed (SoupMessage *msg, + const char *content_type, + GHashTable *params, + gpointer user_data) +{ + SoupRequestHTTP *http = user_data; + GString *sniffed_type; + + sniffed_type = g_string_new (content_type); + if (params) { + GHashTableIter iter; + gpointer key, value; + + g_hash_table_iter_init (&iter, params); + while (g_hash_table_iter_next (&iter, &key, &value)) { + g_string_append (sniffed_type, "; "); + soup_header_g_string_append_param (sniffed_type, key, value); + } + } + g_free (http->priv->content_type); + http->priv->content_type = g_string_free (sniffed_type, FALSE); +} + +static const char * +soup_request_http_get_content_type (SoupRequest *request) +{ + SoupRequestHTTP *http = SOUP_REQUEST_HTTP (request); + + return http->priv->content_type; +} + +static const char *http_schemes[] = { "http", "https", NULL }; + +static void +soup_request_http_class_init (SoupRequestHTTPClass *request_http_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (request_http_class); + SoupRequestClass *request_class = + SOUP_REQUEST_CLASS (request_http_class); + + request_class->schemes = http_schemes; + + object_class->finalize = soup_request_http_finalize; + + request_class->check_uri = soup_request_http_check_uri; + request_class->send = soup_request_http_send; + request_class->send_async = soup_request_http_send_async; + request_class->send_finish = soup_request_http_send_finish; + request_class->get_content_length = soup_request_http_get_content_length; + request_class->get_content_type = soup_request_http_get_content_type; +} + +/** + * soup_request_http_get_message: + * @http: a #SoupRequestHTTP object + * + * Gets a new reference to the #SoupMessage associated to this SoupRequest + * + * Returns: (transfer full): a new reference to the #SoupMessage + * + * Since: 2.40 + */ +SoupMessage * +soup_request_http_get_message (SoupRequestHTTP *http) +{ + g_return_val_if_fail (SOUP_IS_REQUEST_HTTP (http), NULL); + + return g_object_ref (http->priv->msg); +} diff --git a/libsoup/soup-request-http.h b/libsoup/soup-request-http.h new file mode 100644 index 0000000..271a805 --- /dev/null +++ b/libsoup/soup-request-http.h @@ -0,0 +1,56 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2009, 2010 Red Hat, Inc. + * Copyright (C) 2010 Igalia, S.L. + * + * 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, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef SOUP_REQUEST_HTTP_H +#define SOUP_REQUEST_HTTP_H 1 + +#include "soup-request.h" + +G_BEGIN_DECLS + +#define SOUP_TYPE_REQUEST_HTTP (soup_request_http_get_type ()) +#define SOUP_REQUEST_HTTP(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), SOUP_TYPE_REQUEST_HTTP, SoupRequestHTTP)) +#define SOUP_REQUEST_HTTP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_REQUEST_HTTP, SoupRequestHTTPClass)) +#define SOUP_IS_REQUEST_HTTP(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), SOUP_TYPE_REQUEST_HTTP)) +#define SOUP_IS_REQUEST_HTTP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SOUP_TYPE_REQUEST_HTTP)) +#define SOUP_REQUEST_HTTP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_REQUEST_HTTP, SoupRequestHTTPClass)) + +typedef struct _SoupRequestHTTPPrivate SoupRequestHTTPPrivate; + +struct _SoupRequestHTTP { + SoupRequest parent; + + SoupRequestHTTPPrivate *priv; +}; + +typedef struct { + SoupRequestClass parent; +} SoupRequestHTTPClass; + +SOUP_AVAILABLE_IN_2_34 +GType soup_request_http_get_type (void); + +SOUP_AVAILABLE_IN_2_34 +SoupMessage *soup_request_http_get_message (SoupRequestHTTP *http); + +G_END_DECLS + +#endif /* SOUP_REQUEST_HTTP_H */ diff --git a/libsoup/soup-request.c b/libsoup/soup-request.c new file mode 100644 index 0000000..72fc844 --- /dev/null +++ b/libsoup/soup-request.c @@ -0,0 +1,404 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-request.c: Protocol-independent streaming request interface + * + * Copyright (C) 2009, 2010 Red Hat, Inc. + * Copyright (C) 2010, Igalia S.L. + * + * 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, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "soup-request.h" +#include "soup.h" +#include "soup-requester.h" + +/** + * SECTION:soup-request + * @short_description: Protocol-independent streaming request interface + * + * A #SoupRequest is created by #SoupSession, and represents a request + * to retrieve a particular URI. + */ + +/** + * SoupRequest: + * + * A request to retrieve a particular URI. + * + * Since: 2.42 + */ + +enum { + PROP_0, + PROP_URI, + PROP_SESSION +}; + +struct _SoupRequestPrivate { + SoupURI *uri; + SoupSession *session; +}; + +static void soup_request_initable_interface_init (GInitableIface *initable_interface); + +G_DEFINE_TYPE_WITH_CODE (SoupRequest, soup_request, G_TYPE_OBJECT, + G_ADD_PRIVATE (SoupRequest) + G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, + soup_request_initable_interface_init)) + +static void +soup_request_init (SoupRequest *request) +{ + request->priv = soup_request_get_instance_private (request); +} + +static void +soup_request_finalize (GObject *object) +{ + SoupRequest *request = SOUP_REQUEST (object); + + g_clear_pointer (&request->priv->uri, soup_uri_free); + g_clear_object (&request->priv->session); + + G_OBJECT_CLASS (soup_request_parent_class)->finalize (object); +} + +static void +soup_request_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + SoupRequest *request = SOUP_REQUEST (object); + + switch (prop_id) { + case PROP_URI: + if (request->priv->uri) + soup_uri_free (request->priv->uri); + request->priv->uri = g_value_dup_boxed (value); + break; + case PROP_SESSION: + if (request->priv->session) + g_object_unref (request->priv->session); + request->priv->session = g_value_dup_object (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +soup_request_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + SoupRequest *request = SOUP_REQUEST (object); + + switch (prop_id) { + case PROP_URI: + g_value_set_boxed (value, request->priv->uri); + break; + case PROP_SESSION: + g_value_set_object (value, request->priv->session); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static gboolean +soup_request_initable_init (GInitable *initable, + GCancellable *cancellable, + GError **error) +{ + SoupRequest *request = SOUP_REQUEST (initable); + gboolean ok; + + if (!request->priv->uri) { + g_set_error (error, SOUP_REQUEST_ERROR, SOUP_REQUEST_ERROR_BAD_URI, + _("No URI provided")); + return FALSE; + } + + ok = SOUP_REQUEST_GET_CLASS (initable)-> + check_uri (request, request->priv->uri, error); + + if (!ok && error && !*error) { + char *uri_string = soup_uri_to_string (request->priv->uri, FALSE); + g_set_error (error, SOUP_REQUEST_ERROR, SOUP_REQUEST_ERROR_BAD_URI, + _("Invalid “%s” URI: %s"), + request->priv->uri->scheme, + uri_string); + g_free (uri_string); + } + + return ok; +} + +static gboolean +soup_request_default_check_uri (SoupRequest *request, + SoupURI *uri, + GError **error) +{ + return TRUE; +} + +/* Default implementation: assume the sync implementation doesn't block */ +static void +soup_request_default_send_async (SoupRequest *request, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GTask *task; + GInputStream *stream; + GError *error = NULL; + + task = g_task_new (request, cancellable, callback, user_data); + + stream = soup_request_send (request, cancellable, &error); + if (stream) + g_task_return_pointer (task, stream, g_object_unref); + else + g_task_return_error (task, error); + g_object_unref (task); +} + +static GInputStream * +soup_request_default_send_finish (SoupRequest *request, + GAsyncResult *result, + GError **error) +{ + return g_task_propagate_pointer (G_TASK (result), error); +} + +/** + * soup_request_send: + * @request: a #SoupRequest + * @cancellable: a #GCancellable or %NULL + * @error: return location for a #GError, or %NULL + * + * Synchronously requests the URI pointed to by @request, and returns + * a #GInputStream that can be used to read its contents. + * + * Note that you cannot use this method with #SoupRequests attached to + * a #SoupSessionAsync. + * + * Return value: (transfer full): a #GInputStream that can be used to + * read from the URI pointed to by @request. + * + * Since: 2.42 + */ +GInputStream * +soup_request_send (SoupRequest *request, + GCancellable *cancellable, + GError **error) +{ + return SOUP_REQUEST_GET_CLASS (request)-> + send (request, cancellable, error); +} + +/** + * soup_request_send_async: + * @request: a #SoupRequest + * @cancellable: a #GCancellable or %NULL + * @callback: a #GAsyncReadyCallback + * @user_data: user data passed to @callback + * + * Begins an asynchronously request for the URI pointed to by + * @request. + * + * Note that you cannot use this method with #SoupRequests attached to + * a #SoupSessionSync. + * + * Since: 2.42 + */ +void +soup_request_send_async (SoupRequest *request, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + SOUP_REQUEST_GET_CLASS (request)-> + send_async (request, cancellable, callback, user_data); +} + +/** + * soup_request_send_finish: + * @request: a #SoupRequest + * @result: the #GAsyncResult + * @error: return location for a #GError, or %NULL + * + * Gets the result of a soup_request_send_async(). + * + * Return value: (transfer full): a #GInputStream that can be used to + * read from the URI pointed to by @request. + * + * Since: 2.42 + */ +GInputStream * +soup_request_send_finish (SoupRequest *request, + GAsyncResult *result, + GError **error) +{ + return SOUP_REQUEST_GET_CLASS (request)-> + send_finish (request, result, error); +} + +static void +soup_request_class_init (SoupRequestClass *request_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (request_class); + + request_class->check_uri = soup_request_default_check_uri; + request_class->send_async = soup_request_default_send_async; + request_class->send_finish = soup_request_default_send_finish; + + object_class->finalize = soup_request_finalize; + object_class->set_property = soup_request_set_property; + object_class->get_property = soup_request_get_property; + + /** + * SOUP_REQUEST_URI: + * + * Alias for the #SoupRequest:uri property, qv. + * + * Since: 2.42 + */ + /** + * SoupRequest:uri: + * + * The request URI. + * + * Since: 2.42 + */ + g_object_class_install_property ( + object_class, PROP_URI, + g_param_spec_boxed (SOUP_REQUEST_URI, + "URI", + "The request URI", + SOUP_TYPE_URI, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + /** + * SOUP_REQUEST_SESSION: + * + * Alias for the #SoupRequest:session property, qv. + * + * Since: 2.42 + */ + /** + * SoupRequest:session: + * + * The request's #SoupSession. + * + * Since: 2.42 + */ + g_object_class_install_property ( + object_class, PROP_SESSION, + g_param_spec_object (SOUP_REQUEST_SESSION, + "Session", + "The request's session", + SOUP_TYPE_SESSION, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); +} + +static void +soup_request_initable_interface_init (GInitableIface *initable_interface) +{ + initable_interface->init = soup_request_initable_init; +} + +/** + * soup_request_get_uri: + * @request: a #SoupRequest + * + * Gets @request's URI + * + * Return value: (transfer none): @request's URI + * + * Since: 2.42 + */ +SoupURI * +soup_request_get_uri (SoupRequest *request) +{ + return request->priv->uri; +} + +/** + * soup_request_get_session: + * @request: a #SoupRequest + * + * Gets @request's #SoupSession + * + * Return value: (transfer none): @request's #SoupSession + * + * Since: 2.42 + */ +SoupSession * +soup_request_get_session (SoupRequest *request) +{ + return request->priv->session; +} + +/** + * soup_request_get_content_length: + * @request: a #SoupRequest + * + * Gets the length of the data represented by @request. For most + * request types, this will not be known until after you call + * soup_request_send() or soup_request_send_finish(). + * + * Return value: the length of the data represented by @request, + * or -1 if not known. + * + * Since: 2.42 + */ +goffset +soup_request_get_content_length (SoupRequest *request) +{ + return SOUP_REQUEST_GET_CLASS (request)->get_content_length (request); +} + +/** + * soup_request_get_content_type: + * @request: a #SoupRequest + * + * Gets the type of the data represented by @request. For most request + * types, this will not be known until after you call + * soup_request_send() or soup_request_send_finish(). + * + * As in the HTTP Content-Type header, this may include parameters + * after the MIME type. + * + * Return value: (nullable): the type of the data represented by + * @request, or %NULL if not known. + * + * Since: 2.42 + */ +const char * +soup_request_get_content_type (SoupRequest *request) +{ + return SOUP_REQUEST_GET_CLASS (request)->get_content_type (request); +} diff --git a/libsoup/soup-request.h b/libsoup/soup-request.h new file mode 100644 index 0000000..84ad6d6 --- /dev/null +++ b/libsoup/soup-request.h @@ -0,0 +1,103 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2009, 2010 Red Hat, Inc. + * Copyright (C) 2010 Igalia, S.L. + * + * 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, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef SOUP_REQUEST_H +#define SOUP_REQUEST_H 1 + +#include + +#include + +G_BEGIN_DECLS + +#define SOUP_TYPE_REQUEST (soup_request_get_type ()) +#define SOUP_REQUEST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SOUP_TYPE_REQUEST, SoupRequest)) +#define SOUP_REQUEST_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_REQUEST, SoupRequestClass)) +#define SOUP_IS_REQUEST(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SOUP_TYPE_REQUEST)) +#define SOUP_IS_REQUEST_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SOUP_TYPE_REQUEST)) +#define SOUP_REQUEST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_REQUEST, SoupRequestClass)) + +typedef struct _SoupRequestPrivate SoupRequestPrivate; +typedef struct _SoupRequestClass SoupRequestClass; + +struct _SoupRequest { + GObject parent; + + SoupRequestPrivate *priv; +}; + +struct _SoupRequestClass { + GObjectClass parent; + + const char **schemes; + + gboolean (*check_uri) (SoupRequest *req_base, + SoupURI *uri, + GError **error); + + GInputStream * (*send) (SoupRequest *request, + GCancellable *cancellable, + GError **error); + void (*send_async) (SoupRequest *request, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + GInputStream * (*send_finish) (SoupRequest *request, + GAsyncResult *result, + GError **error); + + goffset (*get_content_length) (SoupRequest *request); + const char * (*get_content_type) (SoupRequest *request); +}; + +SOUP_AVAILABLE_IN_2_34 +GType soup_request_get_type (void); + +#define SOUP_REQUEST_URI "uri" +#define SOUP_REQUEST_SESSION "session" + +SOUP_AVAILABLE_IN_2_34 +GInputStream *soup_request_send (SoupRequest *request, + GCancellable *cancellable, + GError **error); +SOUP_AVAILABLE_IN_2_34 +void soup_request_send_async (SoupRequest *request, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +SOUP_AVAILABLE_IN_2_34 +GInputStream *soup_request_send_finish (SoupRequest *request, + GAsyncResult *result, + GError **error); + +SOUP_AVAILABLE_IN_2_34 +SoupURI *soup_request_get_uri (SoupRequest *request); +SOUP_AVAILABLE_IN_2_34 +SoupSession *soup_request_get_session (SoupRequest *request); + +SOUP_AVAILABLE_IN_2_34 +goffset soup_request_get_content_length (SoupRequest *request); +SOUP_AVAILABLE_IN_2_34 +const char *soup_request_get_content_type (SoupRequest *request); + +G_END_DECLS + +#endif /* SOUP_REQUEST_H */ diff --git a/libsoup/soup-requester.c b/libsoup/soup-requester.c new file mode 100644 index 0000000..61f6678 --- /dev/null +++ b/libsoup/soup-requester.c @@ -0,0 +1,198 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-requester.c: + * + * Copyright (C) 2010, Igalia S.L. + * + * 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, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" + +#define LIBSOUP_USE_UNSTABLE_REQUEST_API + +#include "soup-requester.h" +#include "soup.h" + +G_GNUC_BEGIN_IGNORE_DEPRECATIONS + +static SoupSessionFeatureInterface *soup_requester_default_feature_interface; +static void soup_requester_session_feature_init (SoupSessionFeatureInterface *feature_interface, gpointer interface_data); + +struct _SoupRequesterPrivate { + SoupSession *session; +}; + +G_DEFINE_TYPE_WITH_CODE (SoupRequester, soup_requester, G_TYPE_OBJECT, + G_ADD_PRIVATE (SoupRequester) + G_IMPLEMENT_INTERFACE (SOUP_TYPE_SESSION_FEATURE, + soup_requester_session_feature_init)) + +static void +soup_requester_init (SoupRequester *requester) +{ + requester->priv = soup_requester_get_instance_private (requester); +} + +static void +soup_requester_class_init (SoupRequesterClass *requester_class) +{ +} + +static void +soup_requester_attach (SoupSessionFeature *feature, SoupSession *session) +{ + SoupRequester *requester = SOUP_REQUESTER (feature); + + requester->priv->session = session; + + soup_requester_default_feature_interface->attach (feature, session); +} + +static void +soup_requester_detach (SoupSessionFeature *feature, SoupSession *session) +{ + SoupRequester *requester = SOUP_REQUESTER (feature); + + requester->priv->session = NULL; + + soup_requester_default_feature_interface->detach (feature, session); +} + +static gboolean +soup_requester_add_feature (SoupSessionFeature *feature, GType type) +{ + SoupRequester *requester = SOUP_REQUESTER (feature); + + if (!g_type_is_a (type, SOUP_TYPE_REQUEST)) + return FALSE; + + soup_session_add_feature_by_type (requester->priv->session, type); + return TRUE; +} + +static gboolean +soup_requester_remove_feature (SoupSessionFeature *feature, GType type) +{ + SoupRequester *requester = SOUP_REQUESTER (feature); + + if (!g_type_is_a (type, SOUP_TYPE_REQUEST)) + return FALSE; + + soup_session_remove_feature_by_type (requester->priv->session, type); + return TRUE; +} + +static gboolean +soup_requester_has_feature (SoupSessionFeature *feature, GType type) +{ + SoupRequester *requester = SOUP_REQUESTER (feature); + + if (!g_type_is_a (type, SOUP_TYPE_REQUEST)) + return FALSE; + + return soup_session_has_feature (requester->priv->session, type); +} + +static void +soup_requester_session_feature_init (SoupSessionFeatureInterface *feature_interface, + gpointer interface_data) +{ + soup_requester_default_feature_interface = + g_type_default_interface_peek (SOUP_TYPE_SESSION_FEATURE); + + feature_interface->attach = soup_requester_attach; + feature_interface->detach = soup_requester_detach; + feature_interface->add_feature = soup_requester_add_feature; + feature_interface->remove_feature = soup_requester_remove_feature; + feature_interface->has_feature = soup_requester_has_feature; +} + +SoupRequester * +soup_requester_new (void) +{ + return g_object_new (SOUP_TYPE_REQUESTER, NULL); +} + +static void +translate_error (GError *error) +{ + if (error->domain != SOUP_REQUEST_ERROR) + return; + + error->domain = SOUP_REQUESTER_ERROR; + if (error->code == SOUP_REQUEST_ERROR_BAD_URI) + error->code = SOUP_REQUESTER_ERROR_BAD_URI; + else if (error->code == SOUP_REQUEST_ERROR_UNSUPPORTED_URI_SCHEME) + error->code = SOUP_REQUESTER_ERROR_UNSUPPORTED_URI_SCHEME; + else + g_warn_if_reached (); +} + +/** + * soup_requester_request: + * + * Return value: (transfer full): + */ +SoupRequest * +soup_requester_request (SoupRequester *requester, const char *uri_string, + GError **error) +{ + SoupRequest *req; + + g_return_val_if_fail (SOUP_IS_REQUESTER (requester), NULL); + + req = soup_session_request (requester->priv->session, + uri_string, error); + if (req || !error) + return req; + + translate_error (*error); + return NULL; +} + +/** + * soup_requester_request_uri: + * + * Return value: (transfer full): + */ +SoupRequest * +soup_requester_request_uri (SoupRequester *requester, SoupURI *uri, + GError **error) +{ + SoupRequest *req; + + g_return_val_if_fail (SOUP_IS_REQUESTER (requester), NULL); + + req = soup_session_request_uri (requester->priv->session, + uri, error); + if (req || !error) + return req; + + translate_error (*error); + return NULL; +} + +GQuark +soup_requester_error_quark (void) +{ + static GQuark error; + if (!error) + error = g_quark_from_static_string ("soup_requester_error_quark"); + return error; +} + +G_GNUC_END_IGNORE_DEPRECATIONS diff --git a/libsoup/soup-requester.h b/libsoup/soup-requester.h new file mode 100644 index 0000000..0635513 --- /dev/null +++ b/libsoup/soup-requester.h @@ -0,0 +1,84 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2010 Igalia S.L. + * + * 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, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef SOUP_REQUESTER_H +#define SOUP_REQUESTER_H 1 + +#ifdef LIBSOUP_USE_UNSTABLE_REQUEST_API + +#include + +G_BEGIN_DECLS + +#define SOUP_TYPE_REQUESTER (soup_requester_get_type ()) +#define SOUP_REQUESTER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SOUP_TYPE_REQUESTER, SoupRequester)) +#define SOUP_REQUESTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_REQUESTER, SoupRequesterClass)) +#define SOUP_IS_REQUESTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SOUP_TYPE_REQUESTER)) +#define SOUP_IS_REQUESTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), SOUP_TYPE_REQUESTER)) +#define SOUP_REQUESTER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_REQUESTER, SoupRequesterClass)) + +typedef struct _SoupRequester SoupRequester; +typedef struct _SoupRequesterPrivate SoupRequesterPrivate; + +struct _SoupRequester { + GObject parent; + + SoupRequesterPrivate *priv; +}; + +typedef struct { + GObjectClass parent_class; +} SoupRequesterClass; + +SOUP_AVAILABLE_IN_2_34 +SOUP_DEPRECATED_IN_2_42 +GType soup_requester_get_type (void); + +SOUP_AVAILABLE_IN_2_34 +SOUP_DEPRECATED_IN_2_42 +SoupRequester *soup_requester_new (void); + +SOUP_AVAILABLE_IN_2_34 +SOUP_DEPRECATED_IN_2_42_FOR(soup_session_request) +SoupRequest *soup_requester_request (SoupRequester *requester, + const char *uri_string, + GError **error); + +SOUP_AVAILABLE_IN_2_34 +SOUP_DEPRECATED_IN_2_42_FOR(soup_session_request_uri) +SoupRequest *soup_requester_request_uri (SoupRequester *requester, + SoupURI *uri, + GError **error); + +SOUP_AVAILABLE_IN_2_34 +SOUP_DEPRECATED_IN_2_42_FOR(SOUP_REQUEST_ERROR) +GQuark soup_requester_error_quark (void); +#define SOUP_REQUESTER_ERROR soup_requester_error_quark () + +typedef enum { + SOUP_REQUESTER_ERROR_BAD_URI, + SOUP_REQUESTER_ERROR_UNSUPPORTED_URI_SCHEME +} SoupRequesterError; + +G_END_DECLS + +#endif /* LIBSOUP_USE_UNSTABLE_REQUEST_API */ + +#endif /* SOUP_REQUESTER_H */ diff --git a/libsoup/soup-server.c b/libsoup/soup-server.c new file mode 100644 index 0000000..21be854 --- /dev/null +++ b/libsoup/soup-server.c @@ -0,0 +1,2819 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-server.c: Asynchronous HTTP server + * + * Copyright (C) 2001-2003, Ximian, Inc. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include + +#include "soup-server.h" +#include "soup.h" +#include "soup-message-private.h" +#include "soup-misc-private.h" +#include "soup-path-map.h" +#include "soup-socket-private.h" +#include "soup-websocket.h" +#include "soup-websocket-connection.h" + +/** + * SECTION:soup-server + * @short_description: HTTP server + * @see_also: #SoupAuthDomain + * + * #SoupServer implements a simple HTTP server. + * + * (The following documentation describes the current #SoupServer API, + * available in libsoup 2.48 and later. See + * the section "The Old SoupServer + * Listening API" in the server how-to documentation for + * details on the older #SoupServer API.) + * + * To begin, create a server using soup_server_new(). Add at least one + * handler by calling soup_server_add_handler() or + * soup_server_add_early_handler(); the handler will be called to + * process any requests underneath the path you pass. (If you want all + * requests to go to the same handler, just pass "/" (or %NULL) for + * the path.) + * + * When a new connection is accepted (or a new request is started on + * an existing persistent connection), the #SoupServer will emit + * #SoupServer::request-started and then begin processing the request + * as described below, but note that once the message is assigned a + * #SoupMessage:status-code, then callbacks after that point will be + * skipped. Note also that it is not defined when the callbacks happen + * relative to various #SoupMessage signals. + * + * Once the headers have been read, #SoupServer will check if there is + * a #SoupAuthDomain (qv) covering the Request-URI; if so, and if the + * message does not contain suitable authorization, then the + * #SoupAuthDomain will set a status of %SOUP_STATUS_UNAUTHORIZED on + * the message. + * + * After checking for authorization, #SoupServer will look for "early" + * handlers (added with soup_server_add_early_handler()) matching the + * Request-URI. If one is found, it will be run; in particular, this + * can be used to connect to signals to do a streaming read of the + * request body. + * + * (At this point, if the request headers contain "Expect: + * 100-continue", and a status code has been set, then + * #SoupServer will skip the remaining steps and return the response. + * If the request headers contain "Expect: + * 100-continue" and no status code has been set, + * #SoupServer will return a %SOUP_STATUS_CONTINUE status before + * continuing.) + * + * The server will then read in the response body (if present). At + * this point, if there are no handlers at all defined for the + * Request-URI, then the server will return %SOUP_STATUS_NOT_FOUND to + * the client. + * + * Otherwise (assuming no previous step assigned a status to the + * message) any "normal" handlers (added with + * soup_server_add_handler()) for the message's Request-URI will be + * run. + * + * Then, if the path has a WebSocket handler registered (and has + * not yet been assigned a status), #SoupServer will attempt to + * validate the WebSocket handshake, filling in the response and + * setting a status of %SOUP_STATUS_SWITCHING_PROTOCOLS or + * %SOUP_STATUS_BAD_REQUEST accordingly. + * + * If the message still has no status code at this point (and has not + * been paused with soup_server_pause_message()), then it will be + * given a status of %SOUP_STATUS_INTERNAL_SERVER_ERROR (because at + * least one handler ran, but returned without assigning a status). + * + * Finally, the server will emit #SoupServer::request-finished (or + * #SoupServer::request-aborted if an I/O error occurred before + * handling was completed). + * + * If you want to handle the special "*" URI (eg, "OPTIONS *"), you + * must explicitly register a handler for "*"; the default handler + * will not be used for that case. + * + * If you want to process https connections in addition to (or instead + * of) http connections, you can either set the + * %SOUP_SERVER_TLS_CERTIFICATE property when creating the server, or + * else call soup_server_set_ssl_certificate() after creating it. + * + * Once the server is set up, make one or more calls to + * soup_server_listen(), soup_server_listen_local(), or + * soup_server_listen_all() to tell it where to listen for + * connections. (All ports on a #SoupServer use the same handlers; if + * you need to handle some ports differently, such as returning + * different data for http and https, you'll need to create multiple + * #SoupServers, or else check the passed-in URI in the handler + * function.). + * + * #SoupServer will begin processing connections as soon as you return + * to (or start) the main loop for the current thread-default + * #GMainContext. + */ + +enum { + REQUEST_STARTED, + REQUEST_READ, + REQUEST_FINISHED, + REQUEST_ABORTED, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +struct SoupClientContext { + SoupServer *server; + SoupSocket *sock; + GSocket *gsock; + SoupMessage *msg; + SoupAuthDomain *auth_domain; + char *auth_user; + + GSocketAddress *remote_addr; + const char *remote_ip; + GSocketAddress *local_addr; + + int ref_count; +}; + +typedef struct { + char *path; + + SoupServerCallback early_callback; + GDestroyNotify early_destroy; + gpointer early_user_data; + + SoupServerCallback callback; + GDestroyNotify destroy; + gpointer user_data; + + char *websocket_origin; + char **websocket_protocols; + SoupServerWebsocketCallback websocket_callback; + GDestroyNotify websocket_destroy; + gpointer websocket_user_data; +} SoupServerHandler; + +typedef struct { + GSList *listeners; + GSList *clients; + + char *ssl_cert_file, *ssl_key_file; + GTlsCertificate *tls_cert; + + char *server_header; + + GMainContext *async_context; + GMainLoop *loop; + + gboolean raw_paths; + SoupPathMap *handlers; + + GSList *auth_domains; + + char **http_aliases, **https_aliases; + + SoupAddress *legacy_iface; + int legacy_port; + + gboolean disposed; + +} SoupServerPrivate; + +#define SOUP_SERVER_SERVER_HEADER_BASE "libsoup/" PACKAGE_VERSION + +enum { + PROP_0, + + PROP_PORT, + PROP_INTERFACE, + PROP_SSL_CERT_FILE, + PROP_SSL_KEY_FILE, + PROP_TLS_CERT_FILE, + PROP_TLS_KEY_FILE, + PROP_TLS_CERTIFICATE, + PROP_ASYNC_CONTEXT, + PROP_RAW_PATHS, + PROP_SERVER_HEADER, + PROP_HTTP_ALIASES, + PROP_HTTPS_ALIASES, + + LAST_PROP +}; + +G_DEFINE_TYPE_WITH_PRIVATE (SoupServer, soup_server, G_TYPE_OBJECT) + +static SoupClientContext *soup_client_context_ref (SoupClientContext *client); +static void soup_client_context_unref (SoupClientContext *client); + +static void +free_handler (SoupServerHandler *handler) +{ + g_free (handler->path); + g_free (handler->websocket_origin); + g_strfreev (handler->websocket_protocols); + if (handler->early_destroy) + handler->early_destroy (handler->early_user_data); + if (handler->destroy) + handler->destroy (handler->user_data); + if (handler->websocket_destroy) + handler->websocket_destroy (handler->websocket_user_data); + g_slice_free (SoupServerHandler, handler); +} + +static void +soup_server_init (SoupServer *server) +{ + SoupServerPrivate *priv = soup_server_get_instance_private (server); + + priv->handlers = soup_path_map_new ((GDestroyNotify)free_handler); + + priv->http_aliases = g_new (char *, 2); + priv->http_aliases[0] = (char *)g_intern_string ("*"); + priv->http_aliases[1] = NULL; + + priv->legacy_port = -1; +} + +static void +soup_server_dispose (GObject *object) +{ + SoupServer *server = SOUP_SERVER (object); + SoupServerPrivate *priv = soup_server_get_instance_private (server); + + priv->disposed = TRUE; + soup_server_disconnect (server); + + G_OBJECT_CLASS (soup_server_parent_class)->dispose (object); +} + +static void +soup_server_finalize (GObject *object) +{ + SoupServer *server = SOUP_SERVER (object); + SoupServerPrivate *priv = soup_server_get_instance_private (server); + + g_clear_object (&priv->legacy_iface); + + g_free (priv->ssl_cert_file); + g_free (priv->ssl_key_file); + g_clear_object (&priv->tls_cert); + + g_free (priv->server_header); + + soup_path_map_free (priv->handlers); + + g_slist_free_full (priv->auth_domains, g_object_unref); + + g_clear_pointer (&priv->loop, g_main_loop_unref); + g_clear_pointer (&priv->async_context, g_main_context_unref); + + g_free (priv->http_aliases); + g_free (priv->https_aliases); + + G_OBJECT_CLASS (soup_server_parent_class)->finalize (object); +} + +static gboolean +soup_server_ensure_listening (SoupServer *server) +{ + SoupServerPrivate *priv = soup_server_get_instance_private (server); + SoupSocket *listener; + + if (priv->listeners) + return TRUE; + + if (!priv->legacy_iface) { + priv->legacy_iface = + soup_address_new_any (SOUP_ADDRESS_FAMILY_IPV4, + priv->legacy_port); + } + + listener = soup_socket_new (SOUP_SOCKET_LOCAL_ADDRESS, priv->legacy_iface, + SOUP_SOCKET_SSL_CREDENTIALS, priv->tls_cert, + SOUP_SOCKET_ASYNC_CONTEXT, priv->async_context, + NULL); + if (!soup_socket_listen (listener)) { + g_object_unref (listener); + return FALSE; + } + + /* Re-resolve the interface address, in particular in case + * the passed-in address had SOUP_ADDRESS_ANY_PORT. + */ + g_object_unref (priv->legacy_iface); + priv->legacy_iface = soup_socket_get_local_address (listener); + g_object_ref (priv->legacy_iface); + priv->legacy_port = soup_address_get_port (priv->legacy_iface); + + priv->listeners = g_slist_prepend (priv->listeners, listener); + return TRUE; +} + +static GObject * +soup_server_constructor (GType type, + guint n_construct_properties, + GObjectConstructParam *construct_properties) +{ + GObject *server; + SoupServerPrivate *priv; + gboolean legacy_port_set; + + server = G_OBJECT_CLASS (soup_server_parent_class)-> + constructor (type, n_construct_properties, construct_properties); + priv = soup_server_get_instance_private (SOUP_SERVER (server)); + + /* For backward compatibility, we have to process the + * :ssl-cert-file, :ssl-key-file, :interface, and :port + * properties now, and return NULL if they are + * invalid/unsatisfiable. + */ + if (priv->ssl_cert_file && priv->ssl_key_file) { + GError *error = NULL; + + if (priv->tls_cert) + g_object_unref (priv->tls_cert); + priv->tls_cert = g_tls_certificate_new_from_files (priv->ssl_cert_file, priv->ssl_key_file, &error); + if (!priv->tls_cert) { + g_warning ("Could not read TLS certificate from '%s': %s", + priv->ssl_cert_file, error->message); + g_error_free (error); + g_object_unref (server); + return NULL; + } + } + + if (priv->legacy_port != -1) + legacy_port_set = TRUE; + else { + legacy_port_set = FALSE; + priv->legacy_port = 0; + } + + if (legacy_port_set || priv->legacy_iface) { + if (!soup_server_ensure_listening (SOUP_SERVER (server))) { + g_object_unref (server); + return NULL; + } + } else { + /* If neither port nor iface was specified, then + * either: (a) the caller is planning to use the new + * listen APIs, so we don't have to do anything now, + * or (b) the caller is using the legacy APIs but + * wants the default values for interface and port + * (address 0.0.0.0, port 0), in which case a later + * call to soup_server_ensure_listening() will set it + * up just-in-time; we don't have to worry about it + * failing in that case, because it can't (unless you + * have no IPv4 addresses configured [even localhost], + * or there are already listeners on all 65,535 ports. + * We assume neither of these will happen.) + */ + } + + return server; +} + +/* priv->http_aliases and priv->https_aliases are stored as arrays of + * *interned* strings, so we can't just use g_strdupv() to set them. + */ +static void +set_aliases (char ***variable, char **value) +{ + int len, i; + + if (*variable) + g_free (*variable); + + if (!value) { + *variable = NULL; + return; + } + + len = g_strv_length (value); + *variable = g_new (char *, len + 1); + for (i = 0; i < len; i++) + (*variable)[i] = (char *)g_intern_string (value[i]); + (*variable)[i] = NULL; +} + +static void +soup_server_set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + SoupServer *server = SOUP_SERVER (object); + SoupServerPrivate *priv = soup_server_get_instance_private (server); + const char *header; + + switch (prop_id) { + case PROP_PORT: + if (g_value_get_uint (value) != 0) + priv->legacy_port = g_value_get_uint (value); + break; + case PROP_INTERFACE: + if (priv->legacy_iface) + g_object_unref (priv->legacy_iface); + priv->legacy_iface = g_value_get_object (value); + if (priv->legacy_iface) + g_object_ref (priv->legacy_iface); + break; + case PROP_SSL_CERT_FILE: + g_free (priv->ssl_cert_file); + priv->ssl_cert_file = g_value_dup_string (value); + break; + case PROP_SSL_KEY_FILE: + g_free (priv->ssl_key_file); + priv->ssl_key_file = g_value_dup_string (value); + break; + case PROP_TLS_CERTIFICATE: + if (priv->tls_cert) + g_object_unref (priv->tls_cert); + priv->tls_cert = g_value_dup_object (value); + break; + case PROP_ASYNC_CONTEXT: + priv->async_context = g_value_get_pointer (value); + if (priv->async_context) + g_main_context_ref (priv->async_context); + break; + case PROP_RAW_PATHS: + priv->raw_paths = g_value_get_boolean (value); + break; + case PROP_SERVER_HEADER: + g_free (priv->server_header); + header = g_value_get_string (value); + if (!header) + priv->server_header = NULL; + else if (!*header) { + priv->server_header = + g_strdup (SOUP_SERVER_SERVER_HEADER_BASE); + } else if (g_str_has_suffix (header, " ")) { + priv->server_header = + g_strdup_printf ("%s%s", header, + SOUP_SERVER_SERVER_HEADER_BASE); + } else + priv->server_header = g_strdup (header); + break; + case PROP_HTTP_ALIASES: + set_aliases (&priv->http_aliases, g_value_get_boxed (value)); + break; + case PROP_HTTPS_ALIASES: + set_aliases (&priv->https_aliases, g_value_get_boxed (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +soup_server_get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + SoupServer *server = SOUP_SERVER (object); + SoupServerPrivate *priv = soup_server_get_instance_private (server); + + switch (prop_id) { + case PROP_PORT: + soup_server_ensure_listening (server); + g_value_set_uint (value, priv->legacy_port > 0 ? priv->legacy_port : 0); + break; + case PROP_INTERFACE: + soup_server_ensure_listening (server); + g_value_set_object (value, priv->legacy_iface); + break; + case PROP_SSL_CERT_FILE: + g_value_set_string (value, priv->ssl_cert_file); + break; + case PROP_SSL_KEY_FILE: + g_value_set_string (value, priv->ssl_key_file); + break; + case PROP_TLS_CERTIFICATE: + g_value_set_object (value, priv->tls_cert); + break; + case PROP_ASYNC_CONTEXT: + g_value_set_pointer (value, priv->async_context ? g_main_context_ref (priv->async_context) : NULL); + break; + case PROP_RAW_PATHS: + g_value_set_boolean (value, priv->raw_paths); + break; + case PROP_SERVER_HEADER: + g_value_set_string (value, priv->server_header); + break; + case PROP_HTTP_ALIASES: + g_value_set_boxed (value, priv->http_aliases); + break; + case PROP_HTTPS_ALIASES: + g_value_set_boxed (value, priv->https_aliases); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +soup_server_class_init (SoupServerClass *server_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (server_class); + + /* virtual method override */ + object_class->constructor = soup_server_constructor; + object_class->dispose = soup_server_dispose; + object_class->finalize = soup_server_finalize; + object_class->set_property = soup_server_set_property; + object_class->get_property = soup_server_get_property; + + /* signals */ + + /** + * SoupServer::request-started: + * @server: the server + * @message: the new message + * @client: the client context + * + * Emitted when the server has started reading a new request. + * @message will be completely blank; not even the + * Request-Line will have been read yet. About the only thing + * you can usefully do with it is connect to its signals. + * + * If the request is read successfully, this will eventually + * be followed by a #SoupServer::request_read signal. If a + * response is then sent, the request processing will end with + * a #SoupServer::request_finished signal. If a network error + * occurs, the processing will instead end with + * #SoupServer::request_aborted. + **/ + signals[REQUEST_STARTED] = + g_signal_new ("request-started", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (SoupServerClass, request_started), + NULL, NULL, + NULL, + G_TYPE_NONE, 2, + SOUP_TYPE_MESSAGE, + SOUP_TYPE_CLIENT_CONTEXT); + + /** + * SoupServer::request-read: + * @server: the server + * @message: the message + * @client: the client context + * + * Emitted when the server has successfully read a request. + * @message will have all of its request-side information + * filled in, and if the message was authenticated, @client + * will have information about that. This signal is emitted + * before any (non-early) handlers are called for the message, + * and if it sets the message's #status_code, then normal + * handler processing will be skipped. + **/ + signals[REQUEST_READ] = + g_signal_new ("request-read", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (SoupServerClass, request_read), + NULL, NULL, + NULL, + G_TYPE_NONE, 2, + SOUP_TYPE_MESSAGE, + SOUP_TYPE_CLIENT_CONTEXT); + + /** + * SoupServer::request-finished: + * @server: the server + * @message: the message + * @client: the client context + * + * Emitted when the server has finished writing a response to + * a request. + **/ + signals[REQUEST_FINISHED] = + g_signal_new ("request-finished", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (SoupServerClass, request_finished), + NULL, NULL, + NULL, + G_TYPE_NONE, 2, + SOUP_TYPE_MESSAGE, + SOUP_TYPE_CLIENT_CONTEXT); + + /** + * SoupServer::request-aborted: + * @server: the server + * @message: the message + * @client: the client context + * + * Emitted when processing has failed for a message; this + * could mean either that it could not be read (if + * #SoupServer::request_read has not been emitted for it yet), + * or that the response could not be written back (if + * #SoupServer::request_read has been emitted but + * #SoupServer::request_finished has not been). + * + * @message is in an undefined state when this signal is + * emitted; the signal exists primarily to allow the server to + * free any state that it may have allocated in + * #SoupServer::request_started. + **/ + signals[REQUEST_ABORTED] = + g_signal_new ("request-aborted", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (SoupServerClass, request_aborted), + NULL, NULL, + NULL, + G_TYPE_NONE, 2, + SOUP_TYPE_MESSAGE, + SOUP_TYPE_CLIENT_CONTEXT); + + /* properties */ + /** + * SoupServer:port: + * + * The port the server is listening on, if you are using the + * old #SoupServer API. (This will not be set if you use + * soup_server_listen(), etc.) + * + * Deprecated: #SoupServers can listen on multiple interfaces + * at once now. Use soup_server_listen(), etc, to listen on a + * port, and soup_server_get_uris() to see what ports are + * being listened on. + */ + /** + * SOUP_SERVER_PORT: + * + * Alias for the deprecated #SoupServer:port property, qv. + * + * Deprecated: #SoupServers can listen on multiple interfaces + * at once now. Use soup_server_listen(), etc, to listen on a + * port, and soup_server_get_uris() to see what ports are + * being listened on. + **/ + g_object_class_install_property ( + object_class, PROP_PORT, + g_param_spec_uint (SOUP_SERVER_PORT, + "Port", + "Port to listen on (Deprecated)", + 0, 65536, 0, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_DEPRECATED)); + /** + * SoupServer:interface: + * + * The address of the network interface the server is + * listening on, if you are using the old #SoupServer API. + * (This will not be set if you use soup_server_listen(), + * etc.) + * + * Deprecated: #SoupServers can listen on multiple interfaces + * at once now. Use soup_server_listen(), etc, to listen on an + * interface, and soup_server_get_uris() to see what addresses + * are being listened on. + */ + /** + * SOUP_SERVER_INTERFACE: + * + * Alias for the #SoupServer:interface property, qv. + * + * Deprecated: #SoupServers can listen on multiple interfaces + * at once now. Use soup_server_listen(), etc, to listen on an + * interface, and soup_server_get_uris() to see what addresses + * are being listened on. + **/ + g_object_class_install_property ( + object_class, PROP_INTERFACE, + g_param_spec_object (SOUP_SERVER_INTERFACE, + "Interface", + "Address of interface to listen on (Deprecated)", + SOUP_TYPE_ADDRESS, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_DEPRECATED)); + /** + * SOUP_SERVER_SSL_CERT_FILE: + * + * Alias for the #SoupServer:ssl-cert-file property, qv. + * + * Deprecated: use #SoupServer:tls-certificate or + * soup_server_set_ssl_certificate(). + */ + /** + * SoupServer:ssl-cert-file: + * + * Path to a file containing a PEM-encoded certificate. + * + * If you set this property and #SoupServer:ssl-key-file at + * construct time, then soup_server_new() will try to read the + * files; if it cannot, it will return %NULL, with no explicit + * indication of what went wrong (and logging a warning with + * newer versions of glib, since returning %NULL from a + * constructor is illegal). + * + * Deprecated: use #SoupServer:tls-certificate or + * soup_server_set_ssl_certificate(). + */ + g_object_class_install_property ( + object_class, PROP_SSL_CERT_FILE, + g_param_spec_string (SOUP_SERVER_SSL_CERT_FILE, + "TLS (aka SSL) certificate file", + "File containing server TLS (aka SSL) certificate", + NULL, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); + /** + * SOUP_SERVER_SSL_KEY_FILE: + * + * Alias for the #SoupServer:ssl-key-file property, qv. + * + * Deprecated: use #SoupServer:tls-certificate or + * soup_server_set_ssl_certificate(). + */ + /** + * SoupServer:ssl-key-file: + * + * Path to a file containing a PEM-encoded private key. See + * #SoupServer:ssl-cert-file for more information about how this + * is used. + * + * Deprecated: use #SoupServer:tls-certificate or + * soup_server_set_ssl_certificate(). + */ + g_object_class_install_property ( + object_class, PROP_SSL_KEY_FILE, + g_param_spec_string (SOUP_SERVER_SSL_KEY_FILE, + "TLS (aka SSL) key file", + "File containing server TLS (aka SSL) key", + NULL, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); + /** + * SOUP_SERVER_TLS_CERTIFICATE: + * + * Alias for the #SoupServer:tls-certificate property, qv. + * + * Since: 2.38 + */ + /** + * SoupServer:tls-certificate: + * + * A #GTlsCertificate that has a #GTlsCertificate:private-key + * set. If this is set, then the server will be able to speak + * https in addition to (or instead of) plain http. + * + * Alternatively, you can call soup_server_set_ssl_cert_file() + * to have #SoupServer read in a a certificate from a file. + * + * Since: 2.38 + */ + g_object_class_install_property ( + object_class, PROP_TLS_CERTIFICATE, + g_param_spec_object (SOUP_SERVER_TLS_CERTIFICATE, + "TLS certificate", + "GTlsCertificate to use for https", + G_TYPE_TLS_CERTIFICATE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + /** + * SoupServer:async-context: + * + * The server's #GMainContext, if you are using the old API. + * Servers created using soup_server_listen() will listen on + * the #GMainContext that was the thread-default context at + * the time soup_server_listen() was called. + * + * Deprecated: The new API uses the thread-default #GMainContext + * rather than having an explicitly-specified one. + */ + /** + * SOUP_SERVER_ASYNC_CONTEXT: + * + * Alias for the deprecated #SoupServer:async-context + * property, qv. + * + * Deprecated: The new API uses the thread-default #GMainContext + * rather than having an explicitly-specified one. + **/ + g_object_class_install_property ( + object_class, PROP_ASYNC_CONTEXT, + g_param_spec_pointer (SOUP_SERVER_ASYNC_CONTEXT, + "Async GMainContext", + "The GMainContext to dispatch async I/O in", + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_DEPRECATED)); + /** + * SOUP_SERVER_RAW_PATHS: + * + * Alias for the #SoupServer:raw-paths property. (If %TRUE, + * percent-encoding in the Request-URI path will not be + * automatically decoded.) + **/ + g_object_class_install_property ( + object_class, PROP_RAW_PATHS, + g_param_spec_boolean (SOUP_SERVER_RAW_PATHS, + "Raw paths", + "If %TRUE, percent-encoding in the Request-URI path will not be automatically decoded.", + FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + /** + * SoupServer:server-header: + * + * If non-%NULL, the value to use for the "Server" header on + * #SoupMessages processed by this server. + * + * The Server header is the server equivalent of the + * User-Agent header, and provides information about the + * server and its components. It contains a list of one or + * more product tokens, separated by whitespace, with the most + * significant product token coming first. The tokens must be + * brief, ASCII, and mostly alphanumeric (although "-", "_", + * and "." are also allowed), and may optionally include a "/" + * followed by a version string. You may also put comments, + * enclosed in parentheses, between or after the tokens. + * + * Some HTTP server implementations intentionally do not use + * version numbers in their Server header, so that + * installations running older versions of the server don't + * end up advertising their vulnerability to specific security + * holes. + * + * As with #SoupSession:user_agent, if you set a + * #SoupServer:server_header property that has trailing whitespace, + * #SoupServer will append its own product token (eg, + * "libsoup/2.3.2") to the end of the + * header for you. + **/ + /** + * SOUP_SERVER_SERVER_HEADER: + * + * Alias for the #SoupServer:server-header property, qv. + **/ + g_object_class_install_property ( + object_class, PROP_SERVER_HEADER, + g_param_spec_string (SOUP_SERVER_SERVER_HEADER, + "Server header", + "Server header", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + + /** + * SoupServer:http-aliases: + * + * A %NULL-terminated array of URI schemes that should be + * considered to be aliases for "http". Eg, if this included + * "dav", than a URI of + * dav://example.com/path would be treated + * identically to http://example.com/path. + * In particular, this is needed in cases where a client + * sends requests with absolute URIs, where those URIs do + * not use "http:". + * + * The default value is an array containing the single element + * "*", a special value which means that + * any scheme except "https" is considered to be an alias for + * "http". + * + * See also #SoupServer:https-aliases. + * + * Since: 2.44 + */ + /** + * SOUP_SERVER_HTTP_ALIASES: + * + * Alias for the #SoupServer:http-aliases property, qv. + * + * Since: 2.44 + */ + g_object_class_install_property ( + object_class, PROP_HTTP_ALIASES, + g_param_spec_boxed (SOUP_SERVER_HTTP_ALIASES, + "http aliases", + "URI schemes that are considered aliases for 'http'", + G_TYPE_STRV, + G_PARAM_READWRITE)); + /** + * SoupServer:https-aliases: + * + * A comma-delimited list of URI schemes that should be + * considered to be aliases for "https". See + * #SoupServer:http-aliases for more information. + * + * The default value is %NULL, meaning that no URI schemes + * are considered aliases for "https". + * + * Since: 2.44 + */ + /** + * SOUP_SERVER_HTTPS_ALIASES: + * + * Alias for the #SoupServer:https-aliases property, qv. + * + * Since: 2.44 + **/ + g_object_class_install_property ( + object_class, PROP_HTTPS_ALIASES, + g_param_spec_boxed (SOUP_SERVER_HTTPS_ALIASES, + "https aliases", + "URI schemes that are considered aliases for 'https'", + G_TYPE_STRV, + G_PARAM_READWRITE)); +} + +/** + * soup_server_new: + * @optname1: name of first property to set + * @...: value of @optname1, followed by additional property/value pairs + * + * Creates a new #SoupServer. This is exactly equivalent to calling + * g_object_new() and specifying %SOUP_TYPE_SERVER as the type. + * + * Return value: (nullable): a new #SoupServer. If you are using + * certain legacy properties, this may also return %NULL if an error + * occurs. + **/ +SoupServer * +soup_server_new (const char *optname1, ...) +{ + SoupServer *server; + va_list ap; + + va_start (ap, optname1); + server = (SoupServer *)g_object_new_valist (SOUP_TYPE_SERVER, + optname1, ap); + va_end (ap); + + return server; +} + +/** + * soup_server_get_port: + * @server: a #SoupServer + * + * Gets the TCP port that @server is listening on, if you are using + * the old API. + * + * Return value: the port @server is listening on. + * + * Deprecated: If you are using soup_server_listen(), etc, then use + * soup_server_get_uris() to get a list of all listening addresses. + **/ +guint +soup_server_get_port (SoupServer *server) +{ + SoupServerPrivate *priv; + + g_return_val_if_fail (SOUP_IS_SERVER (server), 0); + priv = soup_server_get_instance_private (server); + + soup_server_ensure_listening (server); + g_return_val_if_fail (priv->legacy_iface != NULL, 0); + + return priv->legacy_port; +} + +/** + * soup_server_set_ssl_cert_file: + * @server: a #SoupServer + * @ssl_cert_file: path to a file containing a PEM-encoded SSL/TLS + * certificate. + * @ssl_key_file: path to a file containing a PEM-encoded private key. + * @error: return location for a #GError + * + * Sets @server up to do https, using the SSL/TLS certificate + * specified by @ssl_cert_file and @ssl_key_file (which may point to + * the same file). + * + * Alternatively, you can set the #SoupServer:tls-certificate property + * at construction time, if you already have a #GTlsCertificate. + * + * Return value: success or failure. + * + * Since: 2.48 + */ +gboolean +soup_server_set_ssl_cert_file (SoupServer *server, + const char *ssl_cert_file, + const char *ssl_key_file, + GError **error) +{ + SoupServerPrivate *priv; + + g_return_val_if_fail (SOUP_IS_SERVER (server), FALSE); + priv = soup_server_get_instance_private (server); + + if (priv->tls_cert) + g_object_unref (priv->tls_cert); + + g_free (priv->ssl_cert_file); + priv->ssl_cert_file = g_strdup (ssl_cert_file); + + g_free (priv->ssl_key_file); + priv->ssl_key_file = g_strdup (ssl_key_file); + + priv->tls_cert = g_tls_certificate_new_from_files (priv->ssl_cert_file, + priv->ssl_key_file, + error); + return priv->tls_cert != NULL; +} + +/** + * soup_server_is_https: + * @server: a #SoupServer + * + * Checks whether @server is capable of https. + * + * In order for a server to run https, you must call + * soup_server_set_ssl_cert_file(), or set the + * #SoupServer:tls-certificate property, to provide it with a + * certificate to use. + * + * If you are using the deprecated single-listener APIs, then a return + * value of %TRUE indicates that the #SoupServer serves https + * exclusively. If you are using soup_server_listen(), etc, then a + * %TRUE return value merely indicates that the server is + * able to do https, regardless of whether it + * actually currently is or not. Use soup_server_get_uris() to see if + * it currently has any https listeners. + * + * Return value: %TRUE if @server is configured to serve https. + **/ +gboolean +soup_server_is_https (SoupServer *server) +{ + SoupServerPrivate *priv; + + g_return_val_if_fail (SOUP_IS_SERVER (server), 0); + priv = soup_server_get_instance_private (server); + + return priv->tls_cert != NULL; +} + +/** + * soup_server_get_listener: + * @server: a #SoupServer + * + * Gets @server's listening socket, if you are using the old API. + * + * You should treat this socket as read-only; writing to it or + * modifiying it may cause @server to malfunction. + * + * Return value: (transfer none): the listening socket. + * + * Deprecated: If you are using soup_server_listen(), etc, then use + * soup_server_get_listeners() to get a list of all listening sockets, + * but note that that function returns #GSockets, not #SoupSockets. + **/ +SoupSocket * +soup_server_get_listener (SoupServer *server) +{ + SoupServerPrivate *priv; + + g_return_val_if_fail (SOUP_IS_SERVER (server), NULL); + priv = soup_server_get_instance_private (server); + + soup_server_ensure_listening (server); + g_return_val_if_fail (priv->legacy_iface != NULL, NULL); + + return priv->listeners ? priv->listeners->data : NULL; +} + +/** + * soup_server_get_listeners: + * @server: a #SoupServer + * + * Gets @server's list of listening sockets. + * + * You should treat these sockets as read-only; writing to or + * modifiying any of these sockets may cause @server to malfunction. + * + * (Beware that in contrast to the old soup_server_get_listener(), this + * function returns #GSockets, not #SoupSockets.) + * + * Return value: (transfer container) (element-type Gio.Socket): a + * list of listening sockets. + **/ +GSList * +soup_server_get_listeners (SoupServer *server) +{ + SoupServerPrivate *priv; + GSList *listeners, *iter; + + g_return_val_if_fail (SOUP_IS_SERVER (server), NULL); + priv = soup_server_get_instance_private (server); + + listeners = NULL; + for (iter = priv->listeners; iter; iter = iter->next) + listeners = g_slist_prepend (listeners, soup_socket_get_gsocket (iter->data)); + + /* priv->listeners has the sockets in reverse order from how + * they were added, so listeners now has them back in the + * original order. + */ + return listeners; +} + +static void start_request (SoupServer *, SoupClientContext *); +static void socket_disconnected (SoupSocket *sock, SoupClientContext *client); + +static SoupClientContext * +soup_client_context_new (SoupServer *server, SoupSocket *sock) +{ + SoupClientContext *client = g_slice_new0 (SoupClientContext); + + client->server = server; + client->sock = g_object_ref (sock); + client->gsock = soup_socket_get_gsocket (sock); + if (client->gsock) + g_object_ref (client->gsock); + g_signal_connect (sock, "disconnected", + G_CALLBACK (socket_disconnected), client); + client->ref_count = 1; + + return client; +} + +static void +soup_client_context_cleanup (SoupClientContext *client) +{ + g_clear_object (&client->auth_domain); + g_clear_pointer (&client->auth_user, g_free); + g_clear_object (&client->remote_addr); + g_clear_object (&client->local_addr); + + client->msg = NULL; +} + +static SoupClientContext * +soup_client_context_ref (SoupClientContext *client) +{ + g_atomic_int_inc (&client->ref_count); + return client; +} + +static void +soup_client_context_unref (SoupClientContext *client) +{ + if (!g_atomic_int_dec_and_test (&client->ref_count)) + return; + + soup_client_context_cleanup (client); + + g_signal_handlers_disconnect_by_func (client->sock, socket_disconnected, client); + g_object_unref (client->sock); + g_clear_object (&client->gsock); + g_clear_pointer (&client->remote_ip, g_free); + g_slice_free (SoupClientContext, client); +} + +static void +request_finished (SoupMessage *msg, SoupMessageIOCompletion completion, gpointer user_data) +{ + SoupClientContext *client = user_data; + SoupServer *server = client->server; + SoupServerPrivate *priv = soup_server_get_instance_private (server); + SoupSocket *sock = client->sock; + gboolean failed; + + if (completion == SOUP_MESSAGE_IO_STOLEN) { + soup_client_context_unref (client); + g_object_unref (msg); + return; + } + + /* Complete the message, assuming it actually really started. */ + if (msg->method) { + soup_message_finished (msg); + + failed = (completion == SOUP_MESSAGE_IO_INTERRUPTED || + msg->status_code == SOUP_STATUS_IO_ERROR); + g_signal_emit (server, + failed ? signals[REQUEST_ABORTED] : signals[REQUEST_FINISHED], + 0, msg, client); + } + + if (completion == SOUP_MESSAGE_IO_COMPLETE && + soup_socket_is_connected (sock) && + soup_message_is_keepalive (msg) && + priv->listeners) { + start_request (server, client); + } else { + soup_socket_disconnect (client->sock); + soup_client_context_unref (client); + } + g_object_unref (msg); +} + +/* "" was never documented as meaning the same thing as "/", but it + * effectively was. We have to special case it now or otherwise it + * would match "*" too. + */ +#define NORMALIZED_PATH(path) ((path) && *(path) ? (path) : "/") + +static SoupServerHandler * +get_handler (SoupServer *server, SoupMessage *msg) +{ + SoupServerPrivate *priv = soup_server_get_instance_private (server); + SoupURI *uri; + + uri = soup_message_get_uri (msg); + return soup_path_map_lookup (priv->handlers, NORMALIZED_PATH (uri->path)); +} + +static void +call_handler (SoupServer *server, SoupServerHandler *handler, + SoupClientContext *client, SoupMessage *msg, + gboolean early) +{ + GHashTable *form_data_set; + SoupURI *uri; + + if (early && !handler->early_callback) + return; + else if (!early && !handler->callback) + return; + + if (msg->status_code != 0) + return; + + uri = soup_message_get_uri (msg); + if (uri->query) + form_data_set = soup_form_decode (uri->query); + else + form_data_set = NULL; + + if (early) { + (*handler->early_callback) (server, msg, + uri->path, form_data_set, + client, handler->early_user_data); + } else { + (*handler->callback) (server, msg, + uri->path, form_data_set, + client, handler->user_data); + } + + if (form_data_set) + g_hash_table_unref (form_data_set); +} + +static void +got_headers (SoupMessage *msg, SoupClientContext *client) +{ + SoupServer *server = client->server; + SoupServerPrivate *priv = soup_server_get_instance_private (server); + SoupServerHandler *handler; + SoupURI *uri; + SoupDate *date; + char *date_string; + SoupAuthDomain *domain; + GSList *iter; + gboolean rejected = FALSE; + char *auth_user; + + /* Add required response headers */ + date = soup_date_new_from_now (0); + date_string = soup_date_to_string (date, SOUP_DATE_HTTP); + soup_message_headers_replace (msg->response_headers, "Date", + date_string); + g_free (date_string); + soup_date_free (date); + + if (msg->status_code != 0) + return; + + uri = soup_message_get_uri (msg); + if ((soup_socket_is_ssl (client->sock) && !soup_uri_is_https (uri, priv->https_aliases)) || + (!soup_socket_is_ssl (client->sock) && !soup_uri_is_http (uri, priv->http_aliases))) { + soup_message_set_status (msg, SOUP_STATUS_BAD_REQUEST); + return; + } + + if (!priv->raw_paths) { + char *decoded_path; + + decoded_path = soup_uri_decode (uri->path); + + if (strstr (decoded_path, "/../") || + g_str_has_suffix (decoded_path, "/..")) { + /* Introducing new ".." segments is not allowed */ + g_free (decoded_path); + soup_message_set_status (msg, SOUP_STATUS_BAD_REQUEST); + return; + } + + soup_uri_set_path (uri, decoded_path); + g_free (decoded_path); + } + + /* Now handle authentication. (We do this here so that if + * the request uses "Expect: 100-continue", we can reject it + * immediately rather than waiting for the request body to + * be sent. + */ + for (iter = priv->auth_domains; iter; iter = iter->next) { + domain = iter->data; + + if (soup_auth_domain_covers (domain, msg)) { + auth_user = soup_auth_domain_accepts (domain, msg); + if (auth_user) { + client->auth_domain = g_object_ref (domain); + client->auth_user = auth_user; + return; + } + + rejected = TRUE; + } + } + + /* If any auth domain rejected it, then it will need authentication. */ + if (rejected) { + for (iter = priv->auth_domains; iter; iter = iter->next) { + domain = iter->data; + + if (soup_auth_domain_covers (domain, msg)) + soup_auth_domain_challenge (domain, msg); + } + return; + } + + /* Otherwise, call the early handlers. */ + handler = get_handler (server, msg); + if (handler) + call_handler (server, handler, client, msg, TRUE); +} + +static void +complete_websocket_upgrade (SoupMessage *msg, gpointer user_data) +{ + SoupClientContext *client = user_data; + SoupServer *server = client->server; + SoupURI *uri = soup_message_get_uri (msg); + SoupServerHandler *handler; + GIOStream *stream; + SoupWebsocketConnection *conn; + + handler = get_handler (server, msg); + if (!handler || !handler->websocket_callback) + return; + + soup_client_context_ref (client); + stream = soup_client_context_steal_connection (client); + conn = soup_websocket_connection_new (stream, uri, + SOUP_WEBSOCKET_CONNECTION_SERVER, + soup_message_headers_get_one (msg->request_headers, "Origin"), + soup_message_headers_get_one (msg->response_headers, "Sec-WebSocket-Protocol")); + g_object_unref (stream); + soup_client_context_unref (client); + + (*handler->websocket_callback) (server, conn, uri->path, client, + handler->websocket_user_data); + g_object_unref (conn); + soup_client_context_unref (client); +} + +static void +got_body (SoupMessage *msg, SoupClientContext *client) +{ + SoupServer *server = client->server; + SoupServerHandler *handler; + + g_signal_emit (server, signals[REQUEST_READ], 0, msg, client); + + if (msg->status_code != 0) + return; + + handler = get_handler (server, msg); + if (!handler) { + soup_message_set_status (msg, SOUP_STATUS_NOT_FOUND); + return; + } + + call_handler (server, handler, client, msg, FALSE); + if (msg->status_code != 0) + return; + + if (handler->websocket_callback) { + if (soup_websocket_server_process_handshake (msg, + handler->websocket_origin, + handler->websocket_protocols)) { + g_signal_connect (msg, "wrote-informational", + G_CALLBACK (complete_websocket_upgrade), + soup_client_context_ref (client)); + } + } +} + +static void +start_request (SoupServer *server, SoupClientContext *client) +{ + SoupServerPrivate *priv = soup_server_get_instance_private (server); + SoupMessage *msg; + + soup_client_context_cleanup (client); + + /* Listen for another request on this connection */ + msg = g_object_new (SOUP_TYPE_MESSAGE, + SOUP_MESSAGE_SERVER_SIDE, TRUE, + NULL); + client->msg = msg; + + if (priv->server_header) { + soup_message_headers_append (msg->response_headers, "Server", + priv->server_header); + } + + g_signal_connect (msg, "got_headers", G_CALLBACK (got_headers), client); + g_signal_connect (msg, "got_body", G_CALLBACK (got_body), client); + + g_signal_emit (server, signals[REQUEST_STARTED], 0, + msg, client); + + soup_message_read_request (msg, client->sock, + priv->legacy_iface == NULL, + request_finished, client); +} + +static void +socket_disconnected (SoupSocket *sock, SoupClientContext *client) +{ + SoupServerPrivate *priv = soup_server_get_instance_private (client->server); + + priv->clients = g_slist_remove (priv->clients, client); + + if (client->msg) { + soup_message_set_status (client->msg, SOUP_STATUS_IO_ERROR); + soup_message_io_finished (client->msg); + } +} + +static void +soup_server_accept_socket (SoupServer *server, + SoupSocket *sock) +{ + SoupServerPrivate *priv = soup_server_get_instance_private (server); + SoupClientContext *client; + + client = soup_client_context_new (server, sock); + priv->clients = g_slist_prepend (priv->clients, client); + start_request (server, client); +} + +/** + * soup_server_accept_iostream: + * @server: a #SoupServer + * @stream: a #GIOStream + * @local_addr: (allow-none): the local #GSocketAddress associated with the @stream + * @remote_addr: (allow-none): the remote #GSocketAddress associated with the @stream + * @error: return location for a #GError + * + * Add a new client stream to the @server. + * + * Return value: %TRUE on success, %FALSE if the stream could not be + * accepted or any other error occurred (in which case @error will be + * set). + * + * Since: 2.50 + **/ +gboolean +soup_server_accept_iostream (SoupServer *server, + GIOStream *stream, + GSocketAddress *local_addr, + GSocketAddress *remote_addr, + GError **error) +{ + SoupSocket *sock; + SoupAddress *local = NULL, *remote = NULL; + + if (local_addr) + local = soup_address_new_from_gsockaddr (local_addr); + if (remote_addr) + remote = soup_address_new_from_gsockaddr (remote_addr); + + sock = g_initable_new (SOUP_TYPE_SOCKET, NULL, error, + "iostream", stream, + "local-address", local, + "remote-address", remote, + NULL); + + g_clear_object (&local); + g_clear_object (&remote); + + if (!sock) + return FALSE; + + soup_server_accept_socket (server, sock); + g_object_unref (sock); + + return TRUE; +} + +static void +new_connection (SoupSocket *listener, SoupSocket *sock, gpointer user_data) +{ + SoupServer *server = user_data; + + soup_server_accept_socket (server, sock); +} + +/** + * soup_server_run_async: + * @server: a #SoupServer + * + * Starts @server, if you are using the old API, causing it to listen + * for and process incoming connections. + * + * The server runs in @server's #GMainContext. It will not actually + * perform any processing unless the appropriate main loop is running. + * In the simple case where you did not set the server's + * %SOUP_SERVER_ASYNC_CONTEXT property, this means the server will run + * whenever the glib main loop is running. + * + * Deprecated: When using soup_server_listen(), etc, the server will + * always listen for connections, and will process them whenever the + * thread-default #GMainContext is running. + **/ +void +soup_server_run_async (SoupServer *server) +{ + SoupServerPrivate *priv; + SoupSocket *listener; + + g_return_if_fail (SOUP_IS_SERVER (server)); + priv = soup_server_get_instance_private (server); + + soup_server_ensure_listening (server); + + g_return_if_fail (priv->legacy_iface != NULL); + + if (!priv->listeners) { + if (priv->loop) { + g_main_loop_unref (priv->loop); + priv->loop = NULL; + } + return; + } + + listener = priv->listeners->data; + g_signal_connect (listener, "new_connection", + G_CALLBACK (new_connection), server); + + return; +} + +/** + * soup_server_run: + * @server: a #SoupServer + * + * Starts @server, if you are using the old API, causing it to listen + * for and process incoming connections. Unlike + * soup_server_run_async(), this creates a #GMainLoop and runs it, and + * it will not return until someone calls soup_server_quit() to stop + * the server. + * + * Deprecated: When using soup_server_listen(), etc, the server will + * always listen for connections, and will process them whenever the + * thread-default #GMainContext is running. + **/ +void +soup_server_run (SoupServer *server) +{ + SoupServerPrivate *priv; + + g_return_if_fail (SOUP_IS_SERVER (server)); + priv = soup_server_get_instance_private (server); + + if (!priv->loop) { + priv->loop = g_main_loop_new (priv->async_context, TRUE); + G_GNUC_BEGIN_IGNORE_DEPRECATIONS; + soup_server_run_async (server); + G_GNUC_END_IGNORE_DEPRECATIONS; + } + + if (priv->loop) + g_main_loop_run (priv->loop); +} + +/** + * soup_server_quit: + * @server: a #SoupServer + * + * Stops processing for @server, if you are using the old API. Call + * this to clean up after soup_server_run_async(), or to terminate a + * call to soup_server_run(). + * + * Note that messages currently in progress will continue to be + * handled, if the main loop associated with the server is resumed or + * kept running. + * + * @server is still in a working state after this call; you can start + * and stop a server as many times as you want. + * + * Deprecated: When using soup_server_listen(), etc, the server will + * always listen for connections, and will process them whenever the + * thread-default #GMainContext is running. + **/ +void +soup_server_quit (SoupServer *server) +{ + SoupServerPrivate *priv; + SoupSocket *listener; + + g_return_if_fail (SOUP_IS_SERVER (server)); + priv = soup_server_get_instance_private (server); + g_return_if_fail (priv->legacy_iface != NULL); + g_return_if_fail (priv->listeners != NULL); + + listener = priv->listeners->data; + g_signal_handlers_disconnect_by_func (listener, + G_CALLBACK (new_connection), + server); + if (priv->loop) + g_main_loop_quit (priv->loop); +} + +/** + * soup_server_disconnect: + * @server: a #SoupServer + * + * Closes and frees @server's listening sockets. If you are using the + * old #SoupServer APIs, this also includes the effect of + * soup_server_quit(). + * + * Note that if there are currently requests in progress on @server, + * that they will continue to be processed if @server's #GMainContext + * is still running. + * + * You can call soup_server_listen(), etc, after calling this function + * if you want to start listening again. + **/ +void +soup_server_disconnect (SoupServer *server) +{ + SoupServerPrivate *priv; + GSList *listeners, *clients, *iter; + SoupSocket *listener; + SoupClientContext *client; + + g_return_if_fail (SOUP_IS_SERVER (server)); + priv = soup_server_get_instance_private (server); + + if (priv->legacy_iface) { + G_GNUC_BEGIN_IGNORE_DEPRECATIONS; + soup_server_quit (server); + G_GNUC_END_IGNORE_DEPRECATIONS; + } + + clients = priv->clients; + priv->clients = NULL; + listeners = priv->listeners; + priv->listeners = NULL; + + for (iter = clients; iter; iter = iter->next) { + client = iter->data; + soup_socket_disconnect (client->sock); + } + g_slist_free (clients); + + for (iter = listeners; iter; iter = iter->next) { + listener = iter->data; + soup_socket_disconnect (listener); + g_object_unref (listener); + } + g_slist_free (listeners); +} + +/** + * SoupServerListenOptions: + * @SOUP_SERVER_LISTEN_HTTPS: Listen for https connections rather + * than plain http. + * @SOUP_SERVER_LISTEN_IPV4_ONLY: Only listen on IPv4 interfaces. + * @SOUP_SERVER_LISTEN_IPV6_ONLY: Only listen on IPv6 interfaces. + * + * Options to pass to soup_server_listen(), etc. + * + * %SOUP_SERVER_LISTEN_IPV4_ONLY and %SOUP_SERVER_LISTEN_IPV6_ONLY + * only make sense with soup_server_listen_all() and + * soup_server_listen_local(), not plain soup_server_listen() (which + * simply listens on whatever kind of socket you give it). And you + * cannot specify both of them in a single call. + * + * Since: 2.48 + */ + +static gboolean +soup_server_listen_internal (SoupServer *server, SoupSocket *listener, + SoupServerListenOptions options, + GError **error) +{ + SoupServerPrivate *priv = soup_server_get_instance_private (server); + gboolean is_listening; + + if (options & SOUP_SERVER_LISTEN_HTTPS) { + if (!priv->tls_cert) { + g_set_error_literal (error, + G_IO_ERROR, + G_IO_ERROR_INVALID_ARGUMENT, + _("Can’t create a TLS server without a TLS certificate")); + return FALSE; + } + + g_object_set (G_OBJECT (listener), + SOUP_SOCKET_SSL_CREDENTIALS, priv->tls_cert, + NULL); + } + + g_object_get (G_OBJECT (listener), + SOUP_SOCKET_IS_SERVER, &is_listening, + NULL); + if (!is_listening) { + if (!soup_socket_listen_full (listener, error)) { + SoupAddress *saddr = soup_socket_get_local_address (listener); + + g_prefix_error (error, + _("Could not listen on address %s, port %d: "), + soup_address_get_physical (saddr), + soup_address_get_port (saddr)); + return FALSE; + } + } + + g_signal_connect (listener, "new_connection", + G_CALLBACK (new_connection), server); + + /* Note: soup_server_listen_ipv4_ipv6() below relies on the + * fact that this does g_slist_prepend(). + */ + priv->listeners = g_slist_prepend (priv->listeners, g_object_ref (listener)); + return TRUE; +} + +/** + * soup_server_listen: + * @server: a #SoupServer + * @address: the address of the interface to listen on + * @options: listening options for this server + * @error: return location for a #GError + * + * This attempts to set up @server to listen for connections on + * @address. + * + * If @options includes %SOUP_SERVER_LISTEN_HTTPS, and @server has + * been configured for TLS, then @server will listen for https + * connections on this port. Otherwise it will listen for plain http. + * + * You may call this method (along with the other "listen" methods) + * any number of times on a server, if you want to listen on multiple + * ports, or set up both http and https service. + * + * After calling this method, @server will begin accepting and + * processing connections as soon as the appropriate #GMainContext is + * run. + * + * Note that #SoupServer never makes use of dual IPv4/IPv6 sockets; if + * @address is an IPv6 address, it will only accept IPv6 connections. + * You must configure IPv4 listening separately. + * + * Return value: %TRUE on success, %FALSE if @address could not be + * bound or any other error occurred (in which case @error will be + * set). + * + * Since: 2.48 + **/ +gboolean +soup_server_listen (SoupServer *server, GSocketAddress *address, + SoupServerListenOptions options, + GError **error) +{ + SoupServerPrivate *priv; + SoupSocket *listener; + SoupAddress *saddr; + gboolean success; + + g_return_val_if_fail (SOUP_IS_SERVER (server), FALSE); + g_return_val_if_fail (!(options & SOUP_SERVER_LISTEN_IPV4_ONLY) && + !(options & SOUP_SERVER_LISTEN_IPV6_ONLY), FALSE); + + priv = soup_server_get_instance_private (server); + g_return_val_if_fail (priv->disposed == FALSE, FALSE); + + saddr = soup_address_new_from_gsockaddr (address); + listener = soup_socket_new (SOUP_SOCKET_LOCAL_ADDRESS, saddr, + SOUP_SOCKET_USE_THREAD_CONTEXT, TRUE, + SOUP_SOCKET_IPV6_ONLY, TRUE, + NULL); + + success = soup_server_listen_internal (server, listener, options, error); + g_object_unref (listener); + g_object_unref (saddr); + + return success; +} + +static gboolean +soup_server_listen_ipv4_ipv6 (SoupServer *server, + GInetAddress *iaddr4, + GInetAddress *iaddr6, + guint port, + SoupServerListenOptions options, + GError **error) +{ + SoupServerPrivate *priv = soup_server_get_instance_private (server); + GSocketAddress *addr4, *addr6; + GError *my_error = NULL; + SoupSocket *v4sock; + guint v4port; + + g_return_val_if_fail (iaddr4 != NULL || iaddr6 != NULL, FALSE); + + options &= ~(SOUP_SERVER_LISTEN_IPV4_ONLY | SOUP_SERVER_LISTEN_IPV6_ONLY); + + try_again: + if (iaddr4) { + addr4 = g_inet_socket_address_new (iaddr4, port); + if (!soup_server_listen (server, addr4, options, error)) { + g_object_unref (addr4); + return FALSE; + } + g_object_unref (addr4); + + v4sock = priv->listeners->data; + v4port = soup_address_get_port (soup_socket_get_local_address (v4sock)); + } else { + v4sock = NULL; + v4port = port; + } + + if (!iaddr6) + return TRUE; + + addr6 = g_inet_socket_address_new (iaddr6, v4port); + if (soup_server_listen (server, addr6, options, &my_error)) { + g_object_unref (addr6); + return TRUE; + } + g_object_unref (addr6); + + if (v4sock && g_error_matches (my_error, G_IO_ERROR, +#if GLIB_CHECK_VERSION (2, 41, 0) + G_IO_ERROR_NOT_SUPPORTED +#else + G_IO_ERROR_FAILED +#endif + )) { + /* No IPv6 support, but IPV6_ONLY wasn't specified, so just + * ignore the failure. + */ + g_error_free (my_error); + return TRUE; + } + + if (v4sock) { + priv->listeners = g_slist_remove (priv->listeners, v4sock); + soup_socket_disconnect (v4sock); + g_object_unref (v4sock); + } + + if (port == 0 && g_error_matches (my_error, G_IO_ERROR, G_IO_ERROR_ADDRESS_IN_USE)) { + /* The randomly-assigned IPv4 port was in use on the IPv6 side... Try again */ + g_clear_error (&my_error); + goto try_again; + } + + g_propagate_error (error, my_error); + return FALSE; +} + +/** + * soup_server_listen_all: + * @server: a #SoupServer + * @port: the port to listen on, or 0 + * @options: listening options for this server + * @error: return location for a #GError + * + * This attempts to set up @server to listen for connections on all + * interfaces on the system. (That is, it listens on the addresses + * 0.0.0.0 and/or ::, depending + * on whether @options includes %SOUP_SERVER_LISTEN_IPV4_ONLY, + * %SOUP_SERVER_LISTEN_IPV6_ONLY, or neither.) If @port is specified, + * @server will listen on that port. If it is 0, @server will find an + * unused port to listen on. (In that case, you can use + * soup_server_get_uris() to find out what port it ended up choosing.) + * + * See soup_server_listen() for more details. + * + * Return value: %TRUE on success, %FALSE if @port could not be bound + * or any other error occurred (in which case @error will be set). + * + * Since: 2.48 + **/ +gboolean +soup_server_listen_all (SoupServer *server, guint port, + SoupServerListenOptions options, + GError **error) +{ + GInetAddress *iaddr4, *iaddr6; + gboolean success; + + g_return_val_if_fail (SOUP_IS_SERVER (server), FALSE); + g_return_val_if_fail (!(options & SOUP_SERVER_LISTEN_IPV4_ONLY) || + !(options & SOUP_SERVER_LISTEN_IPV6_ONLY), FALSE); + + if (options & SOUP_SERVER_LISTEN_IPV6_ONLY) + iaddr4 = NULL; + else + iaddr4 = g_inet_address_new_any (G_SOCKET_FAMILY_IPV4); + + if (options & SOUP_SERVER_LISTEN_IPV4_ONLY) + iaddr6 = NULL; + else + iaddr6 = g_inet_address_new_any (G_SOCKET_FAMILY_IPV6); + + success = soup_server_listen_ipv4_ipv6 (server, iaddr4, iaddr6, + port, options, error); + + g_clear_object (&iaddr4); + g_clear_object (&iaddr6); + + return success; +} + +/** + * soup_server_listen_local: + * @server: a #SoupServer + * @port: the port to listen on, or 0 + * @options: listening options for this server + * @error: return location for a #GError + * + * This attempts to set up @server to listen for connections on + * "localhost" (that is, 127.0.0.1 and/or + * ::1, depending on whether @options includes + * %SOUP_SERVER_LISTEN_IPV4_ONLY, %SOUP_SERVER_LISTEN_IPV6_ONLY, or + * neither). If @port is specified, @server will listen on that port. + * If it is 0, @server will find an unused port to listen on. (In that + * case, you can use soup_server_get_uris() to find out what port it + * ended up choosing.) + * + * See soup_server_listen() for more details. + * + * Return value: %TRUE on success, %FALSE if @port could not be bound + * or any other error occurred (in which case @error will be set). + * + * Since: 2.48 + **/ +gboolean +soup_server_listen_local (SoupServer *server, guint port, + SoupServerListenOptions options, + GError **error) +{ + GInetAddress *iaddr4, *iaddr6; + gboolean success; + + g_return_val_if_fail (SOUP_IS_SERVER (server), FALSE); + g_return_val_if_fail (!(options & SOUP_SERVER_LISTEN_IPV4_ONLY) || + !(options & SOUP_SERVER_LISTEN_IPV6_ONLY), FALSE); + + if (options & SOUP_SERVER_LISTEN_IPV6_ONLY) + iaddr4 = NULL; + else + iaddr4 = g_inet_address_new_loopback (G_SOCKET_FAMILY_IPV4); + + if (options & SOUP_SERVER_LISTEN_IPV4_ONLY) + iaddr6 = NULL; + else + iaddr6 = g_inet_address_new_loopback (G_SOCKET_FAMILY_IPV6); + + success = soup_server_listen_ipv4_ipv6 (server, iaddr4, iaddr6, + port, options, error); + + g_clear_object (&iaddr4); + g_clear_object (&iaddr6); + + return success; +} + +/** + * soup_server_listen_socket: + * @server: a #SoupServer + * @socket: a listening #GSocket + * @options: listening options for this server + * @error: return location for a #GError + * + * This attempts to set up @server to listen for connections on + * @socket. + * + * See soup_server_listen() for more details. + * + * Return value: %TRUE on success, %FALSE if an error occurred (in + * which case @error will be set). + * + * Since: 2.48 + **/ +gboolean +soup_server_listen_socket (SoupServer *server, GSocket *socket, + SoupServerListenOptions options, + GError **error) +{ + SoupServerPrivate *priv; + SoupSocket *listener; + gboolean success; + + g_return_val_if_fail (SOUP_IS_SERVER (server), FALSE); + g_return_val_if_fail (G_IS_SOCKET (socket), FALSE); + g_return_val_if_fail (!(options & SOUP_SERVER_LISTEN_IPV4_ONLY) && + !(options & SOUP_SERVER_LISTEN_IPV6_ONLY), FALSE); + + priv = soup_server_get_instance_private (server); + g_return_val_if_fail (priv->disposed == FALSE, FALSE); + + listener = g_initable_new (SOUP_TYPE_SOCKET, NULL, error, + SOUP_SOCKET_GSOCKET, socket, + SOUP_SOCKET_USE_THREAD_CONTEXT, TRUE, + SOUP_SOCKET_IPV6_ONLY, TRUE, + NULL); + if (!listener) + return FALSE; + + success = soup_server_listen_internal (server, listener, options, error); + g_object_unref (listener); + + return success; +} + +/** + * soup_server_listen_fd: + * @server: a #SoupServer + * @fd: the file descriptor of a listening socket + * @options: listening options for this server + * @error: return location for a #GError + * + * This attempts to set up @server to listen for connections on + * @fd. + * + * See soup_server_listen() for more details. + * + * Note that @server will close @fd when you free it or call + * soup_server_disconnect(). + * + * Return value: %TRUE on success, %FALSE if an error occurred (in + * which case @error will be set). + * + * Since: 2.48 + **/ +gboolean +soup_server_listen_fd (SoupServer *server, int fd, + SoupServerListenOptions options, + GError **error) +{ + SoupServerPrivate *priv; + SoupSocket *listener; + gboolean success; + + g_return_val_if_fail (SOUP_IS_SERVER (server), FALSE); + g_return_val_if_fail (!(options & SOUP_SERVER_LISTEN_IPV4_ONLY) && + !(options & SOUP_SERVER_LISTEN_IPV6_ONLY), FALSE); + + priv = soup_server_get_instance_private (server); + g_return_val_if_fail (priv->disposed == FALSE, FALSE); + + listener = g_initable_new (SOUP_TYPE_SOCKET, NULL, error, + SOUP_SOCKET_FD, fd, + SOUP_SOCKET_USE_THREAD_CONTEXT, TRUE, + SOUP_SOCKET_IPV6_ONLY, TRUE, + NULL); + if (!listener) + return FALSE; + + success = soup_server_listen_internal (server, listener, options, error); + g_object_unref (listener); + + return success; +} + +/** + * soup_server_get_uris: + * @server: a #SoupServer + * + * Gets a list of URIs corresponding to the interfaces @server is + * listening on. These will contain IP addresses, not hostnames, and + * will also indicate whether the given listener is http or https. + * + * Note that if you used soup_server_listen_all(), the returned URIs + * will use the addresses 0.0.0.0 and + * ::, rather than actually returning separate URIs + * for each interface on the system. + * + * Return value: (transfer full) (element-type Soup.URI): a list of + * #SoupURIs, which you must free when you are done with it. + * + * Since: 2.48 + */ +GSList * +soup_server_get_uris (SoupServer *server) +{ + SoupServerPrivate *priv; + GSList *uris, *l; + SoupSocket *listener; + SoupAddress *addr; + SoupURI *uri; + gpointer creds; + + g_return_val_if_fail (SOUP_IS_SERVER (server), NULL); + priv = soup_server_get_instance_private (server); + + for (l = priv->listeners, uris = NULL; l; l = l->next) { + listener = l->data; + addr = soup_socket_get_local_address (listener); + g_object_get (G_OBJECT (listener), SOUP_SOCKET_SSL_CREDENTIALS, &creds, NULL); + + uri = soup_uri_new (NULL); + soup_uri_set_scheme (uri, creds ? "https" : "http"); + soup_uri_set_host (uri, soup_address_get_physical (addr)); + soup_uri_set_port (uri, soup_address_get_port (addr)); + soup_uri_set_path (uri, "/"); + + uris = g_slist_prepend (uris, uri); + } + + return uris; +} + +/** + * soup_server_get_async_context: + * @server: a #SoupServer + * + * Gets @server's async_context, if you are using the old API. (With + * the new API, the server runs in the thread's thread-default + * #GMainContext, regardless of what this method returns.) + * + * This does not add a ref to the context, so you will need to ref it + * yourself if you want it to outlive its server. + * + * Return value: (nullable) (transfer none): @server's #GMainContext, + * which may be %NULL + * + * Deprecated: If you are using soup_server_listen(), etc, then + * the server listens on the thread-default #GMainContext, and this + * property is ignored. + **/ +GMainContext * +soup_server_get_async_context (SoupServer *server) +{ + SoupServerPrivate *priv; + + g_return_val_if_fail (SOUP_IS_SERVER (server), NULL); + priv = soup_server_get_instance_private (server); + + return priv->async_context; +} + +/** + * SoupClientContext: + * + * A #SoupClientContext provides additional information about the + * client making a particular request. In particular, you can use + * soup_client_context_get_auth_domain() and + * soup_client_context_get_auth_user() to determine if HTTP + * authentication was used successfully. + * + * soup_client_context_get_remote_address() and/or + * soup_client_context_get_host() can be used to get information for + * logging or debugging purposes. soup_client_context_get_gsocket() may + * also be of use in some situations (eg, tracking when multiple + * requests are made on the same connection). + **/ +G_DEFINE_BOXED_TYPE (SoupClientContext, soup_client_context, soup_client_context_ref, soup_client_context_unref) + +/** + * soup_client_context_get_socket: + * @client: a #SoupClientContext + * + * Retrieves the #SoupSocket that @client is associated with. + * + * If you are using this method to observe when multiple requests are + * made on the same persistent HTTP connection (eg, as the ntlm-test + * test program does), you will need to pay attention to socket + * destruction as well (either by using weak references, or by + * connecting to the #SoupSocket::disconnected signal), so that you do + * not get fooled when the allocator reuses the memory address of a + * previously-destroyed socket to represent a new socket. + * + * Return value: (transfer none): the #SoupSocket that @client is + * associated with. + * + * Deprecated: use soup_client_context_get_gsocket(), which returns + * a #GSocket. + **/ +SoupSocket * +soup_client_context_get_socket (SoupClientContext *client) +{ + g_return_val_if_fail (client != NULL, NULL); + + return client->sock; +} + +/** + * soup_client_context_get_gsocket: + * @client: a #SoupClientContext + * + * Retrieves the #GSocket that @client is associated with. + * + * If you are using this method to observe when multiple requests are + * made on the same persistent HTTP connection (eg, as the ntlm-test + * test program does), you will need to pay attention to socket + * destruction as well (eg, by using weak references), so that you do + * not get fooled when the allocator reuses the memory address of a + * previously-destroyed socket to represent a new socket. + * + * Return value: (nullable) (transfer none): the #GSocket that @client is + * associated with, %NULL if you used soup_server_accept_iostream(). + * + * Since: 2.48 + **/ +GSocket * +soup_client_context_get_gsocket (SoupClientContext *client) +{ + g_return_val_if_fail (client != NULL, NULL); + + return client->gsock; +} + +/** + * soup_client_context_get_address: + * @client: a #SoupClientContext + * + * Retrieves the #SoupAddress associated with the remote end + * of a connection. + * + * Return value: (nullable) (transfer none): the #SoupAddress + * associated with the remote end of a connection, it may be + * %NULL if you used soup_server_accept_iostream(). + * + * Deprecated: Use soup_client_context_get_remote_address(), which returns + * a #GSocketAddress. + **/ +SoupAddress * +soup_client_context_get_address (SoupClientContext *client) +{ + g_return_val_if_fail (client != NULL, NULL); + + return soup_socket_get_remote_address (client->sock); +} + +/** + * soup_client_context_get_remote_address: + * @client: a #SoupClientContext + * + * Retrieves the #GSocketAddress associated with the remote end + * of a connection. + * + * Return value: (nullable) (transfer none): the #GSocketAddress + * associated with the remote end of a connection, it may be + * %NULL if you used soup_server_accept_iostream(). + * + * Since: 2.48 + **/ +GSocketAddress * +soup_client_context_get_remote_address (SoupClientContext *client) +{ + g_return_val_if_fail (client != NULL, NULL); + + if (client->remote_addr) + return client->remote_addr; + + client->remote_addr = client->gsock ? + g_socket_get_remote_address (client->gsock, NULL) : + soup_address_get_gsockaddr (soup_socket_get_remote_address (client->sock)); + + return client->remote_addr; +} + +/** + * soup_client_context_get_local_address: + * @client: a #SoupClientContext + * + * Retrieves the #GSocketAddress associated with the local end + * of a connection. + * + * Return value: (nullable) (transfer none): the #GSocketAddress + * associated with the local end of a connection, it may be + * %NULL if you used soup_server_accept_iostream(). + * + * Since: 2.48 + **/ +GSocketAddress * +soup_client_context_get_local_address (SoupClientContext *client) +{ + g_return_val_if_fail (client != NULL, NULL); + + if (client->local_addr) + return client->local_addr; + + client->local_addr = client->gsock ? + g_socket_get_local_address (client->gsock, NULL) : + soup_address_get_gsockaddr (soup_socket_get_local_address (client->sock)); + + return client->local_addr; +} + +/** + * soup_client_context_get_host: + * @client: a #SoupClientContext + * + * Retrieves the IP address associated with the remote end of a + * connection. + * + * Return value: (nullable): the IP address associated with the remote + * end of a connection, it may be %NULL if you used + * soup_server_accept_iostream(). + **/ +const char * +soup_client_context_get_host (SoupClientContext *client) +{ + g_return_val_if_fail (client != NULL, NULL); + + if (client->remote_ip) + return client->remote_ip; + + if (client->gsock) { + GSocketAddress *addr = soup_client_context_get_remote_address (client); + GInetAddress *iaddr; + + if (!addr || !G_IS_INET_SOCKET_ADDRESS (addr)) + return NULL; + iaddr = g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (addr)); + client->remote_ip = g_inet_address_to_string (iaddr); + } else { + SoupAddress *addr; + + G_GNUC_BEGIN_IGNORE_DEPRECATIONS; + addr = soup_client_context_get_address (client); + G_GNUC_END_IGNORE_DEPRECATIONS; + client->remote_ip = g_strdup (soup_address_get_physical (addr)); + } + + return client->remote_ip; +} + +/** + * soup_client_context_get_auth_domain: + * @client: a #SoupClientContext + * + * Checks whether the request associated with @client has been + * authenticated, and if so returns the #SoupAuthDomain that + * authenticated it. + * + * Return value: (transfer none) (nullable): a #SoupAuthDomain, or + * %NULL if the request was not authenticated. + **/ +SoupAuthDomain * +soup_client_context_get_auth_domain (SoupClientContext *client) +{ + g_return_val_if_fail (client != NULL, NULL); + + return client->auth_domain; +} + +/** + * soup_client_context_get_auth_user: + * @client: a #SoupClientContext + * + * Checks whether the request associated with @client has been + * authenticated, and if so returns the username that the client + * authenticated as. + * + * Return value: (nullable): the authenticated-as user, or %NULL if + * the request was not authenticated. + **/ +const char * +soup_client_context_get_auth_user (SoupClientContext *client) +{ + g_return_val_if_fail (client != NULL, NULL); + + return client->auth_user; +} + +/** + * soup_client_context_steal_connection: + * @client: a #SoupClientContext + * + * "Steals" the HTTP connection associated with @client from its + * #SoupServer. This happens immediately, regardless of the current + * state of the connection; if the response to the current + * #SoupMessage has not yet finished being sent, then it will be + * discarded; you can steal the connection from a + * #SoupMessage:wrote-informational or #SoupMessage:wrote-body signal + * handler if you need to wait for part or all of the response to be + * sent. + * + * Note that when calling this function from C, @client will most + * likely be freed as a side effect. + * + * Return value: (transfer full): the #GIOStream formerly associated + * with @client (or %NULL if @client was no longer associated with a + * connection). No guarantees are made about what kind of #GIOStream + * is returned. + * + * Since: 2.50 + **/ +GIOStream * +soup_client_context_steal_connection (SoupClientContext *client) +{ + GIOStream *stream; + + g_return_val_if_fail (client != NULL, NULL); + + soup_client_context_ref (client); + + stream = soup_message_io_steal (client->msg); + if (stream) { + g_object_set_data_full (G_OBJECT (stream), "GSocket", + soup_socket_steal_gsocket (client->sock), + g_object_unref); + } + + socket_disconnected (client->sock, client); + soup_client_context_unref (client); + + return stream; +} + + +/** + * SoupServerCallback: + * @server: the #SoupServer + * @msg: the message being processed + * @path: the path component of @msg's Request-URI + * @query: (element-type utf8 utf8) (allow-none): the parsed query + * component of @msg's Request-URI + * @client: additional contextual information about the client + * @user_data: the data passed to soup_server_add_handler() or + * soup_server_add_early_handler(). + * + * A callback used to handle requests to a #SoupServer. + * + * @path and @query contain the likewise-named components of the + * Request-URI, subject to certain assumptions. By default, + * #SoupServer decodes all percent-encoding in the URI path, such that + * "/foo%2Fbar" is treated the same as "/foo/bar". If your + * server is serving resources in some non-POSIX-filesystem namespace, + * you may want to distinguish those as two distinct paths. In that + * case, you can set the %SOUP_SERVER_RAW_PATHS property when creating + * the #SoupServer, and it will leave those characters undecoded. (You + * may want to call soup_uri_normalize() to decode any percent-encoded + * characters that you aren't handling specially.) + * + * @query contains the query component of the Request-URI parsed + * according to the rules for HTML form handling. Although this is the + * only commonly-used query string format in HTTP, there is nothing + * that actually requires that HTTP URIs use that format; if your + * server needs to use some other format, you can just ignore @query, + * and call soup_message_get_uri() and parse the URI's query field + * yourself. + * + * See soup_server_add_handler() and soup_server_add_early_handler() + * for details of what handlers can/should do. + **/ + +static SoupServerHandler * +get_or_create_handler (SoupServer *server, const char *exact_path) +{ + SoupServerPrivate *priv = soup_server_get_instance_private (server); + SoupServerHandler *handler; + + exact_path = NORMALIZED_PATH (exact_path); + + handler = soup_path_map_lookup (priv->handlers, exact_path); + if (handler && !strcmp (handler->path, exact_path)) + return handler; + + handler = g_slice_new0 (SoupServerHandler); + handler->path = g_strdup (exact_path); + soup_path_map_add (priv->handlers, exact_path, handler); + + return handler; +} + +/** + * soup_server_add_handler: + * @server: a #SoupServer + * @path: (allow-none): the toplevel path for the handler + * @callback: callback to invoke for requests under @path + * @user_data: data for @callback + * @destroy: destroy notifier to free @user_data + * + * Adds a handler to @server for requests under @path. If @path is + * %NULL or "/", then this will be the default handler for all + * requests that don't have a more specific handler. (Note though that + * if you want to handle requests to the special "*" URI, you must + * explicitly register a handler for "*"; the default handler will not + * be used for that case.) + * + * For requests under @path (that have not already been assigned a + * status code by a #SoupAuthDomain, an early #SoupServerHandler, or a + * signal handler), @callback will be invoked after receiving the + * request body; the message's #SoupMessage:method, + * #SoupMessage:request-headers, and #SoupMessage:request-body fields + * will be filled in. + * + * After determining what to do with the request, the callback must at + * a minimum call soup_message_set_status() (or + * soup_message_set_status_full()) on the message to set the response + * status code. Additionally, it may set response headers and/or fill + * in the response body. + * + * If the callback cannot fully fill in the response before returning + * (eg, if it needs to wait for information from a database, or + * another network server), it should call soup_server_pause_message() + * to tell @server to not send the response right away. When the + * response is ready, call soup_server_unpause_message() to cause it + * to be sent. + * + * To send the response body a bit at a time using "chunked" encoding, + * first call soup_message_headers_set_encoding() to set + * %SOUP_ENCODING_CHUNKED on the #SoupMessage:response-headers. Then call + * soup_message_body_append() (or soup_message_body_append_buffer()) + * to append each chunk as it becomes ready, and + * soup_server_unpause_message() to make sure it's running. (The + * server will automatically pause the message if it is using chunked + * encoding but no more chunks are available.) When you are done, call + * soup_message_body_complete() to indicate that no more chunks are + * coming. + **/ +void +soup_server_add_handler (SoupServer *server, + const char *path, + SoupServerCallback callback, + gpointer user_data, + GDestroyNotify destroy) +{ + SoupServerHandler *handler; + + g_return_if_fail (SOUP_IS_SERVER (server)); + g_return_if_fail (callback != NULL); + + handler = get_or_create_handler (server, path); + if (handler->destroy) + handler->destroy (handler->user_data); + + handler->callback = callback; + handler->destroy = destroy; + handler->user_data = user_data; +} + +/** + * soup_server_add_early_handler: + * @server: a #SoupServer + * @path: (allow-none): the toplevel path for the handler + * @callback: callback to invoke for requests under @path + * @user_data: data for @callback + * @destroy: destroy notifier to free @user_data + * + * Adds an "early" handler to @server for requests under @path. Note + * that "normal" and "early" handlers are matched up together, so if + * you add a normal handler for "/foo" and an early handler for + * "/foo/bar", then a request to "/foo/bar" (or any path below it) + * will run only the early handler. (But if you add both handlers at + * the same path, then both will get run.) + * + * For requests under @path (that have not already been assigned a + * status code by a #SoupAuthDomain or a signal handler), @callback + * will be invoked after receiving the request headers, but before + * receiving the request body; the message's #SoupMessage:method and + * #SoupMessage:request-headers fields will be filled in. + * + * Early handlers are generally used for processing requests with + * request bodies in a streaming fashion. If you determine that the + * request will contain a message body, normally you would call + * soup_message_body_set_accumulate() on the message's + * #SoupMessage:request-body to turn off request-body accumulation, + * and connect to the message's #SoupMessage::got-chunk signal to + * process each chunk as it comes in. + * + * To complete the message processing after the full message body has + * been read, you can either also connect to #SoupMessage::got-body, + * or else you can register a non-early handler for @path as well. As + * long as you have not set the #SoupMessage:status-code by the time + * #SoupMessage::got-body is emitted, the non-early handler will be + * run as well. + * + * Since: 2.50 + **/ +void +soup_server_add_early_handler (SoupServer *server, + const char *path, + SoupServerCallback callback, + gpointer user_data, + GDestroyNotify destroy) +{ + SoupServerHandler *handler; + + g_return_if_fail (SOUP_IS_SERVER (server)); + g_return_if_fail (callback != NULL); + + handler = get_or_create_handler (server, path); + if (handler->early_destroy) + handler->early_destroy (handler->early_user_data); + + handler->early_callback = callback; + handler->early_destroy = destroy; + handler->early_user_data = user_data; +} + +/** + * SoupServerWebsocketCallback: + * @server: the #SoupServer + * @path: the path component of @msg's Request-URI + * @connection: the newly created WebSocket connection + * @client: additional contextual information about the client + * @user_data: the data passed to @soup_server_add_handler + * + * A callback used to handle WebSocket requests to a #SoupServer. The + * callback will be invoked after sending the handshake response back + * to the client (and is only invoked if the handshake was + * successful). + * + * @path contains the path of the Request-URI, subject to the same + * rules as #SoupServerCallback (qv). + **/ + +/** + * soup_server_add_websocket_handler: + * @server: a #SoupServer + * @path: (allow-none): the toplevel path for the handler + * @origin: (allow-none): the origin of the connection + * @protocols: (allow-none) (array zero-terminated=1): the protocols + * supported by this handler + * @callback: callback to invoke for successful WebSocket requests under @path + * @user_data: data for @callback + * @destroy: destroy notifier to free @user_data + * + * Adds a WebSocket handler to @server for requests under @path. (If + * @path is %NULL or "/", then this will be the default handler for + * all requests that don't have a more specific handler.) + * + * When a path has a WebSocket handler registered, @server will check + * incoming requests for WebSocket handshakes after all other handlers + * have run (unless some earlier handler has already set a status code + * on the message), and update the request's status, response headers, + * and response body accordingly. + * + * If @origin is non-%NULL, then only requests containing a matching + * "Origin" header will be accepted. If @protocols is non-%NULL, then + * only requests containing a compatible "Sec-WebSocket-Protocols" + * header will be accepted. More complicated requirements can be + * handled by adding a normal handler to @path, and having it perform + * whatever checks are needed (possibly calling + * soup_server_check_websocket_handshake() one or more times), and + * setting a failure status code if the handshake should be rejected. + **/ +void +soup_server_add_websocket_handler (SoupServer *server, + const char *path, + const char *origin, + char **protocols, + SoupServerWebsocketCallback callback, + gpointer user_data, + GDestroyNotify destroy) +{ + SoupServerHandler *handler; + + g_return_if_fail (SOUP_IS_SERVER (server)); + g_return_if_fail (callback != NULL); + + handler = get_or_create_handler (server, path); + if (handler->websocket_destroy) + handler->websocket_destroy (handler->websocket_user_data); + if (handler->websocket_origin) + g_free (handler->websocket_origin); + if (handler->websocket_protocols) + g_strfreev (handler->websocket_protocols); + + handler->websocket_callback = callback; + handler->websocket_destroy = destroy; + handler->websocket_user_data = user_data; + handler->websocket_origin = g_strdup (origin); + handler->websocket_protocols = g_strdupv (protocols); +} + +/** + * soup_server_remove_handler: + * @server: a #SoupServer + * @path: the toplevel path for the handler + * + * Removes all handlers (early and normal) registered at @path. + **/ +void +soup_server_remove_handler (SoupServer *server, const char *path) +{ + SoupServerPrivate *priv; + + g_return_if_fail (SOUP_IS_SERVER (server)); + priv = soup_server_get_instance_private (server); + + soup_path_map_remove (priv->handlers, NORMALIZED_PATH (path)); +} + +/** + * soup_server_add_auth_domain: + * @server: a #SoupServer + * @auth_domain: a #SoupAuthDomain + * + * Adds an authentication domain to @server. Each auth domain will + * have the chance to require authentication for each request that + * comes in; normally auth domains will require authentication for + * requests on certain paths that they have been set up to watch, or + * that meet other criteria set by the caller. If an auth domain + * determines that a request requires authentication (and the request + * doesn't contain authentication), @server will automatically reject + * the request with an appropriate status (401 Unauthorized or 407 + * Proxy Authentication Required). If the request used the + * "100-continue" Expectation, @server will reject it before the + * request body is sent. + **/ +void +soup_server_add_auth_domain (SoupServer *server, SoupAuthDomain *auth_domain) +{ + SoupServerPrivate *priv; + + g_return_if_fail (SOUP_IS_SERVER (server)); + priv = soup_server_get_instance_private (server); + + priv->auth_domains = g_slist_append (priv->auth_domains, auth_domain); + g_object_ref (auth_domain); +} + +/** + * soup_server_remove_auth_domain: + * @server: a #SoupServer + * @auth_domain: a #SoupAuthDomain + * + * Removes @auth_domain from @server. + **/ +void +soup_server_remove_auth_domain (SoupServer *server, SoupAuthDomain *auth_domain) +{ + SoupServerPrivate *priv; + + g_return_if_fail (SOUP_IS_SERVER (server)); + priv = soup_server_get_instance_private (server); + + priv->auth_domains = g_slist_remove (priv->auth_domains, auth_domain); + g_object_unref (auth_domain); +} + +/** + * soup_server_pause_message: + * @server: a #SoupServer + * @msg: a #SoupMessage associated with @server. + * + * Pauses I/O on @msg. This can be used when you need to return from + * the server handler without having the full response ready yet. Use + * soup_server_unpause_message() to resume I/O. + * + * This must only be called on #SoupMessages which were created by the + * #SoupServer and are currently doing I/O, such as those passed into a + * #SoupServerCallback or emitted in a #SoupServer::request-read signal. + **/ +void +soup_server_pause_message (SoupServer *server, + SoupMessage *msg) +{ + g_return_if_fail (SOUP_IS_SERVER (server)); + g_return_if_fail (SOUP_IS_MESSAGE (msg)); + + soup_message_io_pause (msg); +} + +/** + * soup_server_unpause_message: + * @server: a #SoupServer + * @msg: a #SoupMessage associated with @server. + * + * Resumes I/O on @msg. Use this to resume after calling + * soup_server_pause_message(), or after adding a new chunk to a + * chunked response. + * + * I/O won't actually resume until you return to the main loop. + * + * This must only be called on #SoupMessages which were created by the + * #SoupServer and are currently doing I/O, such as those passed into a + * #SoupServerCallback or emitted in a #SoupServer::request-read signal. + **/ +void +soup_server_unpause_message (SoupServer *server, + SoupMessage *msg) +{ + g_return_if_fail (SOUP_IS_SERVER (server)); + g_return_if_fail (SOUP_IS_MESSAGE (msg)); + + soup_message_io_unpause (msg); +} diff --git a/libsoup/soup-server.h b/libsoup/soup-server.h new file mode 100644 index 0000000..6329487 --- /dev/null +++ b/libsoup/soup-server.h @@ -0,0 +1,231 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2000-2003, Ximian, Inc. + */ + +#ifndef SOUP_SERVER_H +#define SOUP_SERVER_H 1 + +#include +#include +#include + +G_BEGIN_DECLS + +#define SOUP_TYPE_SERVER (soup_server_get_type ()) +#define SOUP_SERVER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SOUP_TYPE_SERVER, SoupServer)) +#define SOUP_SERVER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_SERVER, SoupServerClass)) +#define SOUP_IS_SERVER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SOUP_TYPE_SERVER)) +#define SOUP_IS_SERVER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), SOUP_TYPE_SERVER)) +#define SOUP_SERVER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_SERVER, SoupServerClass)) + +typedef struct SoupClientContext SoupClientContext; +SOUP_AVAILABLE_IN_2_4 +GType soup_client_context_get_type (void); +#define SOUP_TYPE_CLIENT_CONTEXT (soup_client_context_get_type ()) + +typedef enum { + SOUP_SERVER_LISTEN_HTTPS = (1 << 0), + SOUP_SERVER_LISTEN_IPV4_ONLY = (1 << 1), + SOUP_SERVER_LISTEN_IPV6_ONLY = (1 << 2) +} SoupServerListenOptions; + +struct _SoupServer { + GObject parent; + +}; + +typedef struct { + GObjectClass parent_class; + + /* signals */ + void (*request_started) (SoupServer *server, SoupMessage *msg, + SoupClientContext *client); + void (*request_read) (SoupServer *server, SoupMessage *msg, + SoupClientContext *client); + void (*request_finished) (SoupServer *server, SoupMessage *msg, + SoupClientContext *client); + void (*request_aborted) (SoupServer *server, SoupMessage *msg, + SoupClientContext *client); + + /* Padding for future expansion */ + void (*_libsoup_reserved1) (void); + void (*_libsoup_reserved2) (void); + void (*_libsoup_reserved3) (void); + void (*_libsoup_reserved4) (void); +} SoupServerClass; + +SOUP_AVAILABLE_IN_2_4 +GType soup_server_get_type (void); + +#define SOUP_SERVER_TLS_CERTIFICATE "tls-certificate" +#define SOUP_SERVER_RAW_PATHS "raw-paths" +#define SOUP_SERVER_SERVER_HEADER "server-header" +#define SOUP_SERVER_HTTP_ALIASES "http-aliases" +#define SOUP_SERVER_HTTPS_ALIASES "https-aliases" + +SOUP_AVAILABLE_IN_2_4 +SoupServer *soup_server_new (const char *optname1, + ...) G_GNUC_NULL_TERMINATED; + +SOUP_AVAILABLE_IN_2_48 +gboolean soup_server_set_ssl_cert_file (SoupServer *server, + const char *ssl_cert_file, + const char *ssl_key_file, + GError **error); +SOUP_AVAILABLE_IN_2_4 +gboolean soup_server_is_https (SoupServer *server); + +SOUP_AVAILABLE_IN_2_48 +gboolean soup_server_listen (SoupServer *server, + GSocketAddress *address, + SoupServerListenOptions options, + GError **error); +SOUP_AVAILABLE_IN_2_48 +gboolean soup_server_listen_all (SoupServer *server, + guint port, + SoupServerListenOptions options, + GError **error); +SOUP_AVAILABLE_IN_2_48 +gboolean soup_server_listen_local (SoupServer *server, + guint port, + SoupServerListenOptions options, + GError **error); +SOUP_AVAILABLE_IN_2_48 +gboolean soup_server_listen_socket (SoupServer *server, + GSocket *socket, + SoupServerListenOptions options, + GError **error); +SOUP_AVAILABLE_IN_2_48 +gboolean soup_server_listen_fd (SoupServer *server, + int fd, + SoupServerListenOptions options, + GError **error); +SOUP_AVAILABLE_IN_2_48 +GSList *soup_server_get_uris (SoupServer *server); +SOUP_AVAILABLE_IN_2_48 +GSList *soup_server_get_listeners (SoupServer *server); + +SOUP_AVAILABLE_IN_2_4 +void soup_server_disconnect (SoupServer *server); + +SOUP_AVAILABLE_IN_2_50 +gboolean soup_server_accept_iostream (SoupServer *server, + GIOStream *stream, + GSocketAddress *local_addr, + GSocketAddress *remote_addr, + GError **error); + +/* Handlers and auth */ + +typedef void (*SoupServerCallback) (SoupServer *server, + SoupMessage *msg, + const char *path, + GHashTable *query, + SoupClientContext *client, + gpointer user_data); + +SOUP_AVAILABLE_IN_2_4 +void soup_server_add_handler (SoupServer *server, + const char *path, + SoupServerCallback callback, + gpointer user_data, + GDestroyNotify destroy); +SOUP_AVAILABLE_IN_2_50 +void soup_server_add_early_handler (SoupServer *server, + const char *path, + SoupServerCallback callback, + gpointer user_data, + GDestroyNotify destroy); + +typedef void (*SoupServerWebsocketCallback) (SoupServer *server, + SoupWebsocketConnection *connection, + const char *path, + SoupClientContext *client, + gpointer user_data); +SOUP_AVAILABLE_IN_2_50 +void soup_server_add_websocket_handler (SoupServer *server, + const char *path, + const char *origin, + char **protocols, + SoupServerWebsocketCallback callback, + gpointer user_data, + GDestroyNotify destroy); + +SOUP_AVAILABLE_IN_2_4 +void soup_server_remove_handler (SoupServer *server, + const char *path); + +SOUP_AVAILABLE_IN_2_4 +void soup_server_add_auth_domain (SoupServer *server, + SoupAuthDomain *auth_domain); +SOUP_AVAILABLE_IN_2_4 +void soup_server_remove_auth_domain (SoupServer *server, + SoupAuthDomain *auth_domain); + +/* I/O */ +SOUP_AVAILABLE_IN_2_4 +void soup_server_pause_message (SoupServer *server, + SoupMessage *msg); +SOUP_AVAILABLE_IN_2_4 +void soup_server_unpause_message (SoupServer *server, + SoupMessage *msg); + +/* Client context */ + +SOUP_AVAILABLE_IN_2_48 +GSocket *soup_client_context_get_gsocket (SoupClientContext *client); +SOUP_AVAILABLE_IN_2_48 +GSocketAddress *soup_client_context_get_local_address (SoupClientContext *client); +SOUP_AVAILABLE_IN_2_48 +GSocketAddress *soup_client_context_get_remote_address (SoupClientContext *client); +SOUP_AVAILABLE_IN_2_4 +const char *soup_client_context_get_host (SoupClientContext *client); +SOUP_AVAILABLE_IN_2_4 +SoupAuthDomain *soup_client_context_get_auth_domain (SoupClientContext *client); +SOUP_AVAILABLE_IN_2_4 +const char *soup_client_context_get_auth_user (SoupClientContext *client); + +SOUP_AVAILABLE_IN_2_50 +GIOStream *soup_client_context_steal_connection (SoupClientContext *client); + +/* Legacy API */ + +#define SOUP_SERVER_PORT "port" +#define SOUP_SERVER_INTERFACE "interface" +#define SOUP_SERVER_ASYNC_CONTEXT "async-context" +#define SOUP_SERVER_SSL_CERT_FILE "ssl-cert-file" +#define SOUP_SERVER_SSL_KEY_FILE "ssl-key-file" + +SOUP_AVAILABLE_IN_2_4 +SOUP_DEPRECATED_IN_2_48 +guint soup_server_get_port (SoupServer *server); + +SOUP_AVAILABLE_IN_2_4 +SOUP_DEPRECATED_IN_2_48 +SoupSocket *soup_server_get_listener (SoupServer *server); + +SOUP_AVAILABLE_IN_2_4 +SOUP_DEPRECATED_IN_2_48 +GMainContext *soup_server_get_async_context (SoupServer *server); + +SOUP_AVAILABLE_IN_2_4 +SOUP_DEPRECATED_IN_2_48 +void soup_server_run (SoupServer *server); +SOUP_AVAILABLE_IN_2_4 +SOUP_DEPRECATED_IN_2_48 +void soup_server_run_async (SoupServer *server); +SOUP_AVAILABLE_IN_2_4 +SOUP_DEPRECATED_IN_2_48 +void soup_server_quit (SoupServer *server); + +SOUP_AVAILABLE_IN_2_4 +SOUP_DEPRECATED_IN_2_48 +SoupAddress *soup_client_context_get_address (SoupClientContext *client); +SOUP_AVAILABLE_IN_2_4 +SOUP_DEPRECATED_IN_2_48 +SoupSocket *soup_client_context_get_socket (SoupClientContext *client); + +G_END_DECLS + +#endif /* SOUP_SERVER_H */ diff --git a/libsoup/soup-session-async.c b/libsoup/soup-session-async.c new file mode 100644 index 0000000..c187989 --- /dev/null +++ b/libsoup/soup-session-async.c @@ -0,0 +1,146 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-session-async.c + * + * Copyright (C) 2000-2003, Ximian, Inc. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "soup-session-async.h" +#include "soup.h" +#include "soup-session-private.h" +#include "soup-message-private.h" +#include "soup-message-queue.h" +#include "soup-misc-private.h" + +/** + * SECTION:soup-session-async + * @short_description: SoupSession for asynchronous (main-loop-based) I/O + * (deprecated). + * + * #SoupSessionAsync is an implementation of #SoupSession that uses + * non-blocking I/O via the glib main loop for all I/O. + * + * Deprecated: 2.42: Use the #SoupSession class (which uses both asynchronous + * and synchronous I/O, depending on the API used). See the + * porting guide. + **/ + +G_GNUC_BEGIN_IGNORE_DEPRECATIONS; + +G_DEFINE_TYPE (SoupSessionAsync, soup_session_async, SOUP_TYPE_SESSION) + +static void +soup_session_async_init (SoupSessionAsync *sa) +{ +} + +/** + * soup_session_async_new: + * + * Creates an asynchronous #SoupSession with the default options. + * + * Return value: the new session. + * + * Deprecated: #SoupSessionAsync is deprecated; use a plain + * #SoupSession, created with soup_session_new(). See the porting guide. + **/ +SoupSession * +soup_session_async_new (void) +{ + return g_object_new (SOUP_TYPE_SESSION_ASYNC, NULL); +} + +/** + * soup_session_async_new_with_options: + * @optname1: name of first property to set + * @...: value of @optname1, followed by additional property/value pairs + * + * Creates an asynchronous #SoupSession with the specified options. + * + * Return value: the new session. + * + * Deprecated: #SoupSessionAsync is deprecated; use a plain + * #SoupSession, created with soup_session_new_with_options(). See the + * porting guide. + **/ +SoupSession * +soup_session_async_new_with_options (const char *optname1, ...) +{ + SoupSession *session; + va_list ap; + + va_start (ap, optname1); + session = (SoupSession *)g_object_new_valist (SOUP_TYPE_SESSION_ASYNC, + optname1, ap); + va_end (ap); + + return session; +} + +static guint +soup_session_async_send_message (SoupSession *session, SoupMessage *msg) +{ + SoupMessageQueueItem *item; + GMainContext *async_context = + soup_session_get_async_context (session); + + item = soup_session_append_queue_item (session, msg, TRUE, FALSE, + NULL, NULL); + soup_session_kick_queue (session); + + while (item->state != SOUP_MESSAGE_FINISHED) + g_main_context_iteration (async_context, TRUE); + + soup_message_queue_item_unref (item); + + return msg->status_code; +} + +static void +soup_session_async_cancel_message (SoupSession *session, SoupMessage *msg, + guint status_code) +{ + SoupMessageQueue *queue; + SoupMessageQueueItem *item; + + SOUP_SESSION_CLASS (soup_session_async_parent_class)-> + cancel_message (session, msg, status_code); + + queue = soup_session_get_queue (session); + item = soup_message_queue_lookup (queue, msg); + if (!item) + return; + + /* Force it to finish immediately, so that + * soup_session_abort (session); g_object_unref (session); + * will work. (The soup_session_cancel_message() docs + * point out that the callback will be invoked from + * within the cancel call.) + */ + if (soup_message_io_in_progress (msg)) + soup_message_io_finished (msg); + else if (item->state != SOUP_MESSAGE_FINISHED) + item->state = SOUP_MESSAGE_FINISHING; + + if (item->state != SOUP_MESSAGE_FINISHED) + soup_session_process_queue_item (session, item, NULL, FALSE); + + soup_message_queue_item_unref (item); +} + +static void +soup_session_async_class_init (SoupSessionAsyncClass *soup_session_async_class) +{ + SoupSessionClass *session_class = SOUP_SESSION_CLASS (soup_session_async_class); + + /* virtual method override */ + session_class->send_message = soup_session_async_send_message; + session_class->cancel_message = soup_session_async_cancel_message; +} + +G_GNUC_END_IGNORE_DEPRECATIONS; diff --git a/libsoup/soup-session-async.h b/libsoup/soup-session-async.h new file mode 100644 index 0000000..d5a450e --- /dev/null +++ b/libsoup/soup-session-async.h @@ -0,0 +1,60 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2000-2003, Ximian, Inc. + */ + +#ifndef SOUP_SESSION_ASYNC_H +#define SOUP_SESSION_ASYNC_H 1 + +#include +#include + +G_BEGIN_DECLS + +#define SOUP_TYPE_SESSION_ASYNC (soup_session_async_get_type ()) +#define SOUP_SESSION_ASYNC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SOUP_TYPE_SESSION_ASYNC, SoupSessionAsync)) +#define SOUP_SESSION_ASYNC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_SESSION_ASYNC, SoupSessionAsyncClass)) +#define SOUP_IS_SESSION_ASYNC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), _soup_session_async_get_type_undeprecated ())) +#define SOUP_IS_SESSION_ASYNC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), SOUP_TYPE_SESSION_ASYNC)) +#define SOUP_SESSION_ASYNC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_SESSION_ASYNC, SoupSessionAsyncClass)) + +struct _SoupSessionAsync { + SoupSession parent; + +}; + +typedef struct { + SoupSessionClass parent_class; + + /* Padding for future expansion */ + void (*_libsoup_reserved1) (void); + void (*_libsoup_reserved2) (void); + void (*_libsoup_reserved3) (void); + void (*_libsoup_reserved4) (void); +} SoupSessionAsyncClass; + +SOUP_AVAILABLE_IN_2_4 +SOUP_DEPRECATED_IN_2_54 +GType soup_session_async_get_type (void); + +static inline GType +_soup_session_async_get_type_undeprecated (void) +{ + G_GNUC_BEGIN_IGNORE_DEPRECATIONS; + return soup_session_async_get_type (); + G_GNUC_END_IGNORE_DEPRECATIONS; +} + +#ifndef SOUP_DISABLE_DEPRECATED +SOUP_AVAILABLE_IN_2_4 +SOUP_DEPRECATED_IN_2_54_FOR(soup_session_new) +SoupSession *soup_session_async_new (void); +SOUP_AVAILABLE_IN_2_4 +SOUP_DEPRECATED_IN_2_54_FOR(soup_session_new) +SoupSession *soup_session_async_new_with_options (const char *optname1, + ...) G_GNUC_NULL_TERMINATED; +#endif + +G_END_DECLS + +#endif /* SOUP_SESSION_ASYNC_H */ diff --git a/libsoup/soup-session-feature.c b/libsoup/soup-session-feature.c new file mode 100644 index 0000000..d8bb10a --- /dev/null +++ b/libsoup/soup-session-feature.c @@ -0,0 +1,230 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-session-feature.c: Miscellaneous session feature-provider interface + * + * Copyright (C) 2008 Red Hat, Inc. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "soup-session-feature.h" +#include "soup.h" +#include "soup-message-private.h" + +/** + * SECTION:soup-session-feature + * @short_description: Interface for miscellaneous session features + * + * #SoupSessionFeature is the interface used by classes that extend + * the functionality of a #SoupSession. Some features like HTTP + * authentication handling are implemented internally via + * #SoupSessionFeatures. Other features can be added to the session + * by the application. (Eg, #SoupLogger, #SoupCookieJar.) + * + * See soup_session_add_feature(), etc, to add a feature to a session. + **/ + +/** + * SoupSessionFeature: + * + * An object that implement some sort of optional feature for + * #SoupSession. + * + * Since: 2.24 + **/ + +/** + * SoupSessionFeatureInterface: + * @parent: The parent interface. + * @attach: Perform setup when a feature is added to a session + * @detach: Perform cleanup when a feature is removed from a session + * @request_queued: Proxies the session's #SoupSession::request_queued signal + * @request_started: Proxies the session's #SoupSession::request_started signal. Deprecated 2.50. Use #SoupMessage::starting instead. + * @request_unqueued: Proxies the session's #SoupSession::request_unqueued signal + * @add_feature: adds a sub-feature to the main feature + * @remove_feature: removes a sub-feature from the main feature + * @has_feature: tests if the feature includes a sub-feature + * + * The interface implemented by #SoupSessionFeatures. + * + * Since: 2.24 + **/ + +G_DEFINE_INTERFACE (SoupSessionFeature, soup_session_feature, G_TYPE_OBJECT) + +static void +weak_notify_unref (gpointer feature, GObject *ex_object) +{ + g_object_unref (feature); +} + +static void +request_queued (SoupSession *session, SoupMessage *msg, gpointer feature) +{ + if (soup_message_disables_feature (msg, feature)) + return; + + SOUP_SESSION_FEATURE_GET_CLASS (feature)-> + request_queued (feature, session, msg); +} + +static void +request_started (SoupSession *session, SoupMessage *msg, + SoupSocket *socket, gpointer feature) +{ + if (soup_message_disables_feature (msg, feature)) + return; + + SOUP_SESSION_FEATURE_GET_CLASS (feature)-> + request_started (feature, session, msg, socket); +} + +static void +request_unqueued (SoupSession *session, SoupMessage *msg, gpointer feature) +{ + if (soup_message_disables_feature (msg, feature)) + return; + + SOUP_SESSION_FEATURE_GET_CLASS (feature)-> + request_unqueued (feature, session, msg); +} + +static void +soup_session_feature_real_attach (SoupSessionFeature *feature, SoupSession *session) +{ + g_object_weak_ref (G_OBJECT (session), + weak_notify_unref, g_object_ref (feature)); + + if (SOUP_SESSION_FEATURE_GET_CLASS (feature)->request_queued) { + g_signal_connect (session, "request_queued", + G_CALLBACK (request_queued), feature); + } + + if (SOUP_SESSION_FEATURE_GET_CLASS (feature)->request_started) { + g_signal_connect (session, "request_started", + G_CALLBACK (request_started), feature); + } + + if (SOUP_SESSION_FEATURE_GET_CLASS (feature)->request_unqueued) { + g_signal_connect (session, "request_unqueued", + G_CALLBACK (request_unqueued), feature); + } +} + +void +soup_session_feature_attach (SoupSessionFeature *feature, + SoupSession *session) +{ + g_return_if_fail (SOUP_IS_SESSION_FEATURE (feature)); + g_return_if_fail (SOUP_IS_SESSION (session)); + + SOUP_SESSION_FEATURE_GET_CLASS (feature)->attach (feature, session); +} + +static void +soup_session_feature_real_detach (SoupSessionFeature *feature, SoupSession *session) +{ + g_object_weak_unref (G_OBJECT (session), weak_notify_unref, feature); + + g_signal_handlers_disconnect_by_func (session, request_queued, feature); + g_signal_handlers_disconnect_by_func (session, request_started, feature); + g_signal_handlers_disconnect_by_func (session, request_unqueued, feature); + + g_object_unref (feature); +} + +void +soup_session_feature_detach (SoupSessionFeature *feature, + SoupSession *session) +{ + g_return_if_fail (SOUP_IS_SESSION_FEATURE (feature)); + g_return_if_fail (SOUP_IS_SESSION (session)); + + SOUP_SESSION_FEATURE_GET_CLASS (feature)->detach (feature, session); +} + +static void +soup_session_feature_default_init (SoupSessionFeatureInterface *iface) +{ + iface->attach = soup_session_feature_real_attach; + iface->detach = soup_session_feature_real_detach; +} + +/** + * soup_session_feature_add_feature: + * @feature: the "base" feature + * @type: the #GType of a "sub-feature" + * + * Adds a "sub-feature" of type @type to the base feature @feature. + * This is used for features that can be extended with multiple + * different types. Eg, the authentication manager can be extended + * with subtypes of #SoupAuth. + * + * Return value: %TRUE if @feature accepted @type as a subfeature. + * + * Since: 2.34 + */ +gboolean +soup_session_feature_add_feature (SoupSessionFeature *feature, + GType type) +{ + SoupSessionFeatureInterface *feature_iface = + SOUP_SESSION_FEATURE_GET_CLASS (feature); + + if (feature_iface->add_feature) + return feature_iface->add_feature (feature, type); + else + return FALSE; +} + +/** + * soup_session_feature_remove_feature: + * @feature: the "base" feature + * @type: the #GType of a "sub-feature" + * + * Removes the "sub-feature" of type @type from the base feature + * @feature. See soup_session_feature_add_feature(). + * + * Return value: %TRUE if @type was removed from @feature + * + * Since: 2.34 + */ +gboolean +soup_session_feature_remove_feature (SoupSessionFeature *feature, + GType type) +{ + SoupSessionFeatureInterface *feature_iface = + SOUP_SESSION_FEATURE_GET_CLASS (feature); + + if (feature_iface->remove_feature) + return feature_iface->remove_feature (feature, type); + else + return FALSE; +} + +/** + * soup_session_feature_has_feature: + * @feature: the "base" feature + * @type: the #GType of a "sub-feature" + * + * Tests if @feature has a "sub-feature" of type @type. See + * soup_session_feature_add_feature(). + * + * Return value: %TRUE if @feature has a subfeature of type @type + * + * Since: 2.34 + */ +gboolean +soup_session_feature_has_feature (SoupSessionFeature *feature, + GType type) +{ + SoupSessionFeatureInterface *feature_iface = + SOUP_SESSION_FEATURE_GET_CLASS (feature); + + if (feature_iface->has_feature) + return feature_iface->has_feature (feature, type); + else + return FALSE; +} diff --git a/libsoup/soup-session-feature.h b/libsoup/soup-session-feature.h new file mode 100644 index 0000000..962c8e1 --- /dev/null +++ b/libsoup/soup-session-feature.h @@ -0,0 +1,71 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2008 Red Hat, Inc. + */ + +#ifndef SOUP_SESSION_FEATURE_H +#define SOUP_SESSION_FEATURE_H 1 + +#include + +G_BEGIN_DECLS + +#define SOUP_TYPE_SESSION_FEATURE (soup_session_feature_get_type ()) +#define SOUP_SESSION_FEATURE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SOUP_TYPE_SESSION_FEATURE, SoupSessionFeature)) +#define SOUP_SESSION_FEATURE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_SESSION_FEATURE, SoupSessionFeatureInterface)) +#define SOUP_IS_SESSION_FEATURE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SOUP_TYPE_SESSION_FEATURE)) +#define SOUP_IS_SESSION_FEATURE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SOUP_TYPE_SESSION_FEATURE)) +#define SOUP_SESSION_FEATURE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), SOUP_TYPE_SESSION_FEATURE, SoupSessionFeatureInterface)) + +typedef struct { + GTypeInterface parent; + + /* methods */ + void (*attach) (SoupSessionFeature *feature, + SoupSession *session); + void (*detach) (SoupSessionFeature *feature, + SoupSession *session); + + void (*request_queued) (SoupSessionFeature *feature, + SoupSession *session, + SoupMessage *msg); + void (*request_started) (SoupSessionFeature *feature, + SoupSession *session, + SoupMessage *msg, + SoupSocket *socket); + void (*request_unqueued) (SoupSessionFeature *feature, + SoupSession *session, + SoupMessage *msg); + + gboolean (*add_feature) (SoupSessionFeature *feature, + GType type); + gboolean (*remove_feature) (SoupSessionFeature *feature, + GType type); + gboolean (*has_feature) (SoupSessionFeature *feature, + GType type); + +} SoupSessionFeatureInterface; + +SOUP_AVAILABLE_IN_2_24 +GType soup_session_feature_get_type (void); + +SOUP_AVAILABLE_IN_2_24 +void soup_session_feature_attach (SoupSessionFeature *feature, + SoupSession *session); +SOUP_AVAILABLE_IN_2_24 +void soup_session_feature_detach (SoupSessionFeature *feature, + SoupSession *session); + +SOUP_AVAILABLE_IN_2_34 +gboolean soup_session_feature_add_feature (SoupSessionFeature *feature, + GType type); +SOUP_AVAILABLE_IN_2_34 +gboolean soup_session_feature_remove_feature (SoupSessionFeature *feature, + GType type); +SOUP_AVAILABLE_IN_2_34 +gboolean soup_session_feature_has_feature (SoupSessionFeature *feature, + GType type); + +G_END_DECLS + +#endif /* SOUP_SESSION_FEATURE_H */ diff --git a/libsoup/soup-session-private.h b/libsoup/soup-session-private.h new file mode 100644 index 0000000..dc4d300 --- /dev/null +++ b/libsoup/soup-session-private.h @@ -0,0 +1,48 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2000-2003, Ximian, Inc. + */ + +#ifndef SOUP_SESSION_PRIVATE_H +#define SOUP_SESSION_PRIVATE_H 1 + +#include "soup-session.h" +#include "soup-message-private.h" +#include "soup-proxy-uri-resolver.h" + +G_BEGIN_DECLS + +/* "protected" methods for subclasses */ +SoupMessageQueue *soup_session_get_queue (SoupSession *session); + +SoupMessageQueueItem *soup_session_append_queue_item (SoupSession *session, + SoupMessage *msg, + gboolean async, + gboolean new_api, + SoupSessionCallback callback, + gpointer user_data); + +void soup_session_kick_queue (SoupSession *session); + +GInputStream *soup_session_send_request (SoupSession *session, + SoupMessage *msg, + GCancellable *cancellable, + GError **error); + +void soup_session_send_request_async (SoupSession *session, + SoupMessage *msg, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +GInputStream *soup_session_send_request_finish (SoupSession *session, + GAsyncResult *result, + GError **error); + +void soup_session_process_queue_item (SoupSession *session, + SoupMessageQueueItem *item, + gboolean *should_prune, + gboolean loop); + +G_END_DECLS + +#endif /* SOUP_SESSION_PRIVATE_H */ diff --git a/libsoup/soup-session-sync.c b/libsoup/soup-session-sync.c new file mode 100644 index 0000000..229ac1e --- /dev/null +++ b/libsoup/soup-session-sync.c @@ -0,0 +1,132 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-session-sync.c + * + * Copyright (C) 2000-2003, Ximian, Inc. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "soup-session-sync.h" +#include "soup.h" +#include "soup-session-private.h" +#include "soup-message-private.h" +#include "soup-message-queue.h" + +/** + * SECTION:soup-session-sync + * @short_description: SoupSession for blocking I/O in multithreaded programs + * (deprecated). + * + * #SoupSessionSync is an implementation of #SoupSession that uses + * synchronous I/O, intended for use in multi-threaded programs. + * + * Deprecated: 2.42: Use the #SoupSession class (which uses both asynchronous + * and synchronous I/O, depending on the API used). See the + * porting guide. + **/ + +G_GNUC_BEGIN_IGNORE_DEPRECATIONS; + +G_DEFINE_TYPE (SoupSessionSync, soup_session_sync, SOUP_TYPE_SESSION) + +static void +soup_session_sync_init (SoupSessionSync *ss) +{ +} + +/** + * soup_session_sync_new: + * + * Creates an synchronous #SoupSession with the default options. + * + * Return value: the new session. + * + * Deprecated: #SoupSessionSync is deprecated; use a plain + * #SoupSession, created with soup_session_new(). See the porting guide. + **/ +SoupSession * +soup_session_sync_new (void) +{ + return g_object_new (SOUP_TYPE_SESSION_SYNC, NULL); +} + +/** + * soup_session_sync_new_with_options: + * @optname1: name of first property to set + * @...: value of @optname1, followed by additional property/value pairs + * + * Creates an synchronous #SoupSession with the specified options. + * + * Return value: the new session. + * + * Deprecated: #SoupSessionSync is deprecated; use a plain + * #SoupSession, created with soup_session_new_with_options(). See the + * porting guide. + **/ +SoupSession * +soup_session_sync_new_with_options (const char *optname1, ...) +{ + SoupSession *session; + va_list ap; + + va_start (ap, optname1); + session = (SoupSession *)g_object_new_valist (SOUP_TYPE_SESSION_SYNC, + optname1, ap); + va_end (ap); + + return session; +} + +static gboolean +queue_message_callback (gpointer data) +{ + SoupMessageQueueItem *item = data; + + item->callback (item->session, item->msg, item->callback_data); + soup_message_queue_item_unref (item); + return FALSE; +} + +static gpointer +queue_message_thread (gpointer data) +{ + SoupMessageQueueItem *item = data; + + soup_session_process_queue_item (item->session, item, NULL, TRUE); + if (item->callback) { + soup_add_completion (soup_session_get_async_context (item->session), + queue_message_callback, item); + } else + soup_message_queue_item_unref (item); + + return NULL; +} + +static void +soup_session_sync_queue_message (SoupSession *session, SoupMessage *msg, + SoupSessionCallback callback, gpointer user_data) +{ + SoupMessageQueueItem *item; + GThread *thread; + + item = soup_session_append_queue_item (session, msg, FALSE, FALSE, + callback, user_data); + thread = g_thread_new ("SoupSessionSync:queue_message", + queue_message_thread, item); + g_thread_unref (thread); +} + +static void +soup_session_sync_class_init (SoupSessionSyncClass *session_sync_class) +{ + SoupSessionClass *session_class = SOUP_SESSION_CLASS (session_sync_class); + + /* virtual method override */ + session_class->queue_message = soup_session_sync_queue_message; +} + +G_GNUC_END_IGNORE_DEPRECATIONS; diff --git a/libsoup/soup-session-sync.h b/libsoup/soup-session-sync.h new file mode 100644 index 0000000..56c340c --- /dev/null +++ b/libsoup/soup-session-sync.h @@ -0,0 +1,60 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2000-2003, Ximian, Inc. + */ + +#ifndef SOUP_SESSION_SYNC_H +#define SOUP_SESSION_SYNC_H 1 + +#include +#include + +G_BEGIN_DECLS + +#define SOUP_TYPE_SESSION_SYNC (soup_session_sync_get_type ()) +#define SOUP_SESSION_SYNC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SOUP_TYPE_SESSION_SYNC, SoupSessionSync)) +#define SOUP_SESSION_SYNC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_SESSION_SYNC, SoupSessionSyncClass)) +#define SOUP_IS_SESSION_SYNC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), _soup_session_sync_get_type_undeprecated ())) +#define SOUP_IS_SESSION_SYNC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), SOUP_TYPE_SESSION_SYNC)) +#define SOUP_SESSION_SYNC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_SESSION_SYNC, SoupSessionSyncClass)) + +struct _SoupSessionSync { + SoupSession parent; + +}; + +typedef struct { + SoupSessionClass parent_class; + + /* Padding for future expansion */ + void (*_libsoup_reserved1) (void); + void (*_libsoup_reserved2) (void); + void (*_libsoup_reserved3) (void); + void (*_libsoup_reserved4) (void); +} SoupSessionSyncClass; + +SOUP_AVAILABLE_IN_2_4 +SOUP_DEPRECATED_IN_2_54 +GType soup_session_sync_get_type (void); + +static inline GType +_soup_session_sync_get_type_undeprecated (void) +{ + G_GNUC_BEGIN_IGNORE_DEPRECATIONS; + return soup_session_sync_get_type (); + G_GNUC_END_IGNORE_DEPRECATIONS; +} + +#ifndef SOUP_DISABLE_DEPRECATED +SOUP_AVAILABLE_IN_2_4 +SOUP_DEPRECATED_IN_2_54_FOR(soup_session_new) +SoupSession *soup_session_sync_new (void); +SOUP_AVAILABLE_IN_2_4 +SOUP_DEPRECATED_IN_2_54_FOR(soup_session_new_with_options) +SoupSession *soup_session_sync_new_with_options (const char *optname1, + ...) G_GNUC_NULL_TERMINATED; +#endif + +G_END_DECLS + +#endif /* SOUP_SESSION_SYNC_H */ diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c new file mode 100644 index 0000000..ae340b9 --- /dev/null +++ b/libsoup/soup-session.c @@ -0,0 +1,5064 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-session.c + * + * Copyright (C) 2000-2003, Ximian, Inc. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "soup-session.h" +#include "soup.h" +#include "soup-auth-manager.h" +#include "soup-cache-private.h" +#include "soup-connection.h" +#include "soup-message-private.h" +#include "soup-misc-private.h" +#include "soup-message-queue.h" +#include "soup-proxy-resolver-wrapper.h" +#include "soup-session-private.h" +#include "soup-socket-private.h" +#include "soup-websocket.h" +#include "soup-websocket-connection.h" + +#define HOST_KEEP_ALIVE 5 * 60 * 1000 /* 5 min in msecs */ + +/** + * SECTION:soup-session + * @short_description: Soup session state object + * + * #SoupSession is the object that controls client-side HTTP. A + * #SoupSession encapsulates all of the state that libsoup is keeping + * on behalf of your program; cached HTTP connections, authentication + * information, etc. It also keeps track of various global options + * and features that you are using. + * + * Most applications will only need a single #SoupSession; the primary + * reason you might need multiple sessions is if you need to have + * multiple independent authentication contexts. (Eg, you are + * connecting to a server and authenticating as two different users at + * different times; the easiest way to ensure that each #SoupMessage + * is sent with the authentication information you intended is to use + * one session for the first user, and a second session for the other + * user.) + * + * In the past, #SoupSession was an abstract class, and users needed + * to choose between #SoupSessionAsync (which always uses + * #GMainLoop-based I/O), or #SoupSessionSync (which always uses + * blocking I/O and can be used from multiple threads simultaneously). + * This is no longer necessary; you can (and should) use a plain + * #SoupSession, which supports both synchronous and asynchronous use. + * (When using a plain #SoupSession, soup_session_queue_message() + * behaves like it traditionally did on a #SoupSessionAsync, and + * soup_session_send_message() behaves like it traditionally did on a + * #SoupSessionSync.) + * + * Additional #SoupSession functionality is provided by + * #SoupSessionFeature objects, which can be added to a session with + * soup_session_add_feature() or soup_session_add_feature_by_type() + * (or at construct time with the %SOUP_SESSION_ADD_FEATURE_BY_TYPE + * pseudo-property). For example, #SoupLogger provides support for + * logging HTTP traffic, #SoupContentDecoder provides support for + * compressed response handling, and #SoupContentSniffer provides + * support for HTML5-style response body content sniffing. + * Additionally, subtypes of #SoupAuth and #SoupRequest can be added + * as features, to add support for additional authentication and URI + * types. + * + * All #SoupSessions are created with a #SoupAuthManager, and support + * for %SOUP_TYPE_AUTH_BASIC and %SOUP_TYPE_AUTH_DIGEST. For + * #SoupRequest types, #SoupRequestHTTP, #SoupRequestFile, and + * #SoupRequestData are supported. Additionally, sessions using the + * plain #SoupSession class (rather than one of its deprecated + * subtypes) have a #SoupContentDecoder by default. + **/ + +typedef struct { + SoupURI *uri; + SoupAddress *addr; + + GSList *connections; /* CONTAINS: SoupConnection */ + guint num_conns; + + guint num_messages; + + GSource *keep_alive_src; + SoupSession *session; +} SoupSessionHost; +static guint soup_host_uri_hash (gconstpointer key); +static gboolean soup_host_uri_equal (gconstpointer v1, gconstpointer v2); + +typedef struct { + gboolean disposed; + + GTlsDatabase *tlsdb; + GTlsInteraction *tls_interaction; + char *ssl_ca_file; + gboolean ssl_strict; + gboolean tlsdb_use_default; + + guint io_timeout, idle_timeout; + SoupAddress *local_addr; + + GResolver *resolver; + GProxyResolver *proxy_resolver; + gboolean proxy_use_default; + SoupURI *proxy_uri; + + SoupSocketProperties *socket_props; + + SoupMessageQueue *queue; + + char *user_agent; + char *accept_language; + gboolean accept_language_auto; + + GSList *features; + GHashTable *features_cache; + + GHashTable *http_hosts, *https_hosts; /* char* -> SoupSessionHost */ + GHashTable *conns; /* SoupConnection -> SoupSessionHost */ + guint num_conns; + guint max_conns, max_conns_per_host; + + /* Must hold the conn_lock before potentially creating a new + * SoupSessionHost, adding/removing a connection, + * disconnecting a connection, moving a connection from + * IDLE to IN_USE, or when updating socket properties. + * Must not emit signals or destroy objects while holding it. + * The conn_cond is signaled when it may be possible for + * a previously-blocked message to continue. + */ + GMutex conn_lock; + GCond conn_cond; + + GMainContext *async_context; + gboolean use_thread_context; + + char **http_aliases, **https_aliases; + + GHashTable *request_types; +} SoupSessionPrivate; + +#define SOUP_IS_PLAIN_SESSION(o) (G_TYPE_FROM_INSTANCE (o) == SOUP_TYPE_SESSION) + +static void free_host (SoupSessionHost *host); +static void connection_state_changed (GObject *object, GParamSpec *param, + gpointer user_data); +static void connection_disconnected (SoupConnection *conn, gpointer user_data); +static void drop_connection (SoupSession *session, SoupSessionHost *host, + SoupConnection *conn); + +static void auth_manager_authenticate (SoupAuthManager *manager, + SoupMessage *msg, SoupAuth *auth, + gboolean retrying, gpointer user_data); + +static void async_run_queue (SoupSession *session); + +static void async_send_request_running (SoupSession *session, SoupMessageQueueItem *item); + +#define SOUP_SESSION_MAX_CONNS_DEFAULT 10 +#define SOUP_SESSION_MAX_CONNS_PER_HOST_DEFAULT 2 + +#define SOUP_SESSION_MAX_RESEND_COUNT 20 + +#define SOUP_SESSION_USER_AGENT_BASE "libsoup/" PACKAGE_VERSION + +G_DEFINE_TYPE_WITH_PRIVATE (SoupSession, soup_session, G_TYPE_OBJECT) + +enum { + REQUEST_QUEUED, + REQUEST_STARTED, + REQUEST_UNQUEUED, + AUTHENTICATE, + CONNECTION_CREATED, + TUNNELING, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +enum { + PROP_0, + + PROP_PROXY_URI, + PROP_PROXY_RESOLVER, + PROP_MAX_CONNS, + PROP_MAX_CONNS_PER_HOST, + PROP_USE_NTLM, + PROP_SSL_CA_FILE, + PROP_SSL_USE_SYSTEM_CA_FILE, + PROP_TLS_DATABASE, + PROP_SSL_STRICT, + PROP_ASYNC_CONTEXT, + PROP_USE_THREAD_CONTEXT, + PROP_TIMEOUT, + PROP_USER_AGENT, + PROP_ACCEPT_LANGUAGE, + PROP_ACCEPT_LANGUAGE_AUTO, + PROP_IDLE_TIMEOUT, + PROP_ADD_FEATURE, + PROP_ADD_FEATURE_BY_TYPE, + PROP_REMOVE_FEATURE_BY_TYPE, + PROP_HTTP_ALIASES, + PROP_HTTPS_ALIASES, + PROP_LOCAL_ADDRESS, + PROP_TLS_INTERACTION, + + LAST_PROP +}; + +static void +soup_session_init (SoupSession *session) +{ + SoupSessionPrivate *priv = soup_session_get_instance_private (session); + SoupAuthManager *auth_manager; + + priv->queue = soup_message_queue_new (session); + + g_mutex_init (&priv->conn_lock); + g_cond_init (&priv->conn_cond); + priv->http_hosts = g_hash_table_new_full (soup_host_uri_hash, + soup_host_uri_equal, + NULL, (GDestroyNotify)free_host); + priv->https_hosts = g_hash_table_new_full (soup_host_uri_hash, + soup_host_uri_equal, + NULL, (GDestroyNotify)free_host); + priv->conns = g_hash_table_new (NULL, NULL); + + priv->max_conns = SOUP_SESSION_MAX_CONNS_DEFAULT; + priv->max_conns_per_host = SOUP_SESSION_MAX_CONNS_PER_HOST_DEFAULT; + + priv->features_cache = g_hash_table_new (NULL, NULL); + + auth_manager = g_object_new (SOUP_TYPE_AUTH_MANAGER, NULL); + g_signal_connect (auth_manager, "authenticate", + G_CALLBACK (auth_manager_authenticate), session); + soup_session_feature_add_feature (SOUP_SESSION_FEATURE (auth_manager), + SOUP_TYPE_AUTH_BASIC); + soup_session_feature_add_feature (SOUP_SESSION_FEATURE (auth_manager), + SOUP_TYPE_AUTH_DIGEST); + soup_session_add_feature (session, SOUP_SESSION_FEATURE (auth_manager)); + g_object_unref (auth_manager); + + /* We'll be doing DNS continuously-ish while the session is active, + * so hold a ref on the default GResolver. + */ + priv->resolver = g_resolver_get_default (); + + priv->ssl_strict = TRUE; + + priv->http_aliases = g_new (char *, 2); + priv->http_aliases[0] = (char *)g_intern_string ("*"); + priv->http_aliases[1] = NULL; + + priv->request_types = g_hash_table_new (soup_str_case_hash, + soup_str_case_equal); + soup_session_add_feature_by_type (session, SOUP_TYPE_REQUEST_HTTP); + soup_session_add_feature_by_type (session, SOUP_TYPE_REQUEST_FILE); + soup_session_add_feature_by_type (session, SOUP_TYPE_REQUEST_DATA); +} + +static GObject * +soup_session_constructor (GType type, + guint n_construct_properties, + GObjectConstructParam *construct_params) +{ + GObject *object; + + object = G_OBJECT_CLASS (soup_session_parent_class)->constructor (type, n_construct_properties, construct_params); + + /* If this is a "plain" SoupSession, fix up the default + * properties values, etc. + */ + if (type == SOUP_TYPE_SESSION) { + SoupSession *session = SOUP_SESSION (object); + SoupSessionPrivate *priv = soup_session_get_instance_private (session); + + g_clear_pointer (&priv->async_context, g_main_context_unref); + priv->async_context = g_main_context_ref_thread_default (); + priv->use_thread_context = TRUE; + + priv->io_timeout = priv->idle_timeout = 60; + + priv->http_aliases[0] = NULL; + + /* If the user overrides the proxy or tlsdb during construction, + * we don't want to needlessly resolve the extension point. So + * we just set flags saying to do it later. + */ + priv->proxy_use_default = TRUE; + priv->tlsdb_use_default = TRUE; + + soup_session_add_feature_by_type (session, SOUP_TYPE_CONTENT_DECODER); + } + + return object; +} + +static void +soup_session_dispose (GObject *object) +{ + SoupSession *session = SOUP_SESSION (object); + SoupSessionPrivate *priv = soup_session_get_instance_private (session); + + priv->disposed = TRUE; + soup_session_abort (session); + g_warn_if_fail (g_hash_table_size (priv->conns) == 0); + + while (priv->features) + soup_session_remove_feature (session, priv->features->data); + + G_OBJECT_CLASS (soup_session_parent_class)->dispose (object); +} + +static void +soup_session_finalize (GObject *object) +{ + SoupSession *session = SOUP_SESSION (object); + SoupSessionPrivate *priv = soup_session_get_instance_private (session); + + soup_message_queue_destroy (priv->queue); + + g_mutex_clear (&priv->conn_lock); + g_cond_clear (&priv->conn_cond); + g_hash_table_destroy (priv->http_hosts); + g_hash_table_destroy (priv->https_hosts); + g_hash_table_destroy (priv->conns); + + g_free (priv->user_agent); + g_free (priv->accept_language); + + g_clear_object (&priv->tlsdb); + g_clear_object (&priv->tls_interaction); + g_free (priv->ssl_ca_file); + + g_clear_pointer (&priv->async_context, g_main_context_unref); + g_clear_object (&priv->local_addr); + + g_hash_table_destroy (priv->features_cache); + + g_object_unref (priv->resolver); + g_clear_object (&priv->proxy_resolver); + g_clear_pointer (&priv->proxy_uri, soup_uri_free); + + g_free (priv->http_aliases); + g_free (priv->https_aliases); + + g_hash_table_destroy (priv->request_types); + + g_clear_pointer (&priv->socket_props, soup_socket_properties_unref); + + G_OBJECT_CLASS (soup_session_parent_class)->finalize (object); +} + +/* requires conn_lock */ +static void +ensure_socket_props (SoupSession *session) +{ + SoupSessionPrivate *priv = soup_session_get_instance_private (session); + gboolean ssl_strict; + + if (priv->socket_props) + return; + + if (priv->proxy_use_default) { + priv->proxy_resolver = g_object_ref (g_proxy_resolver_get_default ()); + priv->proxy_use_default = FALSE; + } + if (priv->tlsdb_use_default) { + priv->tlsdb = g_tls_backend_get_default_database (g_tls_backend_get_default ()); + priv->tlsdb_use_default = FALSE; + } + + ssl_strict = priv->ssl_strict && (priv->tlsdb != NULL || + SOUP_IS_PLAIN_SESSION (session)); + + priv->socket_props = soup_socket_properties_new (priv->async_context, + priv->use_thread_context, + priv->proxy_resolver, + priv->local_addr, + priv->tlsdb, + priv->tls_interaction, + ssl_strict, + priv->io_timeout, + priv->idle_timeout); +} + +/* Converts a language in POSIX format and to be RFC2616 compliant */ +/* Based on code from epiphany-webkit (ephy_langs_append_languages()) */ +static gchar * +posix_lang_to_rfc2616 (const gchar *language) +{ + /* Don't include charset variants, etc */ + if (strchr (language, '.') || strchr (language, '@')) + return NULL; + + /* Ignore "C" locale, which g_get_language_names() always + * includes as a fallback. + */ + if (!strcmp (language, "C")) + return NULL; + + return g_strdelimit (g_ascii_strdown (language, -1), "_", '-'); +} + +/* Converts @quality from 0-100 to 0.0-1.0 and appends to @str */ +static gchar * +add_quality_value (const gchar *str, int quality) +{ + g_return_val_if_fail (str != NULL, NULL); + + if (quality >= 0 && quality < 100) { + /* We don't use %.02g because of "." vs "," locale issues */ + if (quality % 10) + return g_strdup_printf ("%s;q=0.%02d", str, quality); + else + return g_strdup_printf ("%s;q=0.%d", str, quality / 10); + } else + return g_strdup (str); +} + +/* Returns a RFC2616 compliant languages list from system locales */ +static gchar * +accept_languages_from_system (void) +{ + const char * const * lang_names; + GPtrArray *langs = NULL; + char *lang, *langs_str; + int delta; + guint i; + + lang_names = g_get_language_names (); + g_return_val_if_fail (lang_names != NULL, NULL); + + /* Build the array of languages */ + langs = g_ptr_array_new_with_free_func (g_free); + for (i = 0; lang_names[i] != NULL; i++) { + lang = posix_lang_to_rfc2616 (lang_names[i]); + if (lang) + g_ptr_array_add (langs, lang); + } + + /* Add quality values */ + if (langs->len < 10) + delta = 10; + else if (langs->len < 20) + delta = 5; + else + delta = 1; + + for (i = 0; i < langs->len; i++) { + lang = langs->pdata[i]; + langs->pdata[i] = add_quality_value (lang, 100 - i * delta); + g_free (lang); + } + + /* Fallback: add "en" if list is empty */ + if (langs->len == 0) + g_ptr_array_add (langs, g_strdup ("en")); + + g_ptr_array_add (langs, NULL); + langs_str = g_strjoinv (", ", (char **)langs->pdata); + g_ptr_array_free (langs, TRUE); + + return langs_str; +} + +static void +set_tlsdb (SoupSession *session, GTlsDatabase *tlsdb) +{ + SoupSessionPrivate *priv = soup_session_get_instance_private (session); + GTlsDatabase *system_default; + + priv->tlsdb_use_default = FALSE; + if (tlsdb == priv->tlsdb) + return; + + g_object_freeze_notify (G_OBJECT (session)); + + system_default = g_tls_backend_get_default_database (g_tls_backend_get_default ()); + if (system_default) { + if (priv->tlsdb == system_default || tlsdb == system_default) { + g_object_notify (G_OBJECT (session), "ssl-use-system-ca-file"); + } + g_object_unref (system_default); + } + + if (priv->ssl_ca_file) { + g_free (priv->ssl_ca_file); + priv->ssl_ca_file = NULL; + g_object_notify (G_OBJECT (session), "ssl-ca-file"); + } + + if (priv->tlsdb) + g_object_unref (priv->tlsdb); + priv->tlsdb = tlsdb; + if (priv->tlsdb) + g_object_ref (priv->tlsdb); + + g_object_notify (G_OBJECT (session), "tls-database"); + g_object_thaw_notify (G_OBJECT (session)); +} + +static void +set_use_system_ca_file (SoupSession *session, gboolean use_system_ca_file) +{ + SoupSessionPrivate *priv = soup_session_get_instance_private (session); + GTlsDatabase *system_default; + + priv->tlsdb_use_default = FALSE; + + system_default = g_tls_backend_get_default_database (g_tls_backend_get_default ()); + + if (use_system_ca_file) + set_tlsdb (session, system_default); + else if (priv->tlsdb == system_default) + set_tlsdb (session, NULL); + + g_clear_object (&system_default); +} + +static void +set_ssl_ca_file (SoupSession *session, const char *ssl_ca_file) +{ + SoupSessionPrivate *priv = soup_session_get_instance_private (session); + GTlsDatabase *tlsdb; + GError *error = NULL; + + priv->tlsdb_use_default = FALSE; + if (!g_strcmp0 (priv->ssl_ca_file, ssl_ca_file)) + return; + + g_object_freeze_notify (G_OBJECT (session)); + + if (g_path_is_absolute (ssl_ca_file)) + tlsdb = g_tls_file_database_new (ssl_ca_file, &error); + else { + char *path, *cwd; + + cwd = g_get_current_dir (); + path = g_build_filename (cwd, ssl_ca_file, NULL); + tlsdb = g_tls_file_database_new (path, &error); + g_free (path); + g_free (cwd); + } + + if (error) { + if (!g_error_matches (error, G_TLS_ERROR, G_TLS_ERROR_UNAVAILABLE)) { + g_warning ("Could not set SSL credentials from '%s': %s", + ssl_ca_file, error->message); + + tlsdb = g_tls_file_database_new ("/dev/null", NULL); + } + g_error_free (error); + } + + set_tlsdb (session, tlsdb); + if (tlsdb) { + g_object_unref (tlsdb); + + priv->ssl_ca_file = g_strdup (ssl_ca_file); + g_object_notify (G_OBJECT (session), "ssl-ca-file"); + } else if (priv->ssl_ca_file) { + g_clear_pointer (&priv->ssl_ca_file, g_free); + g_object_notify (G_OBJECT (session), "ssl-ca-file"); + } + + g_object_thaw_notify (G_OBJECT (session)); +} + +/* priv->http_aliases and priv->https_aliases are stored as arrays of + * *interned* strings, so we can't just use g_strdupv() to set them. + */ +static void +set_aliases (char ***variable, char **value) +{ + int len, i; + + if (*variable) + g_free (*variable); + + if (!value) { + *variable = NULL; + return; + } + + len = g_strv_length (value); + *variable = g_new (char *, len + 1); + for (i = 0; i < len; i++) + (*variable)[i] = (char *)g_intern_string (value[i]); + (*variable)[i] = NULL; +} + +static void +set_proxy_resolver (SoupSession *session, SoupURI *uri, + SoupProxyURIResolver *soup_resolver, + GProxyResolver *g_resolver) +{ + SoupSessionPrivate *priv = soup_session_get_instance_private (session); + + G_GNUC_BEGIN_IGNORE_DEPRECATIONS; + soup_session_remove_feature_by_type (session, SOUP_TYPE_PROXY_URI_RESOLVER); + G_GNUC_END_IGNORE_DEPRECATIONS; + g_clear_object (&priv->proxy_resolver); + g_clear_pointer (&priv->proxy_uri, soup_uri_free); + priv->proxy_use_default = FALSE; + + if (uri) { + char *uri_string; + + priv->proxy_uri = soup_uri_copy (uri); + uri_string = soup_uri_to_string_internal (uri, FALSE, TRUE, TRUE); + priv->proxy_resolver = g_simple_proxy_resolver_new (uri_string, NULL); + g_free (uri_string); + } else if (soup_resolver) { + G_GNUC_BEGIN_IGNORE_DEPRECATIONS; + if (SOUP_IS_PROXY_RESOLVER_DEFAULT (soup_resolver)) + priv->proxy_resolver = g_object_ref (g_proxy_resolver_get_default ()); + else + priv->proxy_resolver = soup_proxy_resolver_wrapper_new (soup_resolver); + G_GNUC_END_IGNORE_DEPRECATIONS; + } else if (g_resolver) + priv->proxy_resolver = g_object_ref (g_resolver); +} + +static void +soup_session_set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + SoupSession *session = SOUP_SESSION (object); + SoupSessionPrivate *priv = soup_session_get_instance_private (session); + const char *user_agent; + SoupSessionFeature *feature; + GMainContext *async_context; + gboolean socket_props_changed = FALSE; + + switch (prop_id) { + case PROP_LOCAL_ADDRESS: + priv->local_addr = g_value_dup_object (value); + socket_props_changed = TRUE; + break; + case PROP_PROXY_URI: + set_proxy_resolver (session, g_value_get_boxed (value), + NULL, NULL); + soup_session_abort (session); + socket_props_changed = TRUE; + break; + case PROP_PROXY_RESOLVER: + set_proxy_resolver (session, NULL, NULL, + g_value_get_object (value)); + socket_props_changed = TRUE; + break; + case PROP_MAX_CONNS: + priv->max_conns = g_value_get_int (value); + break; + case PROP_MAX_CONNS_PER_HOST: + priv->max_conns_per_host = g_value_get_int (value); + break; + case PROP_USE_NTLM: + g_return_if_fail (!SOUP_IS_PLAIN_SESSION (session)); + feature = soup_session_get_feature (session, SOUP_TYPE_AUTH_MANAGER); + if (feature) { + if (g_value_get_boolean (value)) + soup_session_feature_add_feature (feature, SOUP_TYPE_AUTH_NTLM); + else + soup_session_feature_remove_feature (feature, SOUP_TYPE_AUTH_NTLM); + } else + g_warning ("Trying to set use-ntlm on session with no auth-manager"); + break; + case PROP_SSL_CA_FILE: + set_ssl_ca_file (session, g_value_get_string (value)); + socket_props_changed = TRUE; + break; + case PROP_SSL_USE_SYSTEM_CA_FILE: + set_use_system_ca_file (session, g_value_get_boolean (value)); + socket_props_changed = TRUE; + break; + case PROP_TLS_DATABASE: + set_tlsdb (session, g_value_get_object (value)); + socket_props_changed = TRUE; + break; + case PROP_TLS_INTERACTION: + priv->tls_interaction = g_value_dup_object (value); + socket_props_changed = TRUE; + break; + case PROP_SSL_STRICT: + priv->ssl_strict = g_value_get_boolean (value); + socket_props_changed = TRUE; + break; + case PROP_ASYNC_CONTEXT: + async_context = g_value_get_pointer (value); + if (async_context && async_context != g_main_context_get_thread_default ()) + g_return_if_fail (!SOUP_IS_PLAIN_SESSION (session)); + priv->async_context = async_context; + if (priv->async_context) + g_main_context_ref (priv->async_context); + socket_props_changed = TRUE; + break; + case PROP_USE_THREAD_CONTEXT: + if (!g_value_get_boolean (value)) + g_return_if_fail (!SOUP_IS_PLAIN_SESSION (session)); + priv->use_thread_context = g_value_get_boolean (value); + if (priv->use_thread_context) { + if (priv->async_context) + g_main_context_unref (priv->async_context); + priv->async_context = g_main_context_get_thread_default (); + if (priv->async_context) + g_main_context_ref (priv->async_context); + } + socket_props_changed = TRUE; + break; + case PROP_TIMEOUT: + priv->io_timeout = g_value_get_uint (value); + socket_props_changed = TRUE; + break; + case PROP_USER_AGENT: + g_free (priv->user_agent); + user_agent = g_value_get_string (value); + if (!user_agent) + priv->user_agent = NULL; + else if (!*user_agent) { + priv->user_agent = + g_strdup (SOUP_SESSION_USER_AGENT_BASE); + } else if (g_str_has_suffix (user_agent, " ")) { + priv->user_agent = + g_strdup_printf ("%s%s", user_agent, + SOUP_SESSION_USER_AGENT_BASE); + } else + priv->user_agent = g_strdup (user_agent); + break; + case PROP_ACCEPT_LANGUAGE: + g_free (priv->accept_language); + priv->accept_language = g_strdup (g_value_get_string (value)); + priv->accept_language_auto = FALSE; + break; + case PROP_ACCEPT_LANGUAGE_AUTO: + priv->accept_language_auto = g_value_get_boolean (value); + if (priv->accept_language) { + g_free (priv->accept_language); + priv->accept_language = NULL; + } + + /* Get languages from system if needed */ + if (priv->accept_language_auto) + priv->accept_language = accept_languages_from_system (); + break; + case PROP_IDLE_TIMEOUT: + priv->idle_timeout = g_value_get_uint (value); + socket_props_changed = TRUE; + break; + case PROP_ADD_FEATURE: + soup_session_add_feature (session, g_value_get_object (value)); + break; + case PROP_ADD_FEATURE_BY_TYPE: + soup_session_add_feature_by_type (session, g_value_get_gtype (value)); + break; + case PROP_REMOVE_FEATURE_BY_TYPE: + soup_session_remove_feature_by_type (session, g_value_get_gtype (value)); + break; + case PROP_HTTP_ALIASES: + set_aliases (&priv->http_aliases, g_value_get_boxed (value)); + break; + case PROP_HTTPS_ALIASES: + set_aliases (&priv->https_aliases, g_value_get_boxed (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + + g_mutex_lock (&priv->conn_lock); + if (priv->socket_props && socket_props_changed) { + soup_socket_properties_unref (priv->socket_props); + priv->socket_props = NULL; + ensure_socket_props (session); + } + g_mutex_unlock (&priv->conn_lock); +} + +static void +soup_session_get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + SoupSession *session = SOUP_SESSION (object); + SoupSessionPrivate *priv = soup_session_get_instance_private (session); + SoupSessionFeature *feature; + GTlsDatabase *tlsdb; + + switch (prop_id) { + case PROP_LOCAL_ADDRESS: + g_value_set_object (value, priv->local_addr); + break; + case PROP_PROXY_URI: + g_value_set_boxed (value, priv->proxy_uri); + break; + case PROP_PROXY_RESOLVER: + g_mutex_lock (&priv->conn_lock); + ensure_socket_props (session); + g_mutex_unlock (&priv->conn_lock); + g_value_set_object (value, priv->proxy_resolver); + break; + case PROP_MAX_CONNS: + g_value_set_int (value, priv->max_conns); + break; + case PROP_MAX_CONNS_PER_HOST: + g_value_set_int (value, priv->max_conns_per_host); + break; + case PROP_USE_NTLM: + feature = soup_session_get_feature (session, SOUP_TYPE_AUTH_MANAGER); + if (feature) + g_value_set_boolean (value, soup_session_feature_has_feature (feature, SOUP_TYPE_AUTH_NTLM)); + else + g_value_set_boolean (value, FALSE); + break; + case PROP_SSL_CA_FILE: + g_value_set_string (value, priv->ssl_ca_file); + break; + case PROP_SSL_USE_SYSTEM_CA_FILE: + tlsdb = g_tls_backend_get_default_database (g_tls_backend_get_default ()); + g_mutex_lock (&priv->conn_lock); + ensure_socket_props (session); + g_mutex_unlock (&priv->conn_lock); + g_value_set_boolean (value, priv->tlsdb == tlsdb); + g_clear_object (&tlsdb); + break; + case PROP_TLS_DATABASE: + g_mutex_lock (&priv->conn_lock); + ensure_socket_props (session); + g_mutex_unlock (&priv->conn_lock); + g_value_set_object (value, priv->tlsdb); + break; + case PROP_TLS_INTERACTION: + g_value_set_object (value, priv->tls_interaction); + break; + case PROP_SSL_STRICT: + g_value_set_boolean (value, priv->ssl_strict); + break; + case PROP_ASYNC_CONTEXT: + g_value_set_pointer (value, priv->async_context ? g_main_context_ref (priv->async_context) : NULL); + break; + case PROP_USE_THREAD_CONTEXT: + g_value_set_boolean (value, priv->use_thread_context); + break; + case PROP_TIMEOUT: + g_value_set_uint (value, priv->io_timeout); + break; + case PROP_USER_AGENT: + g_value_set_string (value, priv->user_agent); + break; + case PROP_ACCEPT_LANGUAGE: + g_value_set_string (value, priv->accept_language); + break; + case PROP_ACCEPT_LANGUAGE_AUTO: + g_value_set_boolean (value, priv->accept_language_auto); + break; + case PROP_IDLE_TIMEOUT: + g_value_set_uint (value, priv->idle_timeout); + break; + case PROP_HTTP_ALIASES: + g_value_set_boxed (value, priv->http_aliases); + break; + case PROP_HTTPS_ALIASES: + g_value_set_boxed (value, priv->https_aliases); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/** + * soup_session_new: + * + * Creates a #SoupSession with the default options. + * + * Return value: the new session. + * + * Since: 2.42 + */ +SoupSession * +soup_session_new (void) +{ + return g_object_new (SOUP_TYPE_SESSION, NULL); +} + +/** + * soup_session_new_with_options: + * @optname1: name of first property to set + * @...: value of @optname1, followed by additional property/value pairs + * + * Creates a #SoupSession with the specified options. + * + * Return value: the new session. + * + * Since: 2.42 + */ +SoupSession * +soup_session_new_with_options (const char *optname1, + ...) +{ + SoupSession *session; + va_list ap; + + va_start (ap, optname1); + session = (SoupSession *)g_object_new_valist (SOUP_TYPE_SESSION, + optname1, ap); + va_end (ap); + + return session; +} + +/** + * soup_session_get_async_context: + * @session: a #SoupSession + * + * Gets @session's #SoupSession:async-context. This does not add a ref + * to the context, so you will need to ref it yourself if you want it + * to outlive its session. + * + * For a modern #SoupSession, this will always just return the + * thread-default #GMainContext, and so is not especially useful. + * + * Return value: (nullable) (transfer none): @session's #GMainContext, + * which may be %NULL + **/ +GMainContext * +soup_session_get_async_context (SoupSession *session) +{ + SoupSessionPrivate *priv; + + g_return_val_if_fail (SOUP_IS_SESSION (session), NULL); + priv = soup_session_get_instance_private (session); + + if (priv->use_thread_context) + return g_main_context_get_thread_default (); + else + return priv->async_context; +} + +/* Hosts */ + +/* Note that we can't use soup_uri_host_hash() and soup_uri_host_equal() + * because we want to ignore the protocol; http://example.com and + * webcal://example.com are the same host. + */ +static guint +soup_host_uri_hash (gconstpointer key) +{ + const SoupURI *uri = key; + + g_return_val_if_fail (uri != NULL && uri->host != NULL, 0); + + return uri->port + soup_str_case_hash (uri->host); +} + +static gboolean +soup_host_uri_equal (gconstpointer v1, gconstpointer v2) +{ + const SoupURI *one = v1; + const SoupURI *two = v2; + + g_return_val_if_fail (one != NULL && two != NULL, one == two); + g_return_val_if_fail (one->host != NULL && two->host != NULL, one->host == two->host); + + if (one->port != two->port) + return FALSE; + + return g_ascii_strcasecmp (one->host, two->host) == 0; +} + + +static SoupSessionHost * +soup_session_host_new (SoupSession *session, SoupURI *uri) +{ + SoupSessionHost *host; + + host = g_slice_new0 (SoupSessionHost); + host->uri = soup_uri_copy_host (uri); + if (host->uri->scheme != SOUP_URI_SCHEME_HTTP && + host->uri->scheme != SOUP_URI_SCHEME_HTTPS) { + SoupSessionPrivate *priv = soup_session_get_instance_private (session); + + if (soup_uri_is_https (host->uri, priv->https_aliases)) + host->uri->scheme = SOUP_URI_SCHEME_HTTPS; + else + host->uri->scheme = SOUP_URI_SCHEME_HTTP; + } + + host->addr = g_object_new (SOUP_TYPE_ADDRESS, + SOUP_ADDRESS_NAME, host->uri->host, + SOUP_ADDRESS_PORT, host->uri->port, + SOUP_ADDRESS_PROTOCOL, host->uri->scheme, + NULL); + host->keep_alive_src = NULL; + host->session = session; + + return host; +} + +/* Requires conn_lock to be locked */ +static SoupSessionHost * +get_host_for_uri (SoupSession *session, SoupURI *uri) +{ + SoupSessionPrivate *priv = soup_session_get_instance_private (session); + SoupSessionHost *host; + gboolean https; + SoupURI *uri_tmp = NULL; + + https = soup_uri_is_https (uri, priv->https_aliases); + if (https) + host = g_hash_table_lookup (priv->https_hosts, uri); + else + host = g_hash_table_lookup (priv->http_hosts, uri); + if (host) + return host; + + if (uri->scheme != SOUP_URI_SCHEME_HTTP && + uri->scheme != SOUP_URI_SCHEME_HTTPS) { + uri = uri_tmp = soup_uri_copy (uri); + uri->scheme = https ? SOUP_URI_SCHEME_HTTPS : SOUP_URI_SCHEME_HTTP; + } + host = soup_session_host_new (session, uri); + if (uri_tmp) + soup_uri_free (uri_tmp); + + if (https) + g_hash_table_insert (priv->https_hosts, host->uri, host); + else + g_hash_table_insert (priv->http_hosts, host->uri, host); + + return host; +} + +/* Requires conn_lock to be locked */ +static SoupSessionHost * +get_host_for_message (SoupSession *session, SoupMessage *msg) +{ + return get_host_for_uri (session, soup_message_get_uri (msg)); +} + +static void +free_host (SoupSessionHost *host) +{ + g_warn_if_fail (host->connections == NULL); + + if (host->keep_alive_src) { + g_source_destroy (host->keep_alive_src); + g_source_unref (host->keep_alive_src); + } + + soup_uri_free (host->uri); + g_object_unref (host->addr); + g_slice_free (SoupSessionHost, host); +} + +static void +auth_manager_authenticate (SoupAuthManager *manager, SoupMessage *msg, + SoupAuth *auth, gboolean retrying, + gpointer session) +{ + g_signal_emit (session, signals[AUTHENTICATE], 0, msg, auth, retrying); +} + +#define SOUP_SESSION_WOULD_REDIRECT_AS_GET(session, msg) \ + ((msg)->status_code == SOUP_STATUS_SEE_OTHER || \ + ((msg)->status_code == SOUP_STATUS_FOUND && \ + !SOUP_METHOD_IS_SAFE ((msg)->method)) || \ + ((msg)->status_code == SOUP_STATUS_MOVED_PERMANENTLY && \ + (msg)->method == SOUP_METHOD_POST)) + +#define SOUP_SESSION_WOULD_REDIRECT_AS_SAFE(session, msg) \ + (((msg)->status_code == SOUP_STATUS_MOVED_PERMANENTLY || \ + (msg)->status_code == SOUP_STATUS_TEMPORARY_REDIRECT || \ + (msg)->status_code == SOUP_STATUS_FOUND) && \ + SOUP_METHOD_IS_SAFE ((msg)->method)) + +static inline SoupURI * +redirection_uri (SoupMessage *msg) +{ + const char *new_loc; + SoupURI *new_uri; + + new_loc = soup_message_headers_get_one (msg->response_headers, + "Location"); + if (!new_loc) + return NULL; + new_uri = soup_uri_new_with_base (soup_message_get_uri (msg), new_loc); + if (!new_uri || !new_uri->host) { + if (new_uri) + soup_uri_free (new_uri); + return NULL; + } + + return new_uri; +} + +/** + * soup_session_would_redirect: + * @session: a #SoupSession + * @msg: a #SoupMessage that has response headers + * + * Checks if @msg contains a response that would cause @session to + * redirect it to a new URL (ignoring @msg's %SOUP_MESSAGE_NO_REDIRECT + * flag, and the number of times it has already been redirected). + * + * Return value: whether @msg would be redirected + * + * Since: 2.38 + */ +gboolean +soup_session_would_redirect (SoupSession *session, SoupMessage *msg) +{ + SoupSessionPrivate *priv = soup_session_get_instance_private (session); + SoupURI *new_uri; + + /* It must have an appropriate status code and method */ + if (!SOUP_SESSION_WOULD_REDIRECT_AS_GET (session, msg) && + !SOUP_SESSION_WOULD_REDIRECT_AS_SAFE (session, msg)) + return FALSE; + + /* and a Location header that parses to an http URI */ + if (!soup_message_headers_get_one (msg->response_headers, "Location")) + return FALSE; + new_uri = redirection_uri (msg); + if (!new_uri) + return FALSE; + if (!new_uri->host || !*new_uri->host || + (!soup_uri_is_http (new_uri, priv->http_aliases) && + !soup_uri_is_https (new_uri, priv->https_aliases))) { + soup_uri_free (new_uri); + return FALSE; + } + + soup_uri_free (new_uri); + return TRUE; +} + +/** + * soup_session_redirect_message: + * @session: the session + * @msg: a #SoupMessage that has received a 3xx response + * + * Updates @msg's URI according to its status code and "Location" + * header, and requeues it on @session. Use this when you have set + * %SOUP_MESSAGE_NO_REDIRECT on a message, but have decided to allow a + * particular redirection to occur, or if you want to allow a + * redirection that #SoupSession will not perform automatically (eg, + * redirecting a non-safe method such as DELETE). + * + * If @msg's status code indicates that it should be retried as a GET + * request, then @msg will be modified accordingly. + * + * If @msg has already been redirected too many times, this will + * cause it to fail with %SOUP_STATUS_TOO_MANY_REDIRECTS. + * + * Return value: %TRUE if a redirection was applied, %FALSE if not + * (eg, because there was no Location header, or it could not be + * parsed). + * + * Since: 2.38 + */ +gboolean +soup_session_redirect_message (SoupSession *session, SoupMessage *msg) +{ + SoupURI *new_uri; + + new_uri = redirection_uri (msg); + if (!new_uri) + return FALSE; + + if (SOUP_SESSION_WOULD_REDIRECT_AS_GET (session, msg)) { + if (msg->method != SOUP_METHOD_HEAD) { + g_object_set (msg, + SOUP_MESSAGE_METHOD, SOUP_METHOD_GET, + NULL); + } + soup_message_set_request (msg, NULL, + SOUP_MEMORY_STATIC, NULL, 0); + soup_message_headers_set_encoding (msg->request_headers, + SOUP_ENCODING_NONE); + } + + soup_message_set_uri (msg, new_uri); + soup_uri_free (new_uri); + + soup_session_requeue_message (session, msg); + return TRUE; +} + +static void +redirect_handler (SoupMessage *msg, gpointer user_data) +{ + SoupMessageQueueItem *item = user_data; + SoupSession *session = item->session; + + if (!soup_session_would_redirect (session, msg)) { + SoupURI *new_uri = redirection_uri (msg); + gboolean invalid = !new_uri || !new_uri->host; + + if (new_uri) + soup_uri_free (new_uri); + if (invalid && !item->new_api) { + soup_message_set_status_full (msg, + SOUP_STATUS_MALFORMED, + "Invalid Redirect URL"); + } + return; + } + + soup_session_redirect_message (session, msg); +} + +static void +re_emit_connection_event (SoupConnection *conn, + GSocketClientEvent event, + GIOStream *connection, + gpointer user_data) +{ + SoupMessageQueueItem *item = user_data; + + soup_message_network_event (item->msg, event, connection); +} + +static void +soup_session_set_item_connection (SoupSession *session, + SoupMessageQueueItem *item, + SoupConnection *conn) +{ + if (item->conn) { + g_signal_handlers_disconnect_by_func (item->conn, re_emit_connection_event, item); + g_object_unref (item->conn); + } + + item->conn = conn; + item->conn_is_dedicated = FALSE; + soup_message_set_connection (item->msg, conn); + + if (item->conn) { + g_object_ref (item->conn); + g_signal_connect (item->conn, "event", + G_CALLBACK (re_emit_connection_event), item); + } +} + +static void +message_restarted (SoupMessage *msg, gpointer user_data) +{ + SoupMessageQueueItem *item = user_data; + + if (item->conn && + (!soup_message_is_keepalive (msg) || + SOUP_STATUS_IS_REDIRECTION (msg->status_code))) { + if (soup_connection_get_state (item->conn) == SOUP_CONNECTION_IN_USE) + soup_connection_set_state (item->conn, SOUP_CONNECTION_IDLE); + soup_session_set_item_connection (item->session, item, NULL); + } + + soup_message_cleanup_response (msg); +} + +SoupMessageQueueItem * +soup_session_append_queue_item (SoupSession *session, SoupMessage *msg, + gboolean async, gboolean new_api, + SoupSessionCallback callback, gpointer user_data) +{ + SoupSessionPrivate *priv = soup_session_get_instance_private (session); + SoupMessageQueueItem *item; + SoupSessionHost *host; + + soup_message_cleanup_response (msg); + + item = soup_message_queue_append (priv->queue, msg, callback, user_data); + item->async = async; + item->new_api = new_api; + + g_mutex_lock (&priv->conn_lock); + host = get_host_for_message (session, item->msg); + host->num_messages++; + g_mutex_unlock (&priv->conn_lock); + + if (!(soup_message_get_flags (msg) & SOUP_MESSAGE_NO_REDIRECT)) { + soup_message_add_header_handler ( + msg, "got_body", "Location", + G_CALLBACK (redirect_handler), item); + } + g_signal_connect (msg, "restarted", + G_CALLBACK (message_restarted), item); + + g_signal_emit (session, signals[REQUEST_QUEUED], 0, msg); + + soup_message_queue_item_ref (item); + return item; +} + +static void +soup_session_send_queue_item (SoupSession *session, + SoupMessageQueueItem *item, + SoupMessageCompletionFn completion_cb) +{ + SoupSessionPrivate *priv = soup_session_get_instance_private (session); + + if (priv->user_agent) { + soup_message_headers_replace (item->msg->request_headers, + "User-Agent", priv->user_agent); + } + + if (priv->accept_language && + !soup_message_headers_get_list (item->msg->request_headers, + "Accept-Language")) { + soup_message_headers_append (item->msg->request_headers, + "Accept-Language", + priv->accept_language); + } + + /* Force keep alive connections for HTTP 1.0. Performance will + * improve when issuing multiple requests to the same host in + * a short period of time, as we wouldn't need to establish + * new connections. Keep alive is implicit for HTTP 1.1. + */ + if (!soup_message_headers_header_contains (item->msg->request_headers, + "Connection", "Keep-Alive") && + !soup_message_headers_header_contains (item->msg->request_headers, + "Connection", "close") && + !soup_message_headers_header_contains (item->msg->request_headers, + "Connection", "Upgrade")) { + soup_message_headers_append (item->msg->request_headers, + "Connection", "Keep-Alive"); + } + + g_signal_emit (session, signals[REQUEST_STARTED], 0, + item->msg, soup_connection_get_socket (item->conn)); + soup_message_starting (item->msg); + if (item->state == SOUP_MESSAGE_RUNNING) + soup_connection_send_request (item->conn, item, completion_cb, item); +} + +static gboolean +soup_session_cleanup_connections (SoupSession *session, + gboolean cleanup_idle) +{ + SoupSessionPrivate *priv = soup_session_get_instance_private (session); + GSList *conns = NULL, *c; + GHashTableIter iter; + gpointer conn, host; + SoupConnectionState state; + + g_mutex_lock (&priv->conn_lock); + g_hash_table_iter_init (&iter, priv->conns); + while (g_hash_table_iter_next (&iter, &conn, &host)) { + state = soup_connection_get_state (conn); + if (state == SOUP_CONNECTION_REMOTE_DISCONNECTED || + (cleanup_idle && state == SOUP_CONNECTION_IDLE)) { + conns = g_slist_prepend (conns, g_object_ref (conn)); + g_hash_table_iter_remove (&iter); + drop_connection (session, host, conn); + } + } + g_mutex_unlock (&priv->conn_lock); + + if (!conns) + return FALSE; + + for (c = conns; c; c = c->next) { + conn = c->data; + soup_connection_disconnect (conn); + g_object_unref (conn); + } + g_slist_free (conns); + + return TRUE; +} + +static gboolean +free_unused_host (gpointer user_data) +{ + SoupSessionHost *host = (SoupSessionHost *) user_data; + SoupSessionPrivate *priv = soup_session_get_instance_private (host->session); + + g_mutex_lock (&priv->conn_lock); + + /* In a multithreaded session, a connection might have been + * added while we were waiting for conn_lock. + */ + if (host->connections) { + g_mutex_unlock (&priv->conn_lock); + return FALSE; + } + + /* This will free the host in addition to removing it from the + * hash table + */ + if (host->uri->scheme == SOUP_URI_SCHEME_HTTPS) + g_hash_table_remove (priv->https_hosts, host->uri); + else + g_hash_table_remove (priv->http_hosts, host->uri); + g_mutex_unlock (&priv->conn_lock); + + return FALSE; +} + +static void +drop_connection (SoupSession *session, SoupSessionHost *host, SoupConnection *conn) +{ + SoupSessionPrivate *priv = soup_session_get_instance_private (session); + + /* Note: caller must hold conn_lock, and must remove @conn + * from priv->conns itself. + */ + + if (host) { + host->connections = g_slist_remove (host->connections, conn); + host->num_conns--; + + /* Free the SoupHost (and its SoupAddress) if there + * has not been any new connection to the host during + * the last HOST_KEEP_ALIVE msecs. + */ + if (host->num_conns == 0) { + g_assert (host->keep_alive_src == NULL); + host->keep_alive_src = soup_add_timeout (priv->async_context, + HOST_KEEP_ALIVE, + free_unused_host, + host); + host->keep_alive_src = g_source_ref (host->keep_alive_src); + } + } + + g_signal_handlers_disconnect_by_func (conn, connection_disconnected, session); + g_signal_handlers_disconnect_by_func (conn, connection_state_changed, session); + priv->num_conns--; + + g_object_unref (conn); +} + +static void +connection_disconnected (SoupConnection *conn, gpointer user_data) +{ + SoupSession *session = user_data; + SoupSessionPrivate *priv = soup_session_get_instance_private (session); + SoupSessionHost *host; + + g_mutex_lock (&priv->conn_lock); + + host = g_hash_table_lookup (priv->conns, conn); + if (host) + g_hash_table_remove (priv->conns, conn); + drop_connection (session, host, conn); + + g_mutex_unlock (&priv->conn_lock); + + soup_session_kick_queue (session); +} + +static void +connection_state_changed (GObject *object, GParamSpec *param, gpointer user_data) +{ + SoupSession *session = user_data; + SoupConnection *conn = SOUP_CONNECTION (object); + + if (soup_connection_get_state (conn) == SOUP_CONNECTION_IDLE) + soup_session_kick_queue (session); +} + +SoupMessageQueue * +soup_session_get_queue (SoupSession *session) +{ + SoupSessionPrivate *priv = soup_session_get_instance_private (session); + + return priv->queue; +} + +static void +soup_session_unqueue_item (SoupSession *session, + SoupMessageQueueItem *item) +{ + SoupSessionPrivate *priv = soup_session_get_instance_private (session); + SoupSessionHost *host; + SoupConnection *dedicated_conn = NULL; + + if (item->conn) { + if (item->conn_is_dedicated) + dedicated_conn = g_object_ref (item->conn); + else if (item->msg->method != SOUP_METHOD_CONNECT || + !SOUP_STATUS_IS_SUCCESSFUL (item->msg->status_code)) + soup_connection_set_state (item->conn, SOUP_CONNECTION_IDLE); + soup_session_set_item_connection (session, item, NULL); + } + + if (item->state != SOUP_MESSAGE_FINISHED) { + g_warning ("finished an item with state %d", item->state); + return; + } + + soup_message_queue_remove (priv->queue, item); + + g_mutex_lock (&priv->conn_lock); + host = get_host_for_message (session, item->msg); + host->num_messages--; + if (dedicated_conn) { + /* FIXME: Do not drop the connection if current number of connections + * is no longer over the limits, just mark it as IDLE so it can be reused. + */ + g_hash_table_remove (priv->conns, dedicated_conn); + drop_connection (session, host, dedicated_conn); + } + g_cond_broadcast (&priv->conn_cond); + g_mutex_unlock (&priv->conn_lock); + + if (dedicated_conn) { + soup_connection_disconnect (dedicated_conn); + g_object_unref (dedicated_conn); + } + + /* g_signal_handlers_disconnect_by_func doesn't work if you + * have a metamarshal, meaning it doesn't work with + * soup_message_add_header_handler() + */ + g_signal_handlers_disconnect_matched (item->msg, G_SIGNAL_MATCH_DATA, + 0, 0, NULL, NULL, item); + g_signal_emit (session, signals[REQUEST_UNQUEUED], 0, item->msg); + soup_message_queue_item_unref (item); +} + +static void +soup_session_set_item_status (SoupSession *session, + SoupMessageQueueItem *item, + guint status_code, + GError *error) +{ + SoupURI *uri = NULL; + + switch (status_code) { + case SOUP_STATUS_CANT_RESOLVE: + case SOUP_STATUS_CANT_CONNECT: + uri = soup_message_get_uri (item->msg); + break; + + case SOUP_STATUS_CANT_RESOLVE_PROXY: + case SOUP_STATUS_CANT_CONNECT_PROXY: + if (item->conn) + uri = soup_connection_get_proxy_uri (item->conn); + break; + + case SOUP_STATUS_SSL_FAILED: + if (!g_tls_backend_supports_tls (g_tls_backend_get_default ())) { + soup_message_set_status_full (item->msg, status_code, + "TLS/SSL support not available; install glib-networking"); + return; + } + break; + + default: + break; + } + + if (error) + soup_message_set_status_full (item->msg, status_code, error->message); + else if (uri && uri->host) { + char *msg = g_strdup_printf ("%s (%s)", + soup_status_get_phrase (status_code), + uri->host); + soup_message_set_status_full (item->msg, status_code, msg); + g_free (msg); + } else + soup_message_set_status (item->msg, status_code); +} + + +static void +message_completed (SoupMessage *msg, SoupMessageIOCompletion completion, gpointer user_data) +{ + SoupMessageQueueItem *item = user_data; + + if (item->async) + soup_session_kick_queue (item->session); + + if (completion == SOUP_MESSAGE_IO_STOLEN) { + item->state = SOUP_MESSAGE_FINISHED; + soup_session_unqueue_item (item->session, item); + return; + } + + if (item->state != SOUP_MESSAGE_RESTARTING) { + item->state = SOUP_MESSAGE_FINISHING; + + if (item->new_api && !item->async) + soup_session_process_queue_item (item->session, item, NULL, TRUE); + } +} + +static guint +status_from_connect_error (SoupMessageQueueItem *item, GError *error) +{ + guint status; + + if (!error) + return SOUP_STATUS_OK; + + if (error->domain == G_TLS_ERROR) + status = SOUP_STATUS_SSL_FAILED; + else if (error->domain == G_RESOLVER_ERROR) + status = SOUP_STATUS_CANT_RESOLVE; + else if (error->domain == G_IO_ERROR) { + if (error->code == G_IO_ERROR_CANCELLED) + status = SOUP_STATUS_CANCELLED; + else if (error->code == G_IO_ERROR_HOST_UNREACHABLE || + error->code == G_IO_ERROR_NETWORK_UNREACHABLE || + error->code == G_IO_ERROR_CONNECTION_REFUSED) + status = SOUP_STATUS_CANT_CONNECT; + else if (error->code == G_IO_ERROR_PROXY_FAILED || + error->code == G_IO_ERROR_PROXY_AUTH_FAILED || + error->code == G_IO_ERROR_PROXY_NEED_AUTH || + error->code == G_IO_ERROR_PROXY_NOT_ALLOWED) + status = SOUP_STATUS_CANT_CONNECT_PROXY; + else + status = SOUP_STATUS_IO_ERROR; + } else + status = SOUP_STATUS_IO_ERROR; + + if (item->conn && soup_connection_is_via_proxy (item->conn)) + return soup_status_proxify (status); + else + return status; +} + +static void +tunnel_complete (SoupMessageQueueItem *tunnel_item, + guint status, GError *error) +{ + SoupMessageQueueItem *item = tunnel_item->related; + SoupSession *session = tunnel_item->session; + + soup_message_finished (tunnel_item->msg); + soup_message_queue_item_unref (tunnel_item); + + if (item->msg->status_code) + item->state = SOUP_MESSAGE_FINISHING; + soup_message_set_https_status (item->msg, item->conn); + + item->error = error; + if (!status) + status = status_from_connect_error (item, error); + if (!SOUP_STATUS_IS_SUCCESSFUL (status)) { + soup_connection_disconnect (item->conn); + soup_session_set_item_connection (session, item, NULL); + if (!item->new_api || item->msg->status_code == 0) + soup_session_set_item_status (session, item, status, error); + } + + item->state = SOUP_MESSAGE_READY; + if (item->async) + soup_session_kick_queue (session); + soup_message_queue_item_unref (item); +} + +static void +tunnel_handshake_complete (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + SoupConnection *conn = SOUP_CONNECTION (object); + SoupMessageQueueItem *tunnel_item = user_data; + GError *error = NULL; + + soup_connection_start_ssl_finish (conn, result, &error); + tunnel_complete (tunnel_item, 0, error); +} + +static void +tunnel_message_completed (SoupMessage *msg, SoupMessageIOCompletion completion, + gpointer user_data) +{ + SoupMessageQueueItem *tunnel_item = user_data; + SoupMessageQueueItem *item = tunnel_item->related; + SoupSession *session = tunnel_item->session; + guint status; + + if (tunnel_item->state == SOUP_MESSAGE_RESTARTING) { + soup_message_restarted (msg); + if (tunnel_item->conn) { + tunnel_item->state = SOUP_MESSAGE_RUNNING; + soup_session_send_queue_item (session, tunnel_item, + tunnel_message_completed); + return; + } + + soup_message_set_status (msg, SOUP_STATUS_TRY_AGAIN); + } + + tunnel_item->state = SOUP_MESSAGE_FINISHED; + soup_session_unqueue_item (session, tunnel_item); + + status = tunnel_item->msg->status_code; + if (!SOUP_STATUS_IS_SUCCESSFUL (status)) { + tunnel_complete (tunnel_item, status, NULL); + return; + } + + if (tunnel_item->async) { + soup_connection_start_ssl_async (item->conn, item->cancellable, + tunnel_handshake_complete, + tunnel_item); + } else { + GError *error = NULL; + + soup_connection_start_ssl_sync (item->conn, item->cancellable, &error); + tunnel_complete (tunnel_item, 0, error); + } +} + +static void +tunnel_connect (SoupMessageQueueItem *item) +{ + SoupSession *session = item->session; + SoupMessageQueueItem *tunnel_item; + SoupURI *uri; + SoupMessage *msg; + + item->state = SOUP_MESSAGE_TUNNELING; + + uri = soup_connection_get_remote_uri (item->conn); + msg = soup_message_new_from_uri (SOUP_METHOD_CONNECT, uri); + soup_message_set_flags (msg, SOUP_MESSAGE_NO_REDIRECT); + + tunnel_item = soup_session_append_queue_item (session, msg, + item->async, FALSE, + NULL, NULL); + g_object_unref (msg); + tunnel_item->related = item; + soup_message_queue_item_ref (item); + soup_session_set_item_connection (session, tunnel_item, item->conn); + tunnel_item->state = SOUP_MESSAGE_RUNNING; + + g_signal_emit (session, signals[TUNNELING], 0, tunnel_item->conn); + + soup_session_send_queue_item (session, tunnel_item, + tunnel_message_completed); +} + +static void +connect_complete (SoupMessageQueueItem *item, SoupConnection *conn, GError *error) +{ + SoupSession *session = item->session; + guint status; + + soup_message_set_https_status (item->msg, item->conn); + + if (!error) { + item->state = SOUP_MESSAGE_CONNECTED; + return; + } + + item->error = error; + status = status_from_connect_error (item, error); + soup_connection_disconnect (conn); + if (item->state == SOUP_MESSAGE_CONNECTING) { + if (!item->new_api || item->msg->status_code == 0) + soup_session_set_item_status (session, item, status, error); + soup_session_set_item_connection (session, item, NULL); + item->state = SOUP_MESSAGE_READY; + } +} + +static void +connect_async_complete (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + SoupConnection *conn = SOUP_CONNECTION (object); + SoupMessageQueueItem *item = user_data; + GError *error = NULL; + + soup_connection_connect_finish (conn, result, &error); + connect_complete (item, conn, error); + + if (item->state == SOUP_MESSAGE_CONNECTED || + item->state == SOUP_MESSAGE_READY) + async_run_queue (item->session); + else + soup_session_kick_queue (item->session); + + soup_message_queue_item_unref (item); +} + +/* requires conn_lock */ +static SoupConnection * +get_connection_for_host (SoupSession *session, + SoupMessageQueueItem *item, + SoupSessionHost *host, + gboolean need_new_connection, + gboolean ignore_connection_limits, + gboolean *try_cleanup, + gboolean *is_dedicated_connection) +{ + SoupSessionPrivate *priv = soup_session_get_instance_private (session); + SoupConnection *conn; + GSList *conns; + guint num_pending = 0; + + if (priv->disposed) + return NULL; + + if (item->conn) { + g_return_val_if_fail (soup_connection_get_state (item->conn) != SOUP_CONNECTION_DISCONNECTED, FALSE); + return item->conn; + } + + for (conns = host->connections; conns; conns = conns->next) { + conn = conns->data; + + if (!need_new_connection && soup_connection_get_state (conn) == SOUP_CONNECTION_IDLE) { + soup_connection_set_state (conn, SOUP_CONNECTION_IN_USE); + return conn; + } else if (soup_connection_get_state (conn) == SOUP_CONNECTION_CONNECTING) + num_pending++; + } + + /* Limit the number of pending connections; num_messages / 2 + * is somewhat arbitrary... + */ + if (num_pending > host->num_messages / 2) { + if (!ignore_connection_limits) + return NULL; + + *is_dedicated_connection = TRUE; + } + + if (host->num_conns >= priv->max_conns_per_host) { + if (!ignore_connection_limits) { + if (need_new_connection) + *try_cleanup = TRUE; + return NULL; + } + + *is_dedicated_connection = TRUE; + } + + if (priv->num_conns >= priv->max_conns) { + if (!ignore_connection_limits) { + *try_cleanup = TRUE; + return NULL; + } + + *is_dedicated_connection = TRUE; + } + + ensure_socket_props (session); + conn = g_object_new (SOUP_TYPE_CONNECTION, + SOUP_CONNECTION_REMOTE_URI, host->uri, + SOUP_CONNECTION_SSL, soup_uri_is_https (host->uri, priv->https_aliases), + SOUP_CONNECTION_SOCKET_PROPERTIES, priv->socket_props, + NULL); + + g_signal_connect (conn, "disconnected", + G_CALLBACK (connection_disconnected), + session); + g_signal_connect (conn, "notify::state", + G_CALLBACK (connection_state_changed), + session); + + /* This is a debugging-related signal, and so can ignore the + * usual rule about not emitting signals while holding + * conn_lock. + */ + g_signal_emit (session, signals[CONNECTION_CREATED], 0, conn); + + g_hash_table_insert (priv->conns, conn, host); + + priv->num_conns++; + host->num_conns++; + host->connections = g_slist_prepend (host->connections, conn); + + if (host->keep_alive_src) { + g_source_destroy (host->keep_alive_src); + g_source_unref (host->keep_alive_src); + host->keep_alive_src = NULL; + } + + return conn; +} + +static gboolean +get_connection (SoupMessageQueueItem *item, gboolean *should_cleanup) +{ + SoupSession *session = item->session; + SoupSessionPrivate *priv = soup_session_get_instance_private (session); + SoupSessionHost *host; + SoupConnection *conn = NULL; + gboolean my_should_cleanup = FALSE; + gboolean need_new_connection; + gboolean ignore_connection_limits; + gboolean is_dedicated_connection = FALSE; + + soup_session_cleanup_connections (session, FALSE); + + need_new_connection = + (soup_message_get_flags (item->msg) & SOUP_MESSAGE_NEW_CONNECTION) || + (!(soup_message_get_flags (item->msg) & SOUP_MESSAGE_IDEMPOTENT) && + !SOUP_METHOD_IS_IDEMPOTENT (item->msg->method)); + ignore_connection_limits = + (soup_message_get_flags (item->msg) & SOUP_MESSAGE_IGNORE_CONNECTION_LIMITS); + + g_mutex_lock (&priv->conn_lock); + host = get_host_for_message (session, item->msg); + while (TRUE) { + conn = get_connection_for_host (session, item, host, + need_new_connection, + ignore_connection_limits, + &my_should_cleanup, + &is_dedicated_connection); + if (conn || item->async) + break; + + if (my_should_cleanup) { + g_mutex_unlock (&priv->conn_lock); + soup_session_cleanup_connections (session, TRUE); + g_mutex_lock (&priv->conn_lock); + + my_should_cleanup = FALSE; + continue; + } + + g_cond_wait (&priv->conn_cond, &priv->conn_lock); + } + g_mutex_unlock (&priv->conn_lock); + + if (!conn) { + if (should_cleanup) + *should_cleanup = my_should_cleanup; + return FALSE; + } + + soup_session_set_item_connection (session, item, conn); + item->conn_is_dedicated = is_dedicated_connection; + + if (soup_connection_get_state (item->conn) != SOUP_CONNECTION_NEW) { + item->state = SOUP_MESSAGE_READY; + soup_message_set_https_status (item->msg, item->conn); + return TRUE; + } + + item->state = SOUP_MESSAGE_CONNECTING; + + if (item->async) { + soup_message_queue_item_ref (item); + soup_connection_connect_async (item->conn, item->cancellable, + connect_async_complete, item); + return FALSE; + } else { + GError *error = NULL; + + soup_connection_connect_sync (item->conn, item->cancellable, &error); + connect_complete (item, conn, error); + + return TRUE; + } +} + +void +soup_session_process_queue_item (SoupSession *session, + SoupMessageQueueItem *item, + gboolean *should_cleanup, + gboolean loop) +{ + g_assert (item->session == session); + + do { + if (item->paused) + return; + + switch (item->state) { + case SOUP_MESSAGE_STARTING: + if (!get_connection (item, should_cleanup)) + return; + break; + + case SOUP_MESSAGE_CONNECTED: + if (soup_connection_is_tunnelled (item->conn)) + tunnel_connect (item); + else + item->state = SOUP_MESSAGE_READY; + break; + + case SOUP_MESSAGE_READY: + if (item->connect_only) { + item->state = SOUP_MESSAGE_FINISHING; + break; + } + + if (item->msg->status_code) { + if (item->msg->status_code == SOUP_STATUS_TRY_AGAIN) { + soup_message_cleanup_response (item->msg); + item->state = SOUP_MESSAGE_STARTING; + } else + item->state = SOUP_MESSAGE_FINISHING; + break; + } + + item->state = SOUP_MESSAGE_RUNNING; + + soup_session_send_queue_item (session, item, message_completed); + + if (item->new_api) { + if (item->async) + async_send_request_running (session, item); + return; + } + break; + + case SOUP_MESSAGE_RUNNING: + if (item->async) + return; + + g_warn_if_fail (item->new_api); + item->state = SOUP_MESSAGE_FINISHING; + break; + + case SOUP_MESSAGE_CACHED: + /* Will be handled elsewhere */ + return; + + case SOUP_MESSAGE_RESTARTING: + item->state = SOUP_MESSAGE_STARTING; + soup_message_restarted (item->msg); + break; + + case SOUP_MESSAGE_FINISHING: + item->state = SOUP_MESSAGE_FINISHED; + soup_message_finished (item->msg); + if (item->state != SOUP_MESSAGE_FINISHED) { + g_return_if_fail (!item->new_api); + break; + } + + soup_message_queue_item_ref (item); + soup_session_unqueue_item (session, item); + if (item->async && item->callback) + item->callback (session, item->msg, item->callback_data); + soup_message_queue_item_unref (item); + return; + + default: + /* Nothing to do with this message in any + * other state. + */ + g_warn_if_fail (item->async); + return; + } + } while (loop && item->state != SOUP_MESSAGE_FINISHED); +} + +static void +async_run_queue (SoupSession *session) +{ + SoupSessionPrivate *priv = soup_session_get_instance_private (session); + SoupMessageQueueItem *item; + SoupMessage *msg; + gboolean try_cleanup = TRUE, should_cleanup = FALSE; + + g_object_ref (session); + soup_session_cleanup_connections (session, FALSE); + + try_again: + for (item = soup_message_queue_first (priv->queue); + item; + item = soup_message_queue_next (priv->queue, item)) { + msg = item->msg; + + /* CONNECT messages are handled specially */ + if (msg->method == SOUP_METHOD_CONNECT) + continue; + + if (!item->async || + item->async_context != soup_session_get_async_context (session)) + continue; + + item->async_pending = FALSE; + soup_session_process_queue_item (session, item, &should_cleanup, TRUE); + } + + if (try_cleanup && should_cleanup) { + /* There is at least one message in the queue that + * could be sent if we cleanupd an idle connection from + * some other server. + */ + if (soup_session_cleanup_connections (session, TRUE)) { + try_cleanup = should_cleanup = FALSE; + goto try_again; + } + } + + g_object_unref (session); +} + +static gboolean +idle_run_queue (gpointer user_data) +{ + GWeakRef *wref = user_data; + SoupSession *session; + + session = g_weak_ref_get (wref); + if (!session) + return FALSE; + + async_run_queue (session); + g_object_unref (session); + return FALSE; +} + +static void +idle_run_queue_dnotify (gpointer user_data) +{ + GWeakRef *wref = user_data; + + g_weak_ref_clear (wref); + g_slice_free (GWeakRef, wref); +} + +/** + * SoupSessionCallback: + * @session: the session + * @msg: the message that has finished + * @user_data: the data passed to soup_session_queue_message + * + * Prototype for the callback passed to soup_session_queue_message(), + * qv. + **/ + +static void +soup_session_real_queue_message (SoupSession *session, SoupMessage *msg, + SoupSessionCallback callback, gpointer user_data) +{ + SoupMessageQueueItem *item; + + item = soup_session_append_queue_item (session, msg, TRUE, FALSE, + callback, user_data); + soup_session_kick_queue (session); + soup_message_queue_item_unref (item); +} + +/** + * soup_session_queue_message: + * @session: a #SoupSession + * @msg: (transfer full): the message to queue + * @callback: (allow-none) (scope async): a #SoupSessionCallback which will + * be called after the message completes or when an unrecoverable error occurs. + * @user_data: (allow-none): a pointer passed to @callback. + * + * Queues the message @msg for asynchronously sending the request and + * receiving a response in the current thread-default #GMainContext. + * If @msg has been processed before, any resources related to the + * time it was last sent are freed. + * + * Upon message completion, the callback specified in @callback will + * be invoked. If after returning from this callback the message has not + * been requeued, @msg will be unreffed. + * + * (The behavior above applies to a plain #SoupSession; if you are + * using #SoupSessionAsync or #SoupSessionSync, then the #GMainContext + * that is used depends on the settings of #SoupSession:async-context + * and #SoupSession:use-thread-context, and for #SoupSessionSync, the + * message will actually be sent and processed in another thread, with + * only the final callback occurring in the indicated #GMainContext.) + * + * Contrast this method with soup_session_send_async(), which also + * asynchronously sends a message, but returns before reading the + * response body, and allows you to read the response via a + * #GInputStream. + */ +void +soup_session_queue_message (SoupSession *session, SoupMessage *msg, + SoupSessionCallback callback, gpointer user_data) +{ + g_return_if_fail (SOUP_IS_SESSION (session)); + g_return_if_fail (SOUP_IS_MESSAGE (msg)); + + SOUP_SESSION_GET_CLASS (session)->queue_message (session, msg, + callback, user_data); + /* The SoupMessageQueueItem will hold a ref on @msg until it is + * finished, so we can drop the ref adopted from the caller now. + */ + g_object_unref (msg); +} + +static void +soup_session_real_requeue_message (SoupSession *session, SoupMessage *msg) +{ + SoupSessionPrivate *priv = soup_session_get_instance_private (session); + SoupMessageQueueItem *item; + + item = soup_message_queue_lookup (priv->queue, msg); + g_return_if_fail (item != NULL); + + if (item->resend_count >= SOUP_SESSION_MAX_RESEND_COUNT) { + if (SOUP_STATUS_IS_REDIRECTION (msg->status_code)) + soup_message_set_status (msg, SOUP_STATUS_TOO_MANY_REDIRECTS); + else + g_warning ("SoupMessage %p stuck in infinite loop?", msg); + } else { + item->resend_count++; + item->state = SOUP_MESSAGE_RESTARTING; + } + + soup_message_queue_item_unref (item); +} + +/** + * soup_session_requeue_message: + * @session: a #SoupSession + * @msg: the message to requeue + * + * This causes @msg to be placed back on the queue to be attempted + * again. + **/ +void +soup_session_requeue_message (SoupSession *session, SoupMessage *msg) +{ + g_return_if_fail (SOUP_IS_SESSION (session)); + g_return_if_fail (SOUP_IS_MESSAGE (msg)); + + SOUP_SESSION_GET_CLASS (session)->requeue_message (session, msg); +} + +static guint +soup_session_real_send_message (SoupSession *session, SoupMessage *msg) +{ + SoupMessageQueueItem *item; + guint status; + + item = soup_session_append_queue_item (session, msg, FALSE, FALSE, + NULL, NULL); + soup_session_process_queue_item (session, item, NULL, TRUE); + status = msg->status_code; + soup_message_queue_item_unref (item); + return status; +} + +/** + * soup_session_send_message: + * @session: a #SoupSession + * @msg: the message to send + * + * Synchronously send @msg. This call will not return until the + * transfer is finished successfully or there is an unrecoverable + * error. + * + * Unlike with soup_session_queue_message(), @msg is not freed upon + * return. + * + * (Note that if you call this method on a #SoupSessionAsync, it will + * still use asynchronous I/O internally, running the glib main loop + * to process the message, which may also cause other events to be + * processed.) + * + * Contrast this method with soup_session_send(), which also + * synchronously sends a message, but returns before reading the + * response body, and allows you to read the response via a + * #GInputStream. + * + * Return value: the HTTP status code of the response + */ +guint +soup_session_send_message (SoupSession *session, SoupMessage *msg) +{ + g_return_val_if_fail (SOUP_IS_SESSION (session), SOUP_STATUS_MALFORMED); + g_return_val_if_fail (SOUP_IS_MESSAGE (msg), SOUP_STATUS_MALFORMED); + + return SOUP_SESSION_GET_CLASS (session)->send_message (session, msg); +} + + +/** + * soup_session_pause_message: + * @session: a #SoupSession + * @msg: a #SoupMessage currently running on @session + * + * Pauses HTTP I/O on @msg. Call soup_session_unpause_message() to + * resume I/O. + * + * This may only be called for asynchronous messages (those sent on a + * #SoupSessionAsync or using soup_session_queue_message()). + **/ +void +soup_session_pause_message (SoupSession *session, + SoupMessage *msg) +{ + SoupSessionPrivate *priv; + SoupMessageQueueItem *item; + + g_return_if_fail (SOUP_IS_SESSION (session)); + g_return_if_fail (SOUP_IS_MESSAGE (msg)); + + priv = soup_session_get_instance_private (session); + item = soup_message_queue_lookup (priv->queue, msg); + g_return_if_fail (item != NULL); + g_return_if_fail (item->async); + + item->paused = TRUE; + if (item->state == SOUP_MESSAGE_RUNNING) + soup_message_io_pause (msg); + soup_message_queue_item_unref (item); +} + +static void +soup_session_real_kick_queue (SoupSession *session) +{ + SoupSessionPrivate *priv = soup_session_get_instance_private (session); + SoupMessageQueueItem *item; + GHashTable *async_pending; + gboolean have_sync_items = FALSE; + + if (priv->disposed) + return; + + async_pending = g_hash_table_new (NULL, NULL); + for (item = soup_message_queue_first (priv->queue); + item; + item = soup_message_queue_next (priv->queue, item)) { + if (item->async) { + GMainContext *context = item->async_context ? item->async_context : g_main_context_default (); + + if (!g_hash_table_contains (async_pending, context)) { + if (!item->async_pending) { + GWeakRef *wref = g_slice_new (GWeakRef); + GSource *source; + + g_weak_ref_init (wref, session); + source = soup_add_completion_reffed (context, idle_run_queue, wref, idle_run_queue_dnotify); + g_source_unref (source); + } + g_hash_table_add (async_pending, context); + } + item->async_pending = TRUE; + } else + have_sync_items = TRUE; + } + g_hash_table_unref (async_pending); + + if (have_sync_items) { + g_mutex_lock (&priv->conn_lock); + g_cond_broadcast (&priv->conn_cond); + g_mutex_unlock (&priv->conn_lock); + } +} + +void +soup_session_kick_queue (SoupSession *session) +{ + SOUP_SESSION_GET_CLASS (session)->kick (session); +} + +/** + * soup_session_unpause_message: + * @session: a #SoupSession + * @msg: a #SoupMessage currently running on @session + * + * Resumes HTTP I/O on @msg. Use this to resume after calling + * soup_session_pause_message(). + * + * If @msg is being sent via blocking I/O, this will resume reading or + * writing immediately. If @msg is using non-blocking I/O, then + * reading or writing won't resume until you return to the main loop. + * + * This may only be called for asynchronous messages (those sent on a + * #SoupSessionAsync or using soup_session_queue_message()). + **/ +void +soup_session_unpause_message (SoupSession *session, + SoupMessage *msg) +{ + SoupSessionPrivate *priv; + SoupMessageQueueItem *item; + + g_return_if_fail (SOUP_IS_SESSION (session)); + g_return_if_fail (SOUP_IS_MESSAGE (msg)); + + priv = soup_session_get_instance_private (session); + item = soup_message_queue_lookup (priv->queue, msg); + g_return_if_fail (item != NULL); + g_return_if_fail (item->async); + + item->paused = FALSE; + if (item->state == SOUP_MESSAGE_RUNNING) + soup_message_io_unpause (msg); + soup_message_queue_item_unref (item); + + soup_session_kick_queue (session); +} + + +static void +soup_session_real_cancel_message (SoupSession *session, SoupMessage *msg, guint status_code) +{ + SoupSessionPrivate *priv = soup_session_get_instance_private (session); + SoupMessageQueueItem *item; + + item = soup_message_queue_lookup (priv->queue, msg); + g_return_if_fail (item != NULL); + + if (item->paused) { + item->paused = FALSE; + + if (soup_message_io_in_progress (msg)) + soup_message_io_unpause (msg); + } + + soup_message_set_status (msg, status_code); + g_cancellable_cancel (item->cancellable); + + soup_session_kick_queue (item->session); + soup_message_queue_item_unref (item); +} + +/** + * soup_session_cancel_message: + * @session: a #SoupSession + * @msg: the message to cancel + * @status_code: status code to set on @msg (generally + * %SOUP_STATUS_CANCELLED) + * + * Causes @session to immediately finish processing @msg (regardless + * of its current state) with a final status_code of @status_code. You + * may call this at any time after handing @msg off to @session; if + * @session has started sending the request but has not yet received + * the complete response, then it will close the request's connection. + * Note that with requests that have side effects (eg, + * POST, PUT, + * DELETE) it is possible that you might cancel the + * request after the server acts on it, but before it returns a + * response, leaving the remote resource in an unknown state. + * + * If the message is cancelled while its response body is being read, + * then the response body in @msg will be left partially-filled-in. + * The response headers, on the other hand, will always be either + * empty or complete. + * + * Beware that with the deprecated #SoupSessionAsync, messages queued + * with soup_session_queue_message() will have their callbacks invoked + * before soup_session_cancel_message() returns. The plain + * #SoupSession does not have this behavior; cancelling an + * asynchronous message will merely queue its callback to be run after + * returning to the main loop. + **/ +void +soup_session_cancel_message (SoupSession *session, SoupMessage *msg, + guint status_code) +{ + SoupSessionPrivate *priv; + SoupMessageQueueItem *item; + + g_return_if_fail (SOUP_IS_SESSION (session)); + g_return_if_fail (SOUP_IS_MESSAGE (msg)); + + priv = soup_session_get_instance_private (session); + item = soup_message_queue_lookup (priv->queue, msg); + /* If the message is already ending, don't do anything */ + if (!item) + return; + if (item->state == SOUP_MESSAGE_FINISHED) { + soup_message_queue_item_unref (item); + return; + } + + SOUP_SESSION_GET_CLASS (session)->cancel_message (session, msg, status_code); + soup_message_queue_item_unref (item); +} + +static void +soup_session_real_flush_queue (SoupSession *session) +{ + SoupSessionPrivate *priv = soup_session_get_instance_private (session); + SoupMessageQueueItem *item; + GHashTable *current = NULL; + gboolean done = FALSE; + + if (SOUP_IS_SESSION_SYNC (session)) { + /* Record the current contents of the queue */ + current = g_hash_table_new (NULL, NULL); + for (item = soup_message_queue_first (priv->queue); + item; + item = soup_message_queue_next (priv->queue, item)) + g_hash_table_insert (current, item, item); + } + + /* Cancel everything */ + for (item = soup_message_queue_first (priv->queue); + item; + item = soup_message_queue_next (priv->queue, item)) { + soup_session_cancel_message (session, item->msg, + SOUP_STATUS_CANCELLED); + } + + if (SOUP_IS_SESSION_SYNC (session)) { + /* Wait until all of the items in @current have been + * removed from the queue. (This is not the same as + * "wait for the queue to be empty", because the app + * may queue new requests in response to the + * cancellation of the old ones. We don't try to + * cancel those requests as well, since we'd likely + * just end up looping forever.) + */ + g_mutex_lock (&priv->conn_lock); + do { + done = TRUE; + for (item = soup_message_queue_first (priv->queue); + item; + item = soup_message_queue_next (priv->queue, item)) { + if (g_hash_table_lookup (current, item)) + done = FALSE; + } + + if (!done) + g_cond_wait (&priv->conn_cond, &priv->conn_lock); + } while (!done); + g_mutex_unlock (&priv->conn_lock); + + g_hash_table_destroy (current); + } +} + +/** + * soup_session_abort: + * @session: the session + * + * Cancels all pending requests in @session and closes all idle + * persistent connections. + * + * The message cancellation has the same semantics as with + * soup_session_cancel_message(); asynchronous requests on a + * #SoupSessionAsync will have their callback called before + * soup_session_abort() returns. Requests on a plain #SoupSession will + * not. + **/ +void +soup_session_abort (SoupSession *session) +{ + SoupSessionPrivate *priv; + GSList *conns, *c; + GHashTableIter iter; + gpointer conn, host; + + g_return_if_fail (SOUP_IS_SESSION (session)); + priv = soup_session_get_instance_private (session); + + SOUP_SESSION_GET_CLASS (session)->flush_queue (session); + + /* Close all idle connections */ + g_mutex_lock (&priv->conn_lock); + conns = NULL; + g_hash_table_iter_init (&iter, priv->conns); + while (g_hash_table_iter_next (&iter, &conn, &host)) { + SoupConnectionState state; + + state = soup_connection_get_state (conn); + if (state == SOUP_CONNECTION_IDLE || + state == SOUP_CONNECTION_REMOTE_DISCONNECTED) { + conns = g_slist_prepend (conns, g_object_ref (conn)); + g_hash_table_iter_remove (&iter); + drop_connection (session, host, conn); + } + } + g_mutex_unlock (&priv->conn_lock); + + for (c = conns; c; c = c->next) { + soup_connection_disconnect (c->data); + g_object_unref (c->data); + } + + g_slist_free (conns); +} + +static void +prefetch_uri (SoupSession *session, SoupURI *uri, + GCancellable *cancellable, + SoupAddressCallback callback, gpointer user_data) +{ + SoupSessionPrivate *priv; + SoupSessionHost *host; + SoupAddress *addr; + + priv = soup_session_get_instance_private (session); + + g_mutex_lock (&priv->conn_lock); + host = get_host_for_uri (session, uri); + addr = g_object_ref (host->addr); + g_mutex_unlock (&priv->conn_lock); + + soup_address_resolve_async (addr, + soup_session_get_async_context (session), + cancellable, callback, user_data); + g_object_unref (addr); +} + +/** + * soup_session_prepare_for_uri: + * @session: a #SoupSession + * @uri: a #SoupURI which may be required + * + * Tells @session that @uri may be requested shortly, and so the + * session can try to prepare (resolving the domain name, obtaining + * proxy address, etc.) in order to work more quickly once the URI is + * actually requested. + * + * Since: 2.30 + * + * Deprecated: 2.38: use soup_session_prefetch_dns() instead + **/ +void +soup_session_prepare_for_uri (SoupSession *session, SoupURI *uri) +{ + g_return_if_fail (SOUP_IS_SESSION (session)); + g_return_if_fail (uri != NULL); + + if (!uri->host) + return; + + prefetch_uri (session, uri, NULL, NULL, NULL); +} + +/** +* soup_session_prefetch_dns: +* @session: a #SoupSession +* @hostname: a hostname to be resolved +* @cancellable: (allow-none): a #GCancellable object, or %NULL +* @callback: (scope async) (allow-none): callback to call with the +* result, or %NULL +* @user_data: data for @callback +* +* Tells @session that an URI from the given @hostname may be requested +* shortly, and so the session can try to prepare by resolving the +* domain name in advance, in order to work more quickly once the URI +* is actually requested. +* +* If @cancellable is non-%NULL, it can be used to cancel the +* resolution. @callback will still be invoked in this case, with a +* status of %SOUP_STATUS_CANCELLED. +* +* Since: 2.38 +**/ +void +soup_session_prefetch_dns (SoupSession *session, const char *hostname, + GCancellable *cancellable, + SoupAddressCallback callback, gpointer user_data) +{ + SoupURI *uri; + + g_return_if_fail (SOUP_IS_SESSION (session)); + g_return_if_fail (hostname != NULL); + + /* FIXME: Prefetching should work for both HTTP and HTTPS */ + uri = soup_uri_new (NULL); + soup_uri_set_scheme (uri, SOUP_URI_SCHEME_HTTP); + soup_uri_set_host (uri, hostname); + soup_uri_set_path (uri, ""); + + prefetch_uri (session, uri, cancellable, callback, user_data); + soup_uri_free (uri); +} + +/** + * soup_session_add_feature: + * @session: a #SoupSession + * @feature: an object that implements #SoupSessionFeature + * + * Adds @feature's functionality to @session. You can also add a + * feature to the session at construct time by using the + * %SOUP_SESSION_ADD_FEATURE property. + * + * See the main #SoupSession documentation for information on what + * features are present in sessions by default. + * + * Since: 2.24 + **/ +void +soup_session_add_feature (SoupSession *session, SoupSessionFeature *feature) +{ + SoupSessionPrivate *priv; + + g_return_if_fail (SOUP_IS_SESSION (session)); + g_return_if_fail (SOUP_IS_SESSION_FEATURE (feature)); + + priv = soup_session_get_instance_private (session); + + G_GNUC_BEGIN_IGNORE_DEPRECATIONS; + if (SOUP_IS_PROXY_URI_RESOLVER (feature)) { + set_proxy_resolver (session, NULL, + SOUP_PROXY_URI_RESOLVER (feature), + NULL); + } + G_GNUC_END_IGNORE_DEPRECATIONS; + + priv->features = g_slist_prepend (priv->features, g_object_ref (feature)); + g_hash_table_remove_all (priv->features_cache); + soup_session_feature_attach (feature, session); +} + +/** + * soup_session_add_feature_by_type: + * @session: a #SoupSession + * @feature_type: a #GType + * + * If @feature_type is the type of a class that implements + * #SoupSessionFeature, this creates a new feature of that type and + * adds it to @session as with soup_session_add_feature(). You can use + * this when you don't need to customize the new feature in any way. + * + * If @feature_type is not a #SoupSessionFeature type, this gives each + * existing feature on @session the chance to accept @feature_type as + * a "subfeature". This can be used to add new #SoupAuth or + * #SoupRequest types, for instance. + * + * You can also add a feature to the session at construct time by + * using the %SOUP_SESSION_ADD_FEATURE_BY_TYPE property. + * + * See the main #SoupSession documentation for information on what + * features are present in sessions by default. + * + * Since: 2.24 + **/ +void +soup_session_add_feature_by_type (SoupSession *session, GType feature_type) +{ + SoupSessionPrivate *priv; + + g_return_if_fail (SOUP_IS_SESSION (session)); + + priv = soup_session_get_instance_private (session); + + if (g_type_is_a (feature_type, SOUP_TYPE_SESSION_FEATURE)) { + SoupSessionFeature *feature; + + feature = g_object_new (feature_type, NULL); + soup_session_add_feature (session, feature); + g_object_unref (feature); + } else if (g_type_is_a (feature_type, SOUP_TYPE_REQUEST)) { + SoupRequestClass *request_class; + int i; + + request_class = g_type_class_ref (feature_type); + for (i = 0; request_class->schemes[i]; i++) { + g_hash_table_insert (priv->request_types, + (char *)request_class->schemes[i], + GSIZE_TO_POINTER (feature_type)); + } + } else { + GSList *f; + + for (f = priv->features; f; f = f->next) { + if (soup_session_feature_add_feature (f->data, feature_type)) + return; + } + g_warning ("No feature manager for feature of type '%s'", g_type_name (feature_type)); + } +} + +/** + * soup_session_remove_feature: + * @session: a #SoupSession + * @feature: a feature that has previously been added to @session + * + * Removes @feature's functionality from @session. + * + * Since: 2.24 + **/ +void +soup_session_remove_feature (SoupSession *session, SoupSessionFeature *feature) +{ + SoupSessionPrivate *priv; + + g_return_if_fail (SOUP_IS_SESSION (session)); + + priv = soup_session_get_instance_private (session); + if (g_slist_find (priv->features, feature)) { + priv->features = g_slist_remove (priv->features, feature); + g_hash_table_remove_all (priv->features_cache); + soup_session_feature_detach (feature, session); + + G_GNUC_BEGIN_IGNORE_DEPRECATIONS; + if (SOUP_IS_PROXY_URI_RESOLVER (feature)) { + if (SOUP_IS_PROXY_RESOLVER_WRAPPER (priv->proxy_resolver) && + SOUP_PROXY_RESOLVER_WRAPPER (priv->proxy_resolver)->soup_resolver == SOUP_PROXY_URI_RESOLVER (feature)) + g_clear_object (&priv->proxy_resolver); + } + G_GNUC_END_IGNORE_DEPRECATIONS; + + g_object_unref (feature); + } +} + +/** + * soup_session_remove_feature_by_type: + * @session: a #SoupSession + * @feature_type: a #GType + * + * Removes all features of type @feature_type (or any subclass of + * @feature_type) from @session. You can also remove standard features + * from the session at construct time by using the + * %SOUP_SESSION_REMOVE_FEATURE_BY_TYPE property. + * + * Since: 2.24 + **/ +void +soup_session_remove_feature_by_type (SoupSession *session, GType feature_type) +{ + SoupSessionPrivate *priv; + GSList *f; + + g_return_if_fail (SOUP_IS_SESSION (session)); + + priv = soup_session_get_instance_private (session); + + if (g_type_is_a (feature_type, SOUP_TYPE_SESSION_FEATURE)) { + restart: + for (f = priv->features; f; f = f->next) { + if (G_TYPE_CHECK_INSTANCE_TYPE (f->data, feature_type)) { + soup_session_remove_feature (session, f->data); + goto restart; + } + } + G_GNUC_BEGIN_IGNORE_DEPRECATIONS; + if (g_type_is_a (feature_type, SOUP_TYPE_PROXY_URI_RESOLVER)) + priv->proxy_use_default = FALSE; + G_GNUC_END_IGNORE_DEPRECATIONS; + } else if (g_type_is_a (feature_type, SOUP_TYPE_REQUEST)) { + SoupRequestClass *request_class; + int i; + + request_class = g_type_class_peek (feature_type); + if (!request_class) + return; + for (i = 0; request_class->schemes[i]; i++) { + g_hash_table_remove (priv->request_types, + request_class->schemes[i]); + } + } else { + for (f = priv->features; f; f = f->next) { + if (soup_session_feature_remove_feature (f->data, feature_type)) + return; + } + g_warning ("No feature manager for feature of type '%s'", g_type_name (feature_type)); + } +} + +/** + * soup_session_has_feature: + * @session: a #SoupSession + * @feature_type: the #GType of the class of features to check for + * + * Tests if @session has at a feature of type @feature_type (which can + * be the type of either a #SoupSessionFeature, or else a subtype of + * some class managed by another feature, such as #SoupAuth or + * #SoupRequest). + * + * Return value: %TRUE or %FALSE + * + * Since: 2.42 + **/ +gboolean +soup_session_has_feature (SoupSession *session, + GType feature_type) +{ + SoupSessionPrivate *priv; + GSList *f; + + g_return_val_if_fail (SOUP_IS_SESSION (session), FALSE); + + priv = soup_session_get_instance_private (session); + + if (g_type_is_a (feature_type, SOUP_TYPE_SESSION_FEATURE)) { + for (f = priv->features; f; f = f->next) { + if (G_TYPE_CHECK_INSTANCE_TYPE (f->data, feature_type)) + return TRUE; + } + } else if (g_type_is_a (feature_type, SOUP_TYPE_REQUEST)) { + return g_hash_table_lookup (priv->request_types, + GSIZE_TO_POINTER (feature_type)) != NULL; + } else { + for (f = priv->features; f; f = f->next) { + if (soup_session_feature_has_feature (f->data, feature_type)) + return TRUE; + } + } + + return FALSE; +} + +/** + * soup_session_get_features: + * @session: a #SoupSession + * @feature_type: the #GType of the class of features to get + * + * Generates a list of @session's features of type @feature_type. (If + * you want to see all features, you can pass %SOUP_TYPE_SESSION_FEATURE + * for @feature_type.) + * + * Return value: (transfer container) (element-type Soup.SessionFeature): + * a list of features. You must free the list, but not its contents + * + * Since: 2.26 + **/ +GSList * +soup_session_get_features (SoupSession *session, GType feature_type) +{ + SoupSessionPrivate *priv; + GSList *f, *ret; + + g_return_val_if_fail (SOUP_IS_SESSION (session), NULL); + + priv = soup_session_get_instance_private (session); + for (f = priv->features, ret = NULL; f; f = f->next) { + if (G_TYPE_CHECK_INSTANCE_TYPE (f->data, feature_type)) + ret = g_slist_prepend (ret, f->data); + } + return g_slist_reverse (ret); +} + +/** + * soup_session_get_feature: + * @session: a #SoupSession + * @feature_type: the #GType of the feature to get + * + * Gets the first feature in @session of type @feature_type. For + * features where there may be more than one feature of a given type, + * use soup_session_get_features(). + * + * Return value: (nullable) (transfer none): a #SoupSessionFeature, or + * %NULL. The feature is owned by @session. + * + * Since: 2.26 + **/ +SoupSessionFeature * +soup_session_get_feature (SoupSession *session, GType feature_type) +{ + SoupSessionPrivate *priv; + SoupSessionFeature *feature; + GSList *f; + + g_return_val_if_fail (SOUP_IS_SESSION (session), NULL); + + priv = soup_session_get_instance_private (session); + + feature = g_hash_table_lookup (priv->features_cache, + GSIZE_TO_POINTER (feature_type)); + if (feature) + return feature; + + for (f = priv->features; f; f = f->next) { + feature = f->data; + if (G_TYPE_CHECK_INSTANCE_TYPE (feature, feature_type)) { + g_hash_table_insert (priv->features_cache, + GSIZE_TO_POINTER (feature_type), + feature); + return feature; + } + } + return NULL; +} + +/** + * soup_session_get_feature_for_message: + * @session: a #SoupSession + * @feature_type: the #GType of the feature to get + * @msg: a #SoupMessage + * + * Gets the first feature in @session of type @feature_type, provided + * that it is not disabled for @msg. As with + * soup_session_get_feature(), this should only be used for features + * where @feature_type is only expected to match a single feature. In + * particular, if there are two matching features, and the first is + * disabled on @msg, and the second is not, then this will return + * %NULL, not the second feature. + * + * Return value: (nullable) (transfer none): a #SoupSessionFeature, or %NULL. The + * feature is owned by @session. + * + * Since: 2.28 + **/ +SoupSessionFeature * +soup_session_get_feature_for_message (SoupSession *session, GType feature_type, + SoupMessage *msg) +{ + SoupSessionFeature *feature; + + feature = soup_session_get_feature (session, feature_type); + if (feature && soup_message_disables_feature (msg, feature)) + return NULL; + return feature; +} + +static void +soup_session_class_init (SoupSessionClass *session_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (session_class); + + /* virtual method definition */ + session_class->queue_message = soup_session_real_queue_message; + session_class->send_message = soup_session_real_send_message; + session_class->requeue_message = soup_session_real_requeue_message; + session_class->cancel_message = soup_session_real_cancel_message; + session_class->flush_queue = soup_session_real_flush_queue; + session_class->kick = soup_session_real_kick_queue; + + /* virtual method override */ + object_class->constructor = soup_session_constructor; + object_class->dispose = soup_session_dispose; + object_class->finalize = soup_session_finalize; + object_class->set_property = soup_session_set_property; + object_class->get_property = soup_session_get_property; + + /* signals */ + + /** + * SoupSession::request-queued: + * @session: the session + * @msg: the request that was queued + * + * Emitted when a request is queued on @session. (Note that + * "queued" doesn't just mean soup_session_queue_message(); + * soup_session_send_message() implicitly queues the message + * as well.) + * + * When sending a request, first #SoupSession::request_queued + * is emitted, indicating that the session has become aware of + * the request. + * + * Once a connection is available to send the request on, the + * session emits #SoupSession::request_started. Then, various + * #SoupMessage signals are emitted as the message is + * processed. If the message is requeued, it will emit + * #SoupMessage::restarted, which will then be followed by + * another #SoupSession::request_started and another set of + * #SoupMessage signals when the message is re-sent. + * + * Eventually, the message will emit #SoupMessage::finished. + * Normally, this signals the completion of message + * processing. However, it is possible that the application + * will requeue the message from the "finished" handler (or + * equivalently, from the soup_session_queue_message() + * callback). In that case, the process will loop back to + * #SoupSession::request_started. + * + * Eventually, a message will reach "finished" and not be + * requeued. At that point, the session will emit + * #SoupSession::request_unqueued to indicate that it is done + * with the message. + * + * To sum up: #SoupSession::request_queued and + * #SoupSession::request_unqueued are guaranteed to be emitted + * exactly once, but #SoupSession::request_started and + * #SoupMessage::finished (and all of the other #SoupMessage + * signals) may be invoked multiple times for a given message. + * + * Since: 2.24 + **/ + signals[REQUEST_QUEUED] = + g_signal_new ("request-queued", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + 0, /* FIXME? */ + NULL, NULL, + NULL, + G_TYPE_NONE, 1, + SOUP_TYPE_MESSAGE); + + /** + * SoupSession::request-started: + * @session: the session + * @msg: the request being sent + * @socket: the socket the request is being sent on + * + * Emitted just before a request is sent. See + * #SoupSession::request_queued for a detailed description of + * the message lifecycle within a session. + * + * Deprecated: 2.50. Use #SoupMessage::starting instead. + **/ + signals[REQUEST_STARTED] = + g_signal_new ("request-started", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (SoupSessionClass, request_started), + NULL, NULL, + NULL, + G_TYPE_NONE, 2, + SOUP_TYPE_MESSAGE, + SOUP_TYPE_SOCKET); + + /** + * SoupSession::request-unqueued: + * @session: the session + * @msg: the request that was unqueued + * + * Emitted when a request is removed from @session's queue, + * indicating that @session is done with it. See + * #SoupSession::request_queued for a detailed description of the + * message lifecycle within a session. + * + * Since: 2.24 + **/ + signals[REQUEST_UNQUEUED] = + g_signal_new ("request-unqueued", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + 0, /* FIXME? */ + NULL, NULL, + NULL, + G_TYPE_NONE, 1, + SOUP_TYPE_MESSAGE); + + /** + * SoupSession::authenticate: + * @session: the session + * @msg: the #SoupMessage being sent + * @auth: the #SoupAuth to authenticate + * @retrying: %TRUE if this is the second (or later) attempt + * + * Emitted when the session requires authentication. If + * credentials are available call soup_auth_authenticate() on + * @auth. If these credentials fail, the signal will be + * emitted again, with @retrying set to %TRUE, which will + * continue until you return without calling + * soup_auth_authenticate() on @auth. + * + * Note that this may be emitted before @msg's body has been + * fully read. + * + * If you call soup_session_pause_message() on @msg before + * returning, then you can authenticate @auth asynchronously + * (as long as you g_object_ref() it to make sure it doesn't + * get destroyed), and then unpause @msg when you are ready + * for it to continue. + **/ + signals[AUTHENTICATE] = + g_signal_new ("authenticate", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (SoupSessionClass, authenticate), + NULL, NULL, + NULL, + G_TYPE_NONE, 3, + SOUP_TYPE_MESSAGE, + SOUP_TYPE_AUTH, + G_TYPE_BOOLEAN); + + /** + * SoupSession::connection-created: + * @session: the #SoupSession + * @connection: the connection + * + * Emitted when a new connection is created. This is an + * internal signal intended only to be used for debugging + * purposes, and may go away in the future. + * + * Since: 2.30 + */ + signals[CONNECTION_CREATED] = + g_signal_new ("connection-created", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + 0, + NULL, NULL, + NULL, + G_TYPE_NONE, 1, + /* SoupConnection is private, so we can't use + * SOUP_TYPE_CONNECTION here. + */ + G_TYPE_OBJECT); + + /** + * SoupSession::tunneling: + * @session: the #SoupSession + * @connection: the connection + * + * Emitted when an SSL tunnel is being created on a proxy + * connection. This is an internal signal intended only to be + * used for debugging purposes, and may go away in the future. + * + * Since: 2.30 + */ + signals[TUNNELING] = + g_signal_new ("tunneling", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + 0, + NULL, NULL, + NULL, + G_TYPE_NONE, 1, + /* SoupConnection is private, so we can't use + * SOUP_TYPE_CONNECTION here. + */ + G_TYPE_OBJECT); + + + /* properties */ + /** + * SoupSession:proxy-uri: + * + * A proxy to use for all http and https requests in this + * session. Setting this will clear the + * #SoupSession:proxy-resolver property, and remove any + * SoupProxyURIResolver features that have been + * added to the session. Setting this property will also + * cancel all currently pending messages. + * + * Note that #SoupSession will normally handle looking up the + * user's proxy settings for you; you should only use + * #SoupSession:proxy-uri if you need to override the user's + * normal proxy settings. + * + * Also note that this proxy will be used for + * all requests; even requests to + * localhost. If you need more control over + * proxies, you can create a #GSimpleProxyResolver and set the + * #SoupSession:proxy-resolver property. + */ + /** + * SOUP_SESSION_PROXY_URI: + * + * Alias for the #SoupSession:proxy-uri property, qv. + **/ + g_object_class_install_property ( + object_class, PROP_PROXY_URI, + g_param_spec_boxed (SOUP_SESSION_PROXY_URI, + "Proxy URI", + "The HTTP Proxy to use for this session", + SOUP_TYPE_URI, + G_PARAM_READWRITE)); + /** + * SoupSession:proxy-resolver: + * + * A #GProxyResolver to use with this session. Setting this + * will clear the #SoupSession:proxy-uri property, and remove + * any SoupProxyURIResolver features that have + * been added to the session. + * + * By default, in a plain #SoupSession, this is set to the + * default #GProxyResolver, but you can set it to %NULL if you + * don't want to use proxies, or set it to your own + * #GProxyResolver if you want to control what proxies get + * used. + * + * Since: 2.42 + */ + /** + * SOUP_SESSION_PROXY_RESOLVER: + * + * Alias for the #SoupSession:proxy-resolver property, qv. + **/ + g_object_class_install_property ( + object_class, PROP_PROXY_RESOLVER, + g_param_spec_object (SOUP_SESSION_PROXY_RESOLVER, + "Proxy Resolver", + "The GProxyResolver to use for this session", + G_TYPE_PROXY_RESOLVER, + G_PARAM_READWRITE)); + /** + * SOUP_SESSION_MAX_CONNS: + * + * Alias for the #SoupSession:max-conns property, qv. + **/ + g_object_class_install_property ( + object_class, PROP_MAX_CONNS, + g_param_spec_int (SOUP_SESSION_MAX_CONNS, + "Max Connection Count", + "The maximum number of connections that the session can open at once", + 1, + G_MAXINT, + SOUP_SESSION_MAX_CONNS_DEFAULT, + G_PARAM_READWRITE)); + /** + * SOUP_SESSION_MAX_CONNS_PER_HOST: + * + * Alias for the #SoupSession:max-conns-per-host property, qv. + **/ + g_object_class_install_property ( + object_class, PROP_MAX_CONNS_PER_HOST, + g_param_spec_int (SOUP_SESSION_MAX_CONNS_PER_HOST, + "Max Per-Host Connection Count", + "The maximum number of connections that the session can open at once to a given host", + 1, + G_MAXINT, + SOUP_SESSION_MAX_CONNS_PER_HOST_DEFAULT, + G_PARAM_READWRITE)); + /** + * SoupSession:idle-timeout: + * + * Connection lifetime (in seconds) when idle. Any connection + * left idle longer than this will be closed. + * + * Although you can change this property at any time, it will + * only affect newly-created connections, not currently-open + * ones. You can call soup_session_abort() after setting this + * if you want to ensure that all future connections will have + * this timeout value. + * + * Note that the default value of 60 seconds only applies to + * plain #SoupSessions. If you are using #SoupSessionAsync or + * #SoupSessionSync, the default value is 0 (meaning idle + * connections will never time out). + * + * Since: 2.24 + **/ + /** + * SOUP_SESSION_IDLE_TIMEOUT: + * + * Alias for the #SoupSession:idle-timeout property, qv. + * + * Since: 2.24 + **/ + g_object_class_install_property ( + object_class, PROP_IDLE_TIMEOUT, + g_param_spec_uint (SOUP_SESSION_IDLE_TIMEOUT, + "Idle Timeout", + "Connection lifetime when idle", + 0, G_MAXUINT, 60, + G_PARAM_READWRITE)); + /** + * SoupSession:use-ntlm: + * + * Whether or not to use NTLM authentication. + * + * Deprecated: use soup_session_add_feature_by_type() with + * #SOUP_TYPE_AUTH_NTLM. + **/ + /** + * SOUP_SESSION_USE_NTLM: + * + * Alias for the #SoupSession:use-ntlm property, qv. + **/ + g_object_class_install_property ( + object_class, PROP_USE_NTLM, + g_param_spec_boolean (SOUP_SESSION_USE_NTLM, + "Use NTLM", + "Whether or not to use NTLM authentication", + FALSE, + G_PARAM_READWRITE | G_PARAM_DEPRECATED)); + /** + * SoupSession:ssl-ca-file: + * + * File containing SSL CA certificates. + * + * If the specified file does not exist or cannot be read, + * then libsoup will print a warning, and then behave as + * though it had read in a empty CA file, meaning that all SSL + * certificates will be considered invalid. + * + * Deprecated: use #SoupSession:ssl-use-system-ca-file, or + * else #SoupSession:tls-database with a #GTlsFileDatabase + * (which allows you to do explicit error handling). + **/ + /** + * SOUP_SESSION_SSL_CA_FILE: + * + * Alias for the #SoupSession:ssl-ca-file property, qv. + **/ + g_object_class_install_property ( + object_class, PROP_SSL_CA_FILE, + g_param_spec_string (SOUP_SESSION_SSL_CA_FILE, + "SSL CA file", + "File containing SSL CA certificates", + NULL, + G_PARAM_READWRITE | G_PARAM_DEPRECATED)); + /** + * SOUP_SESSION_SSL_USE_SYSTEM_CA_FILE: + * + * Alias for the #SoupSession:ssl-use-system-ca-file property, + * qv. + * + * Since: 2.38 + **/ + /** + * SoupSession:ssl-use-system-ca-file: + * + * Setting this to %TRUE is equivalent to setting + * #SoupSession:tls-database to the default system CA database. + * (and likewise, setting #SoupSession:tls-database to the + * default database by hand will cause this property to + * become %TRUE). + * + * Setting this to %FALSE (when it was previously %TRUE) will + * clear the #SoupSession:tls-database field. + * + * See #SoupSession:ssl-strict for more information on how + * https certificate validation is handled. + * + * Note that the default value of %TRUE only applies to plain + * #SoupSessions. If you are using #SoupSessionAsync or + * #SoupSessionSync, the default value is %FALSE, for backward + * compatibility. + * + * Since: 2.38 + **/ + g_object_class_install_property ( + object_class, PROP_SSL_USE_SYSTEM_CA_FILE, + g_param_spec_boolean (SOUP_SESSION_SSL_USE_SYSTEM_CA_FILE, + "Use system CA file", + "Use the system certificate database", + TRUE, + G_PARAM_READWRITE)); + /** + * SOUP_SESSION_TLS_DATABASE: + * + * Alias for the #SoupSession:tls-database property, qv. + * + * Since: 2.38 + **/ + /** + * SoupSession:tls-database: + * + * Sets the #GTlsDatabase to use for validating SSL/TLS + * certificates. + * + * Note that setting the #SoupSession:ssl-ca-file or + * #SoupSession:ssl-use-system-ca-file property will cause + * this property to be set to a #GTlsDatabase corresponding to + * the indicated file or system default. + * + * See #SoupSession:ssl-strict for more information on how + * https certificate validation is handled. + * + * If you are using a plain #SoupSession then + * #SoupSession:ssl-use-system-ca-file will be %TRUE by + * default, and so this property will be a copy of the system + * CA database. If you are using #SoupSessionAsync or + * #SoupSessionSync, this property will be %NULL by default. + * + * Since: 2.38 + **/ + g_object_class_install_property ( + object_class, PROP_TLS_DATABASE, + g_param_spec_object (SOUP_SESSION_TLS_DATABASE, + "TLS Database", + "TLS database to use", + G_TYPE_TLS_DATABASE, + G_PARAM_READWRITE)); + /** + * SOUP_SESSION_SSL_STRICT: + * + * Alias for the #SoupSession:ssl-strict property, qv. + * + * Since: 2.30 + **/ + /** + * SoupSession:ssl-strict: + * + * Normally, if #SoupSession:tls-database is set (including if + * it was set via #SoupSession:ssl-use-system-ca-file or + * #SoupSession:ssl-ca-file), then libsoup will reject any + * certificate that is invalid (ie, expired) or that is not + * signed by one of the given CA certificates, and the + * #SoupMessage will fail with the status + * %SOUP_STATUS_SSL_FAILED. + * + * If you set #SoupSession:ssl-strict to %FALSE, then all + * certificates will be accepted, and you will need to call + * soup_message_get_https_status() to distinguish valid from + * invalid certificates. (This can be used, eg, if you want to + * accept invalid certificates after giving some sort of + * warning.) + * + * For a plain #SoupSession, if the session has no CA file or + * TLS database, and this property is %TRUE, then all + * certificates will be rejected. However, beware that the + * deprecated #SoupSession subclasses (#SoupSessionAsync and + * #SoupSessionSync) have the opposite behavior: if there is + * no CA file or TLS database, then all certificates are always + * accepted, and this property has no effect. + * + * Since: 2.30 + */ + g_object_class_install_property ( + object_class, PROP_SSL_STRICT, + g_param_spec_boolean (SOUP_SESSION_SSL_STRICT, + "Strictly validate SSL certificates", + "Whether certificate errors should be considered a connection error", + TRUE, + G_PARAM_READWRITE)); + /** + * SoupSession:async-context: + * + * The #GMainContext that miscellaneous session-related + * asynchronous callbacks are invoked on. (Eg, setting + * #SoupSession:idle-timeout will add a timeout source on this + * context.) + * + * For a plain #SoupSession, this property is always set to + * the #GMainContext that is the thread-default at the time + * the session was created, and cannot be overridden. For the + * deprecated #SoupSession subclasses, the default value is + * %NULL, meaning to use the global default #GMainContext. + * + * If #SoupSession:use-thread-context is %FALSE, this context + * will also be used for asynchronous HTTP I/O. + */ + /** + * SOUP_SESSION_ASYNC_CONTEXT: + * + * Alias for the #SoupSession:async-context property, qv. + */ + g_object_class_install_property ( + object_class, PROP_ASYNC_CONTEXT, + g_param_spec_pointer (SOUP_SESSION_ASYNC_CONTEXT, + "Async GMainContext", + "The GMainContext to dispatch async I/O in", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + /** + * SOUP_SESSION_USE_THREAD_CONTEXT: + * + * Alias for the #SoupSession:use-thread-context property, qv. + * + * Since: 2.38 + */ + /** + * SoupSession:use-thread-context: + * + * If %TRUE (which it always is on a plain #SoupSession), + * asynchronous HTTP requests in this session will run in + * whatever the thread-default #GMainContext is at the time + * they are started, rather than always occurring in + * #SoupSession:async-context. + * + * Since: 2.38 + */ + g_object_class_install_property ( + object_class, PROP_USE_THREAD_CONTEXT, + g_param_spec_boolean (SOUP_SESSION_USE_THREAD_CONTEXT, + "Use thread-default GMainContext", + "Whether to use thread-default main contexts", + FALSE, + G_PARAM_READWRITE)); + /** + * SoupSession:timeout: + * + * The timeout (in seconds) for socket I/O operations + * (including connecting to a server, and waiting for a reply + * to an HTTP request). + * + * Although you can change this property at any time, it will + * only affect newly-created connections, not currently-open + * ones. You can call soup_session_abort() after setting this + * if you want to ensure that all future connections will have + * this timeout value. + * + * Note that the default value of 60 seconds only applies to + * plain #SoupSessions. If you are using #SoupSessionAsync or + * #SoupSessionSync, the default value is 0 (meaning socket I/O + * will not time out). + * + * Not to be confused with #SoupSession:idle-timeout (which is + * the length of time that idle persistent connections will be + * kept open). + */ + /** + * SOUP_SESSION_TIMEOUT: + * + * Alias for the #SoupSession:timeout property, qv. + **/ + g_object_class_install_property ( + object_class, PROP_TIMEOUT, + g_param_spec_uint (SOUP_SESSION_TIMEOUT, + "Timeout value", + "Value in seconds to timeout a blocking I/O", + 0, G_MAXUINT, 0, + G_PARAM_READWRITE)); + + /** + * SoupSession:user-agent: + * + * If non-%NULL, the value to use for the "User-Agent" header + * on #SoupMessages sent from this session. + * + * RFC 2616 says: "The User-Agent request-header field + * contains information about the user agent originating the + * request. This is for statistical purposes, the tracing of + * protocol violations, and automated recognition of user + * agents for the sake of tailoring responses to avoid + * particular user agent limitations. User agents SHOULD + * include this field with requests." + * + * The User-Agent header contains a list of one or more + * product tokens, separated by whitespace, with the most + * significant product token coming first. The tokens must be + * brief, ASCII, and mostly alphanumeric (although "-", "_", + * and "." are also allowed), and may optionally include a "/" + * followed by a version string. You may also put comments, + * enclosed in parentheses, between or after the tokens. + * + * If you set a #SoupSession:user_agent property that has trailing + * whitespace, #SoupSession will append its own product token + * (eg, "libsoup/2.3.2") to the end of the + * header for you. + **/ + /** + * SOUP_SESSION_USER_AGENT: + * + * Alias for the #SoupSession:user-agent property, qv. + **/ + g_object_class_install_property ( + object_class, PROP_USER_AGENT, + g_param_spec_string (SOUP_SESSION_USER_AGENT, + "User-Agent string", + "User-Agent string", + NULL, + G_PARAM_READWRITE)); + + /** + * SoupSession:accept-language: + * + * If non-%NULL, the value to use for the "Accept-Language" header + * on #SoupMessages sent from this session. + * + * Setting this will disable + * #SoupSession:accept-language-auto. + * + * Since: 2.30 + **/ + /** + * SOUP_SESSION_ACCEPT_LANGUAGE: + * + * Alias for the #SoupSession:accept-language property, qv. + * + * Since: 2.30 + **/ + g_object_class_install_property ( + object_class, PROP_ACCEPT_LANGUAGE, + g_param_spec_string (SOUP_SESSION_ACCEPT_LANGUAGE, + "Accept-Language string", + "Accept-Language string", + NULL, + G_PARAM_READWRITE)); + + /** + * SoupSession:accept-language-auto: + * + * If %TRUE, #SoupSession will automatically set the string + * for the "Accept-Language" header on every #SoupMessage + * sent, based on the return value of g_get_language_names(). + * + * Setting this will override any previous value of + * #SoupSession:accept-language. + * + * Since: 2.30 + **/ + /** + * SOUP_SESSION_ACCEPT_LANGUAGE_AUTO: + * + * Alias for the #SoupSession:accept-language-auto property, qv. + * + * Since: 2.30 + **/ + g_object_class_install_property ( + object_class, PROP_ACCEPT_LANGUAGE_AUTO, + g_param_spec_boolean (SOUP_SESSION_ACCEPT_LANGUAGE_AUTO, + "Accept-Language automatic mode", + "Accept-Language automatic mode", + FALSE, + G_PARAM_READWRITE)); + + /** + * SoupSession:add-feature: (skip) + * + * Add a feature object to the session. (Shortcut for calling + * soup_session_add_feature().) + * + * Since: 2.24 + **/ + /** + * SOUP_SESSION_ADD_FEATURE: (skip) + * + * Alias for the #SoupSession:add-feature property, qv. + * + * Since: 2.24 + **/ + g_object_class_install_property ( + object_class, PROP_ADD_FEATURE, + g_param_spec_object (SOUP_SESSION_ADD_FEATURE, + "Add Feature", + "Add a feature object to the session", + SOUP_TYPE_SESSION_FEATURE, + G_PARAM_READWRITE)); + /** + * SoupSession:add-feature-by-type: (skip) + * + * Add a feature object of the given type to the session. + * (Shortcut for calling soup_session_add_feature_by_type().) + * + * Since: 2.24 + **/ + /** + * SOUP_SESSION_ADD_FEATURE_BY_TYPE: (skip) + * + * Alias for the #SoupSession:add-feature-by-type property, qv. + * + * Since: 2.24 + **/ + g_object_class_install_property ( + object_class, PROP_ADD_FEATURE_BY_TYPE, + g_param_spec_gtype (SOUP_SESSION_ADD_FEATURE_BY_TYPE, + "Add Feature By Type", + "Add a feature object of the given type to the session", + G_TYPE_OBJECT, + G_PARAM_READWRITE)); + /** + * SoupSession:remove-feature-by-type: (skip) + * + * Remove feature objects from the session. (Shortcut for + * calling soup_session_remove_feature_by_type().) + * + * Since: 2.24 + **/ + /** + * SOUP_SESSION_REMOVE_FEATURE_BY_TYPE: (skip) + * + * Alias for the #SoupSession:remove-feature-by-type property, + * qv. + * + * Since: 2.24 + **/ + g_object_class_install_property ( + object_class, PROP_REMOVE_FEATURE_BY_TYPE, + g_param_spec_gtype (SOUP_SESSION_REMOVE_FEATURE_BY_TYPE, + "Remove Feature By Type", + "Remove features of the given type from the session", + G_TYPE_OBJECT, + G_PARAM_READWRITE)); + /** + * SoupSession:http-aliases: + * + * A %NULL-terminated array of URI schemes that should be + * considered to be aliases for "http". Eg, if this included + * "dav", than a URI of + * dav://example.com/path would be treated + * identically to http://example.com/path. + * + * In a plain #SoupSession, the default value is %NULL, + * meaning that only "http" is recognized as meaning "http". + * In #SoupSessionAsync and #SoupSessionSync, for backward + * compatibility, the default value is an array containing the + * single element "*", a special value + * which means that any scheme except "https" is considered to + * be an alias for "http". + * + * See also #SoupSession:https-aliases. + * + * Since: 2.38 + */ + /** + * SOUP_SESSION_HTTP_ALIASES: + * + * Alias for the #SoupSession:http-aliases property, qv. + * + * Since: 2.38 + */ + g_object_class_install_property ( + object_class, PROP_HTTP_ALIASES, + g_param_spec_boxed (SOUP_SESSION_HTTP_ALIASES, + "http aliases", + "URI schemes that are considered aliases for 'http'", + G_TYPE_STRV, + G_PARAM_READWRITE)); + /** + * SoupSession:https-aliases: + * + * A comma-delimited list of URI schemes that should be + * considered to be aliases for "https". See + * #SoupSession:http-aliases for more information. + * + * The default value is %NULL, meaning that no URI schemes + * are considered aliases for "https". + * + * Since: 2.38 + */ + /** + * SOUP_SESSION_HTTPS_ALIASES: + * + * Alias for the #SoupSession:https-aliases property, qv. + * + * Since: 2.38 + **/ + g_object_class_install_property ( + object_class, PROP_HTTPS_ALIASES, + g_param_spec_boxed (SOUP_SESSION_HTTPS_ALIASES, + "https aliases", + "URI schemes that are considered aliases for 'https'", + G_TYPE_STRV, + G_PARAM_READWRITE)); + + /** + * SOUP_SESSION_LOCAL_ADDRESS: + * + * Alias for the #SoupSession:local-address property, qv. + * + * Since: 2.42 + **/ + /** + * SoupSession:local-address: + * + * Sets the #SoupAddress to use for the client side of + * the connection. + * + * Use this property if you want for instance to bind the + * local socket to a specific IP address. + * + * Since: 2.42 + **/ + g_object_class_install_property ( + object_class, PROP_LOCAL_ADDRESS, + g_param_spec_object (SOUP_SESSION_LOCAL_ADDRESS, + "Local address", + "Address of local end of socket", + SOUP_TYPE_ADDRESS, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + /** + * SOUP_SESSION_TLS_INTERACTION: + * + * Alias for the #SoupSession:tls-interaction property, qv. + * + * Since: 2.48 + **/ + /** + * SoupSession:tls-interaction: + * + * A #GTlsInteraction object that will be passed on to any + * #GTlsConnections created by the session. (This can be used to + * provide client-side certificates, for example.) + * + * Since: 2.48 + **/ + g_object_class_install_property ( + object_class, PROP_TLS_INTERACTION, + g_param_spec_object (SOUP_SESSION_TLS_INTERACTION, + "TLS Interaction", + "TLS interaction to use", + G_TYPE_TLS_INTERACTION, + G_PARAM_READWRITE)); +} + + +static gboolean +expected_to_be_requeued (SoupSession *session, SoupMessage *msg) +{ + if (msg->status_code == SOUP_STATUS_UNAUTHORIZED || + msg->status_code == SOUP_STATUS_PROXY_UNAUTHORIZED) { + SoupSessionFeature *feature = + soup_session_get_feature (session, SOUP_TYPE_AUTH_MANAGER); + return !feature || !soup_message_disables_feature (msg, feature); + } + + if (!(soup_message_get_flags (msg) & SOUP_MESSAGE_NO_REDIRECT)) + return soup_session_would_redirect (session, msg); + + return FALSE; +} + +/* send_request_async */ + +static void +async_send_request_return_result (SoupMessageQueueItem *item, + gpointer stream, GError *error) +{ + GTask *task; + + g_return_if_fail (item->task != NULL); + + g_signal_handlers_disconnect_matched (item->msg, G_SIGNAL_MATCH_DATA, + 0, 0, NULL, NULL, item); + + task = item->task; + item->task = NULL; + + if (item->io_source) { + g_source_destroy (item->io_source); + g_clear_pointer (&item->io_source, g_source_unref); + } + + if (error) + g_task_return_error (task, error); + else if (item->error) { + if (stream) + g_object_unref (stream); + g_task_return_error (task, g_error_copy (item->error)); + } else if (SOUP_STATUS_IS_TRANSPORT_ERROR (item->msg->status_code)) { + if (stream) + g_object_unref (stream); + g_task_return_new_error (task, SOUP_HTTP_ERROR, + item->msg->status_code, + "%s", + item->msg->reason_phrase); + } else + g_task_return_pointer (task, stream, g_object_unref); + g_object_unref (task); +} + +static void +async_send_request_restarted (SoupMessage *msg, gpointer user_data) +{ + SoupMessageQueueItem *item = user_data; + + /* We won't be needing this, then. */ + g_object_set_data (G_OBJECT (item->msg), "SoupSession:ostream", NULL); + item->io_started = FALSE; +} + +static void +async_send_request_finished (SoupMessage *msg, gpointer user_data) +{ + SoupMessageQueueItem *item = user_data; + GMemoryOutputStream *mostream; + GInputStream *istream = NULL; + GError *error = NULL; + + if (!item->task) { + /* Something else already took care of it. */ + return; + } + + mostream = g_object_get_data (G_OBJECT (item->task), "SoupSession:ostream"); + if (mostream) { + gpointer data; + gssize size; + + /* We thought it would be requeued, but it wasn't, so + * return the original body. + */ + size = g_memory_output_stream_get_data_size (mostream); + data = size ? g_memory_output_stream_steal_data (mostream) : g_strdup (""); + istream = g_memory_input_stream_new_from_data (data, size, g_free); + } else if (item->io_started) { + /* The message finished before becoming readable. This + * will happen, eg, if it's cancelled from got-headers. + * Do nothing; the op will complete via read_ready_cb() + * after we return; + */ + return; + } else { + /* The message finished before even being started; + * probably a tunnel connect failure. + */ + istream = g_memory_input_stream_new (); + } + + async_send_request_return_result (item, istream, error); +} + +static void +send_async_spliced (GObject *source, GAsyncResult *result, gpointer user_data) +{ + SoupMessageQueueItem *item = user_data; + GInputStream *istream = g_object_get_data (source, "istream"); + GError *error = NULL; + + /* It should be safe to call the sync close() method here since + * the message body has already been written. + */ + g_input_stream_close (istream, NULL, NULL); + g_object_unref (istream); + + /* If the message was cancelled, it will be completed via other means */ + if (g_cancellable_is_cancelled (item->cancellable) || + !item->task) { + soup_message_queue_item_unref (item); + return; + } + + if (g_output_stream_splice_finish (G_OUTPUT_STREAM (source), + result, &error) == -1) { + async_send_request_return_result (item, NULL, error); + soup_message_queue_item_unref (item); + return; + } + + /* Otherwise either restarted or finished will eventually be called. */ + soup_session_kick_queue (item->session); + soup_message_queue_item_unref (item); +} + +static void +send_async_maybe_complete (SoupMessageQueueItem *item, + GInputStream *stream) +{ + if (expected_to_be_requeued (item->session, item->msg)) { + GOutputStream *ostream; + + /* Gather the current message body... */ + ostream = g_memory_output_stream_new (NULL, 0, g_realloc, g_free); + g_object_set_data_full (G_OBJECT (item->task), "SoupSession:ostream", + ostream, g_object_unref); + + g_object_set_data (G_OBJECT (ostream), "istream", stream); + + /* Give the splice op its own ref on item */ + soup_message_queue_item_ref (item); + /* We don't use CLOSE_SOURCE because we need to control when the + * side effects of closing the SoupClientInputStream happen. + */ + g_output_stream_splice_async (ostream, stream, + G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET, + G_PRIORITY_DEFAULT, + item->cancellable, + send_async_spliced, item); + return; + } + + async_send_request_return_result (item, stream, NULL); +} + +static void try_run_until_read (SoupMessageQueueItem *item); + +static gboolean +read_ready_cb (SoupMessage *msg, gpointer user_data) +{ + SoupMessageQueueItem *item = user_data; + + g_clear_pointer (&item->io_source, g_source_unref); + try_run_until_read (item); + return FALSE; +} + +static void +try_run_until_read (SoupMessageQueueItem *item) +{ + GError *error = NULL; + GInputStream *stream = NULL; + + if (soup_message_io_run_until_read (item->msg, FALSE, item->cancellable, &error)) + stream = soup_message_io_get_response_istream (item->msg, &error); + if (stream) { + send_async_maybe_complete (item, stream); + return; + } + + if (g_error_matches (error, SOUP_HTTP_ERROR, SOUP_STATUS_TRY_AGAIN)) { + item->state = SOUP_MESSAGE_RESTARTING; + soup_message_io_finished (item->msg); + g_error_free (error); + return; + } + + if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) { + if (item->state != SOUP_MESSAGE_FINISHED) { + if (soup_message_io_in_progress (item->msg)) + soup_message_io_finished (item->msg); + item->state = SOUP_MESSAGE_FINISHING; + soup_session_process_queue_item (item->session, item, NULL, FALSE); + } + async_send_request_return_result (item, NULL, error); + return; + } + + g_clear_error (&error); + item->io_source = soup_message_io_get_source (item->msg, item->cancellable, + read_ready_cb, item); + g_source_attach (item->io_source, soup_session_get_async_context (item->session)); +} + +static void +async_send_request_running (SoupSession *session, SoupMessageQueueItem *item) +{ + item->io_started = TRUE; + try_run_until_read (item); +} + +static void +cache_stream_finished (GInputStream *stream, + SoupMessageQueueItem *item) +{ + g_signal_handlers_disconnect_matched (stream, G_SIGNAL_MATCH_DATA, + 0, 0, NULL, NULL, item); + item->state = SOUP_MESSAGE_FINISHING; + soup_session_kick_queue (item->session); + soup_message_queue_item_unref (item); +} + +static void +async_return_from_cache (SoupMessageQueueItem *item, + GInputStream *stream) +{ + const char *content_type; + GHashTable *params = NULL; + + soup_message_got_headers (item->msg); + + content_type = soup_message_headers_get_content_type (item->msg->response_headers, ¶ms); + if (content_type) { + soup_message_content_sniffed (item->msg, content_type, params); + g_hash_table_unref (params); + } + + soup_message_queue_item_ref (item); + g_signal_connect (stream, "eof", G_CALLBACK (cache_stream_finished), item); + g_signal_connect (stream, "closed", G_CALLBACK (cache_stream_finished), item); + + async_send_request_return_result (item, g_object_ref (stream), NULL); +} + +typedef struct { + SoupCache *cache; + SoupMessage *conditional_msg; +} AsyncCacheCancelData; + + +static void +free_async_cache_cancel_data (AsyncCacheCancelData *data) +{ + g_object_unref (data->conditional_msg); + g_object_unref (data->cache); + g_slice_free (AsyncCacheCancelData, data); +} + +static void +cancel_cache_response (SoupMessageQueueItem *item) +{ + item->paused = FALSE; + item->state = SOUP_MESSAGE_FINISHING; + soup_message_set_status (item->msg, SOUP_STATUS_CANCELLED); + soup_session_kick_queue (item->session); +} + +static void +conditional_request_cancelled_cb (GCancellable *cancellable, AsyncCacheCancelData *data) +{ + soup_cache_cancel_conditional_request (data->cache, data->conditional_msg); +} + +static void +conditional_get_ready_cb (SoupSession *session, SoupMessage *msg, gpointer user_data) +{ + SoupMessageQueueItem *item = user_data; + GInputStream *stream; + SoupCache *cache; + + if (g_cancellable_is_cancelled (item->cancellable)) { + cancel_cache_response (item); + return; + } else { + gulong handler_id = GPOINTER_TO_SIZE (g_object_get_data (G_OBJECT (msg), "SoupSession:handler-id")); + g_cancellable_disconnect (item->cancellable, handler_id); + } + + cache = (SoupCache *)soup_session_get_feature (session, SOUP_TYPE_CACHE); + soup_cache_update_from_conditional_request (cache, msg); + + if (msg->status_code == SOUP_STATUS_NOT_MODIFIED) { + stream = soup_cache_send_response (cache, item->msg); + if (stream) { + async_return_from_cache (item, stream); + g_object_unref (stream); + return; + } + } + + /* The resource was modified or the server returned a 200 + * OK. Either way we reload it. FIXME. + */ + item->state = SOUP_MESSAGE_STARTING; + soup_session_kick_queue (session); +} + +static gboolean +idle_return_from_cache_cb (gpointer data) +{ + GTask *task = data; + SoupMessageQueueItem *item = g_task_get_task_data (task); + GInputStream *istream; + + if (item->state == SOUP_MESSAGE_FINISHED) { + /* The original request was cancelled using + * soup_session_cancel_message () so it has been + * already handled by the cancellation code path. + */ + return FALSE; + } else if (g_cancellable_is_cancelled (item->cancellable)) { + /* Cancel original msg after g_cancellable_cancel(). */ + cancel_cache_response (item); + return FALSE; + } + + istream = g_object_get_data (G_OBJECT (task), "SoupSession:istream"); + async_return_from_cache (item, istream); + + return FALSE; +} + + +static gboolean +async_respond_from_cache (SoupSession *session, + SoupMessageQueueItem *item) +{ + SoupCache *cache; + SoupCacheResponse response; + + cache = (SoupCache *)soup_session_get_feature (session, SOUP_TYPE_CACHE); + if (!cache) + return FALSE; + + response = soup_cache_has_response (cache, item->msg); + if (response == SOUP_CACHE_RESPONSE_FRESH) { + GInputStream *stream; + GSource *source; + + stream = soup_cache_send_response (cache, item->msg); + if (!stream) { + /* Cached file was deleted? */ + return FALSE; + } + g_object_set_data_full (G_OBJECT (item->task), "SoupSession:istream", + stream, g_object_unref); + + source = g_timeout_source_new (0); + g_task_attach_source (item->task, source, + (GSourceFunc) idle_return_from_cache_cb); + g_source_unref (source); + return TRUE; + } else if (response == SOUP_CACHE_RESPONSE_NEEDS_VALIDATION) { + SoupMessage *conditional_msg; + AsyncCacheCancelData *data; + gulong handler_id; + + conditional_msg = soup_cache_generate_conditional_request (cache, item->msg); + if (!conditional_msg) + return FALSE; + + /* Detect any quick cancellation before the cache is able to return data. */ + data = g_slice_new0 (AsyncCacheCancelData); + data->cache = g_object_ref (cache); + data->conditional_msg = g_object_ref (conditional_msg); + handler_id = g_cancellable_connect (item->cancellable, G_CALLBACK (conditional_request_cancelled_cb), + data, (GDestroyNotify) free_async_cache_cancel_data); + + g_object_set_data (G_OBJECT (conditional_msg), "SoupSession:handler-id", + GSIZE_TO_POINTER (handler_id)); + soup_session_queue_message (session, conditional_msg, + conditional_get_ready_cb, + item); + + + return TRUE; + } else + return FALSE; +} + +/** + * soup_session_send_async: + * @session: a #SoupSession + * @msg: a #SoupMessage + * @cancellable: a #GCancellable + * @callback: the callback to invoke + * @user_data: data for @callback + * + * Asynchronously sends @msg and waits for the beginning of a + * response. When @callback is called, then either @msg has been sent, + * and its response headers received, or else an error has occurred. + * Call soup_session_send_finish() to get a #GInputStream for reading + * the response body. + * + * See soup_session_send() for more details on the general semantics. + * + * Contrast this method with soup_session_queue_message(), which also + * asynchronously sends a #SoupMessage, but doesn't invoke its + * callback until the response has been completely read. + * + * (Note that this method cannot be called on the deprecated + * #SoupSessionSync subclass, and can only be called on + * #SoupSessionAsync if you have set the + * #SoupSession:use-thread-context property.) + * + * Since: 2.42 + */ +void +soup_session_send_async (SoupSession *session, + SoupMessage *msg, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + SoupMessageQueueItem *item; + gboolean use_thread_context; + + g_return_if_fail (SOUP_IS_SESSION (session)); + g_return_if_fail (!SOUP_IS_SESSION_SYNC (session)); + + g_object_get (G_OBJECT (session), + SOUP_SESSION_USE_THREAD_CONTEXT, &use_thread_context, + NULL); + g_return_if_fail (use_thread_context); + + item = soup_session_append_queue_item (session, msg, TRUE, TRUE, + NULL, NULL); + g_signal_connect (msg, "restarted", + G_CALLBACK (async_send_request_restarted), item); + g_signal_connect (msg, "finished", + G_CALLBACK (async_send_request_finished), item); + + if (cancellable) { + g_object_unref (item->cancellable); + item->cancellable = g_object_ref (cancellable); + } + + item->new_api = TRUE; + item->task = g_task_new (session, item->cancellable, callback, user_data); + g_task_set_task_data (item->task, item, (GDestroyNotify) soup_message_queue_item_unref); + + /* Do not check for cancellations as we do not want to + * overwrite custom error messages set during cancellations + * (for example SOUP_HTTP_ERROR is set for cancelled messages + * in async_send_request_return_result() (status_code==1 + * means CANCEL and is considered a TRANSPORT_ERROR)). + */ + g_task_set_check_cancellable (item->task, FALSE); + + if (async_respond_from_cache (session, item)) + item->state = SOUP_MESSAGE_CACHED; + else + soup_session_kick_queue (session); +} + +/** + * soup_session_send_finish: + * @session: a #SoupSession + * @result: the #GAsyncResult passed to your callback + * @error: return location for a #GError, or %NULL + * + * Gets the response to a soup_session_send_async() call and (if + * successful), returns a #GInputStream that can be used to read the + * response body. + * + * Return value: (transfer full): a #GInputStream for reading the + * response body, or %NULL on error. + * + * Since: 2.42 + */ +GInputStream * +soup_session_send_finish (SoupSession *session, + GAsyncResult *result, + GError **error) +{ + GTask *task; + + g_return_val_if_fail (SOUP_IS_SESSION (session), NULL); + g_return_val_if_fail (!SOUP_IS_SESSION_SYNC (session), NULL); + g_return_val_if_fail (g_task_is_valid (result, session), NULL); + + task = G_TASK (result); + if (g_task_had_error (task)) { + SoupMessageQueueItem *item = g_task_get_task_data (task); + + if (soup_message_io_in_progress (item->msg)) + soup_message_io_finished (item->msg); + else if (item->state != SOUP_MESSAGE_FINISHED) + item->state = SOUP_MESSAGE_FINISHING; + + if (item->state != SOUP_MESSAGE_FINISHED) + soup_session_process_queue_item (session, item, NULL, FALSE); + } + + return g_task_propagate_pointer (task, error); +} + +/** + * soup_session_send: + * @session: a #SoupSession + * @msg: a #SoupMessage + * @cancellable: a #GCancellable + * @error: return location for a #GError, or %NULL + * + * Synchronously sends @msg and waits for the beginning of a response. + * On success, a #GInputStream will be returned which you can use to + * read the response body. ("Success" here means only that an HTTP + * response was received and understood; it does not necessarily mean + * that a 2xx class status code was received.) + * + * If non-%NULL, @cancellable can be used to cancel the request; + * soup_session_send() will return a %G_IO_ERROR_CANCELLED error. Note + * that with requests that have side effects (eg, + * POST, PUT, + * DELETE) it is possible that you might cancel the + * request after the server acts on it, but before it returns a + * response, leaving the remote resource in an unknown state. + * + * If @msg is requeued due to a redirect or authentication, the + * initial (3xx/401/407) response body will be suppressed, and + * soup_session_send() will only return once a final response has been + * received. + * + * Contrast this method with soup_session_send_message(), which also + * synchronously sends a #SoupMessage, but doesn't return until the + * response has been completely read. + * + * (Note that this method cannot be called on the deprecated + * #SoupSessionAsync subclass.) + * + * Return value: (transfer full): a #GInputStream for reading the + * response body, or %NULL on error. + * + * Since: 2.42 + */ +GInputStream * +soup_session_send (SoupSession *session, + SoupMessage *msg, + GCancellable *cancellable, + GError **error) +{ + SoupMessageQueueItem *item; + GInputStream *stream = NULL; + GOutputStream *ostream; + GMemoryOutputStream *mostream; + gssize size; + GError *my_error = NULL; + + g_return_val_if_fail (SOUP_IS_SESSION (session), NULL); + g_return_val_if_fail (!SOUP_IS_SESSION_ASYNC (session), NULL); + + item = soup_session_append_queue_item (session, msg, FALSE, TRUE, + NULL, NULL); + + item->new_api = TRUE; + if (cancellable) { + g_object_unref (item->cancellable); + item->cancellable = g_object_ref (cancellable); + } + + while (!stream) { + /* Get a connection, etc */ + soup_session_process_queue_item (session, item, NULL, TRUE); + if (item->state != SOUP_MESSAGE_RUNNING) + break; + + /* Send request, read headers */ + if (!soup_message_io_run_until_read (msg, TRUE, item->cancellable, &my_error)) { + if (g_error_matches (my_error, SOUP_HTTP_ERROR, SOUP_STATUS_TRY_AGAIN)) { + item->state = SOUP_MESSAGE_RESTARTING; + soup_message_io_finished (item->msg); + g_clear_error (&my_error); + continue; + } else + break; + } + + stream = soup_message_io_get_response_istream (msg, &my_error); + if (!stream) + break; + + if (!expected_to_be_requeued (session, msg)) + break; + + /* Gather the current message body... */ + ostream = g_memory_output_stream_new (NULL, 0, g_realloc, g_free); + if (g_output_stream_splice (ostream, stream, + G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | + G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET, + item->cancellable, &my_error) == -1) { + g_object_unref (stream); + g_object_unref (ostream); + stream = NULL; + break; + } + g_object_unref (stream); + stream = NULL; + + /* If the message was requeued, loop */ + if (item->state == SOUP_MESSAGE_RESTARTING) { + g_object_unref (ostream); + continue; + } + + /* Not requeued, so return the original body */ + mostream = G_MEMORY_OUTPUT_STREAM (ostream); + size = g_memory_output_stream_get_data_size (mostream); + stream = g_memory_input_stream_new (); + if (size) { + g_memory_input_stream_add_data (G_MEMORY_INPUT_STREAM (stream), + g_memory_output_stream_steal_data (mostream), + size, g_free); + } + g_object_unref (ostream); + } + + if (my_error) + g_propagate_error (error, my_error); + else if (item->error) { + g_clear_object (&stream); + if (error) + *error = g_error_copy (item->error); + } else if (SOUP_STATUS_IS_TRANSPORT_ERROR (msg->status_code)) { + g_clear_object (&stream); + g_set_error_literal (error, SOUP_HTTP_ERROR, msg->status_code, + msg->reason_phrase); + } else if (!stream) + stream = g_memory_input_stream_new (); + + if (!stream) { + if (soup_message_io_in_progress (msg)) + soup_message_io_finished (msg); + else if (item->state != SOUP_MESSAGE_FINISHED) + item->state = SOUP_MESSAGE_FINISHING; + + if (item->state != SOUP_MESSAGE_FINISHED) + soup_session_process_queue_item (session, item, NULL, TRUE); + } + + soup_message_queue_item_unref (item); + return stream; +} + +/** + * soup_session_request: + * @session: a #SoupSession + * @uri_string: a URI, in string form + * @error: return location for a #GError, or %NULL + * + * Creates a #SoupRequest for retrieving @uri_string. + * + * Return value: (transfer full): a new #SoupRequest, or + * %NULL on error. + * + * Since: 2.42 + */ +SoupRequest * +soup_session_request (SoupSession *session, const char *uri_string, + GError **error) +{ + SoupURI *uri; + SoupRequest *req; + + uri = soup_uri_new (uri_string); + if (!uri) { + g_set_error (error, SOUP_REQUEST_ERROR, + SOUP_REQUEST_ERROR_BAD_URI, + _("Could not parse URI “%s”"), uri_string); + return NULL; + } + + req = soup_session_request_uri (session, uri, error); + soup_uri_free (uri); + return req; +} + +/** + * soup_session_request_uri: + * @session: a #SoupSession + * @uri: a #SoupURI representing the URI to retrieve + * @error: return location for a #GError, or %NULL + * + * Creates a #SoupRequest for retrieving @uri. + * + * Return value: (transfer full): a new #SoupRequest, or + * %NULL on error. + * + * Since: 2.42 + */ +SoupRequest * +soup_session_request_uri (SoupSession *session, SoupURI *uri, + GError **error) +{ + SoupSessionPrivate *priv; + GType request_type; + + g_return_val_if_fail (SOUP_IS_SESSION (session), NULL); + + priv = soup_session_get_instance_private (session); + + request_type = (GType)GPOINTER_TO_SIZE (g_hash_table_lookup (priv->request_types, uri->scheme)); + if (!request_type) { + g_set_error (error, SOUP_REQUEST_ERROR, + SOUP_REQUEST_ERROR_UNSUPPORTED_URI_SCHEME, + _("Unsupported URI scheme “%s”"), uri->scheme); + return NULL; + } + + return g_initable_new (request_type, NULL, error, + "uri", uri, + "session", session, + NULL); +} + +static SoupRequestHTTP * +initialize_http_request (SoupRequest *req, + const char *method, + GError **error) +{ + SoupRequestHTTP *http; + SoupMessage *msg; + + if (!SOUP_IS_REQUEST_HTTP (req)) { + g_object_unref (req); + g_set_error (error, SOUP_REQUEST_ERROR, + SOUP_REQUEST_ERROR_BAD_URI, + _("Not an HTTP URI")); + return NULL; + } + + http = SOUP_REQUEST_HTTP (req); + msg = soup_request_http_get_message (http); + g_object_set (G_OBJECT (msg), + SOUP_MESSAGE_METHOD, method, + NULL); + g_object_unref (msg); + + return http; +} + +/** + * soup_session_request_http: + * @session: a #SoupSession + * @method: an HTTP method + * @uri_string: a URI, in string form + * @error: return location for a #GError, or %NULL + * + * Creates a #SoupRequest for retrieving @uri_string, which must be an + * "http" or "https" URI (or another protocol listed in @session's + * #SoupSession:http-aliases or #SoupSession:https-aliases). + * + * Return value: (transfer full): a new #SoupRequestHTTP, or + * %NULL on error. + * + * Since: 2.42 + */ +SoupRequestHTTP * +soup_session_request_http (SoupSession *session, + const char *method, + const char *uri_string, + GError **error) +{ + SoupRequest *req; + + req = soup_session_request (session, uri_string, error); + if (!req) + return NULL; + + return initialize_http_request (req, method, error); +} + +/** + * soup_session_request_http_uri: + * @session: a #SoupSession + * @method: an HTTP method + * @uri: a #SoupURI representing the URI to retrieve + * @error: return location for a #GError, or %NULL + * + * Creates a #SoupRequest for retrieving @uri, which must be an + * "http" or "https" URI (or another protocol listed in @session's + * #SoupSession:http-aliases or #SoupSession:https-aliases). + * + * Return value: (transfer full): a new #SoupRequestHTTP, or + * %NULL on error. + * + * Since: 2.42 + */ +SoupRequestHTTP * +soup_session_request_http_uri (SoupSession *session, + const char *method, + SoupURI *uri, + GError **error) +{ + SoupRequest *req; + + req = soup_session_request_uri (session, uri, error); + if (!req) + return NULL; + + return initialize_http_request (req, method, error); +} + +/** + * SOUP_REQUEST_ERROR: + * + * A #GError domain for #SoupRequest-related errors. Used with + * #SoupRequestError. + * + * Since: 2.42 + */ +/** + * SoupRequestError: + * @SOUP_REQUEST_ERROR_BAD_URI: the URI could not be parsed + * @SOUP_REQUEST_ERROR_UNSUPPORTED_URI_SCHEME: the URI scheme is not + * supported by this #SoupSession + * @SOUP_REQUEST_ERROR_PARSING: the server's response could not + * be parsed + * @SOUP_REQUEST_ERROR_ENCODING: the server's response was in an + * unsupported format + * + * A #SoupRequest error. + * + * Since: 2.42 + */ + +GQuark +soup_request_error_quark (void) +{ + static GQuark error; + if (!error) + error = g_quark_from_static_string ("soup_request_error_quark"); + return error; +} + +static GIOStream * +steal_connection (SoupSession *session, + SoupMessageQueueItem *item) +{ + SoupSessionPrivate *priv = soup_session_get_instance_private (session); + SoupConnection *conn; + SoupSocket *sock; + SoupSessionHost *host; + GIOStream *stream; + + conn = g_object_ref (item->conn); + soup_session_set_item_connection (session, item, NULL); + + g_mutex_lock (&priv->conn_lock); + host = get_host_for_message (session, item->msg); + g_hash_table_remove (priv->conns, conn); + drop_connection (session, host, conn); + g_mutex_unlock (&priv->conn_lock); + + sock = soup_connection_get_socket (conn); + g_object_set (sock, + SOUP_SOCKET_TIMEOUT, 0, + NULL); + + if (item->connect_only) + stream = g_object_ref (soup_socket_get_connection (sock)); + else + stream = soup_message_io_steal (item->msg); + g_object_set_data_full (G_OBJECT (stream), "GSocket", + soup_socket_steal_gsocket (sock), + g_object_unref); + g_object_unref (conn); + + return stream; +} + +/** + * soup_session_steal_connection: + * @session: a #SoupSession + * @msg: the message whose connection is to be stolen + * + * "Steals" the HTTP connection associated with @msg from @session. + * This happens immediately, regardless of the current state of the + * connection, and @msg's callback will not be called. You can steal + * the connection from a #SoupMessage signal handler if you need to + * wait for part or all of the response to be received first. + * + * Calling this function may cause @msg to be freed if you are not + * holding any other reference to it. + * + * Return value: (transfer full): the #GIOStream formerly associated + * with @msg (or %NULL if @msg was no longer associated with a + * connection). No guarantees are made about what kind of #GIOStream + * is returned. + * + * Since: 2.50 + **/ +GIOStream * +soup_session_steal_connection (SoupSession *session, + SoupMessage *msg) +{ + SoupSessionPrivate *priv = soup_session_get_instance_private (session); + SoupMessageQueueItem *item; + GIOStream *stream = NULL; + + item = soup_message_queue_lookup (priv->queue, msg); + if (!item) + return NULL; + + if (item->conn && soup_connection_get_state (item->conn) == SOUP_CONNECTION_IN_USE) + stream = steal_connection (session, item); + + soup_message_queue_item_unref (item); + + return stream; +} + +static void websocket_connect_async_stop (SoupMessage *msg, gpointer user_data); + +static void +websocket_connect_async_complete (SoupSession *session, SoupMessage *msg, gpointer user_data) +{ + GTask *task = user_data; + + /* Disconnect websocket_connect_async_stop() handler. */ + g_signal_handlers_disconnect_matched (msg, G_SIGNAL_MATCH_DATA, + 0, 0, NULL, NULL, task); + + g_task_return_new_error (task, + SOUP_WEBSOCKET_ERROR, SOUP_WEBSOCKET_ERROR_NOT_WEBSOCKET, + "%s", _("The server did not accept the WebSocket handshake.")); + g_object_unref (task); +} + +static void +websocket_connect_async_stop (SoupMessage *msg, gpointer user_data) +{ + GTask *task = user_data; + SoupMessageQueueItem *item = g_task_get_task_data (task); + GIOStream *stream; + SoupWebsocketConnection *client; + GError *error = NULL; + + /* Disconnect websocket_connect_async_stop() handler. */ + g_signal_handlers_disconnect_matched (msg, G_SIGNAL_MATCH_DATA, + 0, 0, NULL, NULL, task); + + if (soup_websocket_client_verify_handshake (item->msg, &error)){ + stream = soup_session_steal_connection (item->session, item->msg); + client = soup_websocket_connection_new (stream, + soup_message_get_uri (item->msg), + SOUP_WEBSOCKET_CONNECTION_CLIENT, + soup_message_headers_get_one (msg->request_headers, "Origin"), + soup_message_headers_get_one (msg->response_headers, "Sec-WebSocket-Protocol")); + g_object_unref (stream); + + g_task_return_pointer (task, client, g_object_unref); + } else + g_task_return_error (task, error); + g_object_unref (task); +} + +/** + * soup_session_websocket_connect_async: + * @session: a #SoupSession + * @msg: #SoupMessage indicating the WebSocket server to connect to + * @origin: (allow-none): origin of the connection + * @protocols: (allow-none) (array zero-terminated=1): a + * %NULL-terminated array of protocols supported + * @cancellable: a #GCancellable + * @callback: the callback to invoke + * @user_data: data for @callback + * + * Asynchronously creates a #SoupWebsocketConnection to communicate + * with a remote server. + * + * All necessary WebSocket-related headers will be added to @msg, and + * it will then be sent and asynchronously processed normally + * (including handling of redirection and HTTP authentication). + * + * If the server returns "101 Switching Protocols", then @msg's status + * code and response headers will be updated, and then the WebSocket + * handshake will be completed. On success, + * soup_session_websocket_connect_finish() will return a new + * #SoupWebsocketConnection. On failure it will return a #GError. + * + * If the server returns a status other than "101 Switching + * Protocols", then @msg will contain the complete response headers + * and body from the server's response, and + * soup_session_websocket_connect_finish() will return + * %SOUP_WEBSOCKET_ERROR_NOT_WEBSOCKET. + * + * Since: 2.50 + */ +void +soup_session_websocket_connect_async (SoupSession *session, + SoupMessage *msg, + const char *origin, + char **protocols, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + SoupSessionPrivate *priv = soup_session_get_instance_private (session); + SoupMessageQueueItem *item; + GTask *task; + + g_return_if_fail (SOUP_IS_SESSION (session)); + g_return_if_fail (priv->use_thread_context); + g_return_if_fail (SOUP_IS_MESSAGE (msg)); + + soup_websocket_client_prepare_handshake (msg, origin, protocols); + + task = g_task_new (session, cancellable, callback, user_data); + item = soup_session_append_queue_item (session, msg, TRUE, FALSE, + websocket_connect_async_complete, task); + g_task_set_task_data (task, item, (GDestroyNotify) soup_message_queue_item_unref); + + soup_message_add_status_code_handler (msg, "got-informational", + SOUP_STATUS_SWITCHING_PROTOCOLS, + G_CALLBACK (websocket_connect_async_stop), task); + soup_session_kick_queue (session); +} + +/** + * soup_session_websocket_connect_finish: + * @session: a #SoupSession + * @result: the #GAsyncResult passed to your callback + * @error: return location for a #GError, or %NULL + * + * Gets the #SoupWebsocketConnection response to a + * soup_session_websocket_connect_async() call and (if successful), + * returns a #SoupWebsocketConnection that can be used to communicate + * with the server. + * + * Return value: (transfer full): a new #SoupWebsocketConnection, or + * %NULL on error. + * + * Since: 2.50 + */ +SoupWebsocketConnection * +soup_session_websocket_connect_finish (SoupSession *session, + GAsyncResult *result, + GError **error) +{ + g_return_val_if_fail (SOUP_IS_SESSION (session), NULL); + g_return_val_if_fail (g_task_is_valid (result, session), NULL); + + return g_task_propagate_pointer (G_TASK (result), error); +} + +/** + * SoupSessionConnectProgressCallback: + * @session: the #SoupSession + * @event: a #GSocketClientEvent + * @connection: the current state of the network connection + * @user_data: the data passed to soup_session_connect_async(). + * + * Prototype for the progress callback passed to soup_session_connect_async(). + * + * Since: 2.62 + */ + +typedef struct { + SoupMessageQueueItem *item; + SoupSessionConnectProgressCallback progress_callback; + gpointer user_data; +} ConnectAsyncData; + +static ConnectAsyncData * +connect_async_data_new (SoupMessageQueueItem *item, + SoupSessionConnectProgressCallback progress_callback, + gpointer user_data) +{ + ConnectAsyncData *data; + + soup_message_queue_item_ref (item); + + data = g_slice_new (ConnectAsyncData); + data->item = item; + data->progress_callback = progress_callback; + data->user_data = user_data; + + return data; +} + +static void +connect_async_data_free (ConnectAsyncData *data) +{ + soup_message_queue_item_unref (data->item); + + g_slice_free (ConnectAsyncData, data); +} + +static void +connect_async_message_network_event (SoupMessage *msg, + GSocketClientEvent event, + GIOStream *connection, + GTask *task) +{ + ConnectAsyncData *data = g_task_get_task_data (task); + + if (data->progress_callback) + data->progress_callback (data->item->session, event, connection, data->user_data); +} + +static void +connect_async_message_finished (SoupMessage *msg, + GTask *task) +{ + ConnectAsyncData *data = g_task_get_task_data (task); + SoupMessageQueueItem *item = data->item; + + if (!item->conn || item->error) { + g_task_return_error (task, g_error_copy (item->error)); + } else { + g_task_return_pointer (task, + steal_connection (item->session, item), + g_object_unref); + } + g_object_unref (task); +} + +/** + * soup_session_connect_async: + * @session: a #SoupSession + * @uri: a #SoupURI to connect to + * @cancellable: a #GCancellable + * @progress_callback: (allow-none) (scope async): a #SoupSessionConnectProgressCallback which + * will be called for every network event that occurs during the connection. + * @callback: (allow-none) (scope async): the callback to invoke when the operation finishes + * @user_data: data for @progress_callback and @callback + * + * Start a connection to @uri. The operation can be monitored by providing a @progress_callback + * and finishes when the connection is done or an error ocurred. + * + * Call soup_session_connect_finish() to get the #GIOStream to communicate with the server. + * + * Since: 2.62 + */ +void +soup_session_connect_async (SoupSession *session, + SoupURI *uri, + GCancellable *cancellable, + SoupSessionConnectProgressCallback progress_callback, + GAsyncReadyCallback callback, + gpointer user_data) +{ + SoupSessionPrivate *priv; + SoupMessage *msg; + SoupMessageQueueItem *item; + ConnectAsyncData *data; + GTask *task; + + g_return_if_fail (SOUP_IS_SESSION (session)); + g_return_if_fail (!SOUP_IS_SESSION_SYNC (session)); + priv = soup_session_get_instance_private (session); + g_return_if_fail (priv->use_thread_context); + g_return_if_fail (uri != NULL); + + task = g_task_new (session, cancellable, callback, user_data); + + msg = soup_message_new_from_uri (SOUP_METHOD_HEAD, uri); + soup_message_set_flags (msg, SOUP_MESSAGE_NEW_CONNECTION); + g_signal_connect_object (msg, "finished", + G_CALLBACK (connect_async_message_finished), + task, 0); + if (progress_callback) { + g_signal_connect_object (msg, "network-event", + G_CALLBACK (connect_async_message_network_event), + task, 0); + } + + item = soup_session_append_queue_item (session, msg, TRUE, FALSE, NULL, NULL); + item->connect_only = TRUE; + data = connect_async_data_new (item, progress_callback, user_data); + g_task_set_task_data (task, data, (GDestroyNotify) connect_async_data_free); + soup_session_kick_queue (session); + soup_message_queue_item_unref (item); + g_object_unref (msg); +} + +/** + * soup_session_connect_finish: + * @session: a #SoupSession + * @result: the #GAsyncResult passed to your callback + * @error: return location for a #GError, or %NULL + * + * Gets the #GIOStream created for the connection to communicate with the server. + * + * Return value: (transfer full): a new #GIOStream, or %NULL on error. + * + * Since: 2.62 + */ +GIOStream * +soup_session_connect_finish (SoupSession *session, + GAsyncResult *result, + GError **error) +{ + g_return_val_if_fail (SOUP_IS_SESSION (session), NULL); + g_return_val_if_fail (g_task_is_valid (result, session), NULL); + + return g_task_propagate_pointer (G_TASK (result), error); +} diff --git a/libsoup/soup-session.h b/libsoup/soup-session.h new file mode 100644 index 0000000..24e90b2 --- /dev/null +++ b/libsoup/soup-session.h @@ -0,0 +1,257 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2000-2003, Ximian, Inc. + */ + +#ifndef SOUP_SESSION_H +#define SOUP_SESSION_H 1 + +#include +#include +#include +#include + +G_BEGIN_DECLS + +#define SOUP_TYPE_SESSION (soup_session_get_type ()) +#define SOUP_SESSION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SOUP_TYPE_SESSION, SoupSession)) +#define SOUP_SESSION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_SESSION, SoupSessionClass)) +#define SOUP_IS_SESSION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SOUP_TYPE_SESSION)) +#define SOUP_IS_SESSION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), SOUP_TYPE_SESSION)) +#define SOUP_SESSION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_SESSION, SoupSessionClass)) + +typedef void (*SoupSessionCallback) (SoupSession *session, + SoupMessage *msg, + gpointer user_data); + +struct _SoupSession { + GObject parent; + +}; + +typedef struct { + GObjectClass parent_class; + + /* signals */ + void (*request_started) (SoupSession *session, SoupMessage *msg, + SoupSocket *socket); + void (*authenticate) (SoupSession *session, SoupMessage *msg, + SoupAuth *auth, gboolean retrying); + + /* methods */ + void (*queue_message) (SoupSession *session, SoupMessage *msg, + SoupSessionCallback callback, + gpointer user_data); + void (*requeue_message) (SoupSession *session, SoupMessage *msg); + guint (*send_message) (SoupSession *session, SoupMessage *msg); + + void (*cancel_message) (SoupSession *session, SoupMessage *msg, + guint status_code); + + void (*auth_required) (SoupSession *session, SoupMessage *msg, + SoupAuth *auth, gboolean retrying); + + void (*flush_queue) (SoupSession *session); + + void (*kick) (SoupSession *session); + + /* Padding for future expansion */ + void (*_libsoup_reserved4) (void); +} SoupSessionClass; + +SOUP_AVAILABLE_IN_2_42 +GType soup_session_get_type (void); + +#define SOUP_SESSION_LOCAL_ADDRESS "local-address" +#define SOUP_SESSION_PROXY_URI "proxy-uri" +#define SOUP_SESSION_PROXY_RESOLVER "proxy-resolver" +#define SOUP_SESSION_MAX_CONNS "max-conns" +#define SOUP_SESSION_MAX_CONNS_PER_HOST "max-conns-per-host" +#define SOUP_SESSION_USE_NTLM "use-ntlm" +#define SOUP_SESSION_SSL_CA_FILE "ssl-ca-file" +#define SOUP_SESSION_SSL_USE_SYSTEM_CA_FILE "ssl-use-system-ca-file" +#define SOUP_SESSION_TLS_DATABASE "tls-database" +#define SOUP_SESSION_SSL_STRICT "ssl-strict" +#define SOUP_SESSION_TLS_INTERACTION "tls-interaction" +#define SOUP_SESSION_ASYNC_CONTEXT "async-context" +#define SOUP_SESSION_USE_THREAD_CONTEXT "use-thread-context" +#define SOUP_SESSION_TIMEOUT "timeout" +#define SOUP_SESSION_USER_AGENT "user-agent" +#define SOUP_SESSION_ACCEPT_LANGUAGE "accept-language" +#define SOUP_SESSION_ACCEPT_LANGUAGE_AUTO "accept-language-auto" +#define SOUP_SESSION_IDLE_TIMEOUT "idle-timeout" +#define SOUP_SESSION_ADD_FEATURE "add-feature" +#define SOUP_SESSION_ADD_FEATURE_BY_TYPE "add-feature-by-type" +#define SOUP_SESSION_REMOVE_FEATURE_BY_TYPE "remove-feature-by-type" +#define SOUP_SESSION_HTTP_ALIASES "http-aliases" +#define SOUP_SESSION_HTTPS_ALIASES "https-aliases" + +SOUP_AVAILABLE_IN_2_42 +SoupSession *soup_session_new (void); + +SOUP_AVAILABLE_IN_2_42 +SoupSession *soup_session_new_with_options (const char *optname1, + ...) G_GNUC_NULL_TERMINATED; + +SOUP_AVAILABLE_IN_2_4 +void soup_session_queue_message (SoupSession *session, + SoupMessage *msg, + SoupSessionCallback callback, + gpointer user_data); +SOUP_AVAILABLE_IN_2_4 +void soup_session_requeue_message (SoupSession *session, + SoupMessage *msg); + +SOUP_AVAILABLE_IN_2_4 +guint soup_session_send_message (SoupSession *session, + SoupMessage *msg); + +SOUP_AVAILABLE_IN_2_4 +void soup_session_pause_message (SoupSession *session, + SoupMessage *msg); +SOUP_AVAILABLE_IN_2_4 +void soup_session_unpause_message (SoupSession *session, + SoupMessage *msg); + +SOUP_AVAILABLE_IN_2_4 +void soup_session_cancel_message (SoupSession *session, + SoupMessage *msg, + guint status_code); +SOUP_AVAILABLE_IN_2_4 +void soup_session_abort (SoupSession *session); + +SOUP_AVAILABLE_IN_2_4 +GMainContext *soup_session_get_async_context(SoupSession *session); + +SOUP_AVAILABLE_IN_2_42 +void soup_session_send_async (SoupSession *session, + SoupMessage *msg, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +SOUP_AVAILABLE_IN_2_42 +GInputStream *soup_session_send_finish (SoupSession *session, + GAsyncResult *result, + GError **error); +SOUP_AVAILABLE_IN_2_42 +GInputStream *soup_session_send (SoupSession *session, + SoupMessage *msg, + GCancellable *cancellable, + GError **error); + +#ifndef SOUP_DISABLE_DEPRECATED +SOUP_AVAILABLE_IN_2_30 +SOUP_DEPRECATED_IN_2_38_FOR (soup_session_prefetch_dns) +void soup_session_prepare_for_uri (SoupSession *session, + SoupURI *uri); +#endif + +SOUP_AVAILABLE_IN_2_38 +void soup_session_prefetch_dns (SoupSession *session, + const char *hostname, + GCancellable *cancellable, + SoupAddressCallback callback, + gpointer user_data); + +SOUP_AVAILABLE_IN_2_38 +gboolean soup_session_would_redirect (SoupSession *session, + SoupMessage *msg); +SOUP_AVAILABLE_IN_2_38 +gboolean soup_session_redirect_message (SoupSession *session, + SoupMessage *msg); + +SOUP_AVAILABLE_IN_2_24 +void soup_session_add_feature (SoupSession *session, + SoupSessionFeature *feature); +SOUP_AVAILABLE_IN_2_24 +void soup_session_add_feature_by_type (SoupSession *session, + GType feature_type); +SOUP_AVAILABLE_IN_2_24 +void soup_session_remove_feature (SoupSession *session, + SoupSessionFeature *feature); +SOUP_AVAILABLE_IN_2_24 +void soup_session_remove_feature_by_type (SoupSession *session, + GType feature_type); +SOUP_AVAILABLE_IN_2_42 +gboolean soup_session_has_feature (SoupSession *session, + GType feature_type); +SOUP_AVAILABLE_IN_2_26 +GSList *soup_session_get_features (SoupSession *session, + GType feature_type); +SOUP_AVAILABLE_IN_2_26 +SoupSessionFeature *soup_session_get_feature (SoupSession *session, + GType feature_type); +SOUP_AVAILABLE_IN_2_28 +SoupSessionFeature *soup_session_get_feature_for_message(SoupSession *session, + GType feature_type, + SoupMessage *msg); + +SOUP_AVAILABLE_IN_2_42 +SoupRequest *soup_session_request (SoupSession *session, + const char *uri_string, + GError **error); +SOUP_AVAILABLE_IN_2_42 +SoupRequest *soup_session_request_uri (SoupSession *session, + SoupURI *uri, + GError **error); +SOUP_AVAILABLE_IN_2_42 +SoupRequestHTTP *soup_session_request_http (SoupSession *session, + const char *method, + const char *uri_string, + GError **error); +SOUP_AVAILABLE_IN_2_42 +SoupRequestHTTP *soup_session_request_http_uri (SoupSession *session, + const char *method, + SoupURI *uri, + GError **error); + +SOUP_AVAILABLE_IN_2_42 +GQuark soup_request_error_quark (void); +#define SOUP_REQUEST_ERROR soup_request_error_quark () + +typedef enum { + SOUP_REQUEST_ERROR_BAD_URI, + SOUP_REQUEST_ERROR_UNSUPPORTED_URI_SCHEME, + SOUP_REQUEST_ERROR_PARSING, + SOUP_REQUEST_ERROR_ENCODING +} SoupRequestError; + +SOUP_AVAILABLE_IN_2_50 +GIOStream *soup_session_steal_connection (SoupSession *session, + SoupMessage *msg); + +SOUP_AVAILABLE_IN_2_50 +void soup_session_websocket_connect_async (SoupSession *session, + SoupMessage *msg, + const char *origin, + char **protocols, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +SOUP_AVAILABLE_IN_2_50 +SoupWebsocketConnection *soup_session_websocket_connect_finish (SoupSession *session, + GAsyncResult *result, + GError **error); + +typedef void (*SoupSessionConnectProgressCallback) (SoupSession *session, + GSocketClientEvent event, + GIOStream *connection, + gpointer user_data); + +SOUP_AVAILABLE_IN_2_62 +void soup_session_connect_async (SoupSession *session, + SoupURI *uri, + GCancellable *cancellable, + SoupSessionConnectProgressCallback progress_callback, + GAsyncReadyCallback callback, + gpointer user_data); + +SOUP_AVAILABLE_IN_2_62 +GIOStream *soup_session_connect_finish (SoupSession *session, + GAsyncResult *result, + GError **error); + +G_END_DECLS + +#endif /* SOUP_SESSION_H */ diff --git a/libsoup/soup-socket-private.h b/libsoup/soup-socket-private.h new file mode 100644 index 0000000..8677884 --- /dev/null +++ b/libsoup/soup-socket-private.h @@ -0,0 +1,91 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright 2011-2014 Red Hat, Inc. + */ + +#ifndef SOUP_SOCKET_PRIVATE_H +#define SOUP_SOCKET_PRIVATE_H 1 + +#include "soup-socket.h" + +#define SOUP_SOCKET_SOCKET_PROPERTIES "socket-properties" +#define SOUP_SOCKET_FD "fd" +#define SOUP_SOCKET_GSOCKET "gsocket" +#define SOUP_SOCKET_IOSTREAM "iostream" +#define SOUP_SOCKET_IPV6_ONLY "ipv6-only" + +gboolean soup_socket_connect_sync_internal (SoupSocket *sock, + GCancellable *cancellable, + GError **error); +void soup_socket_connect_async_internal (SoupSocket *sock, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean soup_socket_connect_finish_internal (SoupSocket *sock, + GAsyncResult *result, + GError **error); + +gboolean soup_socket_handshake_sync (SoupSocket *sock, + const char *host, + GCancellable *cancellable, + GError **error); +void soup_socket_handshake_async (SoupSocket *sock, + const char *host, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean soup_socket_handshake_finish (SoupSocket *sock, + GAsyncResult *result, + GError **error); + +gboolean soup_socket_is_readable (SoupSocket *sock); +GSocket *soup_socket_get_gsocket (SoupSocket *sock); +GSocket *soup_socket_steal_gsocket (SoupSocket *sock); +GIOStream *soup_socket_get_connection (SoupSocket *sock); +GIOStream *soup_socket_get_iostream (SoupSocket *sock); + +SoupURI *soup_socket_get_http_proxy_uri (SoupSocket *sock); + +gboolean soup_socket_listen_full (SoupSocket *sock, + GError **error); + + + +typedef struct { + GMainContext *async_context; + gboolean use_thread_context; + + GProxyResolver *proxy_resolver; + SoupAddress *local_addr; + + GTlsDatabase *tlsdb; + GTlsInteraction *tls_interaction; + gboolean ssl_strict; + + guint io_timeout; + guint idle_timeout; + + /*< private >*/ + guint ref_count; +} SoupSocketProperties; + +GType soup_socket_properties_get_type (void); +#define SOUP_TYPE_SOCKET_PROPERTIES (soup_socket_properties_get_type ()) + +SoupSocketProperties *soup_socket_properties_new (GMainContext *async_context, + gboolean use_thread_context, + GProxyResolver *proxy_resolver, + SoupAddress *local_addr, + GTlsDatabase *tlsdb, + GTlsInteraction *tls_interaction, + gboolean ssl_strict, + guint io_timeout, + guint idle_timeout); + +SoupSocketProperties *soup_socket_properties_ref (SoupSocketProperties *props); +void soup_socket_properties_unref (SoupSocketProperties *props); + +void soup_socket_properties_push_async_context (SoupSocketProperties *props); +void soup_socket_properties_pop_async_context (SoupSocketProperties *props); + +#endif /* SOUP_SOCKET_PRIVATE_H */ diff --git a/libsoup/soup-socket-properties.c b/libsoup/soup-socket-properties.c new file mode 100644 index 0000000..3c99be7 --- /dev/null +++ b/libsoup/soup-socket-properties.c @@ -0,0 +1,81 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright 2013 Red Hat, Inc. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "soup-socket-private.h" +#include "soup.h" + +SoupSocketProperties * +soup_socket_properties_new (GMainContext *async_context, + gboolean use_thread_context, + GProxyResolver *proxy_resolver, + SoupAddress *local_addr, + GTlsDatabase *tlsdb, + GTlsInteraction *tls_interaction, + gboolean ssl_strict, + guint io_timeout, + guint idle_timeout) +{ + SoupSocketProperties *props; + + props = g_slice_new (SoupSocketProperties); + props->ref_count = 1; + + props->async_context = async_context ? g_main_context_ref (async_context) : NULL; + props->use_thread_context = use_thread_context; + + props->proxy_resolver = proxy_resolver ? g_object_ref (proxy_resolver) : NULL; + props->local_addr = local_addr ? g_object_ref (local_addr) : NULL; + + props->tlsdb = tlsdb ? g_object_ref (tlsdb) : NULL; + props->tls_interaction = tls_interaction ? g_object_ref (tls_interaction) : NULL; + props->ssl_strict = ssl_strict; + + props->io_timeout = io_timeout; + props->idle_timeout = idle_timeout; + + return props; +} + +SoupSocketProperties * +soup_socket_properties_ref (SoupSocketProperties *props) +{ + g_atomic_int_inc (&props->ref_count); + return props; +} + +void +soup_socket_properties_unref (SoupSocketProperties *props) +{ + if (!g_atomic_int_dec_and_test (&props->ref_count)) + return; + + g_clear_pointer (&props->async_context, g_main_context_unref); + g_clear_object (&props->proxy_resolver); + g_clear_object (&props->local_addr); + g_clear_object (&props->tlsdb); + g_clear_object (&props->tls_interaction); + + g_slice_free (SoupSocketProperties, props); +} + +void +soup_socket_properties_push_async_context (SoupSocketProperties *props) +{ + if (props->async_context && !props->use_thread_context) + g_main_context_push_thread_default (props->async_context); +} + +void +soup_socket_properties_pop_async_context (SoupSocketProperties *props) +{ + if (props->async_context && !props->use_thread_context) + g_main_context_pop_thread_default (props->async_context); +} + +G_DEFINE_BOXED_TYPE (SoupSocketProperties, soup_socket_properties, soup_socket_properties_ref, soup_socket_properties_unref) diff --git a/libsoup/soup-socket.c b/libsoup/soup-socket.c new file mode 100644 index 0000000..311c627 --- /dev/null +++ b/libsoup/soup-socket.c @@ -0,0 +1,2045 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-socket.c: Socket networking code. + * + * Copyright (C) 2000-2003, Ximian, Inc. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include +#include + +#include "soup-socket.h" +#include "soup-socket-private.h" +#include "soup.h" +#include "soup-filter-input-stream.h" +#include "soup-io-stream.h" + +/** + * SECTION:soup-socket + * @short_description: A network socket + * + * #SoupSocket is libsoup's TCP socket type. While it is primarily + * intended for internal use, #SoupSockets are exposed in the + * API in various places, and some of their methods (eg, + * soup_socket_get_remote_address()) may be useful to applications. + **/ + +enum { + READABLE, + WRITABLE, + DISCONNECTED, + NEW_CONNECTION, + EVENT, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +enum { + PROP_0, + + PROP_FD, + PROP_GSOCKET, + PROP_IOSTREAM, + PROP_LOCAL_ADDRESS, + PROP_REMOTE_ADDRESS, + PROP_NON_BLOCKING, + PROP_IPV6_ONLY, + PROP_IS_SERVER, + PROP_SSL_CREDENTIALS, + PROP_SSL_STRICT, + PROP_SSL_FALLBACK, + PROP_ASYNC_CONTEXT, + PROP_USE_THREAD_CONTEXT, + PROP_TIMEOUT, + PROP_TRUSTED_CERTIFICATE, + PROP_TLS_CERTIFICATE, + PROP_TLS_ERRORS, + PROP_SOCKET_PROPERTIES, + + LAST_PROP +}; + +typedef struct { + SoupAddress *local_addr, *remote_addr; + GIOStream *conn, *iostream; + GSocket *gsock; + GInputStream *istream; + GOutputStream *ostream; + GTlsCertificateFlags tls_errors; + GTlsInteraction *tls_interaction; + GProxyResolver *proxy_resolver; + + guint non_blocking:1; + guint ipv6_only:1; + guint is_server:1; + guint ssl:1; + guint ssl_strict:1; + guint ssl_fallback:1; + guint clean_dispose:1; + guint use_thread_context:1; + gpointer ssl_creds; + + GMainContext *async_context; + GSource *watch_src; + GSource *read_src, *write_src; + + GMutex iolock, addrlock; + guint timeout; + + GCancellable *connect_cancel; + int fd; +} SoupSocketPrivate; + +static void soup_socket_initable_interface_init (GInitableIface *initable_interface); + +G_DEFINE_TYPE_WITH_CODE (SoupSocket, soup_socket, G_TYPE_OBJECT, + G_ADD_PRIVATE (SoupSocket) + G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, + soup_socket_initable_interface_init)) + +static void soup_socket_peer_certificate_changed (GObject *conn, + GParamSpec *pspec, + gpointer user_data); +static void finish_socket_setup (SoupSocket *sock); +static void finish_listener_setup (SoupSocket *sock); + +static void +soup_socket_init (SoupSocket *sock) +{ + SoupSocketPrivate *priv = soup_socket_get_instance_private (sock); + + priv->non_blocking = TRUE; + priv->fd = -1; + g_mutex_init (&priv->addrlock); + g_mutex_init (&priv->iolock); +} + +static gboolean +soup_socket_initable_init (GInitable *initable, + GCancellable *cancellable, + GError **error) +{ + SoupSocket *sock = SOUP_SOCKET (initable); + SoupSocketPrivate *priv = soup_socket_get_instance_private (sock); + + if (priv->conn) { + g_warn_if_fail (priv->gsock == NULL); + g_warn_if_fail (priv->fd == -1); + + finish_socket_setup (sock); + } + + if (priv->fd != -1) { + guint type, len = sizeof (type); + + g_warn_if_fail (priv->gsock == NULL); + + /* GSocket will g_error() this, so we have to check ourselves. */ + if (getsockopt (priv->fd, SOL_SOCKET, SO_TYPE, + (gpointer)&type, (gpointer)&len) == -1) { + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, + _("Can’t import non-socket as SoupSocket")); + return FALSE; + } + + priv->gsock = g_socket_new_from_fd (priv->fd, error); + if (!priv->gsock) + return FALSE; + } + + if (priv->gsock != NULL) { + int listening; + + g_warn_if_fail (priv->local_addr == NULL); + g_warn_if_fail (priv->remote_addr == NULL); + + if (!g_socket_get_option (priv->gsock, + SOL_SOCKET, SO_ACCEPTCONN, + &listening, error)) { + g_prefix_error (error, _("Could not import existing socket: ")); + return FALSE; + } + + finish_socket_setup (sock); + if (listening) + finish_listener_setup (sock); + else if (!g_socket_is_connected (priv->gsock)) { + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, + _("Can’t import unconnected socket")); + return FALSE; + } + } + + return TRUE; +} + +static void +disconnect_internal (SoupSocket *sock, gboolean close) +{ + SoupSocketPrivate *priv = soup_socket_get_instance_private (sock); + + g_clear_object (&priv->gsock); + if (priv->conn && close) { + g_io_stream_close (priv->conn, NULL, NULL); + g_signal_handlers_disconnect_by_data (priv->conn, sock); + g_clear_object (&priv->conn); + } + + if (priv->read_src) { + g_source_destroy (priv->read_src); + priv->read_src = NULL; + } + if (priv->write_src) { + g_source_destroy (priv->write_src); + priv->write_src = NULL; + } +} + +static void +soup_socket_finalize (GObject *object) +{ + SoupSocket *sock = SOUP_SOCKET (object); + SoupSocketPrivate *priv = soup_socket_get_instance_private (sock); + + if (priv->connect_cancel) { + if (priv->clean_dispose) + g_warning ("Disposing socket %p during connect", object); + g_object_unref (priv->connect_cancel); + } + if (priv->conn) { + if (priv->clean_dispose) + g_warning ("Disposing socket %p while still connected", object); + disconnect_internal (SOUP_SOCKET (object), TRUE); + } + + g_clear_object (&priv->conn); + g_clear_object (&priv->iostream); + g_clear_object (&priv->istream); + g_clear_object (&priv->ostream); + + g_clear_object (&priv->local_addr); + g_clear_object (&priv->remote_addr); + + g_clear_object (&priv->tls_interaction); + g_clear_object (&priv->proxy_resolver); + g_clear_object (&priv->ssl_creds); + + if (priv->watch_src) { + if (priv->clean_dispose && !priv->is_server) + g_warning ("Disposing socket %p during async op", object); + g_source_destroy (priv->watch_src); + } + g_clear_pointer (&priv->async_context, g_main_context_unref); + + g_mutex_clear (&priv->addrlock); + g_mutex_clear (&priv->iolock); + + G_OBJECT_CLASS (soup_socket_parent_class)->finalize (object); +} + +static void +finish_socket_setup (SoupSocket *sock) +{ + SoupSocketPrivate *priv = soup_socket_get_instance_private (sock); + + if (priv->gsock) { + if (!priv->conn) + priv->conn = (GIOStream *)g_socket_connection_factory_create_connection (priv->gsock); + + g_socket_set_timeout (priv->gsock, priv->timeout); + g_socket_set_option (priv->gsock, IPPROTO_TCP, TCP_NODELAY, TRUE, NULL); + } + + if (!priv->conn) + return; + + if (!priv->iostream) + priv->iostream = soup_io_stream_new (priv->conn, FALSE); + if (!priv->istream) + priv->istream = g_object_ref (g_io_stream_get_input_stream (priv->iostream)); + if (!priv->ostream) + priv->ostream = g_object_ref (g_io_stream_get_output_stream (priv->iostream)); +} + +static void +soup_socket_set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + SoupSocket *sock = SOUP_SOCKET (object); + SoupSocketPrivate *priv = soup_socket_get_instance_private (sock); + SoupSocketProperties *props; + + switch (prop_id) { + case PROP_FD: + priv->fd = g_value_get_int (value); + break; + case PROP_GSOCKET: + priv->gsock = g_value_dup_object (value); + break; + case PROP_IOSTREAM: + priv->conn = g_value_dup_object (value); + break; + case PROP_LOCAL_ADDRESS: + priv->local_addr = g_value_dup_object (value); + break; + case PROP_REMOTE_ADDRESS: + priv->remote_addr = g_value_dup_object (value); + break; + case PROP_NON_BLOCKING: + priv->non_blocking = g_value_get_boolean (value); + break; + case PROP_IPV6_ONLY: + priv->ipv6_only = g_value_get_boolean (value); + break; + case PROP_SSL_CREDENTIALS: + priv->ssl_creds = g_value_get_pointer (value); + if (priv->ssl_creds) + g_object_ref (priv->ssl_creds); + break; + case PROP_SSL_STRICT: + priv->ssl_strict = g_value_get_boolean (value); + break; + case PROP_SSL_FALLBACK: + priv->ssl_fallback = g_value_get_boolean (value); + break; + case PROP_ASYNC_CONTEXT: + if (!priv->use_thread_context) { + priv->async_context = g_value_get_pointer (value); + if (priv->async_context) + g_main_context_ref (priv->async_context); + } + break; + case PROP_USE_THREAD_CONTEXT: + priv->use_thread_context = g_value_get_boolean (value); + if (priv->use_thread_context) { + g_clear_pointer (&priv->async_context, g_main_context_unref); + priv->async_context = g_main_context_ref_thread_default (); + } + break; + case PROP_TIMEOUT: + priv->timeout = g_value_get_uint (value); + if (priv->conn) + g_socket_set_timeout (priv->gsock, priv->timeout); + break; + case PROP_SOCKET_PROPERTIES: + props = g_value_get_boxed (value); + if (props) { + g_clear_pointer (&priv->async_context, g_main_context_unref); + if (props->use_thread_context) { + priv->use_thread_context = TRUE; + priv->async_context = g_main_context_ref_thread_default (); + } else { + priv->use_thread_context = FALSE; + if (props->async_context) + priv->async_context = g_main_context_ref (props->async_context); + } + + g_clear_object (&priv->proxy_resolver); + if (props->proxy_resolver) + priv->proxy_resolver = g_object_ref (props->proxy_resolver); + + g_clear_object (&priv->local_addr); + if (props->local_addr) + priv->local_addr = g_object_ref (props->local_addr); + + g_clear_object (&priv->ssl_creds); + if (props->tlsdb) + priv->ssl_creds = g_object_ref (props->tlsdb); + g_clear_object (&priv->tls_interaction); + if (props->tls_interaction) + priv->tls_interaction = g_object_ref (props->tls_interaction); + priv->ssl_strict = props->ssl_strict; + + priv->timeout = props->io_timeout; + if (priv->conn) + g_socket_set_timeout (priv->gsock, priv->timeout); + + priv->clean_dispose = TRUE; + } + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +soup_socket_get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + SoupSocket *sock = SOUP_SOCKET (object); + SoupSocketPrivate *priv = soup_socket_get_instance_private (sock); + + switch (prop_id) { + case PROP_FD: + g_value_set_int (value, priv->fd); + break; + case PROP_LOCAL_ADDRESS: + g_value_set_object (value, soup_socket_get_local_address (SOUP_SOCKET (object))); + break; + case PROP_REMOTE_ADDRESS: + g_value_set_object (value, soup_socket_get_remote_address (SOUP_SOCKET (object))); + break; + case PROP_NON_BLOCKING: + g_value_set_boolean (value, priv->non_blocking); + break; + case PROP_IPV6_ONLY: + g_value_set_boolean (value, priv->ipv6_only); + break; + case PROP_IS_SERVER: + g_value_set_boolean (value, priv->is_server); + break; + case PROP_SSL_CREDENTIALS: + g_value_set_pointer (value, priv->ssl_creds); + break; + case PROP_SSL_STRICT: + g_value_set_boolean (value, priv->ssl_strict); + break; + case PROP_SSL_FALLBACK: + g_value_set_boolean (value, priv->ssl_fallback); + break; + case PROP_TRUSTED_CERTIFICATE: + g_value_set_boolean (value, priv->tls_errors == 0); + break; + case PROP_ASYNC_CONTEXT: + g_value_set_pointer (value, priv->async_context ? g_main_context_ref (priv->async_context) : NULL); + break; + case PROP_USE_THREAD_CONTEXT: + g_value_set_boolean (value, priv->use_thread_context); + break; + case PROP_TIMEOUT: + g_value_set_uint (value, priv->timeout); + break; + case PROP_TLS_CERTIFICATE: + if (G_IS_TLS_CONNECTION (priv->conn)) + g_value_set_object (value, g_tls_connection_get_peer_certificate (G_TLS_CONNECTION (priv->conn))); + else + g_value_set_object (value, NULL); + break; + case PROP_TLS_ERRORS: + g_value_set_flags (value, priv->tls_errors); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +soup_socket_class_init (SoupSocketClass *socket_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (socket_class); + + /* virtual method override */ + object_class->finalize = soup_socket_finalize; + object_class->set_property = soup_socket_set_property; + object_class->get_property = soup_socket_get_property; + + /* signals */ + + /** + * SoupSocket::readable: + * @sock: the socket + * + * Emitted when an async socket is readable. See + * soup_socket_read(), soup_socket_read_until() and + * #SoupSocket:non-blocking. + **/ + signals[READABLE] = + g_signal_new ("readable", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (SoupSocketClass, readable), + NULL, NULL, + NULL, + G_TYPE_NONE, 0); + + /** + * SoupSocket::writable: + * @sock: the socket + * + * Emitted when an async socket is writable. See + * soup_socket_write() and #SoupSocket:non-blocking. + **/ + signals[WRITABLE] = + g_signal_new ("writable", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (SoupSocketClass, writable), + NULL, NULL, + NULL, + G_TYPE_NONE, 0); + + /** + * SoupSocket::disconnected: + * @sock: the socket + * + * Emitted when the socket is disconnected, for whatever + * reason. + **/ + signals[DISCONNECTED] = + g_signal_new ("disconnected", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (SoupSocketClass, disconnected), + NULL, NULL, + NULL, + G_TYPE_NONE, 0); + + /** + * SoupSocket::new-connection: + * @sock: the socket + * @new: the new socket + * + * Emitted when a listening socket (set up with + * soup_socket_listen()) receives a new connection. + * + * You must ref the @new if you want to keep it; otherwise it + * will be destroyed after the signal is emitted. + **/ + signals[NEW_CONNECTION] = + g_signal_new ("new_connection", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (SoupSocketClass, new_connection), + NULL, NULL, + NULL, + G_TYPE_NONE, 1, + SOUP_TYPE_SOCKET); + /** + * SoupSocket::event: + * @sock: the socket + * @event: the event that occurred + * @connection: the current connection state + * + * Emitted when a network-related event occurs. See + * #GSocketClient::event for more details. + * + * Since: 2.38 + **/ + signals[EVENT] = + g_signal_new ("event", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + NULL, + G_TYPE_NONE, 2, + G_TYPE_SOCKET_CLIENT_EVENT, + G_TYPE_IO_STREAM); + + + /* properties */ + g_object_class_install_property ( + object_class, PROP_FD, + g_param_spec_int (SOUP_SOCKET_FD, + "FD", + "The socket's file descriptor", + -1, G_MAXINT, -1, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + g_object_class_install_property ( + object_class, PROP_GSOCKET, + g_param_spec_object (SOUP_SOCKET_GSOCKET, + "GSocket", + "The socket's underlying GSocket", + G_TYPE_SOCKET, + G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); + g_object_class_install_property ( + object_class, PROP_IOSTREAM, + g_param_spec_object (SOUP_SOCKET_IOSTREAM, + "GIOStream", + "The socket's underlying GIOStream", + G_TYPE_IO_STREAM, + G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); + + /** + * SOUP_SOCKET_LOCAL_ADDRESS: + * + * Alias for the #SoupSocket:local-address property. (Address + * of local end of socket.) + **/ + g_object_class_install_property ( + object_class, PROP_LOCAL_ADDRESS, + g_param_spec_object (SOUP_SOCKET_LOCAL_ADDRESS, + "Local address", + "Address of local end of socket", + SOUP_TYPE_ADDRESS, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + /** + * SOUP_SOCKET_REMOTE_ADDRESS: + * + * Alias for the #SoupSocket:remote-address property. (Address + * of remote end of socket.) + **/ + g_object_class_install_property ( + object_class, PROP_REMOTE_ADDRESS, + g_param_spec_object (SOUP_SOCKET_REMOTE_ADDRESS, + "Remote address", + "Address of remote end of socket", + SOUP_TYPE_ADDRESS, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + /** + * SoupSocket:non-blocking: + * + * Whether or not the socket uses non-blocking I/O. + * + * #SoupSocket's I/O methods are designed around the idea of + * using a single codepath for both synchronous and + * asynchronous I/O. If you want to read off a #SoupSocket, + * the "correct" way to do it is to call soup_socket_read() or + * soup_socket_read_until() repeatedly until you have read + * everything you want. If it returns %SOUP_SOCKET_WOULD_BLOCK + * at any point, stop reading and wait for it to emit the + * #SoupSocket::readable signal. Then go back to the + * reading-as-much-as-you-can loop. Likewise, for writing to a + * #SoupSocket, you should call soup_socket_write() either + * until you have written everything, or it returns + * %SOUP_SOCKET_WOULD_BLOCK (in which case you wait for + * #SoupSocket::writable and then go back into the loop). + * + * Code written this way will work correctly with both + * blocking and non-blocking sockets; blocking sockets will + * simply never return %SOUP_SOCKET_WOULD_BLOCK, and so the + * code that handles that case just won't get used for them. + **/ + /** + * SOUP_SOCKET_FLAG_NONBLOCKING: + * + * Alias for the #SoupSocket:non-blocking property. (Whether + * or not the socket uses non-blocking I/O.) + **/ + g_object_class_install_property ( + object_class, PROP_NON_BLOCKING, + g_param_spec_boolean (SOUP_SOCKET_FLAG_NONBLOCKING, + "Non-blocking", + "Whether or not the socket uses non-blocking I/O", + TRUE, + G_PARAM_READWRITE)); + g_object_class_install_property ( + object_class, PROP_IPV6_ONLY, + g_param_spec_boolean (SOUP_SOCKET_IPV6_ONLY, + "IPv6 only", + "IPv6 only", + FALSE, + G_PARAM_READWRITE)); + /** + * SOUP_SOCKET_IS_SERVER: + * + * Alias for the #SoupSocket:is-server property, qv. + **/ + /** + * SoupSocket:is-server: + * + * Whether or not the socket is a server socket. + * + * Note that for "ordinary" #SoupSockets this will be set for + * both listening sockets and the sockets emitted by + * #SoupSocket::new-connection, but for sockets created by + * setting #SoupSocket:fd, it will only be set for listening + * sockets. + **/ + g_object_class_install_property ( + object_class, PROP_IS_SERVER, + g_param_spec_boolean (SOUP_SOCKET_IS_SERVER, + "Server", + "Whether or not the socket is a server socket", + FALSE, + G_PARAM_READABLE)); + /** + * SOUP_SOCKET_SSL_CREDENTIALS: + * + * Alias for the #SoupSocket:ssl-creds property. + * (SSL credential information.) + **/ + /* For historical reasons, there's only a single property + * here, which is a GTlsDatabase for client sockets, and + * a GTlsCertificate for server sockets. Whee! + */ + g_object_class_install_property ( + object_class, PROP_SSL_CREDENTIALS, + g_param_spec_pointer (SOUP_SOCKET_SSL_CREDENTIALS, + "SSL credentials", + "SSL credential information, passed from the session to the SSL implementation", + G_PARAM_READWRITE)); + /** + * SOUP_SOCKET_SSL_STRICT: + * + * Alias for the #SoupSocket:ssl-strict property. + **/ + g_object_class_install_property ( + object_class, PROP_SSL_STRICT, + g_param_spec_boolean (SOUP_SOCKET_SSL_STRICT, + "Strictly validate SSL certificates", + "Whether certificate errors should be considered a connection error", + TRUE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + /** + * SOUP_SOCKET_SSL_FALLBACK: + * + * Alias for the #SoupSocket:ssl-fallback property. + **/ + g_object_class_install_property ( + object_class, PROP_SSL_FALLBACK, + g_param_spec_boolean (SOUP_SOCKET_SSL_FALLBACK, + "SSLv3 fallback", + "Use SSLv3 instead of TLS (client-side only)", + FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + /** + * SOUP_SOCKET_TRUSTED_CERTIFICATE: + * + * Alias for the #SoupSocket:trusted-certificate + * property. + **/ + g_object_class_install_property ( + object_class, PROP_TRUSTED_CERTIFICATE, + g_param_spec_boolean (SOUP_SOCKET_TRUSTED_CERTIFICATE, + "Trusted Certificate", + "Whether the server certificate is trusted, if this is an SSL socket", + FALSE, + G_PARAM_READABLE)); + /** + * SOUP_SOCKET_ASYNC_CONTEXT: + * + * Alias for the #SoupSocket:async-context property. (The + * socket's #GMainContext.) + **/ + g_object_class_install_property ( + object_class, PROP_ASYNC_CONTEXT, + g_param_spec_pointer (SOUP_SOCKET_ASYNC_CONTEXT, + "Async GMainContext", + "The GMainContext to dispatch this socket's async I/O in", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + /** + * SOUP_SOCKET_USE_THREAD_CONTEXT: + * + * Alias for the #SoupSocket:use-thread-context property. (Use + * g_main_context_get_thread_default()) + * + * Since: 2.38 + */ + /** + * SoupSocket:use-thread-context: + * + * Use g_main_context_get_thread_default(). + * + * Since: 2.38 + */ + g_object_class_install_property ( + object_class, PROP_USE_THREAD_CONTEXT, + g_param_spec_boolean (SOUP_SOCKET_USE_THREAD_CONTEXT, + "Use thread context", + "Use g_main_context_get_thread_default", + FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + /** + * SOUP_SOCKET_TIMEOUT: + * + * Alias for the #SoupSocket:timeout property. (The timeout + * in seconds for blocking socket I/O operations.) + **/ + g_object_class_install_property ( + object_class, PROP_TIMEOUT, + g_param_spec_uint (SOUP_SOCKET_TIMEOUT, + "Timeout value", + "Value in seconds to timeout a blocking I/O", + 0, G_MAXUINT, 0, + G_PARAM_READWRITE)); + + /** + * SOUP_SOCKET_TLS_CERTIFICATE: + * + * Alias for the #SoupSocket:tls-certificate + * property. Note that this property's value is only useful + * if the socket is for a TLS connection, and only reliable + * after some data has been transferred to or from it. + * + * Since: 2.34 + **/ + g_object_class_install_property ( + object_class, PROP_TLS_CERTIFICATE, + g_param_spec_object (SOUP_SOCKET_TLS_CERTIFICATE, + "TLS certificate", + "The peer's TLS certificate", + G_TYPE_TLS_CERTIFICATE, + G_PARAM_READABLE)); + /** + * SOUP_SOCKET_TLS_ERRORS: + * + * Alias for the #SoupSocket:tls-errors + * property. Note that this property's value is only useful + * if the socket is for a TLS connection, and only reliable + * after some data has been transferred to or from it. + * + * Since: 2.34 + **/ + g_object_class_install_property ( + object_class, PROP_TLS_ERRORS, + g_param_spec_flags (SOUP_SOCKET_TLS_ERRORS, + "TLS errors", + "Errors with the peer's TLS certificate", + G_TYPE_TLS_CERTIFICATE_FLAGS, 0, + G_PARAM_READABLE)); + + g_object_class_install_property ( + object_class, PROP_SOCKET_PROPERTIES, + g_param_spec_boxed (SOUP_SOCKET_SOCKET_PROPERTIES, + "Socket properties", + "Socket properties", + SOUP_TYPE_SOCKET_PROPERTIES, + G_PARAM_WRITABLE)); +} + +static void +soup_socket_initable_interface_init (GInitableIface *initable_interface) +{ + initable_interface->init = soup_socket_initable_init; +} + + +/** + * soup_socket_new: + * @optname1: name of first property to set (or %NULL) + * @...: value of @optname1, followed by additional property/value pairs + * + * Creates a new (disconnected) socket + * + * Return value: the new socket + **/ +SoupSocket * +soup_socket_new (const char *optname1, ...) +{ + SoupSocket *sock; + va_list ap; + + va_start (ap, optname1); + sock = (SoupSocket *)g_object_new_valist (SOUP_TYPE_SOCKET, + optname1, ap); + va_end (ap); + + return sock; +} + +static void +soup_socket_event (SoupSocket *sock, + GSocketClientEvent event, + GIOStream *connection) +{ + g_signal_emit (sock, signals[EVENT], 0, + event, connection); +} + +static void +re_emit_socket_client_event (GSocketClient *client, + GSocketClientEvent event, + GSocketConnectable *connectable, + GIOStream *connection, + gpointer user_data) +{ + SoupSocket *sock = user_data; + + soup_socket_event (sock, event, connection); +} + +static gboolean +socket_connect_finish (SoupSocket *sock, GSocketConnection *conn) +{ + SoupSocketPrivate *priv = soup_socket_get_instance_private (sock); + + g_clear_object (&priv->connect_cancel); + + if (conn) { + priv->conn = (GIOStream *)conn; + priv->gsock = g_object_ref (g_socket_connection_get_socket (conn)); + finish_socket_setup (sock); + return TRUE; + } else + return FALSE; +} + +static guint +socket_legacy_error (SoupSocket *sock, GError *error) +{ + guint status; + + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + status = SOUP_STATUS_CANCELLED; + else if (error->domain == G_RESOLVER_ERROR) + status = SOUP_STATUS_CANT_RESOLVE; + else + status = SOUP_STATUS_CANT_CONNECT; + + g_error_free (error); + return status; +} + +static GSocketClient * +new_socket_client (SoupSocket *sock) +{ + SoupSocketPrivate *priv = soup_socket_get_instance_private (sock); + GSocketClient *client = g_socket_client_new (); + + g_signal_connect (client, "event", + G_CALLBACK (re_emit_socket_client_event), sock); + if (priv->proxy_resolver) { + g_socket_client_set_proxy_resolver (client, priv->proxy_resolver); + g_socket_client_add_application_proxy (client, "http"); + } else + g_socket_client_set_enable_proxy (client, FALSE); + if (priv->timeout) + g_socket_client_set_timeout (client, priv->timeout); + + if (priv->local_addr) { + GSocketAddress *addr; + + addr = soup_address_get_gsockaddr (priv->local_addr); + g_socket_client_set_local_address (client, addr); + g_object_unref (addr); + } + + return client; +} + +static void +async_connected (GObject *client, GAsyncResult *result, gpointer data) +{ + GTask *task = data; + SoupSocket *sock = g_task_get_source_object (task); + GSocketConnection *conn; + GError *error = NULL; + + conn = g_socket_client_connect_finish (G_SOCKET_CLIENT (client), + result, &error); + if (socket_connect_finish (sock, conn)) + g_task_return_boolean (task, TRUE); + else + g_task_return_error (task, error); + g_object_unref (task); +} + +gboolean +soup_socket_connect_finish_internal (SoupSocket *sock, + GAsyncResult *result, + GError **error) +{ + return g_task_propagate_boolean (G_TASK (result), error); +} + +void +soup_socket_connect_async_internal (SoupSocket *sock, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + SoupSocketPrivate *priv; + GSocketClient *client; + GTask *task; + + g_return_if_fail (SOUP_IS_SOCKET (sock)); + priv = soup_socket_get_instance_private (sock); + g_return_if_fail (!priv->is_server); + g_return_if_fail (priv->gsock == NULL); + g_return_if_fail (priv->remote_addr != NULL); + + priv->connect_cancel = cancellable ? g_object_ref (cancellable) : g_cancellable_new (); + task = g_task_new (sock, priv->connect_cancel, callback, user_data); + + client = new_socket_client (sock); + g_socket_client_connect_async (client, + G_SOCKET_CONNECTABLE (priv->remote_addr), + priv->connect_cancel, + async_connected, task); + g_object_unref (client); +} + +/** + * SoupSocketCallback: + * @sock: the #SoupSocket + * @status: an HTTP status code indicating success or failure + * @user_data: the data passed to soup_socket_connect_async() + * + * The callback function passed to soup_socket_connect_async(). + **/ + +typedef struct { + SoupSocket *sock; + SoupSocketCallback callback; + gpointer user_data; +} SoupSocketAsyncConnectData; + +static void +legacy_connect_async_cb (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + SoupSocket *sock = SOUP_SOCKET (object); + SoupSocketAsyncConnectData *sacd = user_data; + GError *error = NULL; + guint status; + + if (soup_socket_connect_finish_internal (sock, result, &error)) + status = SOUP_STATUS_OK; + else + status = socket_legacy_error (sock, error); + + sacd->callback (sock, status, sacd->user_data); + g_object_unref (sacd->sock); + g_slice_free (SoupSocketAsyncConnectData, sacd); +} + +/** + * soup_socket_connect_async: + * @sock: a client #SoupSocket (which must not already be connected) + * @cancellable: a #GCancellable, or %NULL + * @callback: (scope async): callback to call after connecting + * @user_data: data to pass to @callback + * + * Begins asynchronously connecting to @sock's remote address. The + * socket will call @callback when it succeeds or fails (but not + * before returning from this function). + * + * If @cancellable is non-%NULL, it can be used to cancel the + * connection. @callback will still be invoked in this case, with a + * status of %SOUP_STATUS_CANCELLED. + **/ +void +soup_socket_connect_async (SoupSocket *sock, GCancellable *cancellable, + SoupSocketCallback callback, gpointer user_data) +{ + SoupSocketPrivate *priv; + SoupSocketAsyncConnectData *sacd; + + g_return_if_fail (SOUP_IS_SOCKET (sock)); + priv = soup_socket_get_instance_private (sock); + g_return_if_fail (!priv->is_server); + g_return_if_fail (priv->gsock == NULL); + g_return_if_fail (priv->remote_addr != NULL); + + sacd = g_slice_new0 (SoupSocketAsyncConnectData); + sacd->sock = g_object_ref (sock); + sacd->callback = callback; + sacd->user_data = user_data; + + if (priv->async_context && !priv->use_thread_context) + g_main_context_push_thread_default (priv->async_context); + + soup_socket_connect_async_internal (sock, cancellable, + legacy_connect_async_cb, + sacd); + + if (priv->async_context && !priv->use_thread_context) + g_main_context_pop_thread_default (priv->async_context); +} + +gboolean +soup_socket_connect_sync_internal (SoupSocket *sock, + GCancellable *cancellable, + GError **error) +{ + SoupSocketPrivate *priv; + GSocketClient *client; + GSocketConnection *conn; + + g_return_val_if_fail (SOUP_IS_SOCKET (sock), SOUP_STATUS_MALFORMED); + priv = soup_socket_get_instance_private (sock); + g_return_val_if_fail (!priv->is_server, SOUP_STATUS_MALFORMED); + g_return_val_if_fail (priv->gsock == NULL, SOUP_STATUS_MALFORMED); + g_return_val_if_fail (priv->remote_addr != NULL, SOUP_STATUS_MALFORMED); + + priv->connect_cancel = cancellable ? g_object_ref (cancellable) : g_cancellable_new (); + + client = new_socket_client (sock); + conn = g_socket_client_connect (client, + G_SOCKET_CONNECTABLE (priv->remote_addr), + priv->connect_cancel, error); + g_object_unref (client); + + return socket_connect_finish (sock, conn); +} + +/** + * soup_socket_connect_sync: + * @sock: a client #SoupSocket (which must not already be connected) + * @cancellable: a #GCancellable, or %NULL + * + * Attempt to synchronously connect @sock to its remote address. + * + * If @cancellable is non-%NULL, it can be used to cancel the + * connection, in which case soup_socket_connect_sync() will return + * %SOUP_STATUS_CANCELLED. + * + * Return value: a success or failure code. + **/ +guint +soup_socket_connect_sync (SoupSocket *sock, GCancellable *cancellable) +{ + SoupSocketPrivate *priv; + GError *error = NULL; + + g_return_val_if_fail (SOUP_IS_SOCKET (sock), SOUP_STATUS_MALFORMED); + priv = soup_socket_get_instance_private (sock); + g_return_val_if_fail (!priv->is_server, SOUP_STATUS_MALFORMED); + g_return_val_if_fail (priv->gsock == NULL, SOUP_STATUS_MALFORMED); + g_return_val_if_fail (priv->remote_addr != NULL, SOUP_STATUS_MALFORMED); + + if (soup_socket_connect_sync_internal (sock, cancellable, &error)) + return SOUP_STATUS_OK; + else + return socket_legacy_error (sock, error); +} + +/** + * soup_socket_get_fd: + * @sock: a #SoupSocket + * + * Gets @sock's underlying file descriptor. + * + * Note that fiddling with the file descriptor may break the + * #SoupSocket. + * + * Return value: @sock's file descriptor. + */ +int +soup_socket_get_fd (SoupSocket *sock) +{ + SoupSocketPrivate *priv; + + g_return_val_if_fail (SOUP_IS_SOCKET (sock), -1); + + priv = soup_socket_get_instance_private (sock); + + return g_socket_get_fd (priv->gsock); +} + +GSocket * +soup_socket_get_gsocket (SoupSocket *sock) +{ + SoupSocketPrivate *priv; + + g_return_val_if_fail (SOUP_IS_SOCKET (sock), NULL); + + priv = soup_socket_get_instance_private (sock); + + return priv->gsock; +} + +GSocket * +soup_socket_steal_gsocket (SoupSocket *sock) +{ + SoupSocketPrivate *priv; + GSocket *gsock; + + g_return_val_if_fail (SOUP_IS_SOCKET (sock), NULL); + priv = soup_socket_get_instance_private (sock); + + gsock = priv->gsock; + priv->gsock = NULL; + g_clear_object (&priv->conn); + g_clear_object (&priv->iostream); + + return gsock; +} + +gboolean +soup_socket_is_readable (SoupSocket *sock) +{ + SoupSocketPrivate *priv; + + g_return_val_if_fail (SOUP_IS_SOCKET (sock), FALSE); + priv = soup_socket_get_instance_private (sock); + + return g_pollable_input_stream_is_readable (G_POLLABLE_INPUT_STREAM (priv->istream)); +} + +GIOStream * +soup_socket_get_connection (SoupSocket *sock) +{ + SoupSocketPrivate *priv; + + g_return_val_if_fail (SOUP_IS_SOCKET (sock), NULL); + + priv = soup_socket_get_instance_private (sock); + + return priv->conn; +} + +GIOStream * +soup_socket_get_iostream (SoupSocket *sock) +{ + SoupSocketPrivate *priv; + + g_return_val_if_fail (SOUP_IS_SOCKET (sock), NULL); + + priv = soup_socket_get_instance_private (sock); + + return priv->iostream; +} + +static GSource * +soup_socket_create_watch (SoupSocketPrivate *priv, GIOCondition cond, + GPollableSourceFunc callback, gpointer user_data, + GCancellable *cancellable) +{ + GSource *watch; + + if (cond == G_IO_IN) + watch = g_pollable_input_stream_create_source (G_POLLABLE_INPUT_STREAM (priv->istream), cancellable); + else + watch = g_pollable_output_stream_create_source (G_POLLABLE_OUTPUT_STREAM (priv->ostream), cancellable); + g_source_set_callback (watch, (GSourceFunc)callback, user_data, NULL); + + g_source_attach (watch, priv->async_context); + g_source_unref (watch); + + return watch; +} + +static gboolean +listen_watch (GObject *pollable, gpointer data) +{ + SoupSocket *sock = data, *new; + SoupSocketPrivate *priv = soup_socket_get_instance_private (sock), *new_priv; + GSocket *new_gsock; + + new_gsock = g_socket_accept (priv->gsock, NULL, NULL); + if (!new_gsock) + return FALSE; + + new = g_object_new (SOUP_TYPE_SOCKET, NULL); + new_priv = soup_socket_get_instance_private (new); + new_priv->gsock = new_gsock; + if (priv->async_context) + new_priv->async_context = g_main_context_ref (priv->async_context); + new_priv->use_thread_context = priv->use_thread_context; + new_priv->non_blocking = priv->non_blocking; + new_priv->clean_dispose = priv->clean_dispose; + new_priv->is_server = TRUE; + new_priv->ssl = priv->ssl; + if (priv->ssl_creds) + new_priv->ssl_creds = g_object_ref (priv->ssl_creds); + finish_socket_setup (new); + + if (new_priv->ssl_creds) { + if (!soup_socket_start_proxy_ssl (new, NULL, NULL)) { + g_object_unref (new); + return TRUE; + } + } + + g_signal_emit (sock, signals[NEW_CONNECTION], 0, new); + g_object_unref (new); + + return TRUE; +} + +static void +finish_listener_setup (SoupSocket *sock) +{ + SoupSocketPrivate *priv = soup_socket_get_instance_private (sock); + + priv->is_server = TRUE; + priv->watch_src = soup_socket_create_watch (priv, G_IO_IN, + listen_watch, sock, + NULL); +} + +/** + * soup_socket_listen: + * @sock: a server #SoupSocket (which must not already be connected or + * listening) + * + * Makes @sock start listening on its local address. When connections + * come in, @sock will emit #SoupSocket::new_connection. + * + * Return value: whether or not @sock is now listening. + **/ +gboolean +soup_socket_listen (SoupSocket *sock) +{ + return soup_socket_listen_full (sock, NULL); +} + +/** + * soup_socket_listen_full: + * @sock: a server #SoupSocket (which must not already be connected or listening) + * @error: error pointer + * + * Makes @sock start listening on its local address. When connections + * come in, @sock will emit #SoupSocket::new_connection. + * + * Return value: whether or not @sock is now listening. + **/ +gboolean +soup_socket_listen_full (SoupSocket *sock, + GError **error) + +{ + SoupSocketPrivate *priv; + GSocketAddress *addr; + + g_return_val_if_fail (SOUP_IS_SOCKET (sock), FALSE); + priv = soup_socket_get_instance_private (sock); + g_return_val_if_fail (priv->gsock == NULL, FALSE); + g_return_val_if_fail (priv->local_addr != NULL, FALSE); + + /* @local_addr may have its port set to 0. So we intentionally + * don't store it in priv->local_addr, so that if the + * caller calls soup_socket_get_local_address() later, we'll + * have to make a new addr by calling getsockname(), which + * will have the right port number. + */ + addr = soup_address_get_gsockaddr (priv->local_addr); + g_return_val_if_fail (addr != NULL, FALSE); + + priv->gsock = g_socket_new (g_socket_address_get_family (addr), + G_SOCKET_TYPE_STREAM, + G_SOCKET_PROTOCOL_DEFAULT, + error); + if (!priv->gsock) + goto cant_listen; + finish_socket_setup (sock); + +#if defined (IPPROTO_IPV6) && defined (IPV6_V6ONLY) + if (priv->ipv6_only) { + int fd, v6_only; + + fd = g_socket_get_fd (priv->gsock); + v6_only = TRUE; + setsockopt (fd, IPPROTO_IPV6, IPV6_V6ONLY, + &v6_only, sizeof (v6_only)); + } +#endif + + /* Bind */ + if (!g_socket_bind (priv->gsock, addr, TRUE, error)) + goto cant_listen; + /* Force local_addr to be re-resolved now */ + g_object_unref (priv->local_addr); + priv->local_addr = NULL; + + /* Listen */ + if (!g_socket_listen (priv->gsock, error)) + goto cant_listen; + finish_listener_setup (sock); + + g_object_unref (addr); + return TRUE; + + cant_listen: + if (priv->conn) + disconnect_internal (sock, TRUE); + g_object_unref (addr); + + return FALSE; +} + +static void +soup_socket_peer_certificate_changed (GObject *conn, GParamSpec *pspec, + gpointer sock) +{ + SoupSocketPrivate *priv = soup_socket_get_instance_private (sock); + + priv->tls_errors = g_tls_connection_get_peer_certificate_errors (G_TLS_CONNECTION (priv->conn)); + + g_object_notify (sock, "tls-certificate"); + g_object_notify (sock, "tls-errors"); +} + +static gboolean +soup_socket_accept_certificate (GTlsConnection *conn, GTlsCertificate *cert, + GTlsCertificateFlags errors, gpointer sock) +{ + return TRUE; +} + +static gboolean +soup_socket_setup_ssl (SoupSocket *sock, + const char *ssl_host, + GCancellable *cancellable, + GError **error) +{ + SoupSocketPrivate *priv = soup_socket_get_instance_private (sock); + GTlsBackend *backend = g_tls_backend_get_default (); + + if (G_IS_TLS_CONNECTION (priv->conn)) + return TRUE; + + if (g_cancellable_set_error_if_cancelled (cancellable, error)) + return FALSE; + + priv->ssl = TRUE; + + if (!priv->is_server) { + GTlsClientConnection *conn; + GSocketConnectable *identity; + + identity = g_network_address_new (ssl_host, 0); + conn = g_initable_new (g_tls_backend_get_client_connection_type (backend), + cancellable, error, + "base-io-stream", priv->conn, + "server-identity", identity, + "database", priv->ssl_creds, + "require-close-notify", FALSE, + "use-ssl3", priv->ssl_fallback, + NULL); + g_object_unref (identity); + + if (!conn) + return FALSE; + + /* GLib < 2.41 mistakenly doesn't implement this property in the + * dummy TLS backend, so we don't include it in the g_initable_new() + * call above. + */ + g_object_set (G_OBJECT (conn), + "interaction", priv->tls_interaction, + NULL); + + g_object_unref (priv->conn); + priv->conn = G_IO_STREAM (conn); + + if (!priv->ssl_strict) { + g_signal_connect (conn, "accept-certificate", + G_CALLBACK (soup_socket_accept_certificate), + sock); + } + } else { + GTlsServerConnection *conn; + + conn = g_initable_new (g_tls_backend_get_server_connection_type (backend), + cancellable, error, + "base-io-stream", priv->conn, + "certificate", priv->ssl_creds, + "use-system-certdb", FALSE, + "require-close-notify", FALSE, + NULL); + if (!conn) + return FALSE; + + g_object_unref (priv->conn); + priv->conn = G_IO_STREAM (conn); + } + + g_signal_connect (priv->conn, "notify::peer-certificate", + G_CALLBACK (soup_socket_peer_certificate_changed), sock); + + g_clear_object (&priv->istream); + g_clear_object (&priv->ostream); + g_clear_object (&priv->iostream); + priv->iostream = soup_io_stream_new (priv->conn, FALSE); + priv->istream = g_object_ref (g_io_stream_get_input_stream (priv->iostream)); + priv->ostream = g_object_ref (g_io_stream_get_output_stream (priv->iostream)); + + return TRUE; +} + +/** + * soup_socket_start_ssl: + * @sock: the socket + * @cancellable: a #GCancellable + * + * Starts using SSL on @socket. + * + * Return value: success or failure + **/ +gboolean +soup_socket_start_ssl (SoupSocket *sock, GCancellable *cancellable) +{ + SoupSocketPrivate *priv = soup_socket_get_instance_private (sock); + + return soup_socket_setup_ssl (sock, soup_address_get_name (priv->remote_addr), + cancellable, NULL); +} + +/** + * soup_socket_start_proxy_ssl: + * @sock: the socket + * @ssl_host: hostname of the SSL server + * @cancellable: a #GCancellable + * + * Starts using SSL on @socket, expecting to find a host named + * @ssl_host. + * + * Return value: success or failure + **/ +gboolean +soup_socket_start_proxy_ssl (SoupSocket *sock, const char *ssl_host, + GCancellable *cancellable) +{ + return soup_socket_setup_ssl (sock, ssl_host, cancellable, NULL); +} + +gboolean +soup_socket_handshake_sync (SoupSocket *sock, + const char *ssl_host, + GCancellable *cancellable, + GError **error) +{ + SoupSocketPrivate *priv = soup_socket_get_instance_private (sock); + + if (!soup_socket_setup_ssl (sock, ssl_host, cancellable, error)) + return FALSE; + + soup_socket_event (sock, G_SOCKET_CLIENT_TLS_HANDSHAKING, priv->conn); + + if (!g_tls_connection_handshake (G_TLS_CONNECTION (priv->conn), + cancellable, error)) + return FALSE; + + soup_socket_event (sock, G_SOCKET_CLIENT_TLS_HANDSHAKED, priv->conn); + return TRUE; +} + +static void +handshake_async_ready (GObject *source, GAsyncResult *result, gpointer user_data) +{ + GTask *task = user_data; + GError *error = NULL; + + if (g_tls_connection_handshake_finish (G_TLS_CONNECTION (source), + result, &error)) { + SoupSocket *sock = g_task_get_source_object (task); + SoupSocketPrivate *priv = soup_socket_get_instance_private (sock); + + soup_socket_event (sock, G_SOCKET_CLIENT_TLS_HANDSHAKED, priv->conn); + g_task_return_boolean (task, TRUE); + } else + g_task_return_error (task, error); + g_object_unref (task); +} + +void +soup_socket_handshake_async (SoupSocket *sock, + const char *ssl_host, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + SoupSocketPrivate *priv = soup_socket_get_instance_private (sock); + GTask *task; + GError *error = NULL; + + task = g_task_new (sock, cancellable, callback, user_data); + + if (!soup_socket_setup_ssl (sock, ssl_host, cancellable, &error)) { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + soup_socket_event (sock, G_SOCKET_CLIENT_TLS_HANDSHAKING, priv->conn); + + g_tls_connection_handshake_async (G_TLS_CONNECTION (priv->conn), + G_PRIORITY_DEFAULT, + cancellable, handshake_async_ready, + task); +} + +gboolean +soup_socket_handshake_finish (SoupSocket *sock, + GAsyncResult *result, + GError **error) +{ + return g_task_propagate_boolean (G_TASK (result), error); +} + +/** + * soup_socket_is_ssl: + * @sock: a #SoupSocket + * + * Tests if @sock is doing (or has attempted to do) SSL. + * + * Return value: %TRUE if @sock has SSL credentials set + **/ +gboolean +soup_socket_is_ssl (SoupSocket *sock) +{ + SoupSocketPrivate *priv = soup_socket_get_instance_private (sock); + + return priv->ssl; +} + +/** + * soup_socket_disconnect: + * @sock: a #SoupSocket + * + * Disconnects @sock. Any further read or write attempts on it will + * fail. + **/ +void +soup_socket_disconnect (SoupSocket *sock) +{ + SoupSocketPrivate *priv; + gboolean already_disconnected = FALSE; + + g_return_if_fail (SOUP_IS_SOCKET (sock)); + priv = soup_socket_get_instance_private (sock); + + if (priv->connect_cancel) { + disconnect_internal (sock, FALSE); + g_cancellable_cancel (priv->connect_cancel); + return; + } else if (g_mutex_trylock (&priv->iolock)) { + if (priv->conn) + disconnect_internal (sock, TRUE); + else + already_disconnected = TRUE; + g_mutex_unlock (&priv->iolock); + } else { + /* Another thread is currently doing IO, so + * we can't close the socket. So just shutdown + * the file descriptor to force the I/O to fail. + * (It will actually be closed when the socket + * is destroyed.) + */ + g_socket_shutdown (priv->gsock, TRUE, TRUE, NULL); + } + + if (already_disconnected) + return; + + /* Keep ref around signals in case the object is unreferenced + * in a handler + */ + g_object_ref (sock); + + if (priv->non_blocking) { + /* Give all readers a chance to notice the connection close */ + g_signal_emit (sock, signals[READABLE], 0); + } + + /* FIXME: can't disconnect until all data is read */ + + /* Then let everyone know we're disconnected */ + g_signal_emit (sock, signals[DISCONNECTED], 0); + + g_object_unref (sock); +} + +/** + * soup_socket_is_connected: + * @sock: a #SoupSocket + * + * Tests if @sock is connected to another host + * + * Return value: %TRUE or %FALSE. + **/ +gboolean +soup_socket_is_connected (SoupSocket *sock) +{ + SoupSocketPrivate *priv; + + g_return_val_if_fail (SOUP_IS_SOCKET (sock), FALSE); + priv = soup_socket_get_instance_private (sock); + + return priv->conn && !g_io_stream_is_closed (priv->conn); +} + +/** + * soup_socket_get_local_address: + * @sock: a #SoupSocket + * + * Returns the #SoupAddress corresponding to the local end of @sock. + * + * Calling this method on an unconnected socket is considered to be + * an error, and produces undefined results. + * + * Return value: (transfer none): the #SoupAddress + **/ +SoupAddress * +soup_socket_get_local_address (SoupSocket *sock) +{ + SoupSocketPrivate *priv; + + g_return_val_if_fail (SOUP_IS_SOCKET (sock), NULL); + priv = soup_socket_get_instance_private (sock); + + g_mutex_lock (&priv->addrlock); + if (!priv->local_addr) { + GSocketAddress *addr; + struct sockaddr_storage sa; + gssize sa_len; + GError *error = NULL; + + if (priv->gsock == NULL) { + g_warning ("%s: socket not connected", G_STRLOC); + goto unlock; + } + + addr = g_socket_get_local_address (priv->gsock, &error); + if (addr == NULL) { + g_warning ("%s: %s", G_STRLOC, error->message); + g_error_free (error); + goto unlock; + } + sa_len = g_socket_address_get_native_size (addr); + g_socket_address_to_native (addr, &sa, sa_len, NULL); + priv->local_addr = soup_address_new_from_sockaddr ((struct sockaddr *)&sa, sa_len); + g_object_unref (addr); + } +unlock: + g_mutex_unlock (&priv->addrlock); + + return priv->local_addr; +} + +/** + * soup_socket_get_remote_address: + * @sock: a #SoupSocket + * + * Returns the #SoupAddress corresponding to the remote end of @sock. + * + * Calling this method on an unconnected socket is considered to be + * an error, and produces undefined results. + * + * Return value: (transfer none): the #SoupAddress + **/ +SoupAddress * +soup_socket_get_remote_address (SoupSocket *sock) +{ + SoupSocketPrivate *priv; + + g_return_val_if_fail (SOUP_IS_SOCKET (sock), NULL); + priv = soup_socket_get_instance_private (sock); + + g_mutex_lock (&priv->addrlock); + if (!priv->remote_addr) { + GSocketAddress *addr; + struct sockaddr_storage sa; + gssize sa_len; + GError *error = NULL; + + if (priv->gsock == NULL) { + g_warning ("%s: socket not connected", G_STRLOC); + goto unlock; + } + + addr = g_socket_get_remote_address (priv->gsock, &error); + if (addr == NULL) { + g_warning ("%s: %s", G_STRLOC, error->message); + g_error_free (error); + goto unlock; + } + sa_len = g_socket_address_get_native_size (addr); + g_socket_address_to_native (addr, &sa, sa_len, NULL); + priv->remote_addr = soup_address_new_from_sockaddr ((struct sockaddr *)&sa, sa_len); + g_object_unref (addr); + } +unlock: + g_mutex_unlock (&priv->addrlock); + + return priv->remote_addr; +} + +SoupURI * +soup_socket_get_http_proxy_uri (SoupSocket *sock) +{ + SoupSocketPrivate *priv = soup_socket_get_instance_private (sock); + GSocketAddress *addr; + GProxyAddress *paddr; + SoupURI *uri; + + if (!priv->gsock) + return NULL; + addr = g_socket_get_remote_address (priv->gsock, NULL); + if (!addr || !G_IS_PROXY_ADDRESS (addr)) { + if (addr) + g_object_unref (addr); + return NULL; + } + + paddr = G_PROXY_ADDRESS (addr); + if (strcmp (g_proxy_address_get_protocol (paddr), "http") != 0) + return NULL; + + uri = soup_uri_new (g_proxy_address_get_uri (paddr)); + g_object_unref (addr); + return uri; +} + +static gboolean +socket_read_watch (GObject *pollable, gpointer user_data) +{ + SoupSocket *sock = user_data; + SoupSocketPrivate *priv = soup_socket_get_instance_private (sock); + + priv->read_src = NULL; + g_signal_emit (sock, signals[READABLE], 0); + return FALSE; +} + +static SoupSocketIOStatus +translate_read_status (SoupSocket *sock, GCancellable *cancellable, + gssize my_nread, gsize *nread, + GError *my_err, GError **error) +{ + SoupSocketPrivate *priv = soup_socket_get_instance_private (sock); + + if (my_nread > 0) { + g_assert_no_error (my_err); + *nread = my_nread; + return SOUP_SOCKET_OK; + } else if (my_nread == 0) { + g_assert_no_error (my_err); + *nread = my_nread; + return SOUP_SOCKET_EOF; + } else if (g_error_matches (my_err, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) { + g_clear_error (&my_err); + if (!priv->read_src) { + priv->read_src = + soup_socket_create_watch (priv, G_IO_IN, + socket_read_watch, sock, + cancellable); + } + return SOUP_SOCKET_WOULD_BLOCK; + } + + g_propagate_error (error, my_err); + return SOUP_SOCKET_ERROR; +} + +/** + * SoupSocketIOStatus: + * @SOUP_SOCKET_OK: Success + * @SOUP_SOCKET_WOULD_BLOCK: Cannot read/write any more at this time + * @SOUP_SOCKET_EOF: End of file + * @SOUP_SOCKET_ERROR: Other error + * + * Return value from the #SoupSocket IO methods. + **/ + +/** + * soup_socket_read: + * @sock: the socket + * @buffer: (array length=len) (element-type guint8): buffer to read + * into + * @len: size of @buffer in bytes + * @nread: (out): on return, the number of bytes read into @buffer + * @cancellable: a #GCancellable, or %NULL + * @error: error pointer + * + * Attempts to read up to @len bytes from @sock into @buffer. If some + * data is successfully read, soup_socket_read() will return + * %SOUP_SOCKET_OK, and *@nread will contain the number of bytes + * actually read (which may be less than @len). + * + * If @sock is non-blocking, and no data is available, the return + * value will be %SOUP_SOCKET_WOULD_BLOCK. In this case, the caller + * can connect to the #SoupSocket::readable signal to know when there + * is more data to read. (NB: You MUST read all available data off the + * socket first. #SoupSocket::readable is only emitted after + * soup_socket_read() returns %SOUP_SOCKET_WOULD_BLOCK, and it is only + * emitted once. See the documentation for #SoupSocket:non-blocking.) + * + * Return value: a #SoupSocketIOStatus, as described above (or + * %SOUP_SOCKET_EOF if the socket is no longer connected, or + * %SOUP_SOCKET_ERROR on any other error, in which case @error will + * also be set). + **/ +SoupSocketIOStatus +soup_socket_read (SoupSocket *sock, gpointer buffer, gsize len, + gsize *nread, GCancellable *cancellable, GError **error) +{ + SoupSocketPrivate *priv; + SoupSocketIOStatus status; + gssize my_nread; + GError *my_err = NULL; + + g_return_val_if_fail (SOUP_IS_SOCKET (sock), SOUP_SOCKET_ERROR); + g_return_val_if_fail (nread != NULL, SOUP_SOCKET_ERROR); + + priv = soup_socket_get_instance_private (sock); + + g_mutex_lock (&priv->iolock); + + if (!priv->istream) { + status = SOUP_SOCKET_EOF; + goto out; + } + + if (!priv->non_blocking) { + my_nread = g_input_stream_read (priv->istream, buffer, len, + cancellable, &my_err); + } else { + my_nread = g_pollable_input_stream_read_nonblocking (G_POLLABLE_INPUT_STREAM (priv->istream), + buffer, len, + cancellable, &my_err); + } + status = translate_read_status (sock, cancellable, + my_nread, nread, my_err, error); + +out: + g_mutex_unlock (&priv->iolock); + + return status; +} + +/** + * soup_socket_read_until: + * @sock: the socket + * @buffer: (array length=len) (element-type guint8): buffer to read + * into + * @len: size of @buffer in bytes + * @boundary: boundary to read until + * @boundary_len: length of @boundary in bytes + * @nread: (out): on return, the number of bytes read into @buffer + * @got_boundary: on return, whether or not the data in @buffer + * ends with the boundary string + * @cancellable: a #GCancellable, or %NULL + * @error: error pointer + * + * Like soup_socket_read(), but reads no further than the first + * occurrence of @boundary. (If the boundary is found, it will be + * included in the returned data, and *@got_boundary will be set to + * %TRUE.) Any data after the boundary will returned in future reads. + * + * soup_socket_read_until() will almost always return fewer than @len + * bytes: if the boundary is found, then it will only return the bytes + * up until the end of the boundary, and if the boundary is not found, + * then it will leave the last (boundary_len - 1) + * bytes in its internal buffer, in case they form the start of the + * boundary string. Thus, @len normally needs to be at least 1 byte + * longer than @boundary_len if you want to make any progress at all. + * + * Return value: as for soup_socket_read() + **/ +SoupSocketIOStatus +soup_socket_read_until (SoupSocket *sock, gpointer buffer, gsize len, + gconstpointer boundary, gsize boundary_len, + gsize *nread, gboolean *got_boundary, + GCancellable *cancellable, GError **error) +{ + SoupSocketPrivate *priv; + SoupSocketIOStatus status; + gssize my_nread; + GError *my_err = NULL; + + g_return_val_if_fail (SOUP_IS_SOCKET (sock), SOUP_SOCKET_ERROR); + g_return_val_if_fail (nread != NULL, SOUP_SOCKET_ERROR); + g_return_val_if_fail (len >= boundary_len, SOUP_SOCKET_ERROR); + + priv = soup_socket_get_instance_private (sock); + + g_mutex_lock (&priv->iolock); + + *got_boundary = FALSE; + + if (!priv->istream) + status = SOUP_SOCKET_EOF; + else { + my_nread = soup_filter_input_stream_read_until ( + SOUP_FILTER_INPUT_STREAM (priv->istream), + buffer, len, boundary, boundary_len, + !priv->non_blocking, + TRUE, got_boundary, cancellable, &my_err); + status = translate_read_status (sock, cancellable, + my_nread, nread, my_err, error); + } + + g_mutex_unlock (&priv->iolock); + return status; +} + +static gboolean +socket_write_watch (GObject *pollable, gpointer user_data) +{ + SoupSocket *sock = user_data; + SoupSocketPrivate *priv = soup_socket_get_instance_private (sock); + + priv->write_src = NULL; + g_signal_emit (sock, signals[WRITABLE], 0); + return FALSE; +} + +/** + * soup_socket_write: + * @sock: the socket + * @buffer: (array length=len) (element-type guint8): data to write + * @len: size of @buffer, in bytes + * @nwrote: (out): on return, number of bytes written + * @cancellable: a #GCancellable, or %NULL + * @error: error pointer + * + * Attempts to write @len bytes from @buffer to @sock. If some data is + * successfully written, the return status will be %SOUP_SOCKET_OK, + * and *@nwrote will contain the number of bytes actually written + * (which may be less than @len). + * + * If @sock is non-blocking, and no data could be written right away, + * the return value will be %SOUP_SOCKET_WOULD_BLOCK. In this case, + * the caller can connect to the #SoupSocket::writable signal to know + * when more data can be written. (NB: #SoupSocket::writable is only + * emitted after soup_socket_write() returns %SOUP_SOCKET_WOULD_BLOCK, + * and it is only emitted once. See the documentation for + * #SoupSocket:non-blocking.) + * + * Return value: a #SoupSocketIOStatus, as described above (or + * %SOUP_SOCKET_EOF or %SOUP_SOCKET_ERROR. @error will be set if the + * return value is %SOUP_SOCKET_ERROR.) + **/ +SoupSocketIOStatus +soup_socket_write (SoupSocket *sock, gconstpointer buffer, + gsize len, gsize *nwrote, + GCancellable *cancellable, GError **error) +{ + SoupSocketPrivate *priv; + GError *my_err = NULL; + gssize my_nwrote; + + g_return_val_if_fail (SOUP_IS_SOCKET (sock), SOUP_SOCKET_ERROR); + g_return_val_if_fail (nwrote != NULL, SOUP_SOCKET_ERROR); + + priv = soup_socket_get_instance_private (sock); + + g_mutex_lock (&priv->iolock); + + if (!priv->conn) { + g_mutex_unlock (&priv->iolock); + return SOUP_SOCKET_EOF; + } + if (priv->write_src) { + g_mutex_unlock (&priv->iolock); + return SOUP_SOCKET_WOULD_BLOCK; + } + + if (!priv->non_blocking) { + my_nwrote = g_output_stream_write (priv->ostream, + buffer, len, + cancellable, &my_err); + } else { + my_nwrote = g_pollable_output_stream_write_nonblocking ( + G_POLLABLE_OUTPUT_STREAM (priv->ostream), + buffer, len, cancellable, &my_err); + } + + if (my_nwrote > 0) { + g_mutex_unlock (&priv->iolock); + g_clear_error (&my_err); + *nwrote = my_nwrote; + return SOUP_SOCKET_OK; + } + + if (g_error_matches (my_err, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) { + g_mutex_unlock (&priv->iolock); + g_clear_error (&my_err); + + priv->write_src = + soup_socket_create_watch (priv, + G_IO_OUT, + socket_write_watch, sock, cancellable); + return SOUP_SOCKET_WOULD_BLOCK; + } + + g_mutex_unlock (&priv->iolock); + g_propagate_error (error, my_err); + return SOUP_SOCKET_ERROR; +} diff --git a/libsoup/soup-socket.h b/libsoup/soup-socket.h new file mode 100644 index 0000000..993d1c6 --- /dev/null +++ b/libsoup/soup-socket.h @@ -0,0 +1,136 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2000-2003, Ximian, Inc. + */ + +#ifndef SOUP_SOCKET_H +#define SOUP_SOCKET_H 1 + +#include + +G_BEGIN_DECLS + +#define SOUP_TYPE_SOCKET (soup_socket_get_type ()) +#define SOUP_SOCKET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SOUP_TYPE_SOCKET, SoupSocket)) +#define SOUP_SOCKET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_SOCKET, SoupSocketClass)) +#define SOUP_IS_SOCKET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SOUP_TYPE_SOCKET)) +#define SOUP_IS_SOCKET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), SOUP_TYPE_SOCKET)) +#define SOUP_SOCKET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_SOCKET, SoupSocketClass)) + +struct _SoupSocket { + GObject parent; + +}; + +typedef struct { + GObjectClass parent_class; + + /* signals */ + void (*readable) (SoupSocket *sock); + void (*writable) (SoupSocket *sock); + void (*disconnected) (SoupSocket *sock); + + void (*new_connection) (SoupSocket *listener, SoupSocket *new_sock); + + /* Padding for future expansion */ + void (*_libsoup_reserved1) (void); + void (*_libsoup_reserved2) (void); + void (*_libsoup_reserved3) (void); + void (*_libsoup_reserved4) (void); +} SoupSocketClass; + +#define SOUP_SOCKET_LOCAL_ADDRESS "local-address" +#define SOUP_SOCKET_REMOTE_ADDRESS "remote-address" +#define SOUP_SOCKET_FLAG_NONBLOCKING "non-blocking" +#define SOUP_SOCKET_IS_SERVER "is-server" +#define SOUP_SOCKET_SSL_CREDENTIALS "ssl-creds" +#define SOUP_SOCKET_SSL_STRICT "ssl-strict" +#define SOUP_SOCKET_SSL_FALLBACK "ssl-fallback" +#define SOUP_SOCKET_TRUSTED_CERTIFICATE "trusted-certificate" +#define SOUP_SOCKET_ASYNC_CONTEXT "async-context" +#define SOUP_SOCKET_USE_THREAD_CONTEXT "use-thread-context" +#define SOUP_SOCKET_TIMEOUT "timeout" +#define SOUP_SOCKET_TLS_CERTIFICATE "tls-certificate" +#define SOUP_SOCKET_TLS_ERRORS "tls-errors" + +typedef void (*SoupSocketCallback) (SoupSocket *sock, + guint status, + gpointer user_data); + +SOUP_AVAILABLE_IN_2_4 +GType soup_socket_get_type (void); + +SOUP_AVAILABLE_IN_2_4 +SoupSocket *soup_socket_new (const char *optname1, + ...) G_GNUC_NULL_TERMINATED; + +SOUP_AVAILABLE_IN_2_4 +void soup_socket_connect_async (SoupSocket *sock, + GCancellable *cancellable, + SoupSocketCallback callback, + gpointer user_data); +SOUP_AVAILABLE_IN_2_4 +guint soup_socket_connect_sync (SoupSocket *sock, + GCancellable *cancellable); +SOUP_AVAILABLE_IN_2_4 +int soup_socket_get_fd (SoupSocket *sock); + +SOUP_AVAILABLE_IN_2_4 +gboolean soup_socket_listen (SoupSocket *sock); + +SOUP_AVAILABLE_IN_2_4 +gboolean soup_socket_start_ssl (SoupSocket *sock, + GCancellable *cancellable); +SOUP_AVAILABLE_IN_2_4 +gboolean soup_socket_start_proxy_ssl (SoupSocket *sock, + const char *ssl_host, + GCancellable *cancellable); +SOUP_AVAILABLE_IN_2_4 +gboolean soup_socket_is_ssl (SoupSocket *sock); + +SOUP_AVAILABLE_IN_2_4 +void soup_socket_disconnect (SoupSocket *sock); +SOUP_AVAILABLE_IN_2_4 +gboolean soup_socket_is_connected (SoupSocket *sock); + +SOUP_AVAILABLE_IN_2_4 +SoupAddress *soup_socket_get_local_address (SoupSocket *sock); +SOUP_AVAILABLE_IN_2_4 +SoupAddress *soup_socket_get_remote_address (SoupSocket *sock); + +typedef enum { + SOUP_SOCKET_OK, + SOUP_SOCKET_WOULD_BLOCK, + SOUP_SOCKET_EOF, + SOUP_SOCKET_ERROR +} SoupSocketIOStatus; + +SOUP_AVAILABLE_IN_2_4 +SoupSocketIOStatus soup_socket_read (SoupSocket *sock, + gpointer buffer, + gsize len, + gsize *nread, + GCancellable *cancellable, + GError **error); +SOUP_AVAILABLE_IN_2_4 +SoupSocketIOStatus soup_socket_read_until (SoupSocket *sock, + gpointer buffer, + gsize len, + gconstpointer boundary, + gsize boundary_len, + gsize *nread, + gboolean *got_boundary, + GCancellable *cancellable, + GError **error); + +SOUP_AVAILABLE_IN_2_4 +SoupSocketIOStatus soup_socket_write (SoupSocket *sock, + gconstpointer buffer, + gsize len, + gsize *nwrote, + GCancellable *cancellable, + GError **error); + +G_END_DECLS + +#endif /* SOUP_SOCKET_H */ diff --git a/libsoup/soup-status.c b/libsoup/soup-status.c new file mode 100644 index 0000000..6dbb9ed --- /dev/null +++ b/libsoup/soup-status.c @@ -0,0 +1,322 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-status.c: Status code descriptions + * + * Copyright (C) 2001-2003, Ximian, Inc. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "soup-status.h" +#include "soup.h" + +/** + * SECTION:soup-status + * @short_description: HTTP (and libsoup) status codes + * + **/ + +/** + * SOUP_STATUS_IS_TRANSPORT_ERROR: + * @status: a status code + * + * Tests if @status is a libsoup transport error. + * + * Return value: %TRUE or %FALSE + **/ +/** + * SOUP_STATUS_IS_INFORMATIONAL: + * @status: an HTTP status code + * + * Tests if @status is an Informational (1xx) response. + * + * Return value: %TRUE or %FALSE + **/ +/** + * SOUP_STATUS_IS_SUCCESSFUL: + * @status: an HTTP status code + * + * Tests if @status is a Successful (2xx) response. + * + * Return value: %TRUE or %FALSE + **/ +/** + * SOUP_STATUS_IS_REDIRECTION: + * @status: an HTTP status code + * + * Tests if @status is a Redirection (3xx) response. + * + * Return value: %TRUE or %FALSE + **/ +/** + * SOUP_STATUS_IS_CLIENT_ERROR: + * @status: an HTTP status code + * + * Tests if @status is a Client Error (4xx) response. + * + * Return value: %TRUE or %FALSE + **/ +/** + * SOUP_STATUS_IS_SERVER_ERROR: + * @status: an HTTP status code + * + * Tests if @status is a Server Error (5xx) response. + * + * Return value: %TRUE or %FALSE + **/ + +/** + * SoupStatus: + * @SOUP_STATUS_NONE: No status available. (Eg, the message has not + * been sent yet) + * @SOUP_STATUS_CANCELLED: Message was cancelled locally + * @SOUP_STATUS_CANT_RESOLVE: Unable to resolve destination host name + * @SOUP_STATUS_CANT_RESOLVE_PROXY: Unable to resolve proxy host name + * @SOUP_STATUS_CANT_CONNECT: Unable to connect to remote host + * @SOUP_STATUS_CANT_CONNECT_PROXY: Unable to connect to proxy + * @SOUP_STATUS_SSL_FAILED: SSL/TLS negotiation failed + * @SOUP_STATUS_IO_ERROR: A network error occurred, or the other end + * closed the connection unexpectedly + * @SOUP_STATUS_MALFORMED: Malformed data (usually a programmer error) + * @SOUP_STATUS_TRY_AGAIN: Used internally + * @SOUP_STATUS_TOO_MANY_REDIRECTS: There were too many redirections + * @SOUP_STATUS_TLS_FAILED: Used internally + * @SOUP_STATUS_CONTINUE: 100 Continue (HTTP) + * @SOUP_STATUS_SWITCHING_PROTOCOLS: 101 Switching Protocols (HTTP) + * @SOUP_STATUS_PROCESSING: 102 Processing (WebDAV) + * @SOUP_STATUS_OK: 200 Success (HTTP). Also used by many lower-level + * soup routines to indicate success. + * @SOUP_STATUS_CREATED: 201 Created (HTTP) + * @SOUP_STATUS_ACCEPTED: 202 Accepted (HTTP) + * @SOUP_STATUS_NON_AUTHORITATIVE: 203 Non-Authoritative Information + * (HTTP) + * @SOUP_STATUS_NO_CONTENT: 204 No Content (HTTP) + * @SOUP_STATUS_RESET_CONTENT: 205 Reset Content (HTTP) + * @SOUP_STATUS_PARTIAL_CONTENT: 206 Partial Content (HTTP) + * @SOUP_STATUS_MULTI_STATUS: 207 Multi-Status (WebDAV) + * @SOUP_STATUS_MULTIPLE_CHOICES: 300 Multiple Choices (HTTP) + * @SOUP_STATUS_MOVED_PERMANENTLY: 301 Moved Permanently (HTTP) + * @SOUP_STATUS_FOUND: 302 Found (HTTP) + * @SOUP_STATUS_MOVED_TEMPORARILY: 302 Moved Temporarily (old name, + * RFC 2068) + * @SOUP_STATUS_SEE_OTHER: 303 See Other (HTTP) + * @SOUP_STATUS_NOT_MODIFIED: 304 Not Modified (HTTP) + * @SOUP_STATUS_USE_PROXY: 305 Use Proxy (HTTP) + * @SOUP_STATUS_NOT_APPEARING_IN_THIS_PROTOCOL: 306 [Unused] (HTTP) + * @SOUP_STATUS_TEMPORARY_REDIRECT: 307 Temporary Redirect (HTTP) + * @SOUP_STATUS_BAD_REQUEST: 400 Bad Request (HTTP) + * @SOUP_STATUS_UNAUTHORIZED: 401 Unauthorized (HTTP) + * @SOUP_STATUS_PAYMENT_REQUIRED: 402 Payment Required (HTTP) + * @SOUP_STATUS_FORBIDDEN: 403 Forbidden (HTTP) + * @SOUP_STATUS_NOT_FOUND: 404 Not Found (HTTP) + * @SOUP_STATUS_METHOD_NOT_ALLOWED: 405 Method Not Allowed (HTTP) + * @SOUP_STATUS_NOT_ACCEPTABLE: 406 Not Acceptable (HTTP) + * @SOUP_STATUS_PROXY_AUTHENTICATION_REQUIRED: 407 Proxy Authentication + * Required (HTTP) + * @SOUP_STATUS_PROXY_UNAUTHORIZED: shorter alias for + * %SOUP_STATUS_PROXY_AUTHENTICATION_REQUIRED + * @SOUP_STATUS_REQUEST_TIMEOUT: 408 Request Timeout (HTTP) + * @SOUP_STATUS_CONFLICT: 409 Conflict (HTTP) + * @SOUP_STATUS_GONE: 410 Gone (HTTP) + * @SOUP_STATUS_LENGTH_REQUIRED: 411 Length Required (HTTP) + * @SOUP_STATUS_PRECONDITION_FAILED: 412 Precondition Failed (HTTP) + * @SOUP_STATUS_REQUEST_ENTITY_TOO_LARGE: 413 Request Entity Too Large + * (HTTP) + * @SOUP_STATUS_REQUEST_URI_TOO_LONG: 414 Request-URI Too Long (HTTP) + * @SOUP_STATUS_UNSUPPORTED_MEDIA_TYPE: 415 Unsupported Media Type + * (HTTP) + * @SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE: 416 Requested Range + * Not Satisfiable (HTTP) + * @SOUP_STATUS_INVALID_RANGE: shorter alias for + * %SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE + * @SOUP_STATUS_EXPECTATION_FAILED: 417 Expectation Failed (HTTP) + * @SOUP_STATUS_UNPROCESSABLE_ENTITY: 422 Unprocessable Entity + * (WebDAV) + * @SOUP_STATUS_LOCKED: 423 Locked (WebDAV) + * @SOUP_STATUS_FAILED_DEPENDENCY: 424 Failed Dependency (WebDAV) + * @SOUP_STATUS_INTERNAL_SERVER_ERROR: 500 Internal Server Error + * (HTTP) + * @SOUP_STATUS_NOT_IMPLEMENTED: 501 Not Implemented (HTTP) + * @SOUP_STATUS_BAD_GATEWAY: 502 Bad Gateway (HTTP) + * @SOUP_STATUS_SERVICE_UNAVAILABLE: 503 Service Unavailable (HTTP) + * @SOUP_STATUS_GATEWAY_TIMEOUT: 504 Gateway Timeout (HTTP) + * @SOUP_STATUS_HTTP_VERSION_NOT_SUPPORTED: 505 HTTP Version Not + * Supported (HTTP) + * @SOUP_STATUS_INSUFFICIENT_STORAGE: 507 Insufficient Storage + * (WebDAV) + * @SOUP_STATUS_NOT_EXTENDED: 510 Not Extended (RFC 2774) + * + * These represent the known HTTP status code values, plus various + * network and internal errors. + * + * Note that no libsoup functions take or return this type directly; + * any function that works with status codes will accept unrecognized + * status codes as well. + * + * Prior to 2.44 this type was called + * SoupKnownStatusCode, but the individual values + * have always had the names they have now. + **/ + +/** + * SOUP_HTTP_ERROR: + * + * A #GError domain representing an HTTP status. Use a #SoupStatus for + * the code value. + **/ + + +/* The reason_phrases are not localized because: + * + * 1. Only ASCII can be used portably in the HTTP Status-Line, so we + * would not be able to return localized reason phrases from + * SoupServer anyway. + * + * 2. Having a way for clients to get a localized version of a status + * code would just encourage them to present those strings to the + * user, which is bad because many of them are fairly + * incomprehensible anyway. + */ + +static const struct { + guint code; + const char *phrase; +} reason_phrases [] = { + /* Transport errors */ + { SOUP_STATUS_CANCELLED, "Cancelled" }, + { SOUP_STATUS_CANT_RESOLVE, "Cannot resolve hostname" }, + { SOUP_STATUS_CANT_RESOLVE_PROXY, "Cannot resolve proxy hostname" }, + { SOUP_STATUS_CANT_CONNECT, "Cannot connect to destination" }, + { SOUP_STATUS_CANT_CONNECT_PROXY, "Cannot connect to proxy" }, + { SOUP_STATUS_SSL_FAILED, "SSL handshake failed" }, + { SOUP_STATUS_IO_ERROR, "Connection terminated unexpectedly" }, + { SOUP_STATUS_MALFORMED, "Message Corrupt" }, + { SOUP_STATUS_TOO_MANY_REDIRECTS, "Too many redirects" }, + + /* Informational */ + { SOUP_STATUS_CONTINUE, "Continue" }, + { SOUP_STATUS_SWITCHING_PROTOCOLS, "Switching Protocols" }, + { SOUP_STATUS_PROCESSING, "Processing" }, + + /* Success */ + { SOUP_STATUS_OK, "OK" }, + { SOUP_STATUS_CREATED, "Created" }, + { SOUP_STATUS_ACCEPTED, "Accepted" }, + { SOUP_STATUS_NON_AUTHORITATIVE, "Non-Authoritative Information" }, + { SOUP_STATUS_NO_CONTENT, "No Content" }, + { SOUP_STATUS_RESET_CONTENT, "Reset Content" }, + { SOUP_STATUS_PARTIAL_CONTENT, "Partial Content" }, + { SOUP_STATUS_MULTI_STATUS, "Multi-Status" }, + + /* Redirection */ + { SOUP_STATUS_MULTIPLE_CHOICES, "Multiple Choices" }, + { SOUP_STATUS_MOVED_PERMANENTLY, "Moved Permanently" }, + { SOUP_STATUS_FOUND, "Found" }, + { SOUP_STATUS_SEE_OTHER, "See Other" }, + { SOUP_STATUS_NOT_MODIFIED, "Not Modified" }, + { SOUP_STATUS_USE_PROXY, "Use Proxy" }, + { SOUP_STATUS_TEMPORARY_REDIRECT, "Temporary Redirect" }, + + /* Client error */ + { SOUP_STATUS_BAD_REQUEST, "Bad Request" }, + { SOUP_STATUS_UNAUTHORIZED, "Unauthorized" }, + { SOUP_STATUS_PAYMENT_REQUIRED, "Payment Required" }, + { SOUP_STATUS_FORBIDDEN, "Forbidden" }, + { SOUP_STATUS_NOT_FOUND, "Not Found" }, + { SOUP_STATUS_METHOD_NOT_ALLOWED, "Method Not Allowed" }, + { SOUP_STATUS_NOT_ACCEPTABLE, "Not Acceptable" }, + { SOUP_STATUS_PROXY_UNAUTHORIZED, "Proxy Authentication Required" }, + { SOUP_STATUS_REQUEST_TIMEOUT, "Request Timeout" }, + { SOUP_STATUS_CONFLICT, "Conflict" }, + { SOUP_STATUS_GONE, "Gone" }, + { SOUP_STATUS_LENGTH_REQUIRED, "Length Required" }, + { SOUP_STATUS_PRECONDITION_FAILED, "Precondition Failed" }, + { SOUP_STATUS_REQUEST_ENTITY_TOO_LARGE, "Request Entity Too Large" }, + { SOUP_STATUS_REQUEST_URI_TOO_LONG, "Request-URI Too Long" }, + { SOUP_STATUS_UNSUPPORTED_MEDIA_TYPE, "Unsupported Media Type" }, + { SOUP_STATUS_INVALID_RANGE, "Requested Range Not Satisfiable" }, + { SOUP_STATUS_EXPECTATION_FAILED, "Expectation Failed" }, + { SOUP_STATUS_UNPROCESSABLE_ENTITY, "Unprocessable Entity" }, + { SOUP_STATUS_LOCKED, "Locked" }, + { SOUP_STATUS_FAILED_DEPENDENCY, "Failed Dependency" }, + + /* Server error */ + { SOUP_STATUS_INTERNAL_SERVER_ERROR, "Internal Server Error" }, + { SOUP_STATUS_NOT_IMPLEMENTED, "Not Implemented" }, + { SOUP_STATUS_BAD_GATEWAY, "Bad Gateway" }, + { SOUP_STATUS_SERVICE_UNAVAILABLE, "Service Unavailable" }, + { SOUP_STATUS_GATEWAY_TIMEOUT, "Gateway Timeout" }, + { SOUP_STATUS_HTTP_VERSION_NOT_SUPPORTED, "HTTP Version Not Supported" }, + { SOUP_STATUS_INSUFFICIENT_STORAGE, "Insufficient Storage" }, + { SOUP_STATUS_NOT_EXTENDED, "Not Extended" }, + + { 0 } +}; + +/** + * soup_status_get_phrase: + * @status_code: an HTTP status code + * + * Looks up the stock HTTP description of @status_code. This is used + * by soup_message_set_status() to get the correct text to go with a + * given status code. + * + * There is no reason for you to ever use this + * function. If you wanted the textual description for the + * #SoupMessage:status_code of a given #SoupMessage, you should just + * look at the message's #SoupMessage:reason_phrase. However, you + * should only do that for use in debugging messages; HTTP reason + * phrases are not localized, and are not generally very descriptive + * anyway, and so they should never be presented to the user directly. + * Instead, you should create you own error messages based on the + * status code, and on what you were trying to do. + * + * Return value: the (terse, English) description of @status_code + **/ +const char * +soup_status_get_phrase (guint status_code) +{ + int i; + + for (i = 0; reason_phrases [i].code; i++) { + if (reason_phrases [i].code == status_code) + return reason_phrases [i].phrase; + } + + return "Unknown Error"; +} + +/** + * soup_status_proxify: + * @status_code: a status code + * + * Turns %SOUP_STATUS_CANT_RESOLVE into + * %SOUP_STATUS_CANT_RESOLVE_PROXY and %SOUP_STATUS_CANT_CONNECT into + * %SOUP_STATUS_CANT_CONNECT_PROXY. Other status codes are passed + * through unchanged. + * + * Return value: the "proxified" equivalent of @status_code. + * + * Since: 2.26 + **/ +guint +soup_status_proxify (guint status_code) +{ + if (status_code == SOUP_STATUS_CANT_RESOLVE) + return SOUP_STATUS_CANT_RESOLVE_PROXY; + else if (status_code == SOUP_STATUS_CANT_CONNECT) + return SOUP_STATUS_CANT_CONNECT_PROXY; + else + return status_code; +} + +GQuark +soup_http_error_quark (void) +{ + static GQuark error; + if (!error) + error = g_quark_from_static_string ("soup_http_error_quark"); + return error; +} diff --git a/libsoup/soup-status.h b/libsoup/soup-status.h new file mode 100644 index 0000000..514dfc3 --- /dev/null +++ b/libsoup/soup-status.h @@ -0,0 +1,185 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-status.h: HTTP status code and status class definitions + * + * Copyright (C) 2001-2003, Ximian, Inc. + */ + +#ifndef SOUP_STATUS_H +#define SOUP_STATUS_H 1 + +#include + +G_BEGIN_DECLS + +#define SOUP_STATUS_IS_TRANSPORT_ERROR(status) ((status) > 0 && (status) < 100) +#define SOUP_STATUS_IS_INFORMATIONAL(status) ((status) >= 100 && (status) < 200) +#define SOUP_STATUS_IS_SUCCESSFUL(status) ((status) >= 200 && (status) < 300) +#define SOUP_STATUS_IS_REDIRECTION(status) ((status) >= 300 && (status) < 400) +#define SOUP_STATUS_IS_CLIENT_ERROR(status) ((status) >= 400 && (status) < 500) +#define SOUP_STATUS_IS_SERVER_ERROR(status) ((status) >= 500 && (status) < 600) + +typedef enum { + SOUP_STATUS_NONE, + + /* Transport Errors */ + SOUP_STATUS_CANCELLED = 1, + SOUP_STATUS_CANT_RESOLVE, + SOUP_STATUS_CANT_RESOLVE_PROXY, + SOUP_STATUS_CANT_CONNECT, + SOUP_STATUS_CANT_CONNECT_PROXY, + SOUP_STATUS_SSL_FAILED, + SOUP_STATUS_IO_ERROR, + SOUP_STATUS_MALFORMED, + SOUP_STATUS_TRY_AGAIN, + SOUP_STATUS_TOO_MANY_REDIRECTS, + SOUP_STATUS_TLS_FAILED, + + /* HTTP Status Codes */ + SOUP_STATUS_CONTINUE = 100, + SOUP_STATUS_SWITCHING_PROTOCOLS = 101, + SOUP_STATUS_PROCESSING = 102, /* WebDAV */ + + SOUP_STATUS_OK = 200, + SOUP_STATUS_CREATED = 201, + SOUP_STATUS_ACCEPTED = 202, + SOUP_STATUS_NON_AUTHORITATIVE = 203, + SOUP_STATUS_NO_CONTENT = 204, + SOUP_STATUS_RESET_CONTENT = 205, + SOUP_STATUS_PARTIAL_CONTENT = 206, + SOUP_STATUS_MULTI_STATUS = 207, /* WebDAV */ + + SOUP_STATUS_MULTIPLE_CHOICES = 300, + SOUP_STATUS_MOVED_PERMANENTLY = 301, + SOUP_STATUS_FOUND = 302, + SOUP_STATUS_MOVED_TEMPORARILY = 302, /* RFC 2068 */ + SOUP_STATUS_SEE_OTHER = 303, + SOUP_STATUS_NOT_MODIFIED = 304, + SOUP_STATUS_USE_PROXY = 305, + SOUP_STATUS_NOT_APPEARING_IN_THIS_PROTOCOL = 306, /* (reserved) */ + SOUP_STATUS_TEMPORARY_REDIRECT = 307, + + SOUP_STATUS_BAD_REQUEST = 400, + SOUP_STATUS_UNAUTHORIZED = 401, + SOUP_STATUS_PAYMENT_REQUIRED = 402, /* (reserved) */ + SOUP_STATUS_FORBIDDEN = 403, + SOUP_STATUS_NOT_FOUND = 404, + SOUP_STATUS_METHOD_NOT_ALLOWED = 405, + SOUP_STATUS_NOT_ACCEPTABLE = 406, + SOUP_STATUS_PROXY_AUTHENTICATION_REQUIRED = 407, + SOUP_STATUS_PROXY_UNAUTHORIZED = SOUP_STATUS_PROXY_AUTHENTICATION_REQUIRED, + SOUP_STATUS_REQUEST_TIMEOUT = 408, + SOUP_STATUS_CONFLICT = 409, + SOUP_STATUS_GONE = 410, + SOUP_STATUS_LENGTH_REQUIRED = 411, + SOUP_STATUS_PRECONDITION_FAILED = 412, + SOUP_STATUS_REQUEST_ENTITY_TOO_LARGE = 413, + SOUP_STATUS_REQUEST_URI_TOO_LONG = 414, + SOUP_STATUS_UNSUPPORTED_MEDIA_TYPE = 415, + SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE = 416, + SOUP_STATUS_INVALID_RANGE = SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE, + SOUP_STATUS_EXPECTATION_FAILED = 417, + SOUP_STATUS_UNPROCESSABLE_ENTITY = 422, /* WebDAV */ + SOUP_STATUS_LOCKED = 423, /* WebDAV */ + SOUP_STATUS_FAILED_DEPENDENCY = 424, /* WebDAV */ + + SOUP_STATUS_INTERNAL_SERVER_ERROR = 500, + SOUP_STATUS_NOT_IMPLEMENTED = 501, + SOUP_STATUS_BAD_GATEWAY = 502, + SOUP_STATUS_SERVICE_UNAVAILABLE = 503, + SOUP_STATUS_GATEWAY_TIMEOUT = 504, + SOUP_STATUS_HTTP_VERSION_NOT_SUPPORTED = 505, + SOUP_STATUS_INSUFFICIENT_STORAGE = 507, /* WebDAV search */ + SOUP_STATUS_NOT_EXTENDED = 510 /* RFC 2774 */ +} SoupStatus; + +SOUP_AVAILABLE_IN_2_4 +const char *soup_status_get_phrase (guint status_code); +SOUP_AVAILABLE_IN_2_26 +guint soup_status_proxify (guint status_code); + +#define SOUP_HTTP_ERROR soup_http_error_quark() +SOUP_AVAILABLE_IN_2_4 +GQuark soup_http_error_quark (void); + +#ifndef SOUP_DISABLE_DEPRECATED +/* For introspection purposes, we create a duplicate enum type under + * the deprecated type name, since some (all?) bindings don't handle + * enum type typedefs the way we want. + */ +typedef enum { + SOUP_KNOWN_STATUS_CODE_NONE, + + SOUP_KNOWN_STATUS_CODE_CANCELLED = 1, + SOUP_KNOWN_STATUS_CODE_CANT_RESOLVE, + SOUP_KNOWN_STATUS_CODE_CANT_RESOLVE_PROXY, + SOUP_KNOWN_STATUS_CODE_CANT_CONNECT, + SOUP_KNOWN_STATUS_CODE_CANT_CONNECT_PROXY, + SOUP_KNOWN_STATUS_CODE_SSL_FAILED, + SOUP_KNOWN_STATUS_CODE_IO_ERROR, + SOUP_KNOWN_STATUS_CODE_MALFORMED, + SOUP_KNOWN_STATUS_CODE_TRY_AGAIN, + SOUP_KNOWN_STATUS_CODE_TOO_MANY_REDIRECTS, + SOUP_KNOWN_STATUS_CODE_TLS_FAILED, + + SOUP_KNOWN_STATUS_CODE_CONTINUE = 100, + SOUP_KNOWN_STATUS_CODE_SWITCHING_PROTOCOLS = 101, + SOUP_KNOWN_STATUS_CODE_PROCESSING = 102, + + SOUP_KNOWN_STATUS_CODE_OK = 200, + SOUP_KNOWN_STATUS_CODE_CREATED = 201, + SOUP_KNOWN_STATUS_CODE_ACCEPTED = 202, + SOUP_KNOWN_STATUS_CODE_NON_AUTHORITATIVE = 203, + SOUP_KNOWN_STATUS_CODE_NO_CONTENT = 204, + SOUP_KNOWN_STATUS_CODE_RESET_CONTENT = 205, + SOUP_KNOWN_STATUS_CODE_PARTIAL_CONTENT = 206, + SOUP_KNOWN_STATUS_CODE_MULTI_STATUS = 207, + + SOUP_KNOWN_STATUS_CODE_MULTIPLE_CHOICES = 300, + SOUP_KNOWN_STATUS_CODE_MOVED_PERMANENTLY = 301, + SOUP_KNOWN_STATUS_CODE_FOUND = 302, + SOUP_KNOWN_STATUS_CODE_MOVED_TEMPORARILY = 302, + SOUP_KNOWN_STATUS_CODE_SEE_OTHER = 303, + SOUP_KNOWN_STATUS_CODE_NOT_MODIFIED = 304, + SOUP_KNOWN_STATUS_CODE_USE_PROXY = 305, + SOUP_KNOWN_STATUS_CODE_NOT_APPEARING_IN_THIS_PROTOCOL = 306, + SOUP_KNOWN_STATUS_CODE_TEMPORARY_REDIRECT = 307, + + SOUP_KNOWN_STATUS_CODE_BAD_REQUEST = 400, + SOUP_KNOWN_STATUS_CODE_UNAUTHORIZED = 401, + SOUP_KNOWN_STATUS_CODE_PAYMENT_REQUIRED = 402, + SOUP_KNOWN_STATUS_CODE_FORBIDDEN = 403, + SOUP_KNOWN_STATUS_CODE_NOT_FOUND = 404, + SOUP_KNOWN_STATUS_CODE_METHOD_NOT_ALLOWED = 405, + SOUP_KNOWN_STATUS_CODE_NOT_ACCEPTABLE = 406, + SOUP_KNOWN_STATUS_CODE_PROXY_AUTHENTICATION_REQUIRED = 407, + SOUP_KNOWN_STATUS_CODE_PROXY_UNAUTHORIZED = SOUP_KNOWN_STATUS_CODE_PROXY_AUTHENTICATION_REQUIRED, + SOUP_KNOWN_STATUS_CODE_REQUEST_TIMEOUT = 408, + SOUP_KNOWN_STATUS_CODE_CONFLICT = 409, + SOUP_KNOWN_STATUS_CODE_GONE = 410, + SOUP_KNOWN_STATUS_CODE_LENGTH_REQUIRED = 411, + SOUP_KNOWN_STATUS_CODE_PRECONDITION_FAILED = 412, + SOUP_KNOWN_STATUS_CODE_REQUEST_ENTITY_TOO_LARGE = 413, + SOUP_KNOWN_STATUS_CODE_REQUEST_URI_TOO_LONG = 414, + SOUP_KNOWN_STATUS_CODE_UNSUPPORTED_MEDIA_TYPE = 415, + SOUP_KNOWN_STATUS_CODE_REQUESTED_RANGE_NOT_SATISFIABLE = 416, + SOUP_KNOWN_STATUS_CODE_INVALID_RANGE = SOUP_KNOWN_STATUS_CODE_REQUESTED_RANGE_NOT_SATISFIABLE, + SOUP_KNOWN_STATUS_CODE_EXPECTATION_FAILED = 417, + SOUP_KNOWN_STATUS_CODE_UNPROCESSABLE_ENTITY = 422, + SOUP_KNOWN_STATUS_CODE_LOCKED = 423, + SOUP_KNOWN_STATUS_CODE_FAILED_DEPENDENCY = 424, + + SOUP_KNOWN_STATUS_CODE_INTERNAL_SERVER_ERROR = 500, + SOUP_KNOWN_STATUS_CODE_NOT_IMPLEMENTED = 501, + SOUP_KNOWN_STATUS_CODE_BAD_GATEWAY = 502, + SOUP_KNOWN_STATUS_CODE_SERVICE_UNAVAILABLE = 503, + SOUP_KNOWN_STATUS_CODE_GATEWAY_TIMEOUT = 504, + SOUP_KNOWN_STATUS_CODE_HTTP_VERSION_NOT_SUPPORTED = 505, + SOUP_KNOWN_STATUS_CODE_INSUFFICIENT_STORAGE = 507, + SOUP_KNOWN_STATUS_CODE_NOT_EXTENDED = 510 +} SoupKnownStatusCode; +#endif + +G_END_DECLS + +#endif /* SOUP_STATUS_H */ diff --git a/libsoup/soup-tld-private.h b/libsoup/soup-tld-private.h new file mode 100644 index 0000000..2017951 --- /dev/null +++ b/libsoup/soup-tld-private.h @@ -0,0 +1,26 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-tld-private.h: + * + * Copyright (C) 2012 Igalia, S.L. + */ + +#ifndef SOUP_TLD_PRIVATE_H +#define SOUP_TLD_PRIVATE_H 1 + +G_BEGIN_DECLS + +typedef enum { + SOUP_TLD_RULE_NORMAL, + SOUP_TLD_RULE_MATCH_ALL = 1 << 0, + SOUP_TLD_RULE_EXCEPTION = 1 << 1, +} SoupTLDRuleFlags; + +typedef struct { + char *domain; + guint flags; +} SoupTLDEntry; + +G_END_DECLS + +#endif /* SOUP_TLD_PRIVATE_H */ diff --git a/libsoup/soup-tld.c b/libsoup/soup-tld.c new file mode 100644 index 0000000..f6e4db4 --- /dev/null +++ b/libsoup/soup-tld.c @@ -0,0 +1,318 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-tld.c + * + * Copyright (C) 2012 Igalia S.L. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include + +#include "soup-tld.h" +#include "soup.h" +#include "soup-tld-private.h" + +/** + * SECTION:soup-tld + * @short_description: Top-Level Domain Utilities + * + * These functions can be used to parse hostnames to attempt to determine + * what part of the name belongs to the domain owner, and what part is + * simply a "public suffix" such as ".com". + */ + +static void soup_tld_ensure_rules_hash_table (void); +static const char *soup_tld_get_base_domain_internal (const char *hostname, + guint additional_domains, + GError **error); + +static GHashTable *rules = NULL; +static SoupTLDEntry tld_entries[] = { +#include "tld_data.inc" +}; + +/* Stores the entries data in a hash table to ease and speed up + * searches. + */ +static void +soup_tld_ensure_rules_hash_table (void) +{ + static gsize init = 0; + + if (g_once_init_enter (&init)) { + int i; + + rules = g_hash_table_new (g_str_hash, g_str_equal); + for (i = 0; i < G_N_ELEMENTS (tld_entries); ++i) + g_hash_table_insert (rules, tld_entries[i].domain, + &(tld_entries[i].flags)); + g_once_init_leave (&init, 1); + } +} + +/** + * soup_tld_get_base_domain: + * @hostname: a hostname + * @error: return location for a #GError, or %NULL to ignore + * errors. See #SoupTLDError for the available error codes + * + * Finds the base domain for a given @hostname. The base domain is + * composed by the top level domain (such as .org, .com, .co.uk, etc) + * plus the second level domain, for example for myhost.mydomain.com + * it will return mydomain.com. + * + * Note that %NULL will be returned for private URLs (those not ending + * with any well known TLD) because choosing a base domain for them + * would be totally arbitrary. + * + * Prior to libsoup 2.46, this function required that @hostname be in + * UTF-8 if it was an IDN. From 2.46 on, the name can be in either + * UTF-8 or ASCII format (and the return value will be in the same + * format). + * + * Returns: a pointer to the start of the base domain in @hostname. If + * an error occurs, %NULL will be returned and @error set. + * + * Since: 2.40 + **/ +const char * +soup_tld_get_base_domain (const char *hostname, GError **error) +{ + g_return_val_if_fail (hostname, NULL); + + return soup_tld_get_base_domain_internal (hostname, 1, error); +} + +/** + * soup_tld_domain_is_public_suffix: + * @domain: a domain name + * + * Looks whether the @domain passed as argument is a public domain + * suffix (.org, .com, .co.uk, etc) or not. + * + * Prior to libsoup 2.46, this function required that @domain be in + * UTF-8 if it was an IDN. From 2.46 on, the name can be in either + * UTF-8 or ASCII format. + * + * Returns: %TRUE if it is a public domain, %FALSE otherwise. + * + * Since: 2.40 + **/ +gboolean +soup_tld_domain_is_public_suffix (const char *domain) +{ + const char *base_domain; + GError *error = NULL; + + g_return_val_if_fail (domain, FALSE); + + /* Skip the leading '.' if present */ + if (*domain == '.' && !*(++domain)) + g_return_val_if_reached (FALSE); + + base_domain = soup_tld_get_base_domain_internal (domain, 0, &error); + if (g_strcmp0 (domain, base_domain)) { + g_clear_error (&error); + return FALSE; + } + + if (g_error_matches (error, SOUP_TLD_ERROR, SOUP_TLD_ERROR_NO_BASE_DOMAIN)) { + g_error_free (error); + return FALSE; + } + + if (g_error_matches (error, SOUP_TLD_ERROR, SOUP_TLD_ERROR_IS_IP_ADDRESS) || + g_error_matches (error, SOUP_TLD_ERROR, SOUP_TLD_ERROR_INVALID_HOSTNAME)) { + g_error_free (error); + g_return_val_if_reached (FALSE); + } + + g_clear_error (&error); + + return TRUE; +} + +/** + * SOUP_TLD_ERROR: + * + * The #GError domain for soup-tld-related errors. + * + * Since: 2.40 + */ +/** + * SoupTLDError: + * @SOUP_TLD_ERROR_INVALID_HOSTNAME: A hostname was syntactically + * invalid. + * @SOUP_TLD_ERROR_IS_IP_ADDRESS: The passed-in "hostname" was + * actually an IP address (and thus has no base domain or + * public suffix). + * @SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS: The passed-in hostname + * did not have enough components. Eg, calling + * soup_tld_get_base_domain() on "co.uk". + * @SOUP_TLD_ERROR_NO_BASE_DOMAIN: The passed-in hostname has + * no recognized public suffix. + * + * Error codes for %SOUP_TLD_ERROR. + * + * Since: 2.40 + */ + +GQuark +soup_tld_error_quark (void) +{ + static GQuark error; + if (!error) + error = g_quark_from_static_string ("soup_tld_error_quark"); + return error; +} + +static const char * +soup_tld_get_base_domain_internal (const char *hostname, guint additional_domains, GError **error) +{ + char *prev_domain, *cur_domain, *next_dot; + gint add_domains; + const char *orig_hostname = NULL, *tld; + char *utf8_hostname = NULL; + + soup_tld_ensure_rules_hash_table (); + + if (g_hostname_is_ip_address (hostname)) { + g_set_error_literal (error, SOUP_TLD_ERROR, + SOUP_TLD_ERROR_IS_IP_ADDRESS, + _("Hostname is an IP address")); + return NULL; + } + + if (g_hostname_is_ascii_encoded (hostname)) { + orig_hostname = hostname; + hostname = utf8_hostname = g_hostname_to_unicode (hostname); + if (!hostname) { + g_set_error_literal (error, SOUP_TLD_ERROR, + SOUP_TLD_ERROR_INVALID_HOSTNAME, + _("Invalid hostname")); + return NULL; + } + } + + cur_domain = (char *) hostname; + tld = cur_domain; + prev_domain = NULL; + /* Process matching rules from longest to shortest. Logic + * based on Mozilla's implementation of nsEffectiveTLDService. + */ + while (TRUE) { + char *orig_domain; + gboolean domain_found; + int *flags; + char *normalized_domain = NULL; + int domain_length; + + /* Valid hostnames neither start with a dot nor have more than one + * dot together. + */ + if (*cur_domain == '.') { + g_set_error_literal (error, SOUP_TLD_ERROR, + SOUP_TLD_ERROR_INVALID_HOSTNAME, + _("Invalid hostname")); + g_free (utf8_hostname); + return NULL; + } + + next_dot = strchr (cur_domain, '.'); + + /* Discard trailing dot if any before looking up. */ + domain_length = strlen (cur_domain); + if (cur_domain[domain_length - 1] == '.') + normalized_domain = g_strndup (cur_domain, domain_length - 1); + domain_found = g_hash_table_lookup_extended (rules, normalized_domain ? normalized_domain : cur_domain, (gpointer *) &orig_domain, (gpointer *) &flags); + g_free (normalized_domain); + normalized_domain = NULL; + + /* We compare the keys just to be sure that we haven't hit a collision */ + if (domain_found && !strncmp (orig_domain, cur_domain, strlen (orig_domain))) { + if (*flags & SOUP_TLD_RULE_MATCH_ALL) { + /* If we match a *. rule and there were no previous exceptions + * nor previous domains then treat it as an exact match. + */ + tld = prev_domain ? prev_domain : cur_domain; + break; + } else if (*flags == SOUP_TLD_RULE_NORMAL) { + tld = cur_domain; + break; + } else if (*flags & SOUP_TLD_RULE_EXCEPTION) { + tld = next_dot + 1; + break; + } + } + + /* If we hit the top and haven't matched yet, then it + * has no public suffix. + */ + if (!next_dot) { + g_set_error_literal (error, SOUP_TLD_ERROR, + SOUP_TLD_ERROR_NO_BASE_DOMAIN, + _("Hostname has no base domain")); + g_free (utf8_hostname); + return NULL; + } + + prev_domain = cur_domain; + cur_domain = next_dot + 1; + } + + if (orig_hostname) { + int dots; + const char *p; + + /* Count the number of dots that appear after tld in + * utf8_hostname, and then find the corresponding spot + * in orig_hostname; + */ + for (p = tld, dots = 0; *p; p++) { + if (*p == '.') + dots++; + } + + for (p = orig_hostname + strlen (orig_hostname); p > orig_hostname; p--) { + if (*(p - 1) == '.') { + if (dots) + dots--; + else + break; + } + } + /* It's not possible for utf8_hostname to have had + * more dots than orig_hostname. + */ + g_assert (dots == 0); + + tld = p; + g_free (utf8_hostname); + hostname = orig_hostname; + } + + /* Include the additional number of domains requested. */ + add_domains = additional_domains; + while (tld != hostname) { + if (*(--tld) == '.' && (!(add_domains--))) { + ++add_domains; + ++tld; + break; + } + } + + /* If additional_domains > 0 then we haven't found enough additional domains. */ + if (add_domains) { + g_set_error_literal (error, SOUP_TLD_ERROR, + SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS, + _("Not enough domains")); + return NULL; + } + + return tld; +} diff --git a/libsoup/soup-tld.h b/libsoup/soup-tld.h new file mode 100644 index 0000000..4b099a2 --- /dev/null +++ b/libsoup/soup-tld.h @@ -0,0 +1,34 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2012 Igalia S.L. + */ + +#ifndef __SOUP_TLD_H__ +#define __SOUP_TLD_H__ + +#include + +G_BEGIN_DECLS + +SOUP_AVAILABLE_IN_2_40 +const char *soup_tld_get_base_domain (const char *hostname, + GError **error); + +SOUP_AVAILABLE_IN_2_40 +gboolean soup_tld_domain_is_public_suffix (const char *domain); + +/* Errors */ +SOUP_AVAILABLE_IN_2_40 +GQuark soup_tld_error_quark (void); +#define SOUP_TLD_ERROR soup_tld_error_quark() + +typedef enum { + SOUP_TLD_ERROR_INVALID_HOSTNAME, + SOUP_TLD_ERROR_IS_IP_ADDRESS, + SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS, + SOUP_TLD_ERROR_NO_BASE_DOMAIN +} SoupTLDError; + +G_END_DECLS + +#endif /* __SOUP_TLD_H__ */ diff --git a/libsoup/soup-types.h b/libsoup/soup-types.h new file mode 100644 index 0000000..e020de7 --- /dev/null +++ b/libsoup/soup-types.h @@ -0,0 +1,42 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2003, Ximian, Inc. + */ + +#ifndef SOUP_TYPES_H +#define SOUP_TYPES_H 1 + +#include + +#include +#include + +G_BEGIN_DECLS + +typedef struct _SoupAddress SoupAddress; +typedef struct _SoupAuth SoupAuth; +typedef struct _SoupAuthDomain SoupAuthDomain; +typedef struct _SoupCookie SoupCookie; +typedef struct _SoupCookieJar SoupCookieJar; +typedef struct _SoupDate SoupDate; +typedef struct _SoupMessage SoupMessage; +typedef struct _SoupRequest SoupRequest; +typedef struct _SoupRequestHTTP SoupRequestHTTP; +typedef struct _SoupServer SoupServer; +typedef struct _SoupSession SoupSession; +typedef struct _SoupSessionAsync SoupSessionAsync; +typedef struct _SoupSessionFeature SoupSessionFeature; +typedef struct _SoupSessionSync SoupSessionSync; +typedef struct _SoupSocket SoupSocket; +typedef struct _SoupURI SoupURI; +typedef struct _SoupWebsocketConnection SoupWebsocketConnection; + + +/*< private >*/ +typedef struct _SoupConnection SoupConnection; +typedef struct _SoupMessageQueue SoupMessageQueue; +typedef struct _SoupMessageQueueItem SoupMessageQueueItem; + +G_END_DECLS + +#endif diff --git a/libsoup/soup-uri.c b/libsoup/soup-uri.c new file mode 100644 index 0000000..74c362e --- /dev/null +++ b/libsoup/soup-uri.c @@ -0,0 +1,1379 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* soup-uri.c : utility functions to parse URLs */ + +/* + * Copyright 1999-2003 Ximian, Inc. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include "soup-uri.h" +#include "soup.h" +#include "soup-misc-private.h" + +/** + * SECTION:soup-uri + * @short_description: URIs + * + * A #SoupURI represents a (parsed) URI. + * + * Many applications will not need to use #SoupURI directly at all; on + * the client side, soup_message_new() takes a stringified URI, and on + * the server side, the path and query components are provided for you + * in the server callback. + **/ + +/** + * SoupURI: + * @scheme: the URI scheme (eg, "http") + * @user: a username, or %NULL + * @password: a password, or %NULL + * @host: the hostname or IP address, or %NULL + * @port: the port number on @host + * @path: the path on @host + * @query: a query for @path, or %NULL + * @fragment: a fragment identifier within @path, or %NULL + * + * A #SoupURI represents a (parsed) URI. #SoupURI supports RFC 3986 + * (URI Generic Syntax), and can parse any valid URI. However, libsoup + * only uses "http" and "https" URIs internally; You can use + * SOUP_URI_VALID_FOR_HTTP() to test if a #SoupURI is a valid HTTP + * URI. + * + * @scheme will always be set in any URI. It is an interned string and + * is always all lowercase. (If you parse a URI with a non-lowercase + * scheme, it will be converted to lowercase.) The macros + * %SOUP_URI_SCHEME_HTTP and %SOUP_URI_SCHEME_HTTPS provide the + * interned values for "http" and "https" and can be compared against + * URI @scheme values. + * + * @user and @password are parsed as defined in the older URI specs + * (ie, separated by a colon; RFC 3986 only talks about a single + * "userinfo" field). Note that @password is not included in the + * output of soup_uri_to_string(). libsoup does not normally use these + * fields; authentication is handled via #SoupSession signals. + * + * @host contains the hostname, and @port the port specified in the + * URI. If the URI doesn't contain a hostname, @host will be %NULL, + * and if it doesn't specify a port, @port may be 0. However, for + * "http" and "https" URIs, @host is guaranteed to be non-%NULL + * (trying to parse an http URI with no @host will return %NULL), and + * @port will always be non-0 (because libsoup knows the default value + * to use when it is not specified in the URI). + * + * @path is always non-%NULL. For http/https URIs, @path will never be + * an empty string either; if the input URI has no path, the parsed + * #SoupURI will have a @path of "/". + * + * @query and @fragment are optional for all URI types. + * soup_form_decode() may be useful for parsing @query. + * + * Note that @path, @query, and @fragment may contain + * %-encoded characters. soup_uri_new() calls + * soup_uri_normalize() on them, but not soup_uri_decode(). This is + * necessary to ensure that soup_uri_to_string() will generate a URI + * that has exactly the same meaning as the original. (In theory, + * #SoupURI should leave @user, @password, and @host partially-encoded + * as well, but this would be more annoying than useful.) + **/ + +/** + * SOUP_URI_IS_VALID: + * @uri: a #SoupURI + * + * Tests whether @uri is a valid #SoupURI; that is, that it is non-%NULL + * and its @scheme and @path members are also non-%NULL. + * + * This macro does not check whether http and https URIs have a non-%NULL + * @host member. + * + * Return value: %TRUE if @uri is valid for use. + * + * Since: 2.38 + **/ + +/** + * SOUP_URI_VALID_FOR_HTTP: + * @uri: a #SoupURI + * + * Tests if @uri is a valid #SoupURI for HTTP communication; that is, if + * it can be used to construct a #SoupMessage. + * + * Return value: %TRUE if @uri is a valid "http" or "https" URI. + * + * Since: 2.24 + **/ + +/** + * SOUP_URI_SCHEME_HTTP: + * + * "http" as an interned string; you can compare this directly to a + * #SoupURI's scheme field using + * ==. + */ +/** + * SOUP_URI_SCHEME_HTTPS: + * + * "https" as an interned string; you can compare this directly to a + * #SoupURI's scheme field using + * ==. + */ +/** + * SOUP_URI_SCHEME_FTP: + * + * "ftp" as an interned string; you can compare this directly to a + * #SoupURI's scheme field using + * ==. + * + * Since: 2.30 + */ +/** + * SOUP_URI_SCHEME_FILE: + * + * "file" as an interned string; you can compare this directly to a + * #SoupURI's scheme field using + * ==. + * + * Since: 2.30 + */ +/** + * SOUP_URI_SCHEME_DATA: + * + * "data" as an interned string; you can compare this directly to a + * #SoupURI's scheme field using + * ==. + * + * Since: 2.30 + */ +/** + * SOUP_URI_SCHEME_RESOURCE: + * + * "data" as an interned string; you can compare this directly to a + * #SoupURI's scheme field using + * ==. + * + * Since: 2.42 + */ +/** + * SOUP_URI_SCHEME_WS: + * + * "ws" (WebSocket) as an interned string; you can compare this + * directly to a #SoupURI's scheme field using + * ==. + * + * Since: 2.50 + */ +/** + * SOUP_URI_SCHEME_WSS: + * + * "wss" (WebSocket over TLS) as an interned string; you can compare + * this directly to a #SoupURI's scheme field using + * ==. + * + * Since: 2.50 + */ + +static void append_uri_encoded (GString *str, const char *in, const char *extra_enc_chars); +static char *uri_normalized_copy (const char *str, int length, const char *unescape_extra); + +gpointer _SOUP_URI_SCHEME_HTTP, _SOUP_URI_SCHEME_HTTPS; +gpointer _SOUP_URI_SCHEME_WS, _SOUP_URI_SCHEME_WSS; +gpointer _SOUP_URI_SCHEME_FTP; +gpointer _SOUP_URI_SCHEME_FILE, _SOUP_URI_SCHEME_DATA, _SOUP_URI_SCHEME_RESOURCE; + +static inline const char * +soup_uri_parse_scheme (const char *scheme, int len) +{ + if (len == 4 && !g_ascii_strncasecmp (scheme, "http", len)) { + return SOUP_URI_SCHEME_HTTP; + } else if (len == 5 && !g_ascii_strncasecmp (scheme, "https", len)) { + return SOUP_URI_SCHEME_HTTPS; + } else if (len == 8 && !g_ascii_strncasecmp (scheme, "resource", len)) { + return SOUP_URI_SCHEME_RESOURCE; + } else if (len == 2 && !g_ascii_strncasecmp (scheme, "ws", len)) { + return SOUP_URI_SCHEME_WS; + } else if (len == 3 && !g_ascii_strncasecmp (scheme, "wss", len)) { + return SOUP_URI_SCHEME_WSS; + } else { + char *lower_scheme; + + lower_scheme = g_ascii_strdown (scheme, len); + scheme = g_intern_static_string (lower_scheme); + if (scheme != (const char *)lower_scheme) + g_free (lower_scheme); + return scheme; + } +} + +static inline guint +soup_scheme_default_port (const char *scheme) +{ + if (scheme == SOUP_URI_SCHEME_HTTP || scheme == SOUP_URI_SCHEME_WS) + return 80; + else if (scheme == SOUP_URI_SCHEME_HTTPS || scheme == SOUP_URI_SCHEME_WSS) + return 443; + else if (scheme == SOUP_URI_SCHEME_FTP) + return 21; + else + return 0; +} + +/** + * soup_uri_new_with_base: + * @base: a base URI + * @uri_string: the URI + * + * Parses @uri_string relative to @base. + * + * Return value: a parsed #SoupURI. + **/ +SoupURI * +soup_uri_new_with_base (SoupURI *base, const char *uri_string) +{ + SoupURI *uri, fixed_base; + const char *end, *hash, *colon, *at, *path, *question; + const char *p, *hostend; + gboolean remove_dot_segments = TRUE; + int len; + + g_return_val_if_fail (uri_string != NULL, NULL); + + /* Allow a %NULL path in @base, for compatibility */ + if (base && base->scheme && !base->path) { + g_warn_if_fail (SOUP_URI_IS_VALID (base)); + + memcpy (&fixed_base, base, sizeof (SoupURI)); + fixed_base.path = ""; + base = &fixed_base; + } + + g_return_val_if_fail (base == NULL || SOUP_URI_IS_VALID (base), NULL); + + /* First some cleanup steps (which are supposed to all be no-ops, + * but...). Skip initial whitespace, strip out internal tabs and + * line breaks, and ignore trailing whitespace. + */ + while (g_ascii_isspace (*uri_string)) + uri_string++; + + len = strcspn (uri_string, "\t\n\r"); + if (uri_string[len]) { + char *clean = g_malloc (strlen (uri_string) + 1), *d; + const char *s; + + for (s = uri_string, d = clean; *s; s++) { + if (*s != '\t' && *s != '\n' && *s != '\r') + *d++ = *s; + } + *d = '\0'; + + uri = soup_uri_new_with_base (base, clean); + g_free (clean); + return uri; + } + end = uri_string + len; + while (end > uri_string && g_ascii_isspace (end[-1])) + end--; + + uri = g_slice_new0 (SoupURI); + + /* Find fragment. */ + hash = strchr (uri_string, '#'); + if (hash) { + uri->fragment = uri_normalized_copy (hash + 1, end - hash + 1, + NULL); + end = hash; + } + + /* Find scheme */ + p = uri_string; + while (p < end && (g_ascii_isalpha (*p) || + (p > uri_string && (g_ascii_isdigit (*p) || + *p == '.' || + *p == '+' || + *p == '-')))) + p++; + + if (p > uri_string && *p == ':') { + uri->scheme = soup_uri_parse_scheme (uri_string, p - uri_string); + uri_string = p + 1; + } + + if (uri_string == end && !base && !uri->fragment) { + uri->path = g_strdup (""); + return uri; + } + + /* Check for authority */ + if (strncmp (uri_string, "//", 2) == 0) { + uri_string += 2; + + path = uri_string + strcspn (uri_string, "/?#"); + if (path > end) + path = end; + at = strchr (uri_string, '@'); + if (at && at < path) { + colon = strchr (uri_string, ':'); + if (colon && colon < at) { + uri->password = soup_uri_decoded_copy (colon + 1, + at - colon - 1, NULL); + } else { + uri->password = NULL; + colon = at; + } + + uri->user = soup_uri_decoded_copy (uri_string, + colon - uri_string, NULL); + uri_string = at + 1; + } else + uri->user = uri->password = NULL; + + /* Find host and port. */ + if (*uri_string == '[') { + const char *pct; + + uri_string++; + hostend = strchr (uri_string, ']'); + if (!hostend || hostend > path) { + soup_uri_free (uri); + return NULL; + } + if (*(hostend + 1) == ':') + colon = hostend + 1; + else + colon = NULL; + + pct = memchr (uri_string, '%', hostend - uri_string); + if (!pct || (pct[1] == '2' && pct[2] == '5')) { + uri->host = soup_uri_decoded_copy (uri_string, + hostend - uri_string, NULL); + } else + uri->host = g_strndup (uri_string, hostend - uri_string); + } else { + colon = memchr (uri_string, ':', path - uri_string); + hostend = colon ? colon : path; + uri->host = soup_uri_decoded_copy (uri_string, + hostend - uri_string, NULL); + } + + if (colon && colon != path - 1) { + char *portend; + uri->port = strtoul (colon + 1, &portend, 10); + if (portend != (char *)path) { + soup_uri_free (uri); + return NULL; + } + } + + uri_string = path; + } + + /* Find query */ + question = memchr (uri_string, '?', end - uri_string); + if (question) { + uri->query = uri_normalized_copy (question + 1, + end - (question + 1), + NULL); + end = question; + } + + if (end != uri_string) { + uri->path = uri_normalized_copy (uri_string, end - uri_string, + NULL); + } + + /* Apply base URI. This is spelled out in RFC 3986. */ + if (base && !uri->scheme && uri->host) + uri->scheme = base->scheme; + else if (base && !uri->scheme) { + uri->scheme = base->scheme; + uri->user = g_strdup (base->user); + uri->password = g_strdup (base->password); + uri->host = g_strdup (base->host); + uri->port = base->port; + + if (!uri->path) { + uri->path = g_strdup (base->path); + if (!uri->query) + uri->query = g_strdup (base->query); + remove_dot_segments = FALSE; + } else if (*uri->path != '/') { + char *newpath, *last; + + last = strrchr (base->path, '/'); + if (last) { + newpath = g_strdup_printf ("%.*s%s", + (int)(last + 1 - base->path), + base->path, + uri->path); + } else + newpath = g_strdup_printf ("/%s", uri->path); + + g_free (uri->path); + uri->path = newpath; + } + } + + if (remove_dot_segments && uri->path && *uri->path) { + char *p, *q; + + /* Remove "./" where "." is a complete segment. */ + for (p = uri->path + 1; *p; ) { + if (*(p - 1) == '/' && + *p == '.' && *(p + 1) == '/') + memmove (p, p + 2, strlen (p + 2) + 1); + else + p++; + } + /* Remove "." at end. */ + if (p > uri->path + 2 && + *(p - 1) == '.' && *(p - 2) == '/') + *(p - 1) = '\0'; + + /* Remove "/../" where != ".." */ + for (p = uri->path + 1; *p; ) { + if (!strncmp (p, "../", 3)) { + p += 3; + continue; + } + q = strchr (p + 1, '/'); + if (!q) + break; + if (strncmp (q, "/../", 4) != 0) { + p = q + 1; + continue; + } + memmove (p, q + 4, strlen (q + 4) + 1); + p = uri->path + 1; + } + /* Remove "/.." at end where != ".." */ + q = strrchr (uri->path, '/'); + if (q && q != uri->path && !strcmp (q, "/..")) { + p = q - 1; + while (p > uri->path && *p != '/') + p--; + if (strncmp (p, "/../", 4) != 0) + *(p + 1) = 0; + } + + /* Remove extraneous initial "/.."s */ + while (!strncmp (uri->path, "/../", 4)) + memmove (uri->path, uri->path + 3, strlen (uri->path) - 2); + if (!strcmp (uri->path, "/..")) + uri->path[1] = '\0'; + } + + /* HTTP-specific stuff */ + if (uri->scheme == SOUP_URI_SCHEME_HTTP || + uri->scheme == SOUP_URI_SCHEME_HTTPS) { + if (!uri->path) + uri->path = g_strdup ("/"); + if (!SOUP_URI_VALID_FOR_HTTP (uri)) { + soup_uri_free (uri); + return NULL; + } + } + + if (uri->scheme == SOUP_URI_SCHEME_FTP) { + if (!uri->host) { + soup_uri_free (uri); + return NULL; + } + } + + if (!uri->port) + uri->port = soup_scheme_default_port (uri->scheme); + if (!uri->path) + uri->path = g_strdup (""); + + return uri; +} + +/** + * soup_uri_new: + * @uri_string: (allow-none): a URI + * + * Parses an absolute URI. + * + * You can also pass %NULL for @uri_string if you want to get back an + * "empty" #SoupURI that you can fill in by hand. (You will need to + * call at least soup_uri_set_scheme() and soup_uri_set_path(), since + * those fields are required.) + * + * Return value: (nullable): a #SoupURI, or %NULL if the given string + * was found to be invalid. + **/ +SoupURI * +soup_uri_new (const char *uri_string) +{ + SoupURI *uri; + + if (!uri_string) + return g_slice_new0 (SoupURI); + + uri = soup_uri_new_with_base (NULL, uri_string); + if (!uri) + return NULL; + if (!SOUP_URI_IS_VALID (uri)) { + soup_uri_free (uri); + return NULL; + } + + return uri; +} + + +char * +soup_uri_to_string_internal (SoupURI *uri, gboolean just_path_and_query, + gboolean include_password, gboolean force_port) +{ + GString *str; + char *return_result; + + g_return_val_if_fail (uri != NULL, NULL); + g_warn_if_fail (SOUP_URI_IS_VALID (uri)); + + str = g_string_sized_new (40); + + if (uri->scheme && !just_path_and_query) + g_string_append_printf (str, "%s:", uri->scheme); + if (uri->host && !just_path_and_query) { + g_string_append (str, "//"); + if (uri->user) { + append_uri_encoded (str, uri->user, ":;@?/"); + if (uri->password && include_password) { + g_string_append_c (str, ':'); + append_uri_encoded (str, uri->password, ";@?/"); + } + g_string_append_c (str, '@'); + } + if (strchr (uri->host, ':')) { + const char *pct; + + g_string_append_c (str, '['); + pct = strchr (uri->host, '%'); + if (pct) { + g_string_append_printf (str, "%.*s%%25%s", + (int) (pct - uri->host), + uri->host, pct + 1); + } else + g_string_append (str, uri->host); + g_string_append_c (str, ']'); + } else + append_uri_encoded (str, uri->host, ":/"); + if (uri->port && (force_port || uri->port != soup_scheme_default_port (uri->scheme))) + g_string_append_printf (str, ":%u", uri->port); + if (!uri->path && (uri->query || uri->fragment)) + g_string_append_c (str, '/'); + else if ((!uri->path || !*uri->path) && + (uri->scheme == SOUP_URI_SCHEME_HTTP || + uri->scheme == SOUP_URI_SCHEME_HTTPS)) + g_string_append_c (str, '/'); + } + + if (uri->path && *uri->path) + g_string_append (str, uri->path); + else if (just_path_and_query) + g_string_append_c (str, '/'); + + if (uri->query) { + g_string_append_c (str, '?'); + g_string_append (str, uri->query); + } + if (uri->fragment && !just_path_and_query) { + g_string_append_c (str, '#'); + g_string_append (str, uri->fragment); + } + + return_result = str->str; + g_string_free (str, FALSE); + + return return_result; +} + +/** + * soup_uri_to_string: + * @uri: a #SoupURI + * @just_path_and_query: if %TRUE, output just the path and query portions + * + * Returns a string representing @uri. + * + * If @just_path_and_query is %TRUE, this concatenates the path and query + * together. That is, it constructs the string that would be needed in + * the Request-Line of an HTTP request for @uri. + * + * Note that the output will never contain a password, even if @uri + * does. + * + * Return value: a string representing @uri, which the caller must free. + **/ +char * +soup_uri_to_string (SoupURI *uri, gboolean just_path_and_query) +{ + return soup_uri_to_string_internal (uri, just_path_and_query, FALSE, FALSE); +} + +/** + * soup_uri_copy: + * @uri: a #SoupURI + * + * Copies @uri + * + * Return value: a copy of @uri, which must be freed with soup_uri_free() + **/ +SoupURI * +soup_uri_copy (SoupURI *uri) +{ + SoupURI *dup; + + g_return_val_if_fail (uri != NULL, NULL); + g_warn_if_fail (SOUP_URI_IS_VALID (uri)); + + dup = g_slice_new0 (SoupURI); + dup->scheme = uri->scheme; + dup->user = g_strdup (uri->user); + dup->password = g_strdup (uri->password); + dup->host = g_strdup (uri->host); + dup->port = uri->port; + dup->path = g_strdup (uri->path); + dup->query = g_strdup (uri->query); + dup->fragment = g_strdup (uri->fragment); + + return dup; +} + +static inline gboolean +parts_equal (const char *one, const char *two, gboolean insensitive) +{ + if (!one && !two) + return TRUE; + if (!one || !two) + return FALSE; + return insensitive ? !g_ascii_strcasecmp (one, two) : !strcmp (one, two); +} + +/** + * soup_uri_equal: + * @uri1: a #SoupURI + * @uri2: another #SoupURI + * + * Tests whether or not @uri1 and @uri2 are equal in all parts + * + * Return value: %TRUE or %FALSE + **/ +gboolean +soup_uri_equal (SoupURI *uri1, SoupURI *uri2) +{ + g_return_val_if_fail (uri1 != NULL, FALSE); + g_return_val_if_fail (uri2 != NULL, FALSE); + g_warn_if_fail (SOUP_URI_IS_VALID (uri1)); + g_warn_if_fail (SOUP_URI_IS_VALID (uri2)); + + if (uri1->scheme != uri2->scheme || + uri1->port != uri2->port || + !parts_equal (uri1->user, uri2->user, FALSE) || + !parts_equal (uri1->password, uri2->password, FALSE) || + !parts_equal (uri1->host, uri2->host, TRUE) || + !parts_equal (uri1->path, uri2->path, FALSE) || + !parts_equal (uri1->query, uri2->query, FALSE) || + !parts_equal (uri1->fragment, uri2->fragment, FALSE)) + return FALSE; + + return TRUE; +} + +/** + * soup_uri_free: + * @uri: a #SoupURI + * + * Frees @uri. + **/ +void +soup_uri_free (SoupURI *uri) +{ + g_return_if_fail (uri != NULL); + + g_free (uri->user); + g_free (uri->password); + g_free (uri->host); + g_free (uri->path); + g_free (uri->query); + g_free (uri->fragment); + + g_slice_free (SoupURI, uri); +} + +static void +append_uri_encoded (GString *str, const char *in, const char *extra_enc_chars) +{ + const unsigned char *s = (const unsigned char *)in; + + while (*s) { + if (soup_char_is_uri_percent_encoded (*s) || + soup_char_is_uri_gen_delims (*s) || + (extra_enc_chars && strchr (extra_enc_chars, *s))) + g_string_append_printf (str, "%%%02X", (int)*s++); + else + g_string_append_c (str, *s++); + } +} + +/** + * soup_uri_encode: + * @part: a URI part + * @escape_extra: (allow-none): additional reserved characters to + * escape (or %NULL) + * + * This %-encodes the given URI part and returns the escaped + * version in allocated memory, which the caller must free when it is + * done. + * + * Return value: the encoded URI part + **/ +char * +soup_uri_encode (const char *part, const char *escape_extra) +{ + GString *str; + char *encoded; + + g_return_val_if_fail (part != NULL, NULL); + + str = g_string_new (NULL); + append_uri_encoded (str, part, escape_extra); + encoded = str->str; + g_string_free (str, FALSE); + + return encoded; +} + +#define XDIGIT(c) ((c) <= '9' ? (c) - '0' : ((c) & 0x4F) - 'A' + 10) +#define HEXCHAR(s) ((XDIGIT (s[1]) << 4) + XDIGIT (s[2])) + +char * +soup_uri_decoded_copy (const char *part, int length, int *decoded_length) +{ + unsigned char *s, *d; + char *decoded; + + g_return_val_if_fail (part != NULL, NULL); + + decoded = g_strndup (part, length); + s = d = (unsigned char *)decoded; + do { + if (*s == '%') { + if (!g_ascii_isxdigit (s[1]) || + !g_ascii_isxdigit (s[2])) { + *d++ = *s; + continue; + } + *d++ = HEXCHAR (s); + s += 2; + } else + *d++ = *s; + } while (*s++); + + if (decoded_length) + *decoded_length = d - (unsigned char *)decoded - 1; + + return decoded; +} + +/** + * soup_uri_decode: + * @part: a URI part + * + * Fully %-decodes @part. + * + * In the past, this would return %NULL if @part contained invalid + * percent-encoding, but now it just ignores the problem (as + * soup_uri_new() already did). + * + * Return value: the decoded URI part. + */ +char * +soup_uri_decode (const char *part) +{ + g_return_val_if_fail (part != NULL, NULL); + + return soup_uri_decoded_copy (part, strlen (part), NULL); +} + +static char * +uri_normalized_copy (const char *part, int length, + const char *unescape_extra) +{ + unsigned char *s, *d, c; + char *normalized = g_strndup (part, length); + gboolean need_fixup = FALSE; + + if (!unescape_extra) + unescape_extra = ""; + + s = d = (unsigned char *)normalized; + while (*s) { + if (*s == '%') { + if (!g_ascii_isxdigit (s[1]) || + !g_ascii_isxdigit (s[2])) { + *d++ = *s++; + continue; + } + + c = HEXCHAR (s); + if (soup_char_is_uri_unreserved (c) || + (c && strchr (unescape_extra, c))) { + *d++ = c; + s += 3; + } else { + /* We leave it unchanged. We used to uppercase percent-encoded + * triplets but we do not do it any more as RFC3986 Section 6.2.2.1 + * says that they only SHOULD be case normalized. + */ + *d++ = *s++; + *d++ = *s++; + *d++ = *s++; + } + } else { + if (!g_ascii_isgraph (*s) && + !strchr (unescape_extra, *s)) + need_fixup = TRUE; + *d++ = *s++; + } + } + *d = '\0'; + + if (need_fixup) { + GString *fixed; + + fixed = g_string_new (NULL); + s = (guchar *)normalized; + while (*s) { + if (g_ascii_isgraph (*s) || + strchr (unescape_extra, *s)) + g_string_append_c (fixed, *s); + else + g_string_append_printf (fixed, "%%%02X", (int)*s); + s++; + } + g_free (normalized); + normalized = g_string_free (fixed, FALSE); + } + + return normalized; +} + +/** + * soup_uri_normalize: + * @part: a URI part + * @unescape_extra: (allow-none): reserved characters to unescape (or %NULL) + * + * %-decodes any "unreserved" characters (or characters in + * @unescape_extra) in @part, and %-encodes any non-ASCII + * characters, spaces, and non-printing characters in @part. + * + * "Unreserved" characters are those that are not allowed to be used + * for punctuation according to the URI spec. For example, letters are + * unreserved, so soup_uri_normalize() will turn + * http://example.com/foo/b%61r into + * http://example.com/foo/bar, which is guaranteed + * to mean the same thing. However, "/" is "reserved", so + * http://example.com/foo%2Fbar would not + * be changed, because it might mean something different to the + * server. + * + * In the past, this would return %NULL if @part contained invalid + * percent-encoding, but now it just ignores the problem (as + * soup_uri_new() already did). + * + * Return value: the normalized URI part + */ +char * +soup_uri_normalize (const char *part, const char *unescape_extra) +{ + g_return_val_if_fail (part != NULL, NULL); + + return uri_normalized_copy (part, strlen (part), unescape_extra); +} + + +/** + * soup_uri_uses_default_port: + * @uri: a #SoupURI + * + * Tests if @uri uses the default port for its scheme. (Eg, 80 for + * http.) (This only works for http, https and ftp; libsoup does not know + * the default ports of other protocols.) + * + * Return value: %TRUE or %FALSE + **/ +gboolean +soup_uri_uses_default_port (SoupURI *uri) +{ + g_return_val_if_fail (uri != NULL, FALSE); + g_warn_if_fail (SOUP_URI_IS_VALID (uri)); + + return uri->port == soup_scheme_default_port (uri->scheme); +} + +/** + * soup_uri_get_scheme: + * @uri: a #SoupURI + * + * Gets @uri's scheme. + * + * Return value: @uri's scheme. + * + * Since: 2.32 + **/ +const char * +soup_uri_get_scheme (SoupURI *uri) +{ + g_return_val_if_fail (uri != NULL, NULL); + + return uri->scheme; +} + +/** + * soup_uri_set_scheme: + * @uri: a #SoupURI + * @scheme: the URI scheme + * + * Sets @uri's scheme to @scheme. This will also set @uri's port to + * the default port for @scheme, if known. + **/ +void +soup_uri_set_scheme (SoupURI *uri, const char *scheme) +{ + g_return_if_fail (uri != NULL); + g_return_if_fail (scheme != NULL); + + uri->scheme = soup_uri_parse_scheme (scheme, strlen (scheme)); + uri->port = soup_scheme_default_port (uri->scheme); +} + +/** + * soup_uri_get_user: + * @uri: a #SoupURI + * + * Gets @uri's user. + * + * Return value: @uri's user. + * + * Since: 2.32 + **/ +const char * +soup_uri_get_user (SoupURI *uri) +{ + g_return_val_if_fail (uri != NULL, NULL); + + return uri->user; +} + +/** + * soup_uri_set_user: + * @uri: a #SoupURI + * @user: (allow-none): the username, or %NULL + * + * Sets @uri's user to @user. + **/ +void +soup_uri_set_user (SoupURI *uri, const char *user) +{ + g_return_if_fail (uri != NULL); + + g_free (uri->user); + uri->user = g_strdup (user); +} + +/** + * soup_uri_get_password: + * @uri: a #SoupURI + * + * Gets @uri's password. + * + * Return value: @uri's password. + * + * Since: 2.32 + **/ +const char * +soup_uri_get_password (SoupURI *uri) +{ + g_return_val_if_fail (uri != NULL, NULL); + + return uri->password; +} + +/** + * soup_uri_set_password: + * @uri: a #SoupURI + * @password: (allow-none): the password, or %NULL + * + * Sets @uri's password to @password. + **/ +void +soup_uri_set_password (SoupURI *uri, const char *password) +{ + g_return_if_fail (uri != NULL); + + g_free (uri->password); + uri->password = g_strdup (password); +} + +/** + * soup_uri_get_host: + * @uri: a #SoupURI + * + * Gets @uri's host. + * + * Return value: @uri's host. + * + * Since: 2.32 + **/ +const char * +soup_uri_get_host (SoupURI *uri) +{ + g_return_val_if_fail (uri != NULL, NULL); + + return uri->host; +} + +/** + * soup_uri_set_host: + * @uri: a #SoupURI + * @host: (allow-none): the hostname or IP address, or %NULL + * + * Sets @uri's host to @host. + * + * If @host is an IPv6 IP address, it should not include the brackets + * required by the URI syntax; they will be added automatically when + * converting @uri to a string. + * + * http and https URIs should not have a %NULL @host. + **/ +void +soup_uri_set_host (SoupURI *uri, const char *host) +{ + g_return_if_fail (uri != NULL); + + g_free (uri->host); + uri->host = g_strdup (host); +} + +/** + * soup_uri_get_port: + * @uri: a #SoupURI + * + * Gets @uri's port. + * + * Return value: @uri's port. + * + * Since: 2.32 + **/ +guint +soup_uri_get_port (SoupURI *uri) +{ + g_return_val_if_fail (uri != NULL, 0); + + return uri->port; +} + +/** + * soup_uri_set_port: + * @uri: a #SoupURI + * @port: the port, or 0 + * + * Sets @uri's port to @port. If @port is 0, @uri will not have an + * explicitly-specified port. + **/ +void +soup_uri_set_port (SoupURI *uri, guint port) +{ + g_return_if_fail (uri != NULL); + + uri->port = port; +} + +/** + * soup_uri_get_path: + * @uri: a #SoupURI + * + * Gets @uri's path. + * + * Return value: @uri's path. + * + * Since: 2.32 + **/ +const char * +soup_uri_get_path (SoupURI *uri) +{ + g_return_val_if_fail (uri != NULL, NULL); + + return uri->path; +} + +/** + * soup_uri_set_path: + * @uri: a #SoupURI + * @path: the non-%NULL path + * + * Sets @uri's path to @path. + **/ +void +soup_uri_set_path (SoupURI *uri, const char *path) +{ + g_return_if_fail (uri != NULL); + + /* We allow a NULL path for compatibility, but warn about it. */ + if (!path) { + g_warn_if_fail (path != NULL); + path = ""; + } + + g_free (uri->path); + uri->path = g_strdup (path); +} + +/** + * soup_uri_get_query: + * @uri: a #SoupURI + * + * Gets @uri's query. + * + * Return value: @uri's query. + * + * Since: 2.32 + **/ +const char * +soup_uri_get_query (SoupURI *uri) +{ + g_return_val_if_fail (uri != NULL, NULL); + + return uri->query; +} + +/** + * soup_uri_set_query: + * @uri: a #SoupURI + * @query: (allow-none): the query + * + * Sets @uri's query to @query. + **/ +void +soup_uri_set_query (SoupURI *uri, const char *query) +{ + g_return_if_fail (uri != NULL); + + g_free (uri->query); + uri->query = g_strdup (query); +} + +/** + * soup_uri_set_query_from_form: + * @uri: a #SoupURI + * @form: (element-type utf8 utf8): a #GHashTable containing HTML form + * information + * + * Sets @uri's query to the result of encoding @form according to the + * HTML form rules. See soup_form_encode_hash() for more information. + **/ +void +soup_uri_set_query_from_form (SoupURI *uri, GHashTable *form) +{ + g_return_if_fail (uri != NULL); + + g_free (uri->query); + uri->query = soup_form_encode_hash (form); +} + +/** + * soup_uri_set_query_from_fields: + * @uri: a #SoupURI + * @first_field: name of the first form field to encode into query + * @...: value of @first_field, followed by additional field names + * and values, terminated by %NULL. + * + * Sets @uri's query to the result of encoding the given form fields + * and values according to the * HTML form rules. See + * soup_form_encode() for more information. + **/ +void +soup_uri_set_query_from_fields (SoupURI *uri, + const char *first_field, + ...) +{ + va_list args; + + g_return_if_fail (uri != NULL); + + g_free (uri->query); + va_start (args, first_field); + uri->query = soup_form_encode_valist (first_field, args); + va_end (args); +} + +/** + * soup_uri_get_fragment: + * @uri: a #SoupURI + * + * Gets @uri's fragment. + * + * Return value: @uri's fragment. + * + * Since: 2.32 + **/ +const char * +soup_uri_get_fragment (SoupURI *uri) +{ + g_return_val_if_fail (uri != NULL, NULL); + + return uri->fragment; +} + +/** + * soup_uri_set_fragment: + * @uri: a #SoupURI + * @fragment: (allow-none): the fragment + * + * Sets @uri's fragment to @fragment. + **/ +void +soup_uri_set_fragment (SoupURI *uri, const char *fragment) +{ + g_return_if_fail (uri != NULL); + + g_free (uri->fragment); + uri->fragment = g_strdup (fragment); +} + +/** + * soup_uri_copy_host: + * @uri: a #SoupURI + * + * Makes a copy of @uri, considering only the protocol, host, and port + * + * Return value: the new #SoupURI + * + * Since: 2.28 + **/ +SoupURI * +soup_uri_copy_host (SoupURI *uri) +{ + SoupURI *dup; + + g_return_val_if_fail (uri != NULL, NULL); + g_warn_if_fail (SOUP_URI_IS_VALID (uri)); + + dup = soup_uri_new (NULL); + dup->scheme = uri->scheme; + dup->host = g_strdup (uri->host); + dup->port = uri->port; + dup->path = g_strdup (""); + + return dup; +} + +/** + * soup_uri_host_hash: + * @key: (type Soup.URI): a #SoupURI with a non-%NULL @host member + * + * Hashes @key, considering only the scheme, host, and port. + * + * Return value: a hash + * + * Since: 2.28 + **/ +guint +soup_uri_host_hash (gconstpointer key) +{ + const SoupURI *uri = key; + + g_return_val_if_fail (uri != NULL && uri->host != NULL, 0); + g_warn_if_fail (SOUP_URI_IS_VALID (uri)); + + return GPOINTER_TO_UINT (uri->scheme) + uri->port + + soup_str_case_hash (uri->host); +} + +/** + * soup_uri_host_equal: + * @v1: (type Soup.URI): a #SoupURI with a non-%NULL @host member + * @v2: (type Soup.URI): a #SoupURI with a non-%NULL @host member + * + * Compares @v1 and @v2, considering only the scheme, host, and port. + * + * Return value: whether or not the URIs are equal in scheme, host, + * and port. + * + * Since: 2.28 + **/ +gboolean +soup_uri_host_equal (gconstpointer v1, gconstpointer v2) +{ + const SoupURI *one = v1; + const SoupURI *two = v2; + + g_return_val_if_fail (one != NULL && two != NULL, one == two); + g_return_val_if_fail (one->host != NULL && two->host != NULL, one->host == two->host); + g_warn_if_fail (SOUP_URI_IS_VALID (one)); + g_warn_if_fail (SOUP_URI_IS_VALID (two)); + + if (one->scheme != two->scheme) + return FALSE; + if (one->port != two->port) + return FALSE; + + return g_ascii_strcasecmp (one->host, two->host) == 0; +} + +gboolean +soup_uri_is_http (SoupURI *uri, char **aliases) +{ + int i; + + if (uri->scheme == SOUP_URI_SCHEME_HTTP || + uri->scheme == SOUP_URI_SCHEME_WS) + return TRUE; + else if (uri->scheme == SOUP_URI_SCHEME_HTTPS || + uri->scheme == SOUP_URI_SCHEME_WSS) + return FALSE; + else if (!aliases) + return FALSE; + + for (i = 0; aliases[i]; i++) { + if (uri->scheme == aliases[i]) + return TRUE; + } + + if (aliases[0] && !aliases[1] && !strcmp (aliases[0], "*")) + return TRUE; + else + return FALSE; +} + +gboolean +soup_uri_is_https (SoupURI *uri, char **aliases) +{ + int i; + + if (uri->scheme == SOUP_URI_SCHEME_HTTPS || + uri->scheme == SOUP_URI_SCHEME_WSS) + return TRUE; + else if (uri->scheme == SOUP_URI_SCHEME_HTTP || + uri->scheme == SOUP_URI_SCHEME_WS) + return FALSE; + else if (!aliases) + return FALSE; + + for (i = 0; aliases[i]; i++) { + if (uri->scheme == aliases[i]) + return TRUE; + } + + return FALSE; +} + +G_DEFINE_BOXED_TYPE (SoupURI, soup_uri, soup_uri_copy, soup_uri_free) diff --git a/libsoup/soup-uri.h b/libsoup/soup-uri.h new file mode 100644 index 0000000..b9360c6 --- /dev/null +++ b/libsoup/soup-uri.h @@ -0,0 +1,142 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ + +/* + * Copyright 1999-2002 Ximian, Inc. + */ + + +#ifndef SOUP_URI_H +#define SOUP_URI_H 1 + +#include +#include + +G_BEGIN_DECLS + +struct _SoupURI { + const char *scheme; + + char *user; + char *password; + + char *host; + guint port; + + char *path; + char *query; + + char *fragment; +}; + +SOUP_AVAILABLE_IN_2_4 +GType soup_uri_get_type (void); +#define SOUP_TYPE_URI (soup_uri_get_type ()) + +#define SOUP_URI_SCHEME_HTTP _SOUP_ATOMIC_INTERN_STRING (_SOUP_URI_SCHEME_HTTP, "http") +#define SOUP_URI_SCHEME_HTTPS _SOUP_ATOMIC_INTERN_STRING (_SOUP_URI_SCHEME_HTTPS, "https") +#define SOUP_URI_SCHEME_FTP _SOUP_ATOMIC_INTERN_STRING (_SOUP_URI_SCHEME_FTP, "ftp") +#define SOUP_URI_SCHEME_FILE _SOUP_ATOMIC_INTERN_STRING (_SOUP_URI_SCHEME_FILE, "file") +#define SOUP_URI_SCHEME_DATA _SOUP_ATOMIC_INTERN_STRING (_SOUP_URI_SCHEME_DATA, "data") +#define SOUP_URI_SCHEME_RESOURCE _SOUP_ATOMIC_INTERN_STRING (_SOUP_URI_SCHEME_RESOURCE, "resource") +#define SOUP_URI_SCHEME_WS _SOUP_ATOMIC_INTERN_STRING (_SOUP_URI_SCHEME_WS, "ws") +#define SOUP_URI_SCHEME_WSS _SOUP_ATOMIC_INTERN_STRING (_SOUP_URI_SCHEME_WSS, "wss") + +SOUP_VAR gpointer _SOUP_URI_SCHEME_HTTP, _SOUP_URI_SCHEME_HTTPS; +SOUP_VAR gpointer _SOUP_URI_SCHEME_FTP; +SOUP_VAR gpointer _SOUP_URI_SCHEME_FILE, _SOUP_URI_SCHEME_DATA, _SOUP_URI_SCHEME_RESOURCE; +SOUP_VAR gpointer _SOUP_URI_SCHEME_WS, _SOUP_URI_SCHEME_WSS; + +SOUP_AVAILABLE_IN_2_4 +SoupURI *soup_uri_new_with_base (SoupURI *base, + const char *uri_string); +SOUP_AVAILABLE_IN_2_4 +SoupURI *soup_uri_new (const char *uri_string); + +SOUP_AVAILABLE_IN_2_4 +char *soup_uri_to_string (SoupURI *uri, + gboolean just_path_and_query); + +SOUP_AVAILABLE_IN_2_4 +SoupURI *soup_uri_copy (SoupURI *uri); + +SOUP_AVAILABLE_IN_2_4 +gboolean soup_uri_equal (SoupURI *uri1, + SoupURI *uri2); + +SOUP_AVAILABLE_IN_2_4 +void soup_uri_free (SoupURI *uri); + +SOUP_AVAILABLE_IN_2_4 +char *soup_uri_encode (const char *part, + const char *escape_extra); +SOUP_AVAILABLE_IN_2_4 +char *soup_uri_decode (const char *part); +SOUP_AVAILABLE_IN_2_4 +char *soup_uri_normalize (const char *part, + const char *unescape_extra); + +SOUP_AVAILABLE_IN_2_4 +gboolean soup_uri_uses_default_port (SoupURI *uri); + +SOUP_AVAILABLE_IN_2_32 +const char *soup_uri_get_scheme (SoupURI *uri); +SOUP_AVAILABLE_IN_2_4 +void soup_uri_set_scheme (SoupURI *uri, + const char *scheme); +SOUP_AVAILABLE_IN_2_32 +const char *soup_uri_get_user (SoupURI *uri); +SOUP_AVAILABLE_IN_2_4 +void soup_uri_set_user (SoupURI *uri, + const char *user); +SOUP_AVAILABLE_IN_2_32 +const char *soup_uri_get_password (SoupURI *uri); +SOUP_AVAILABLE_IN_2_4 +void soup_uri_set_password (SoupURI *uri, + const char *password); +SOUP_AVAILABLE_IN_2_32 +const char *soup_uri_get_host (SoupURI *uri); +SOUP_AVAILABLE_IN_2_4 +void soup_uri_set_host (SoupURI *uri, + const char *host); +SOUP_AVAILABLE_IN_2_32 +guint soup_uri_get_port (SoupURI *uri); +SOUP_AVAILABLE_IN_2_4 +void soup_uri_set_port (SoupURI *uri, + guint port); +SOUP_AVAILABLE_IN_2_32 +const char *soup_uri_get_path (SoupURI *uri); +SOUP_AVAILABLE_IN_2_4 +void soup_uri_set_path (SoupURI *uri, + const char *path); +SOUP_AVAILABLE_IN_2_32 +const char *soup_uri_get_query (SoupURI *uri); +SOUP_AVAILABLE_IN_2_4 +void soup_uri_set_query (SoupURI *uri, + const char *query); +SOUP_AVAILABLE_IN_2_4 +void soup_uri_set_query_from_form (SoupURI *uri, + GHashTable *form); +SOUP_AVAILABLE_IN_2_4 +void soup_uri_set_query_from_fields (SoupURI *uri, + const char *first_field, + ...) G_GNUC_NULL_TERMINATED; +SOUP_AVAILABLE_IN_2_32 +const char *soup_uri_get_fragment (SoupURI *uri); +SOUP_AVAILABLE_IN_2_4 +void soup_uri_set_fragment (SoupURI *uri, + const char *fragment); + +SOUP_AVAILABLE_IN_2_28 +SoupURI *soup_uri_copy_host (SoupURI *uri); +SOUP_AVAILABLE_IN_2_28 +guint soup_uri_host_hash (gconstpointer key); +SOUP_AVAILABLE_IN_2_28 +gboolean soup_uri_host_equal (gconstpointer v1, + gconstpointer v2); + +#define SOUP_URI_IS_VALID(uri) ((uri) && (uri)->scheme && (uri)->path) +#define SOUP_URI_VALID_FOR_HTTP(uri) ((uri) && ((uri)->scheme == SOUP_URI_SCHEME_HTTP || (uri)->scheme == SOUP_URI_SCHEME_HTTPS) && (uri)->host && (uri)->path) + +G_END_DECLS + +#endif /*SOUP_URI_H*/ diff --git a/libsoup/soup-value-utils.c b/libsoup/soup-value-utils.c new file mode 100644 index 0000000..014eb5b --- /dev/null +++ b/libsoup/soup-value-utils.c @@ -0,0 +1,529 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-type-utils.c: GValue and GType-related utilities + * + * Copyright (C) 2007 Red Hat, Inc. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "soup-value-utils.h" + +/** + * SECTION:soup-value-utils + * @short_description: GValue utilities + * + * These methods are useful for manipulating #GValues, and in + * particular, arrays and hash tables of #GValues, in a + * slightly nicer way than the standard #GValue API. + * + * They are written for use with soup-xmlrpc, but they also work with + * types not used by XML-RPC. + * + * Deprecated: Use #GVariant API instead. + **/ + +/** + * SOUP_VALUE_SETV: + * @val: a #GValue + * @type: a #GType + * @args: #va_list pointing to a value of type @type + * + * Copies an argument of type @type from @args into @val. @val will + * point directly to the value in @args rather than copying it, so you + * must g_value_copy() it if you want it to remain valid. + * + * Deprecated: Use #GVariant API instead. + **/ + +/** + * SOUP_VALUE_GETV: + * @val: a #GValue + * @type: a #GType + * @args: #va_list pointing to a value of type pointer-to-@type + * + * Extracts a value of type @type from @val into @args. The return + * value will point to the same data as @val rather than being a copy + * of it. + * + * Deprecated: Use #GVariant API instead. + **/ + +/* This whole file is deprecated and replaced by GVariant API */ +G_GNUC_BEGIN_IGNORE_DEPRECATIONS + +static void +soup_value_hash_value_free (gpointer val) +{ + g_value_unset (val); + g_free (val); +} + +/** + * soup_value_hash_new: + * + * Creates a #GHashTable whose keys are strings and whose values + * are #GValue. + * + * Return value: (element-type utf8 GValue) (transfer full): a new + * empty #GHashTable + * + * Deprecated: Use #GVariant API instead. + **/ +GHashTable * +soup_value_hash_new (void) +{ + return g_hash_table_new_full (g_str_hash, g_str_equal, + g_free, soup_value_hash_value_free); +} + +static void +soup_value_hash_insert_valist (GHashTable *hash, const char *first_key, + va_list args) +{ + const char *key; + GType type; + GValue value; + + key = first_key; + while (key) { + type = va_arg (args, GType); + SOUP_VALUE_SETV (&value, type, args); + + soup_value_hash_insert_value (hash, key, &value); + key = va_arg (args, const char *); + } +} + +/** + * soup_value_hash_new_with_vals: + * @first_key: the key for the first value + * @...: the type of @first_key, followed by the value, followed + * by additional key/type/value triplets, terminated by %NULL + * + * Creates a #GHashTable whose keys are strings and whose values + * are #GValue, and initializes it with the provided data. As + * with soup_value_hash_insert(), the keys and values are copied + * rather than being inserted directly. + * + * Return value: (element-type utf8 GValue) (transfer full): a new + * #GHashTable, initialized with the given values + * + * Deprecated: Use #GVariant API instead. + **/ +GHashTable * +soup_value_hash_new_with_vals (const char *first_key, ...) +{ + GHashTable *hash = soup_value_hash_new (); + va_list args; + + va_start (args, first_key); + soup_value_hash_insert_valist (hash, first_key, args); + va_end (args); + + return hash; +} + +/** + * soup_value_hash_insert_value: + * @hash: (element-type utf8 GValue): a value hash + * @key: the key + * @value: a value + * + * Inserts @value into @hash. (Unlike with g_hash_table_insert(), both + * the key and the value are copied). + * + * Deprecated: Use #GVariant API instead. + **/ +void +soup_value_hash_insert_value (GHashTable *hash, const char *key, GValue *value) +{ + GValue *copy = g_new0 (GValue, 1); + + g_value_init (copy, G_VALUE_TYPE (value)); + g_value_copy (value, copy); + g_hash_table_insert (hash, g_strdup (key), copy); +} + +/** + * soup_value_hash_insert: + * @hash: (element-type utf8 GValue): a value hash + * @key: the key + * @type: a #GType + * @...: a value of type @type + * + * Inserts the provided value of type @type into @hash. (Unlike with + * g_hash_table_insert(), both the key and the value are copied). + * + * Deprecated: Use #GVariant API instead. + **/ +void +soup_value_hash_insert (GHashTable *hash, const char *key, GType type, ...) +{ + va_list args; + GValue val; + + va_start (args, type); + SOUP_VALUE_SETV (&val, type, args); + va_end (args); + soup_value_hash_insert_value (hash, key, &val); +} + +/** + * soup_value_hash_insert_vals: + * @hash: (element-type utf8 GValue): a value hash + * @first_key: the key for the first value + * @...: the type of @first_key, followed by the value, followed + * by additional key/type/value triplets, terminated by %NULL + * + * Inserts the given data into @hash. As with + * soup_value_hash_insert(), the keys and values are copied rather + * than being inserted directly. + * + * Deprecated: Use #GVariant API instead. + **/ +void +soup_value_hash_insert_vals (GHashTable *hash, const char *first_key, ...) +{ + va_list args; + + va_start (args, first_key); + soup_value_hash_insert_valist (hash, first_key, args); + va_end (args); +} + +/** + * soup_value_hash_lookup: + * @hash: (element-type utf8 GValue): a value hash + * @key: the key to look up + * @type: a #GType + * @...: a value of type pointer-to-@type + * + * Looks up @key in @hash and stores its value into the provided + * location. + * + * Return value: %TRUE if @hash contained a value with key @key and + * type @type, %FALSE if not. + * + * Deprecated: Use #GVariant API instead. + **/ +gboolean +soup_value_hash_lookup (GHashTable *hash, const char *key, GType type, ...) +{ + va_list args; + GValue *value; + + value = g_hash_table_lookup (hash, key); + if (!value || !G_VALUE_HOLDS (value, type)) + return FALSE; + + va_start (args, type); + SOUP_VALUE_GETV (value, type, args); + va_end (args); + + return TRUE; +} + +/** + * soup_value_hash_lookup_vals: + * @hash: (element-type utf8 GValue): a value hash + * @first_key: the first key to look up + * @...: the type of @first_key, a pointer to that type, and + * then additional key/type/pointer triplets, terminated + * by %NULL. + * + * Looks up a number of keys in @hash and returns their values. + * + * Return value: %TRUE if all of the keys were found, %FALSE + * if any were missing; note that you will generally need to + * initialize each destination variable to a reasonable default + * value, since there is no way to tell which keys were found + * and which were not. + * + * Deprecated: Use #GVariant API instead. + **/ +gboolean +soup_value_hash_lookup_vals (GHashTable *hash, const char *first_key, ...) +{ + va_list args; + GValue *value; + const char *key; + GType type; + gboolean found_all = TRUE; + + va_start (args, first_key); + key = first_key; + while (key) { + type = va_arg (args, GType); + + value = g_hash_table_lookup (hash, key); + if (!value || !G_VALUE_HOLDS (value, type)) { + found_all = FALSE; + /* skip a pointer */ + va_arg (args, gpointer); + } else + SOUP_VALUE_GETV (value, type, args); + + key = va_arg (args, const char *); + } + va_end (args); + + return found_all; +} + + +/** + * soup_value_array_from_args: + * @args: arguments to create a #GValueArray from + * + * Creates a #GValueArray from the provided arguments, which must + * consist of pairs of a #GType and a value of that type, terminated + * by %G_TYPE_INVALID. (The array will contain copies of the provided + * data rather than pointing to the passed-in data directly.) + * + * Return value: (nullable): a new #GValueArray, or %NULL if an error + * occurred. + * + * Deprecated: Use #GVariant API instead. + **/ +GValueArray * +soup_value_array_from_args (va_list args) +{ + GValueArray *array; + GType type; + GValue val; + + array = g_value_array_new (1); + while ((type = va_arg (args, GType)) != G_TYPE_INVALID) { + SOUP_VALUE_SETV (&val, type, args); + g_value_array_append (array, &val); + } + return array; +} + +/** + * soup_value_array_to_args: + * @array: a #GValueArray + * @args: arguments to extract @array into + * + * Extracts a #GValueArray into the provided arguments, which must + * consist of pairs of a #GType and a value of pointer-to-that-type, + * terminated by %G_TYPE_INVALID. The returned values will point to the + * same memory as the values in the array. + * + * Return value: success or failure + * + * Deprecated: Use #GVariant API instead. + **/ +gboolean +soup_value_array_to_args (GValueArray *array, va_list args) +{ + GType type; + GValue *value; + guint i; + + for (i = 0; i < array->n_values; i++) { + type = va_arg (args, GType); + if (type == G_TYPE_INVALID) + return FALSE; + value = g_value_array_get_nth (array, i); + if (!G_VALUE_HOLDS (value, type)) + return FALSE; + SOUP_VALUE_GETV (value, type, args); + } + return TRUE; +} + +/** + * soup_value_array_new: + * + * Creates a new %GValueArray. (This is just a wrapper around + * g_value_array_new(), for naming consistency purposes.) + * + * Return value: a new %GValueArray + * + * Deprecated: Use #GVariant API instead. + **/ +GValueArray * +soup_value_array_new (void) +{ + return g_value_array_new (1); +} + +static void +soup_value_array_append_valist (GValueArray *array, + GType first_type, va_list args) +{ + GType type; + GValue value; + + type = first_type; + while (type != G_TYPE_INVALID) { + SOUP_VALUE_SETV (&value, type, args); + + g_value_array_append (array, &value); + type = va_arg (args, GType); + } +} + +/** + * soup_value_array_new_with_vals: + * @first_type: the type of the first value to add + * @...: the first value to add, followed by other type/value + * pairs, terminated by %G_TYPE_INVALID + * + * Creates a new %GValueArray and copies the provided values + * into it. + * + * Return value: a new %GValueArray + * + * Deprecated: Use #GVariant API instead. + **/ +GValueArray * +soup_value_array_new_with_vals (GType first_type, ...) +{ + GValueArray *array = soup_value_array_new (); + va_list args; + + va_start (args, first_type); + soup_value_array_append_valist (array, first_type, args); + va_end (args); + + return array; +} + +/** + * soup_value_array_insert: + * @array: a #GValueArray + * @index_: the index to insert at + * @type: a #GType + * @...: a value of type @type + * + * Inserts the provided value of type @type into @array as with + * g_value_array_insert(). (The provided data is copied rather than + * being inserted directly.) + * + * Deprecated: Use #GVariant API instead. + **/ +void +soup_value_array_insert (GValueArray *array, guint index_, GType type, ...) +{ + va_list args; + GValue val; + + va_start (args, type); + SOUP_VALUE_SETV (&val, type, args); + va_end (args); + g_value_array_insert (array, index_, &val); +} + +/** + * soup_value_array_append: + * @array: a #GValueArray + * @type: a #GType + * @...: a value of type @type + * + * Appends the provided value of type @type to @array as with + * g_value_array_append(). (The provided data is copied rather than + * being inserted directly.) + * + * Deprecated: Use #GVariant API instead. + **/ +void +soup_value_array_append (GValueArray *array, GType type, ...) +{ + va_list args; + GValue val; + + va_start (args, type); + SOUP_VALUE_SETV (&val, type, args); + va_end (args); + g_value_array_append (array, &val); +} + +/** + * soup_value_array_append_vals: + * @array: a #GValueArray + * @first_type: the type of the first value to add + * @...: the first value to add, followed by other type/value + * pairs, terminated by %G_TYPE_INVALID + * + * Appends the provided values into @array as with + * g_value_array_append(). (The provided data is copied rather than + * being inserted directly.) + * + * Deprecated: Use #GVariant API instead. + **/ +void +soup_value_array_append_vals (GValueArray *array, GType first_type, ...) +{ + va_list args; + + va_start (args, first_type); + soup_value_array_append_valist (array, first_type, args); + va_end (args); +} + +/** + * soup_value_array_get_nth: + * @array: a #GValueArray + * @index_: the index to look up + * @type: a #GType + * @...: a value of type pointer-to-@type + * + * Gets the @index_ element of @array and stores its value into the + * provided location. + * + * Return value: %TRUE if @array contained a value with index @index_ + * and type @type, %FALSE if not. + * + * Deprecated: Use #GVariant API instead. + **/ +gboolean +soup_value_array_get_nth (GValueArray *array, guint index_, GType type, ...) +{ + GValue *value; + va_list args; + + value = g_value_array_get_nth (array, index_); + if (!value || !G_VALUE_HOLDS (value, type)) + return FALSE; + + va_start (args, type); + SOUP_VALUE_GETV (value, type, args); + va_end (args); + return TRUE; +} + +static GByteArray * +soup_byte_array_copy (GByteArray *ba) +{ + GByteArray *copy; + + copy = g_byte_array_sized_new (ba->len); + g_byte_array_append (copy, ba->data, ba->len); + return copy; +} + +static void +soup_byte_array_free (GByteArray *ba) +{ + g_byte_array_free (ba, TRUE); +} + +/** + * SOUP_TYPE_BYTE_ARRAY: + * + * glib did not used to define a #GType for #GByteArray, so libsoup + * defines this one itself. + * + * Deprecated: Use #GVariant API instead. + **/ +typedef GByteArray SoupByteArray; +G_DEFINE_BOXED_TYPE (SoupByteArray, soup_byte_array, soup_byte_array_copy, soup_byte_array_free) + +G_GNUC_END_IGNORE_DEPRECATIONS diff --git a/libsoup/soup-value-utils.h b/libsoup/soup-value-utils.h new file mode 100644 index 0000000..7910bef --- /dev/null +++ b/libsoup/soup-value-utils.h @@ -0,0 +1,114 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2007 Red Hat, Inc. + */ + +#ifndef SOUP_VALUE_UTILS_H +#define SOUP_VALUE_UTILS_H 1 + +#include +#include + +G_BEGIN_DECLS + +#define SOUP_VALUE_SETV(val, type, args) \ +G_STMT_START { \ + char *setv_error = NULL; \ + \ + memset (val, 0, sizeof (GValue)); \ + g_value_init (val, type); \ + G_VALUE_COLLECT (val, args, G_VALUE_NOCOPY_CONTENTS, &setv_error); \ + g_free (setv_error); \ +} G_STMT_END + +#define SOUP_VALUE_GETV(val, type, args) \ +G_STMT_START { \ + char *getv_error = NULL; \ + \ + G_VALUE_LCOPY (val, args, G_VALUE_NOCOPY_CONTENTS, &getv_error); \ + g_free (getv_error); \ +} G_STMT_END + +SOUP_AVAILABLE_IN_2_4 +SOUP_DEPRECATED_IN_2_52 +GHashTable *soup_value_hash_new (void); +SOUP_AVAILABLE_IN_2_4 +SOUP_DEPRECATED_IN_2_52 +GHashTable *soup_value_hash_new_with_vals (const char *first_key, + ...) G_GNUC_NULL_TERMINATED; +SOUP_AVAILABLE_IN_2_4 +SOUP_DEPRECATED_IN_2_52 +void soup_value_hash_insert_value (GHashTable *hash, + const char *key, + GValue *value); +SOUP_AVAILABLE_IN_2_4 +SOUP_DEPRECATED_IN_2_52 +void soup_value_hash_insert (GHashTable *hash, + const char *key, + GType type, + ...); +SOUP_AVAILABLE_IN_2_4 +SOUP_DEPRECATED_IN_2_52 +void soup_value_hash_insert_vals (GHashTable *hash, + const char *first_key, + ...) G_GNUC_NULL_TERMINATED; +SOUP_AVAILABLE_IN_2_4 +SOUP_DEPRECATED_IN_2_52 +gboolean soup_value_hash_lookup (GHashTable *hash, + const char *key, + GType type, + ...); +SOUP_AVAILABLE_IN_2_4 +SOUP_DEPRECATED_IN_2_52 +gboolean soup_value_hash_lookup_vals (GHashTable *hash, + const char *first_key, + ...) G_GNUC_NULL_TERMINATED; + +SOUP_AVAILABLE_IN_2_4 +SOUP_DEPRECATED_IN_2_52 +GValueArray *soup_value_array_from_args (va_list args); +SOUP_AVAILABLE_IN_2_4 +SOUP_DEPRECATED_IN_2_52 +gboolean soup_value_array_to_args (GValueArray *array, + va_list args); + +SOUP_AVAILABLE_IN_2_4 +SOUP_DEPRECATED_IN_2_52 +GValueArray *soup_value_array_new (void); +SOUP_AVAILABLE_IN_2_4 +SOUP_DEPRECATED_IN_2_52 +GValueArray *soup_value_array_new_with_vals (GType first_type, + ...) G_GNUC_NULL_TERMINATED; + +SOUP_AVAILABLE_IN_2_4 +SOUP_DEPRECATED_IN_2_52 +void soup_value_array_insert (GValueArray *array, + guint index_, + GType type, + ...); +SOUP_AVAILABLE_IN_2_4 +SOUP_DEPRECATED_IN_2_52 +void soup_value_array_append (GValueArray *array, + GType type, + ...); +SOUP_AVAILABLE_IN_2_4 +SOUP_DEPRECATED_IN_2_52 +void soup_value_array_append_vals (GValueArray *array, + GType first_type, + ...) G_GNUC_NULL_TERMINATED; +SOUP_AVAILABLE_IN_2_4 +SOUP_DEPRECATED_IN_2_52 +gboolean soup_value_array_get_nth (GValueArray *array, + guint index_, + GType type, + ...); + + +SOUP_AVAILABLE_IN_2_4 +SOUP_DEPRECATED_IN_2_52 +GType soup_byte_array_get_type (void); +#define SOUP_TYPE_BYTE_ARRAY (soup_byte_array_get_type ()) + +G_END_DECLS + +#endif /* SOUP_VALUE_UTILS_H */ diff --git a/libsoup/soup-version.c b/libsoup/soup-version.c new file mode 100644 index 0000000..99c3b53 --- /dev/null +++ b/libsoup/soup-version.c @@ -0,0 +1,337 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-version.c: Version information + * + * Copyright (C) 2012 Igalia S.L. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "soup-version.h" + +/** + * SECTION:soup-version + * @short_description: Variables and functions to check the libsoup version + **/ + +/** + * SOUP_MAJOR_VERSION: + * + * Like soup_get_major_version(), but from the headers used at + * application compile time, rather than from the library linked + * against at application run time. + * + * Since: 2.42 + */ + +/** + * SOUP_MINOR_VERSION: + * + * Like soup_get_minor_version(), but from the headers used at + * application compile time, rather than from the library linked + * against at application run time. + * + * Since: 2.42 + */ + +/** + * SOUP_MICRO_VERSION: + * + * Like soup_get_micro_version(), but from the headers used at + * application compile time, rather than from the library linked + * against at application run time. + * + * Since: 2.42 + */ + +/** + * SOUP_CHECK_VERSION: + * @major: major version (e.g. 2 for version 2.42.0) + * @minor: minor version (e.g. 42 for version 2.42.0) + * @micro: micro version (e.g. 0 for version 2.42.0) + * + * Macro to test the version of libsoup being compiled against. + * + * Returns: %TRUE if the version of the libsoup header files + * is the same as or newer than the passed-in version. + * + * Since: 2.42 + */ + +/** + * soup_get_major_version: + * + * Returns the major version number of the libsoup library. + * (e.g. in libsoup version 2.42.0 this is 2.) + * + * This function is in the library, so it represents the libsoup library + * your code is running against. Contrast with the #SOUP_MAJOR_VERSION + * macro, which represents the major version of the libsoup headers you + * have included when compiling your code. + * + * Returns: the major version number of the libsoup library + * + * Since: 2.42 + */ +guint +soup_get_major_version (void) +{ + return SOUP_MAJOR_VERSION; +} + +/** + * soup_get_minor_version: + * + * Returns the minor version number of the libsoup library. + * (e.g. in libsoup version 2.42.0 this is 42.) + * + * This function is in the library, so it represents the libsoup library + * your code is running against. Contrast with the #SOUP_MINOR_VERSION + * macro, which represents the minor version of the libsoup headers you + * have included when compiling your code. + * + * Returns: the minor version number of the libsoup library + * + * Since: 2.42 + */ +guint +soup_get_minor_version (void) +{ + return SOUP_MINOR_VERSION; +} + +/** + * soup_get_micro_version: + * + * Returns the micro version number of the libsoup library. + * (e.g. in libsoup version 2.42.0 this is 0.) + * + * This function is in the library, so it represents the libsoup library + * your code is running against. Contrast with the #SOUP_MICRO_VERSION + * macro, which represents the micro version of the libsoup headers you + * have included when compiling your code. + * + * Returns: the micro version number of the libsoup library + * + * Since: 2.42 + */ +guint +soup_get_micro_version (void) +{ + return SOUP_MICRO_VERSION; +} + +/** + * soup_check_version: + * @major: the major version to check + * @minor: the minor version to check + * @micro: the micro version to check + * + * Like SOUP_CHECK_VERSION, but the check for soup_check_version is + * at runtime instead of compile time. This is useful for compiling + * against older versions of libsoup, but using features from newer + * versions. + * + * Returns: %TRUE if the version of the libsoup currently loaded + * is the same as or newer than the passed-in version. + * + * Since: 2.42 + */ +gboolean +soup_check_version (guint major, + guint minor, + guint micro) +{ + return SOUP_CHECK_VERSION (major, minor, micro); +} + +/** + * SOUP_VERSION_MIN_REQUIRED: + * + * A macro that should be defined by the user prior to including + * libsoup.h. The definition should be one of the predefined libsoup + * version macros: %SOUP_VERSION_2_24, %SOUP_VERSION_2_26, ... + * + * This macro defines the earliest version of libsoup that the package + * is required to be able to compile against. + * + * If the compiler is configured to warn about the use of deprecated + * functions, then using functions that were deprecated in version + * %SOUP_VERSION_MIN_REQUIRED or earlier will cause warnings (but + * using functions deprecated in later releases will not). + * + * Since: 2.42 + */ + +/** + * SOUP_VERSION_MAX_ALLOWED: + * + * A macro that should be defined by the user prior to including + * libsoup.h. The definition should be one of the predefined libsoup + * version macros: %SOUP_VERSION_2_24, %SOUP_VERSION_2_26, ... + * + * This macro defines the latest version of the libsoup API that the + * package is allowed to make use of. + * + * If the compiler is configured to warn about the use of deprecated + * functions, then using functions added after version + * %SOUP_VERSION_MAX_ALLOWED will cause warnings. + * + * Unless you are using SOUP_CHECK_VERSION() or the like to compile + * different code depending on the libsoup version, then this should be + * set to the same value as %SOUP_VERSION_MIN_REQUIRED. + * + * Since: 2.42 + */ + +/** + * SOUP_VERSION_2_24: + * + * A macro that evaluates to the 2.24 version of libsoup, in a format + * that can be used by %SOUP_VERSION_MIN_REQUIRED and + * %SOUP_VERSION_MAX_ALLOWED. + * + * Since: 2.42 + */ + +/** + * SOUP_VERSION_2_26: + * + * A macro that evaluates to the 2.26 version of libsoup, in a format + * that can be used by %SOUP_VERSION_MIN_REQUIRED and + * %SOUP_VERSION_MAX_ALLOWED. + * + * Since: 2.42 + */ + +/** + * SOUP_VERSION_2_28: + * + * A macro that evaluates to the 2.28 version of libsoup, in a format + * that can be used by %SOUP_VERSION_MIN_REQUIRED and + * %SOUP_VERSION_MAX_ALLOWED. + * + * Since: 2.42 + */ + +/** + * SOUP_VERSION_2_30: + * + * A macro that evaluates to the 2.30 version of libsoup, in a format + * that can be used by %SOUP_VERSION_MIN_REQUIRED and + * %SOUP_VERSION_MAX_ALLOWED. + * + * Since: 2.42 + */ + +/** + * SOUP_VERSION_2_32: + * + * A macro that evaluates to the 2.32 version of libsoup, in a format + * that can be used by %SOUP_VERSION_MIN_REQUIRED and + * %SOUP_VERSION_MAX_ALLOWED. + * + * Since: 2.42 + */ + +/** + * SOUP_VERSION_2_34: + * + * A macro that evaluates to the 2.34 version of libsoup, in a format + * that can be used by %SOUP_VERSION_MIN_REQUIRED and + * %SOUP_VERSION_MAX_ALLOWED. + * + * Since: 2.42 + */ + +/** + * SOUP_VERSION_2_36: + * + * A macro that evaluates to the 2.36 version of libsoup, in a format + * that can be used by %SOUP_VERSION_MIN_REQUIRED and + * %SOUP_VERSION_MAX_ALLOWED. + * + * Since: 2.42 + */ + +/** + * SOUP_VERSION_2_38: + * + * A macro that evaluates to the 2.38 version of libsoup, in a format + * that can be used by %SOUP_VERSION_MIN_REQUIRED and + * %SOUP_VERSION_MAX_ALLOWED. + * + * Since: 2.42 + */ + +/** + * SOUP_VERSION_2_40: + * + * A macro that evaluates to the 2.40 version of libsoup, in a format + * that can be used by %SOUP_VERSION_MIN_REQUIRED and + * %SOUP_VERSION_MAX_ALLOWED. + * + * Since: 2.42 + */ + +/** + * SOUP_VERSION_2_42: + * + * A macro that evaluates to the 2.42 version of libsoup, in a format + * that can be used by %SOUP_VERSION_MIN_REQUIRED and + * %SOUP_VERSION_MAX_ALLOWED. + * + * Since: 2.42 + */ + +/** + * SOUP_VERSION_2_44: + * + * A macro that evaluates to the 2.44 version of libsoup, in a format + * that can be used by %SOUP_VERSION_MIN_REQUIRED and + * %SOUP_VERSION_MAX_ALLOWED. + * + * Since: 2.44 + */ + +/** + * SOUP_VERSION_2_46: + * + * A macro that evaluates to the 2.46 version of libsoup, in a format + * that can be used by %SOUP_VERSION_MIN_REQUIRED and + * %SOUP_VERSION_MAX_ALLOWED. + * + * Since: 2.46 + */ + +/** + * SOUP_VERSION_2_48: + * + * A macro that evaluates to the 2.48 version of libsoup, in a format + * that can be used by %SOUP_VERSION_MIN_REQUIRED and + * %SOUP_VERSION_MAX_ALLOWED. + * + * Since: 2.48 + */ + +/** + * SOUP_VERSION_2_50: + * + * A macro that evaluates to the 2.50 version of libsoup, in a format + * that can be used by %SOUP_VERSION_MIN_REQUIRED and + * %SOUP_VERSION_MAX_ALLOWED. + * + * Since: 2.50 + */ + +/** + * SOUP_VERSION_2_52: + * + * A macro that evaluates to the 2.52 version of libsoup, in a format + * that can be used by %SOUP_VERSION_MIN_REQUIRED and + * %SOUP_VERSION_MAX_ALLOWED. + * + * Since: 2.52 + */ diff --git a/libsoup/soup-version.h.in b/libsoup/soup-version.h.in new file mode 100644 index 0000000..0af245b --- /dev/null +++ b/libsoup/soup-version.h.in @@ -0,0 +1,393 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-version.h: Version information + * + * Copyright (C) 2012 Igalia S.L. + */ + +#ifndef SOUP_VERSION_H +#define SOUP_VERSION_H + +#include + +G_BEGIN_DECLS + +#define SOUP_MAJOR_VERSION (@SOUP_MAJOR_VERSION@) +#define SOUP_MINOR_VERSION (@SOUP_MINOR_VERSION@) +#define SOUP_MICRO_VERSION (@SOUP_MICRO_VERSION@) + +#define SOUP_CHECK_VERSION(major, minor, micro) \ + (SOUP_MAJOR_VERSION > (major) || \ + (SOUP_MAJOR_VERSION == (major) && SOUP_MINOR_VERSION > (minor)) || \ + (SOUP_MAJOR_VERSION == (major) && SOUP_MINOR_VERSION == (minor) && \ + SOUP_MICRO_VERSION >= (micro))) + +#ifndef _SOUP_EXTERN +#define _SOUP_EXTERN extern +#endif + +/* We prefix variable declarations so they can + * properly get exported in Windows DLLs. + */ +#ifndef SOUP_VAR +# ifdef G_PLATFORM_WIN32 +# ifdef LIBSOUP_COMPILATION +# ifdef DLL_EXPORT +# define SOUP_VAR __declspec(dllexport) +# else /* !DLL_EXPORT */ +# define SOUP_VAR extern +# endif /* !DLL_EXPORT */ +# else /* !SOUP_COMPILATION */ +# define SOUP_VAR extern __declspec(dllimport) +# endif /* !LIBSOUP_COMPILATION */ +# else /* !G_PLATFORM_WIN32 */ +# define SOUP_VAR _SOUP_EXTERN +# endif /* !G_PLATFORM_WIN32 */ +#endif /* SOUP_VAR */ + +/* Deprecation / Availability macros */ + +#define SOUP_VERSION_2_24 (G_ENCODE_VERSION (2, 24)) +#define SOUP_VERSION_2_26 (G_ENCODE_VERSION (2, 26)) +#define SOUP_VERSION_2_28 (G_ENCODE_VERSION (2, 28)) +#define SOUP_VERSION_2_30 (G_ENCODE_VERSION (2, 30)) +#define SOUP_VERSION_2_32 (G_ENCODE_VERSION (2, 32)) +#define SOUP_VERSION_2_34 (G_ENCODE_VERSION (2, 34)) +#define SOUP_VERSION_2_36 (G_ENCODE_VERSION (2, 36)) +#define SOUP_VERSION_2_38 (G_ENCODE_VERSION (2, 38)) +#define SOUP_VERSION_2_40 (G_ENCODE_VERSION (2, 40)) +#define SOUP_VERSION_2_42 (G_ENCODE_VERSION (2, 42)) +#define SOUP_VERSION_2_44 (G_ENCODE_VERSION (2, 44)) +#define SOUP_VERSION_2_46 (G_ENCODE_VERSION (2, 46)) +#define SOUP_VERSION_2_48 (G_ENCODE_VERSION (2, 48)) +#define SOUP_VERSION_2_50 (G_ENCODE_VERSION (2, 50)) +#define SOUP_VERSION_2_52 (G_ENCODE_VERSION (2, 52)) +#define SOUP_VERSION_2_54 (G_ENCODE_VERSION (2, 54)) +#define SOUP_VERSION_2_56 (G_ENCODE_VERSION (2, 56)) +#define SOUP_VERSION_2_58 (G_ENCODE_VERSION (2, 58)) +#define SOUP_VERSION_2_62 (G_ENCODE_VERSION (2, 62)) + +/* evaluates to the current stable version; for development cycles, + * this means the next stable target + */ +#if (SOUP_MINOR_VERSION % 2) +#define SOUP_VERSION_CUR_STABLE (G_ENCODE_VERSION (SOUP_MAJOR_VERSION, SOUP_MINOR_VERSION + 1)) +#else +#define SOUP_VERSION_CUR_STABLE (G_ENCODE_VERSION (SOUP_MAJOR_VERSION, SOUP_MINOR_VERSION)) +#endif + +/* evaluates to the previous stable version */ +#if (SOUP_MINOR_VERSION % 2) +#define SOUP_VERSION_PREV_STABLE (G_ENCODE_VERSION (SOUP_MAJOR_VERSION, SOUP_MINOR_VERSION - 1)) +#else +#define SOUP_VERSION_PREV_STABLE (G_ENCODE_VERSION (SOUP_MAJOR_VERSION, SOUP_MINOR_VERSION - 2)) +#endif + +#ifndef SOUP_VERSION_MIN_REQUIRED +# define SOUP_VERSION_MIN_REQUIRED (SOUP_VERSION_CUR_STABLE) +#elif SOUP_VERSION_MIN_REQUIRED == 0 +# undef SOUP_VERSION_MIN_REQUIRED +# define SOUP_VERSION_MIN_REQUIRED (SOUP_VERSION_CUR_STABLE + 2) +#endif + +#if !defined (SOUP_VERSION_MAX_ALLOWED) || (SOUP_VERSION_MAX_ALLOWED == 0) +# undef SOUP_VERSION_MAX_ALLOWED +# define SOUP_VERSION_MAX_ALLOWED (SOUP_VERSION_CUR_STABLE) +#endif + +/* sanity checks */ +#if SOUP_VERSION_MIN_REQUIRED > SOUP_VERSION_CUR_STABLE +#error "SOUP_VERSION_MIN_REQUIRED must be <= SOUP_VERSION_CUR_STABLE" +#endif +#if SOUP_VERSION_MAX_ALLOWED < SOUP_VERSION_MIN_REQUIRED +#error "SOUP_VERSION_MAX_ALLOWED must be >= SOUP_VERSION_MIN_REQUIRED" +#endif +#if SOUP_VERSION_MIN_REQUIRED < SOUP_VERSION_2_24 +#error "SOUP_VERSION_MIN_REQUIRED must be >= SOUP_VERSION_2_24" +#endif + +#define SOUP_AVAILABLE_IN_2_4 _SOUP_EXTERN + +#if SOUP_VERSION_MIN_REQUIRED >= SOUP_VERSION_2_24 +# define SOUP_DEPRECATED_IN_2_24 G_DEPRECATED +# define SOUP_DEPRECATED_IN_2_24_FOR(f) G_DEPRECATED_FOR(f) +#else +# define SOUP_DEPRECATED_IN_2_24 +# define SOUP_DEPRECATED_IN_2_24_FOR(f) +#endif + +#if SOUP_VERSION_MAX_ALLOWED < SOUP_VERSION_2_24 +# define SOUP_AVAILABLE_IN_2_24 G_UNAVAILABLE(2, 24) _SOUP_EXTERN +#else +# define SOUP_AVAILABLE_IN_2_24 _SOUP_EXTERN +#endif + +#if SOUP_VERSION_MIN_REQUIRED >= SOUP_VERSION_2_26 +# define SOUP_DEPRECATED_IN_2_26 G_DEPRECATED +# define SOUP_DEPRECATED_IN_2_26_FOR(f) G_DEPRECATED_FOR(f) +#else +# define SOUP_DEPRECATED_IN_2_26 +# define SOUP_DEPRECATED_IN_2_26_FOR(f) +#endif + +#if SOUP_VERSION_MAX_ALLOWED < SOUP_VERSION_2_26 +# define SOUP_AVAILABLE_IN_2_26 G_UNAVAILABLE(2, 26) _SOUP_EXTERN +#else +# define SOUP_AVAILABLE_IN_2_26 _SOUP_EXTERN +#endif + +#if SOUP_VERSION_MIN_REQUIRED >= SOUP_VERSION_2_28 +# define SOUP_DEPRECATED_IN_2_28 G_DEPRECATED +# define SOUP_DEPRECATED_IN_2_28_FOR(f) G_DEPRECATED_FOR(f) +#else +# define SOUP_DEPRECATED_IN_2_28 +# define SOUP_DEPRECATED_IN_2_28_FOR(f) +#endif + +#if SOUP_VERSION_MAX_ALLOWED < SOUP_VERSION_2_28 +# define SOUP_AVAILABLE_IN_2_28 G_UNAVAILABLE(2, 28) _SOUP_EXTERN +#else +# define SOUP_AVAILABLE_IN_2_28 _SOUP_EXTERN +#endif + +#if SOUP_VERSION_MIN_REQUIRED >= SOUP_VERSION_2_30 +# define SOUP_DEPRECATED_IN_2_30 G_DEPRECATED +# define SOUP_DEPRECATED_IN_2_30_FOR(f) G_DEPRECATED_FOR(f) +#else +# define SOUP_DEPRECATED_IN_2_30 +# define SOUP_DEPRECATED_IN_2_30_FOR(f) +#endif + +#if SOUP_VERSION_MAX_ALLOWED < SOUP_VERSION_2_30 +# define SOUP_AVAILABLE_IN_2_30 G_UNAVAILABLE(2, 30) _SOUP_EXTERN +#else +# define SOUP_AVAILABLE_IN_2_30 _SOUP_EXTERN +#endif + +#if SOUP_VERSION_MIN_REQUIRED >= SOUP_VERSION_2_32 +# define SOUP_DEPRECATED_IN_2_32 G_DEPRECATED +# define SOUP_DEPRECATED_IN_2_32_FOR(f) G_DEPRECATED_FOR(f) +#else +# define SOUP_DEPRECATED_IN_2_32 +# define SOUP_DEPRECATED_IN_2_32_FOR(f) +#endif + +#if SOUP_VERSION_MAX_ALLOWED < SOUP_VERSION_2_32 +# define SOUP_AVAILABLE_IN_2_32 G_UNAVAILABLE(2, 32) _SOUP_EXTERN +#else +# define SOUP_AVAILABLE_IN_2_32 _SOUP_EXTERN +#endif + +#if SOUP_VERSION_MIN_REQUIRED >= SOUP_VERSION_2_34 +# define SOUP_DEPRECATED_IN_2_34 G_DEPRECATED +# define SOUP_DEPRECATED_IN_2_34_FOR(f) G_DEPRECATED_FOR(f) +#else +# define SOUP_DEPRECATED_IN_2_34 +# define SOUP_DEPRECATED_IN_2_34_FOR(f) +#endif + +#if SOUP_VERSION_MAX_ALLOWED < SOUP_VERSION_2_34 +# define SOUP_AVAILABLE_IN_2_34 G_UNAVAILABLE(2, 34) _SOUP_EXTERN +#else +# define SOUP_AVAILABLE_IN_2_34 _SOUP_EXTERN +#endif + +#if SOUP_VERSION_MIN_REQUIRED >= SOUP_VERSION_2_36 +# define SOUP_DEPRECATED_IN_2_36 G_DEPRECATED +# define SOUP_DEPRECATED_IN_2_36_FOR(f) G_DEPRECATED_FOR(f) +#else +# define SOUP_DEPRECATED_IN_2_36 +# define SOUP_DEPRECATED_IN_2_36_FOR(f) +#endif + +#if SOUP_VERSION_MAX_ALLOWED < SOUP_VERSION_2_36 +# define SOUP_AVAILABLE_IN_2_36 G_UNAVAILABLE(2, 36) _SOUP_EXTERN +#else +# define SOUP_AVAILABLE_IN_2_36 _SOUP_EXTERN +#endif + +#if SOUP_VERSION_MIN_REQUIRED >= SOUP_VERSION_2_38 +# define SOUP_DEPRECATED_IN_2_38 G_DEPRECATED +# define SOUP_DEPRECATED_IN_2_38_FOR(f) G_DEPRECATED_FOR(f) +#else +# define SOUP_DEPRECATED_IN_2_38 +# define SOUP_DEPRECATED_IN_2_38_FOR(f) +#endif + +#if SOUP_VERSION_MAX_ALLOWED < SOUP_VERSION_2_38 +# define SOUP_AVAILABLE_IN_2_38 G_UNAVAILABLE(2, 38) _SOUP_EXTERN +#else +# define SOUP_AVAILABLE_IN_2_38 _SOUP_EXTERN +#endif + +#if SOUP_VERSION_MIN_REQUIRED >= SOUP_VERSION_2_40 +# define SOUP_DEPRECATED_IN_2_40 G_DEPRECATED +# define SOUP_DEPRECATED_IN_2_40_FOR(f) G_DEPRECATED_FOR(f) +#else +# define SOUP_DEPRECATED_IN_2_40 +# define SOUP_DEPRECATED_IN_2_40_FOR(f) +#endif + +#if SOUP_VERSION_MAX_ALLOWED < SOUP_VERSION_2_40 +# define SOUP_AVAILABLE_IN_2_40 G_UNAVAILABLE(2, 40) _SOUP_EXTERN +#else +# define SOUP_AVAILABLE_IN_2_40 _SOUP_EXTERN +#endif + +#if SOUP_VERSION_MIN_REQUIRED >= SOUP_VERSION_2_42 +# define SOUP_DEPRECATED_IN_2_42 G_DEPRECATED +# define SOUP_DEPRECATED_IN_2_42_FOR(f) G_DEPRECATED_FOR(f) +#else +# define SOUP_DEPRECATED_IN_2_42 +# define SOUP_DEPRECATED_IN_2_42_FOR(f) +#endif + +#if SOUP_VERSION_MAX_ALLOWED < SOUP_VERSION_2_42 +# define SOUP_AVAILABLE_IN_2_42 G_UNAVAILABLE(2, 42) _SOUP_EXTERN +#else +# define SOUP_AVAILABLE_IN_2_42 _SOUP_EXTERN +#endif + +#if SOUP_VERSION_MIN_REQUIRED >= SOUP_VERSION_2_44 +# define SOUP_DEPRECATED_IN_2_44 G_DEPRECATED +# define SOUP_DEPRECATED_IN_2_44_FOR(f) G_DEPRECATED_FOR(f) +#else +# define SOUP_DEPRECATED_IN_2_44 +# define SOUP_DEPRECATED_IN_2_44_FOR(f) +#endif + +#if SOUP_VERSION_MAX_ALLOWED < SOUP_VERSION_2_44 +# define SOUP_AVAILABLE_IN_2_44 G_UNAVAILABLE(2, 44) _SOUP_EXTERN +#else +# define SOUP_AVAILABLE_IN_2_44 _SOUP_EXTERN +#endif + +#if SOUP_VERSION_MIN_REQUIRED >= SOUP_VERSION_2_46 +# define SOUP_DEPRECATED_IN_2_46 G_DEPRECATED +# define SOUP_DEPRECATED_IN_2_46_FOR(f) G_DEPRECATED_FOR(f) +#else +# define SOUP_DEPRECATED_IN_2_46 +# define SOUP_DEPRECATED_IN_2_46_FOR(f) +#endif + +#if SOUP_VERSION_MAX_ALLOWED < SOUP_VERSION_2_46 +# define SOUP_AVAILABLE_IN_2_46 G_UNAVAILABLE(2, 46) _SOUP_EXTERN +#else +# define SOUP_AVAILABLE_IN_2_46 _SOUP_EXTERN +#endif + +#if SOUP_VERSION_MIN_REQUIRED >= SOUP_VERSION_2_48 +# define SOUP_DEPRECATED_IN_2_48 G_DEPRECATED +# define SOUP_DEPRECATED_IN_2_48_FOR(f) G_DEPRECATED_FOR(f) +#else +# define SOUP_DEPRECATED_IN_2_48 +# define SOUP_DEPRECATED_IN_2_48_FOR(f) +#endif + +#if SOUP_VERSION_MAX_ALLOWED < SOUP_VERSION_2_48 +# define SOUP_AVAILABLE_IN_2_48 G_UNAVAILABLE(2, 48) _SOUP_EXTERN +#else +# define SOUP_AVAILABLE_IN_2_48 _SOUP_EXTERN +#endif + +#if SOUP_VERSION_MIN_REQUIRED >= SOUP_VERSION_2_50 +# define SOUP_DEPRECATED_IN_2_50 G_DEPRECATED +# define SOUP_DEPRECATED_IN_2_50_FOR(f) G_DEPRECATED_FOR(f) +#else +# define SOUP_DEPRECATED_IN_2_50 +# define SOUP_DEPRECATED_IN_2_50_FOR(f) +#endif + +#if SOUP_VERSION_MAX_ALLOWED < SOUP_VERSION_2_50 +# define SOUP_AVAILABLE_IN_2_50 G_UNAVAILABLE(2, 50) _SOUP_EXTERN +#else +# define SOUP_AVAILABLE_IN_2_50 _SOUP_EXTERN +#endif + +#if SOUP_VERSION_MIN_REQUIRED >= SOUP_VERSION_2_52 +# define SOUP_DEPRECATED_IN_2_52 G_DEPRECATED +# define SOUP_DEPRECATED_IN_2_52_FOR(f) G_DEPRECATED_FOR(f) +#else +# define SOUP_DEPRECATED_IN_2_52 +# define SOUP_DEPRECATED_IN_2_52_FOR(f) +#endif + +#if SOUP_VERSION_MAX_ALLOWED < SOUP_VERSION_2_52 +# define SOUP_AVAILABLE_IN_2_52 G_UNAVAILABLE(2, 52) _SOUP_EXTERN +#else +# define SOUP_AVAILABLE_IN_2_52 _SOUP_EXTERN +#endif + +#if SOUP_VERSION_MIN_REQUIRED >= SOUP_VERSION_2_54 +# define SOUP_DEPRECATED_IN_2_54 G_DEPRECATED +# define SOUP_DEPRECATED_IN_2_54_FOR(f) G_DEPRECATED_FOR(f) +#else +# define SOUP_DEPRECATED_IN_2_54 +# define SOUP_DEPRECATED_IN_2_54_FOR(f) +#endif + +#if SOUP_VERSION_MAX_ALLOWED < SOUP_VERSION_2_54 +# define SOUP_AVAILABLE_IN_2_54 G_UNAVAILABLE(2, 54) _SOUP_EXTERN +#else +# define SOUP_AVAILABLE_IN_2_54 _SOUP_EXTERN +#endif + +#if SOUP_VERSION_MIN_REQUIRED >= SOUP_VERSION_2_56 +# define SOUP_DEPRECATED_IN_2_56 G_DEPRECATED +# define SOUP_DEPRECATED_IN_2_56_FOR(f) G_DEPRECATED_FOR(f) +#else +# define SOUP_DEPRECATED_IN_2_56 +# define SOUP_DEPRECATED_IN_2_56_FOR(f) +#endif + +#if SOUP_VERSION_MAX_ALLOWED < SOUP_VERSION_2_56 +# define SOUP_AVAILABLE_IN_2_56 G_UNAVAILABLE(2, 56) _SOUP_EXTERN +#else +# define SOUP_AVAILABLE_IN_2_56 _SOUP_EXTERN +#endif + +#if SOUP_VERSION_MIN_REQUIRED >= SOUP_VERSION_2_58 +# define SOUP_DEPRECATED_IN_2_58 G_DEPRECATED +# define SOUP_DEPRECATED_IN_2_58_FOR(f) G_DEPRECATED_FOR(f) +#else +# define SOUP_DEPRECATED_IN_2_58 +# define SOUP_DEPRECATED_IN_2_58_FOR(f) +#endif + +#if SOUP_VERSION_MAX_ALLOWED < SOUP_VERSION_2_58 +# define SOUP_AVAILABLE_IN_2_58 G_UNAVAILABLE(2, 58) _SOUP_EXTERN +#else +# define SOUP_AVAILABLE_IN_2_58 _SOUP_EXTERN +#endif + +#if SOUP_VERSION_MIN_REQUIRED >= SOUP_VERSION_2_62 +# define SOUP_DEPRECATED_IN_2_62 G_DEPRECATED +# define SOUP_DEPRECATED_IN_2_62_FOR(f) G_DEPRECATED_FOR(f) +#else +# define SOUP_DEPRECATED_IN_2_62 +# define SOUP_DEPRECATED_IN_2_62_FOR(f) +#endif + +#if SOUP_VERSION_MAX_ALLOWED < SOUP_VERSION_2_62 +# define SOUP_AVAILABLE_IN_2_62 G_UNAVAILABLE(2, 62) _SOUP_EXTERN +#else +# define SOUP_AVAILABLE_IN_2_62 _SOUP_EXTERN +#endif + +SOUP_AVAILABLE_IN_2_42 +guint soup_get_major_version (void); + +SOUP_AVAILABLE_IN_2_42 +guint soup_get_minor_version (void); + +SOUP_AVAILABLE_IN_2_42 +guint soup_get_micro_version (void); + +SOUP_AVAILABLE_IN_2_42 +gboolean soup_check_version (guint major, + guint minor, + guint micro); + +G_END_DECLS + +#endif /* SOUP_VERSION_H */ diff --git a/libsoup/soup-websocket-connection.c b/libsoup/soup-websocket-connection.c new file mode 100644 index 0000000..35eee6a --- /dev/null +++ b/libsoup/soup-websocket-connection.c @@ -0,0 +1,1898 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-websocket-connection.c: This file was originally part of Cockpit. + * + * Copyright 2013, 2014 Red Hat, Inc. + * + * Cockpit is free software; you can redistribute it 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. + * + * Cockpit is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 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, see . + */ + +#include "config.h" + +#include + +#include "soup-websocket-connection.h" +#include "soup-enum-types.h" +#include "soup-uri.h" + +/* + * SECTION:websocketconnection + * @title: SoupWebsocketConnection + * @short_description: A WebSocket connection + * + * A #SoupWebsocketConnection is a WebSocket connection to a peer. + * This API is modeled after the W3C API for interacting with + * WebSockets. + * + * The #SoupWebsocketConnection:state property will indicate the + * state of the connection. + * + * Use soup_websocket_connection_send() to send a message to the peer. + * When a message is received the #SoupWebsocketConnection::message + * signal will fire. + * + * The soup_websocket_connection_close() function will perform an + * orderly close of the connection. The + * #SoupWebsocketConnection::closed signal will fire once the + * connection closes, whether it was initiated by this side or the + * peer. + * + * Connect to the #SoupWebsocketConnection::closing signal to detect + * when either peer begins closing the connection. + */ + +/** + * SoupWebsocketConnection: + * + * A class representing a WebSocket connection. + * + * Since: 2.50 + */ + +/** + * SoupWebsocketConnectionClass: + * @message: default handler for the #SoupWebsocketConnection::message signal + * @error: default handler for the #SoupWebsocketConnection::error signal + * @closing: the default handler for the #SoupWebsocketConnection:closing signal + * @closed: default handler for the #SoupWebsocketConnection::closed signal + * @pong: default handler for the #SoupWebsocketConnection::pong signal + * + * The abstract base class for #SoupWebsocketConnection + * + * Since: 2.50 + */ + +enum { + PROP_0, + PROP_IO_STREAM, + PROP_CONNECTION_TYPE, + PROP_URI, + PROP_ORIGIN, + PROP_PROTOCOL, + PROP_STATE, + PROP_MAX_INCOMING_PAYLOAD_SIZE, + PROP_KEEPALIVE_INTERVAL, +}; + +enum { + MESSAGE, + ERROR, + CLOSING, + CLOSED, + PONG, + NUM_SIGNALS +}; + +static guint signals[NUM_SIGNALS] = { 0, }; + +typedef enum { + SOUP_WEBSOCKET_QUEUE_NORMAL = 0, + SOUP_WEBSOCKET_QUEUE_URGENT = 1 << 0, + SOUP_WEBSOCKET_QUEUE_LAST = 1 << 1, +} SoupWebsocketQueueFlags; + +typedef struct { + GBytes *data; + gsize sent; + gsize amount; + SoupWebsocketQueueFlags flags; + gboolean pending; +} Frame; + +struct _SoupWebsocketConnectionPrivate { + GIOStream *io_stream; + SoupWebsocketConnectionType connection_type; + SoupURI *uri; + char *origin; + char *protocol; + guint64 max_incoming_payload_size; + guint keepalive_interval; + + gushort peer_close_code; + char *peer_close_data; + gboolean close_sent; + gboolean close_received; + gboolean dirty_close; + GSource *close_timeout; + + GMainContext *main_context; + + gboolean io_closing; + gboolean io_closed; + + GPollableInputStream *input; + GSource *input_source; + GByteArray *incoming; + + GPollableOutputStream *output; + GSource *output_source; + GQueue outgoing; + + /* Current message being assembled */ + guint8 message_opcode; + GByteArray *message_data; + + GSource *keepalive_timeout; +}; + +#define MAX_INCOMING_PAYLOAD_SIZE_DEFAULT 128 * 1024 + +G_DEFINE_TYPE_WITH_PRIVATE (SoupWebsocketConnection, soup_websocket_connection, G_TYPE_OBJECT) + +static void queue_frame (SoupWebsocketConnection *self, SoupWebsocketQueueFlags flags, + gpointer data, gsize len, gsize amount); + +static void protocol_error_and_close (SoupWebsocketConnection *self); + +static void +frame_free (gpointer data) +{ + Frame *frame = data; + + if (frame) { + g_bytes_unref (frame->data); + g_slice_free (Frame, frame); + } +} + +static void +soup_websocket_connection_init (SoupWebsocketConnection *self) +{ + SoupWebsocketConnectionPrivate *pv; + + pv = self->pv = soup_websocket_connection_get_instance_private (self); + + pv->incoming = g_byte_array_sized_new (1024); + g_queue_init (&pv->outgoing); + pv->main_context = g_main_context_ref_thread_default (); +} + +static void +on_iostream_closed (GObject *source, + GAsyncResult *result, + gpointer user_data) +{ + SoupWebsocketConnection *self = user_data; + SoupWebsocketConnectionPrivate *pv = self->pv; + GError *error = NULL; + + /* We treat connection as closed even if close fails */ + pv->io_closed = TRUE; + g_io_stream_close_finish (pv->io_stream, result, &error); + + if (error) { + g_debug ("error closing web socket stream: %s", error->message); + if (!pv->dirty_close) + g_signal_emit (self, signals[ERROR], 0, error); + pv->dirty_close = TRUE; + g_error_free (error); + } + + g_assert (soup_websocket_connection_get_state (self) == SOUP_WEBSOCKET_STATE_CLOSED); + g_debug ("closed: completed io stream close"); + g_signal_emit (self, signals[CLOSED], 0); + + g_object_unref (self); +} + +static void +stop_input (SoupWebsocketConnection *self) +{ + SoupWebsocketConnectionPrivate *pv = self->pv; + + if (pv->input_source) { + g_debug ("stopping input source"); + g_source_destroy (pv->input_source); + g_source_unref (pv->input_source); + pv->input_source = NULL; + } +} + +static void +stop_output (SoupWebsocketConnection *self) +{ + SoupWebsocketConnectionPrivate *pv = self->pv; + + if (pv->output_source) { + g_debug ("stopping output source"); + g_source_destroy (pv->output_source); + g_source_unref (pv->output_source); + pv->output_source = NULL; + } +} + +static void +keepalive_stop_timeout (SoupWebsocketConnection *self) +{ + SoupWebsocketConnectionPrivate *pv = self->pv; + + if (pv->keepalive_timeout) { + g_source_destroy (pv->keepalive_timeout); + g_source_unref (pv->keepalive_timeout); + pv->keepalive_timeout = NULL; + } +} + +static void +close_io_stop_timeout (SoupWebsocketConnection *self) +{ + SoupWebsocketConnectionPrivate *pv = self->pv; + + if (pv->close_timeout) { + g_source_destroy (pv->close_timeout); + g_source_unref (pv->close_timeout); + pv->close_timeout = NULL; + } +} + +static void +close_io_stream (SoupWebsocketConnection *self) +{ + SoupWebsocketConnectionPrivate *pv = self->pv; + + keepalive_stop_timeout (self); + close_io_stop_timeout (self); + + if (!pv->io_closing) { + stop_input (self); + stop_output (self); + pv->io_closing = TRUE; + g_debug ("closing io stream"); + g_io_stream_close_async (pv->io_stream, G_PRIORITY_DEFAULT, + NULL, on_iostream_closed, g_object_ref (self)); + } + + g_object_notify (G_OBJECT (self), "state"); +} + +static void +shutdown_wr_io_stream (SoupWebsocketConnection *self) +{ + SoupWebsocketConnectionPrivate *pv = self->pv; + GSocket *socket; + GError *error = NULL; + + stop_output (self); + + if (G_IS_SOCKET_CONNECTION (pv->io_stream)) { + socket = g_socket_connection_get_socket (G_SOCKET_CONNECTION (pv->io_stream)); + g_socket_shutdown (socket, FALSE, TRUE, &error); + if (error != NULL) { + g_debug ("error shutting down io stream: %s", error->message); + g_error_free (error); + } + } + + g_object_notify (G_OBJECT (self), "state"); +} + +static gboolean +on_timeout_close_io (gpointer user_data) +{ + SoupWebsocketConnection *self = SOUP_WEBSOCKET_CONNECTION (user_data); + SoupWebsocketConnectionPrivate *pv = self->pv; + + pv->close_timeout = 0; + + g_debug ("peer did not close io when expected"); + close_io_stream (self); + + return FALSE; +} + +static void +close_io_after_timeout (SoupWebsocketConnection *self) +{ + SoupWebsocketConnectionPrivate *pv = self->pv; + const int timeout = 5; + + if (pv->close_timeout) + return; + + g_debug ("waiting %d seconds for peer to close io", timeout); + pv->close_timeout = g_timeout_source_new_seconds (timeout); + g_source_set_callback (pv->close_timeout, on_timeout_close_io, self, NULL); + g_source_attach (pv->close_timeout, pv->main_context); +} + +static void +xor_with_mask (const guint8 *mask, + guint8 *data, + gsize len) +{ + gsize n; + + /* Do the masking */ + for (n = 0; n < len; n++) + data[n] ^= mask[n & 3]; +} + +static void +send_message (SoupWebsocketConnection *self, + SoupWebsocketQueueFlags flags, + guint8 opcode, + const guint8 *data, + gsize length) +{ + gsize buffered_amount = length; + GByteArray *bytes; + gsize frame_len; + guint8 *outer; + guint8 *mask = 0; + guint8 *at; + + if (!(soup_websocket_connection_get_state (self) == SOUP_WEBSOCKET_STATE_OPEN)) { + g_debug ("Ignoring message since the connection is closed or is closing"); + return; + } + + bytes = g_byte_array_sized_new (14 + length); + outer = bytes->data; + outer[0] = 0x80 | opcode; + + /* If control message, check payload size */ + if (opcode & 0x08) { + if (length > 125) { + g_warning ("WebSocket control message payload exceeds size limit"); + protocol_error_and_close (self); + return; + } + + buffered_amount = 0; + } + + if (length < 126) { + outer[1] = (0xFF & length); /* mask | 7-bit-len */ + bytes->len = 2; + } else if (length < 65536) { + outer[1] = 126; /* mask | 16-bit-len */ + outer[2] = (length >> 8) & 0xFF; + outer[3] = (length >> 0) & 0xFF; + bytes->len = 4; + } else { + outer[1] = 127; /* mask | 64-bit-len */ +#if GLIB_SIZEOF_SIZE_T > 4 + outer[2] = (length >> 56) & 0xFF; + outer[3] = (length >> 48) & 0xFF; + outer[4] = (length >> 40) & 0xFF; + outer[5] = (length >> 32) & 0xFF; +#else + outer[2] = outer[3] = outer[4] = outer[5] = 0; +#endif + outer[6] = (length >> 24) & 0xFF; + outer[7] = (length >> 16) & 0xFF; + outer[8] = (length >> 8) & 0xFF; + outer[9] = (length >> 0) & 0xFF; + bytes->len = 10; + } + + /* The server side doesn't need to mask, so we don't. There's + * probably a client somewhere that's not expecting it. + */ + if (self->pv->connection_type == SOUP_WEBSOCKET_CONNECTION_CLIENT) { + guint32 rnd = g_random_int (); + outer[1] |= 0x80; + mask = outer + bytes->len; + memcpy (mask, &rnd, sizeof (rnd)); + bytes->len += 4; + } + + at = bytes->data + bytes->len; + g_byte_array_append (bytes, data, length); + + if (self->pv->connection_type == SOUP_WEBSOCKET_CONNECTION_CLIENT) + xor_with_mask (mask, at, length); + + frame_len = bytes->len; + queue_frame (self, flags, g_byte_array_free (bytes, FALSE), + frame_len, buffered_amount); + g_debug ("queued %d frame of len %u", (int)opcode, (guint)frame_len); +} + +static void +send_close (SoupWebsocketConnection *self, + SoupWebsocketQueueFlags flags, + gushort code, + const char *reason) +{ + /* Note that send_message truncates as expected */ + char buffer[128]; + gsize len = 0; + + if (code != 0) { + buffer[len++] = code >> 8; + buffer[len++] = code & 0xFF; + if (reason) + len += g_strlcpy (buffer + len, reason, sizeof (buffer) - len); + } + + send_message (self, flags, 0x08, (guint8 *)buffer, len); + self->pv->close_sent = TRUE; + + keepalive_stop_timeout (self); +} + +static void +emit_error_and_close (SoupWebsocketConnection *self, + GError *error, + gboolean prejudice) +{ + gboolean ignore = FALSE; + gushort code; + + if (soup_websocket_connection_get_state (self) == SOUP_WEBSOCKET_STATE_CLOSED) { + g_error_free (error); + return; + } + + if (error && error->domain == SOUP_WEBSOCKET_ERROR) + code = error->code; + else + code = SOUP_WEBSOCKET_CLOSE_GOING_AWAY; + + self->pv->dirty_close = TRUE; + g_signal_emit (self, signals[ERROR], 0, error); + g_error_free (error); + + /* If already closing, just ignore this stuff */ + switch (soup_websocket_connection_get_state (self)) { + case SOUP_WEBSOCKET_STATE_CLOSED: + ignore = TRUE; + break; + case SOUP_WEBSOCKET_STATE_CLOSING: + ignore = !prejudice; + break; + default: + break; + } + + if (ignore) { + g_debug ("already closing/closed, ignoring error"); + } else if (prejudice) { + g_debug ("forcing close due to error"); + close_io_stream (self); + } else { + g_debug ("requesting close due to error"); + send_close (self, SOUP_WEBSOCKET_QUEUE_URGENT | SOUP_WEBSOCKET_QUEUE_LAST, code, NULL); + } +} + +static void +protocol_error_and_close_full (SoupWebsocketConnection *self, + gboolean prejudice) +{ + GError *error; + + error = g_error_new_literal (SOUP_WEBSOCKET_ERROR, + SOUP_WEBSOCKET_CLOSE_PROTOCOL_ERROR, + self->pv->connection_type == SOUP_WEBSOCKET_CONNECTION_SERVER ? + "Received invalid WebSocket response from the client" : + "Received invalid WebSocket response from the server"); + emit_error_and_close (self, error, prejudice); +} + +static void +protocol_error_and_close (SoupWebsocketConnection *self) +{ + protocol_error_and_close_full (self, FALSE); +} + +static void +bad_data_error_and_close (SoupWebsocketConnection *self) +{ + GError *error; + + error = g_error_new_literal (SOUP_WEBSOCKET_ERROR, + SOUP_WEBSOCKET_CLOSE_BAD_DATA, + self->pv->connection_type == SOUP_WEBSOCKET_CONNECTION_SERVER ? + "Received invalid WebSocket data from the client" : + "Received invalid WebSocket data from the server"); + emit_error_and_close (self, error, FALSE); +} + +static void +too_big_error_and_close (SoupWebsocketConnection *self, + guint64 payload_len) +{ + GError *error; + + error = g_error_new_literal (SOUP_WEBSOCKET_ERROR, + SOUP_WEBSOCKET_CLOSE_TOO_BIG, + self->pv->connection_type == SOUP_WEBSOCKET_CONNECTION_SERVER ? + "Received extremely large WebSocket data from the client" : + "Received extremely large WebSocket data from the server"); + g_debug ("%s is trying to frame of size %" G_GUINT64_FORMAT " or greater, but max supported size is %" G_GUINT64_FORMAT, + self->pv->connection_type == SOUP_WEBSOCKET_CONNECTION_SERVER ? "server" : "client", + payload_len, self->pv->max_incoming_payload_size); + emit_error_and_close (self, error, TRUE); + + /* The input is in an invalid state now */ + stop_input (self); +} + +static void +close_connection (SoupWebsocketConnection *self, + gushort code, + const char *data) +{ + SoupWebsocketQueueFlags flags; + SoupWebsocketConnectionPrivate *pv; + + pv = self->pv; + + if (pv->close_sent) { + g_debug ("close code already sent"); + return; + } + + /* Validate the closing code received by the peer */ + switch (code) { + case SOUP_WEBSOCKET_CLOSE_NORMAL: + case SOUP_WEBSOCKET_CLOSE_GOING_AWAY: + case SOUP_WEBSOCKET_CLOSE_PROTOCOL_ERROR: + case SOUP_WEBSOCKET_CLOSE_UNSUPPORTED_DATA: + case SOUP_WEBSOCKET_CLOSE_BAD_DATA: + case SOUP_WEBSOCKET_CLOSE_POLICY_VIOLATION: + case SOUP_WEBSOCKET_CLOSE_TOO_BIG: + break; + case SOUP_WEBSOCKET_CLOSE_NO_EXTENSION: + if (pv->connection_type == SOUP_WEBSOCKET_CONNECTION_SERVER) { + g_debug ("Wrong closing code %d received for a server connection", + code); + } + break; + case SOUP_WEBSOCKET_CLOSE_SERVER_ERROR: + if (pv->connection_type != SOUP_WEBSOCKET_CONNECTION_SERVER) { + g_debug ("Wrong closing code %d received for a non server connection", + code); + } + break; + default: + if (code < 3000) { + g_debug ("Wrong closing code %d received", code); + protocol_error_and_close (self); + return; + } + } + + g_signal_emit (self, signals[CLOSING], 0); + + if (pv->close_received) + g_debug ("responding to close request"); + + flags = 0; + if (pv->connection_type == SOUP_WEBSOCKET_CONNECTION_SERVER && pv->close_received) + flags |= SOUP_WEBSOCKET_QUEUE_LAST; + send_close (self, flags, code, data); + close_io_after_timeout (self); +} + +static void +receive_close (SoupWebsocketConnection *self, + const guint8 *data, + gsize len) +{ + SoupWebsocketConnectionPrivate *pv = self->pv; + + pv->peer_close_code = 0; + g_free (pv->peer_close_data); + pv->peer_close_data = NULL; + pv->close_received = TRUE; + + switch (len) { + case 0: + /* Send a clean close when having an empty payload */ + close_connection (self, 1000, NULL); + return; + case 1: + /* Send a protocol error since the close code is incomplete */ + protocol_error_and_close (self); + return; + default: + /* Store the code/data payload */ + pv->peer_close_code = (guint16)data[0] << 8 | data[1]; + break; + } + + if (len > 2) { + data += 2; + len -= 2; + + if (!g_utf8_validate ((char *)data, len, NULL)) { + g_debug ("received non-UTF8 close data: %d '%.*s' %d", (int)len, (int)len, (char *)data, (int)data[0]); + protocol_error_and_close (self); + return; + } + + pv->peer_close_data = g_strndup ((char *)data, len); + } + + /* Once we receive close response on server, close immediately */ + if (pv->close_sent) { + shutdown_wr_io_stream (self); + if (pv->connection_type == SOUP_WEBSOCKET_CONNECTION_SERVER) + close_io_stream (self); + } else { + close_connection (self, pv->peer_close_code, pv->peer_close_data); + } +} + +static void +receive_ping (SoupWebsocketConnection *self, + const guint8 *data, + gsize len) +{ + /* Send back a pong with same data */ + g_debug ("received ping, responding"); + send_message (self, SOUP_WEBSOCKET_QUEUE_URGENT, 0x0A, data, len); +} + +static void +receive_pong (SoupWebsocketConnection *self, + const guint8 *data, + gsize len) +{ + GByteArray *bytes; + + g_debug ("received pong message"); + + bytes = g_byte_array_sized_new (len + 1); + g_byte_array_append (bytes, data, len); + /* Always null terminate, as a convenience */ + g_byte_array_append (bytes, (guchar *)"\0", 1); + /* But don't include the null terminator in the byte count */ + bytes->len--; + + g_signal_emit (self, signals[PONG], 0, bytes); + g_byte_array_unref (bytes); + +} + +static void +process_contents (SoupWebsocketConnection *self, + gboolean control, + gboolean fin, + guint8 opcode, + gconstpointer payload, + gsize payload_len) +{ + SoupWebsocketConnectionPrivate *pv = self->pv; + GBytes *message; + + if (control) { + /* Control frames must never be fragmented */ + if (!fin) { + g_debug ("received fragmented control frame"); + protocol_error_and_close (self); + return; + } + + g_debug ("received control frame %d with %d payload", (int)opcode, (int)payload_len); + + switch (opcode) { + case 0x08: + receive_close (self, payload, payload_len); + break; + case 0x09: + receive_ping (self, payload, payload_len); + break; + case 0x0A: + receive_pong (self, payload, payload_len); + break; + default: + g_debug ("received unsupported control frame: %d", (int)opcode); + protocol_error_and_close (self); + return; + } + } else if (pv->close_received) { + g_debug ("received message after close was received"); + } else { + /* A message frame */ + + if (!fin && opcode) { + /* Initial fragment of a message */ + if (pv->message_data) { + g_debug ("received out of order initial message fragment"); + protocol_error_and_close (self); + return; + } + g_debug ("received initial fragment frame %d with %d payload", (int)opcode, (int)payload_len); + } else if (!fin && !opcode) { + /* Middle fragment of a message */ + if (!pv->message_data) { + g_debug ("received out of order middle message fragment"); + protocol_error_and_close (self); + return; + } + g_debug ("received middle fragment frame with %d payload", (int)payload_len); + } else if (fin && !opcode) { + /* Last fragment of a message */ + if (!pv->message_data) { + g_debug ("received out of order ending message fragment"); + protocol_error_and_close (self); + return; + } + g_debug ("received last fragment frame with %d payload", (int)payload_len); + } else { + /* An unfragmented message */ + g_assert (opcode != 0); + if (pv->message_data) { + g_debug ("received unfragmented message when fragment was expected"); + protocol_error_and_close (self); + return; + } + g_debug ("received frame %d with %d payload", (int)opcode, (int)payload_len); + } + + if (opcode) { + pv->message_opcode = opcode; + pv->message_data = g_byte_array_sized_new (payload_len + 1); + } + + switch (pv->message_opcode) { + case 0x01: + case 0x02: + g_byte_array_append (pv->message_data, payload, payload_len); + break; + default: + g_debug ("received unknown data frame: %d", (int)opcode); + protocol_error_and_close (self); + return; + } + + /* Actually deliver the message? */ + if (fin) { + if (pv->message_opcode == 0x01 && + !g_utf8_validate((char *)pv->message_data->data, + pv->message_data->len, + NULL)) { + + g_debug ("received invalid non-UTF8 text data"); + + /* Discard the entire message */ + g_byte_array_unref (pv->message_data); + pv->message_data = NULL; + pv->message_opcode = 0; + + bad_data_error_and_close (self); + return; + } + + /* Always null terminate, as a convenience */ + g_byte_array_append (pv->message_data, (guchar *)"\0", 1); + + /* But don't include the null terminator in the byte count */ + pv->message_data->len--; + + opcode = pv->message_opcode; + message = g_byte_array_free_to_bytes (pv->message_data); + pv->message_data = NULL; + pv->message_opcode = 0; + g_debug ("message: delivering %d with %d length", + (int)opcode, (int)g_bytes_get_size (message)); + g_signal_emit (self, signals[MESSAGE], 0, (int)opcode, message); + g_bytes_unref (message); + } + } +} + +static gboolean +process_frame (SoupWebsocketConnection *self) +{ + guint8 *header; + guint8 *payload; + guint64 payload_len; + guint8 *mask; + gboolean fin; + gboolean control; + gboolean masked; + guint8 opcode; + gsize len; + gsize at; + + len = self->pv->incoming->len; + if (len < 2) + return FALSE; /* need more data */ + + header = self->pv->incoming->data; + fin = ((header[0] & 0x80) != 0); + control = header[0] & 0x08; + opcode = header[0] & 0x0f; + masked = ((header[1] & 0x80) != 0); + + /* We do not support extensions, reserved bits must be 0 */ + if (header[0] & 0x70) { + protocol_error_and_close (self); + } + + switch (header[1] & 0x7f) { + case 126: + at = 4; + if (len < at) + return FALSE; /* need more data */ + payload_len = (((guint16)header[2] << 8) | + ((guint16)header[3] << 0)); + break; + case 127: + at = 10; + if (len < at) + return FALSE; /* need more data */ + payload_len = (((guint64)header[2] << 56) | + ((guint64)header[3] << 48) | + ((guint64)header[4] << 40) | + ((guint64)header[5] << 32) | + ((guint64)header[6] << 24) | + ((guint64)header[7] << 16) | + ((guint64)header[8] << 8) | + ((guint64)header[9] << 0)); + break; + default: + payload_len = header[1] & 0x7f; + at = 2; + break; + } + + /* Safety valve */ + if (self->pv->max_incoming_payload_size > 0 && + payload_len >= self->pv->max_incoming_payload_size) { + too_big_error_and_close (self, payload_len); + return FALSE; + } + + if (len < at + payload_len) + return FALSE; /* need more data */ + + payload = header + at; + + if (masked) { + mask = header + at; + payload += 4; + at += 4; + + if (len < at + payload_len) + return FALSE; /* need more data */ + + xor_with_mask (mask, payload, payload_len); + } + + /* Note that now that we've unmasked, we've modified the buffer, we can + * only return below via discarding or processing the message + */ + process_contents (self, control, fin, opcode, payload, payload_len); + + /* Move past the parsed frame */ + g_byte_array_remove_range (self->pv->incoming, 0, at + payload_len); + return TRUE; +} + +static void +process_incoming (SoupWebsocketConnection *self) +{ + while (process_frame (self)) + ; +} + +static gboolean +on_web_socket_input (GObject *pollable_stream, + gpointer user_data) +{ + SoupWebsocketConnection *self = SOUP_WEBSOCKET_CONNECTION (user_data); + SoupWebsocketConnectionPrivate *pv = self->pv; + GError *error = NULL; + gboolean end = FALSE; + gssize count; + gsize len; + + do { + len = pv->incoming->len; + g_byte_array_set_size (pv->incoming, len + 1024); + + count = g_pollable_input_stream_read_nonblocking (pv->input, + pv->incoming->data + len, + 1024, NULL, &error); + + if (count < 0) { + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) { + g_error_free (error); + count = 0; + } else { + emit_error_and_close (self, error, TRUE); + return TRUE; + } + } else if (count == 0) { + end = TRUE; + } + + pv->incoming->len = len + count; + } while (count > 0); + + process_incoming (self); + + if (end) { + if (!pv->close_sent || !pv->close_received) { + pv->dirty_close = TRUE; + g_debug ("connection unexpectedly closed by peer"); + } else { + g_debug ("peer has closed socket"); + } + + close_io_stream (self); + } + + return TRUE; +} + +static gboolean +on_web_socket_output (GObject *pollable_stream, + gpointer user_data) +{ + SoupWebsocketConnection *self = SOUP_WEBSOCKET_CONNECTION (user_data); + SoupWebsocketConnectionPrivate *pv = self->pv; + const guint8 *data; + GError *error = NULL; + Frame *frame; + gssize count; + gsize len; + + if (soup_websocket_connection_get_state (self) == SOUP_WEBSOCKET_STATE_CLOSED) { + g_debug ("Ignoring message since the connection is closed"); + stop_output (self); + return TRUE; + } + + frame = g_queue_peek_head (&pv->outgoing); + + /* No more frames to send */ + if (frame == NULL) { + stop_output (self); + return TRUE; + } + + data = g_bytes_get_data (frame->data, &len); + g_assert (len > 0); + g_assert (len > frame->sent); + + count = g_pollable_output_stream_write_nonblocking (pv->output, + data + frame->sent, + len - frame->sent, + NULL, &error); + + if (count < 0) { + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) { + g_clear_error (&error); + count = 0; + + g_debug ("failed to send frame because it would block, marking as pending"); + frame->pending = TRUE; + } else { + emit_error_and_close (self, error, TRUE); + return FALSE; + } + } + + frame->sent += count; + if (frame->sent >= len) { + g_debug ("sent frame"); + g_queue_pop_head (&pv->outgoing); + + if (frame->flags & SOUP_WEBSOCKET_QUEUE_LAST) { + if (pv->connection_type == SOUP_WEBSOCKET_CONNECTION_SERVER) { + close_io_stream (self); + } else { + shutdown_wr_io_stream (self); + close_io_after_timeout (self); + } + } + frame_free (frame); + } + + return TRUE; +} + +static void +start_output (SoupWebsocketConnection *self) +{ + SoupWebsocketConnectionPrivate *pv = self->pv; + + if (pv->output_source) + return; + + g_debug ("starting output source"); + pv->output_source = g_pollable_output_stream_create_source (pv->output, NULL); + g_source_set_callback (pv->output_source, (GSourceFunc)on_web_socket_output, self, NULL); + g_source_attach (pv->output_source, pv->main_context); +} + +static void +queue_frame (SoupWebsocketConnection *self, + SoupWebsocketQueueFlags flags, + gpointer data, + gsize len, + gsize amount) +{ + SoupWebsocketConnectionPrivate *pv = self->pv; + Frame *frame; + + g_return_if_fail (SOUP_IS_WEBSOCKET_CONNECTION (self)); + g_return_if_fail (pv->close_sent == FALSE); + g_return_if_fail (data != NULL); + g_return_if_fail (len > 0); + + frame = g_slice_new0 (Frame); + frame->data = g_bytes_new_take (data, len); + frame->amount = amount; + frame->flags = flags; + + /* If urgent put at front of queue */ + if (flags & SOUP_WEBSOCKET_QUEUE_URGENT) { + GList *l; + + /* Find out the first frame that is not urgent or partially sent or pending */ + for (l = g_queue_peek_head_link (&pv->outgoing); l != NULL; l = l->next) { + Frame *prev = l->data; + + if (!(prev->flags & SOUP_WEBSOCKET_QUEUE_URGENT) && + prev->sent == 0 && !prev->pending) + break; + } + + g_queue_insert_before (&pv->outgoing, l, frame); + } else { + g_queue_push_tail (&pv->outgoing, frame); + } + + start_output (self); +} + +static void +soup_websocket_connection_constructed (GObject *object) +{ + SoupWebsocketConnection *self = SOUP_WEBSOCKET_CONNECTION (object); + SoupWebsocketConnectionPrivate *pv = self->pv; + GInputStream *is; + GOutputStream *os; + + G_OBJECT_CLASS (soup_websocket_connection_parent_class)->constructed (object); + + g_return_if_fail (pv->io_stream != NULL); + + is = g_io_stream_get_input_stream (pv->io_stream); + g_return_if_fail (G_IS_POLLABLE_INPUT_STREAM (is)); + pv->input = G_POLLABLE_INPUT_STREAM (is); + g_return_if_fail (g_pollable_input_stream_can_poll (pv->input)); + + os = g_io_stream_get_output_stream (pv->io_stream); + g_return_if_fail (G_IS_POLLABLE_OUTPUT_STREAM (os)); + pv->output = G_POLLABLE_OUTPUT_STREAM (os); + g_return_if_fail (g_pollable_output_stream_can_poll (pv->output)); + + pv->input_source = g_pollable_input_stream_create_source (pv->input, NULL); + g_source_set_callback (pv->input_source, (GSourceFunc)on_web_socket_input, self, NULL); + g_source_attach (pv->input_source, pv->main_context); +} + +static void +soup_websocket_connection_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + SoupWebsocketConnection *self = SOUP_WEBSOCKET_CONNECTION (object); + SoupWebsocketConnectionPrivate *pv = self->pv; + + switch (prop_id) { + case PROP_IO_STREAM: + g_value_set_object (value, soup_websocket_connection_get_io_stream (self)); + break; + + case PROP_CONNECTION_TYPE: + g_value_set_enum (value, soup_websocket_connection_get_connection_type (self)); + break; + + case PROP_URI: + g_value_set_boxed (value, soup_websocket_connection_get_uri (self)); + break; + + case PROP_ORIGIN: + g_value_set_string (value, soup_websocket_connection_get_origin (self)); + break; + + case PROP_PROTOCOL: + g_value_set_string (value, soup_websocket_connection_get_protocol (self)); + break; + + case PROP_STATE: + g_value_set_enum (value, soup_websocket_connection_get_state (self)); + break; + + case PROP_MAX_INCOMING_PAYLOAD_SIZE: + g_value_set_uint64 (value, pv->max_incoming_payload_size); + break; + + case PROP_KEEPALIVE_INTERVAL: + g_value_set_uint (value, pv->keepalive_interval); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +soup_websocket_connection_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + SoupWebsocketConnection *self = SOUP_WEBSOCKET_CONNECTION (object); + SoupWebsocketConnectionPrivate *pv = self->pv; + + switch (prop_id) { + case PROP_IO_STREAM: + g_return_if_fail (pv->io_stream == NULL); + pv->io_stream = g_value_dup_object (value); + break; + + case PROP_CONNECTION_TYPE: + pv->connection_type = g_value_get_enum (value); + break; + + case PROP_URI: + g_return_if_fail (pv->uri == NULL); + pv->uri = g_value_dup_boxed (value); + break; + + case PROP_ORIGIN: + g_return_if_fail (pv->origin == NULL); + pv->origin = g_value_dup_string (value); + break; + + case PROP_PROTOCOL: + g_return_if_fail (pv->protocol == NULL); + pv->protocol = g_value_dup_string (value); + break; + + case PROP_MAX_INCOMING_PAYLOAD_SIZE: + pv->max_incoming_payload_size = g_value_get_uint64 (value); + break; + + case PROP_KEEPALIVE_INTERVAL: + soup_websocket_connection_set_keepalive_interval (self, + g_value_get_uint (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +soup_websocket_connection_dispose (GObject *object) +{ + SoupWebsocketConnection *self = SOUP_WEBSOCKET_CONNECTION (object); + + self->pv->dirty_close = TRUE; + close_io_stream (self); + + G_OBJECT_CLASS (soup_websocket_connection_parent_class)->dispose (object); +} + +static void +soup_websocket_connection_finalize (GObject *object) +{ + SoupWebsocketConnection *self = SOUP_WEBSOCKET_CONNECTION (object); + SoupWebsocketConnectionPrivate *pv = self->pv; + + g_free (pv->peer_close_data); + + g_main_context_unref (pv->main_context); + + if (pv->incoming) + g_byte_array_free (pv->incoming, TRUE); + while (!g_queue_is_empty (&pv->outgoing)) + frame_free (g_queue_pop_head (&pv->outgoing)); + + g_clear_object (&pv->io_stream); + g_assert (!pv->input_source); + g_assert (!pv->output_source); + g_assert (pv->io_closing); + g_assert (pv->io_closed); + g_assert (!pv->close_timeout); + g_assert (!pv->keepalive_timeout); + + if (pv->message_data) + g_byte_array_free (pv->message_data, TRUE); + + if (pv->uri) + soup_uri_free (pv->uri); + g_free (pv->origin); + g_free (pv->protocol); + + G_OBJECT_CLASS (soup_websocket_connection_parent_class)->finalize (object); +} + +static void +soup_websocket_connection_class_init (SoupWebsocketConnectionClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->constructed = soup_websocket_connection_constructed; + gobject_class->get_property = soup_websocket_connection_get_property; + gobject_class->set_property = soup_websocket_connection_set_property; + gobject_class->dispose = soup_websocket_connection_dispose; + gobject_class->finalize = soup_websocket_connection_finalize; + + /** + * SoupWebsocketConnection:io-stream: + * + * The underlying IO stream the WebSocket is communicating + * over. + * + * The input and output streams must be pollable streams. + * + * Since: 2.50 + */ + g_object_class_install_property (gobject_class, PROP_IO_STREAM, + g_param_spec_object ("io-stream", + "I/O Stream", + "Underlying I/O stream", + G_TYPE_IO_STREAM, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + + /** + * SoupWebsocketConnection:connection-type: + * + * The type of connection (client/server). + * + * Since: 2.50 + */ + g_object_class_install_property (gobject_class, PROP_CONNECTION_TYPE, + g_param_spec_enum ("connection-type", + "Connection type", + "Connection type (client/server)", + SOUP_TYPE_WEBSOCKET_CONNECTION_TYPE, + SOUP_WEBSOCKET_CONNECTION_UNKNOWN, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + + /** + * SoupWebsocketConnection:uri: + * + * The URI of the WebSocket. + * + * For servers this represents the address of the WebSocket, + * and for clients it is the address connected to. + * + * Since: 2.50 + */ + g_object_class_install_property (gobject_class, PROP_URI, + g_param_spec_boxed ("uri", + "URI", + "The WebSocket URI", + SOUP_TYPE_URI, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + + /** + * SoupWebsocketConnection:origin: + * + * The client's Origin. + * + * Since: 2.50 + */ + g_object_class_install_property (gobject_class, PROP_ORIGIN, + g_param_spec_string ("origin", + "Origin", + "The WebSocket origin", + NULL, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + + /** + * SoupWebsocketConnection:protocol: + * + * The chosen protocol, or %NULL if a protocol was not agreed + * upon. + * + * Since: 2.50 + */ + g_object_class_install_property (gobject_class, PROP_PROTOCOL, + g_param_spec_string ("protocol", + "Protocol", + "The chosen WebSocket protocol", + NULL, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + + /** + * SoupWebsocketConnection:state: + * + * The current state of the WebSocket. + * + * Since: 2.50 + */ + g_object_class_install_property (gobject_class, PROP_STATE, + g_param_spec_enum ("state", + "State", + "State ", + SOUP_TYPE_WEBSOCKET_STATE, + SOUP_WEBSOCKET_STATE_OPEN, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * SoupWebsocketConnection:max-incoming-payload-size: + * + * The maximum payload size for incoming packets the protocol expects + * or 0 to not limit it. + * + * Since: 2.56 + */ + g_object_class_install_property (gobject_class, PROP_MAX_INCOMING_PAYLOAD_SIZE, + g_param_spec_uint64 ("max-incoming-payload-size", + "Max incoming payload size", + "Max incoming payload size ", + 0, + G_MAXUINT64, + MAX_INCOMING_PAYLOAD_SIZE_DEFAULT, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS)); + + /** + * SoupWebsocketConnection:keepalive-interval: + * + * Interval in seconds on when to send a ping message which will + * serve as a keepalive message. If set to 0 the keepalive message is + * disabled. + * + * Since: 2.58 + */ + g_object_class_install_property (gobject_class, PROP_KEEPALIVE_INTERVAL, + g_param_spec_uint ("keepalive-interval", + "Keepalive interval", + "Keepalive interval", + 0, + G_MAXUINT, + 0, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS)); + + /** + * SoupWebsocketConnection::message: + * @self: the WebSocket + * @type: the type of message contents + * @message: the message data + * + * Emitted when we receive a message from the peer. + * + * As a convenience, the @message data will always be + * NUL-terminated, but the NUL byte will not be included in + * the length count. + * + * Since: 2.50 + */ + signals[MESSAGE] = g_signal_new ("message", + SOUP_TYPE_WEBSOCKET_CONNECTION, + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (SoupWebsocketConnectionClass, message), + NULL, NULL, g_cclosure_marshal_generic, + G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_BYTES); + + /** + * SoupWebsocketConnection::error: + * @self: the WebSocket + * @error: the error that occured + * + * Emitted when an error occurred on the WebSocket. This may + * be fired multiple times. Fatal errors will be followed by + * the #SoupWebsocketConnection::closed signal being emitted. + * + * Since: 2.50 + */ + signals[ERROR] = g_signal_new ("error", + SOUP_TYPE_WEBSOCKET_CONNECTION, + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (SoupWebsocketConnectionClass, error), + NULL, NULL, g_cclosure_marshal_generic, + G_TYPE_NONE, 1, G_TYPE_ERROR); + + /** + * SoupWebsocketConnection::closing: + * @self: the WebSocket + * + * This signal will be emitted during an orderly close. + * + * Since: 2.50 + */ + signals[CLOSING] = g_signal_new ("closing", + SOUP_TYPE_WEBSOCKET_CONNECTION, + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (SoupWebsocketConnectionClass, closing), + NULL, NULL, g_cclosure_marshal_generic, + G_TYPE_NONE, 0); + + /** + * SoupWebsocketConnection::closed: + * @self: the WebSocket + * + * Emitted when the connection has completely closed, either + * due to an orderly close from the peer, one initiated via + * soup_websocket_connection_close() or a fatal error + * condition that caused a close. + * + * This signal will be emitted once. + * + * Since: 2.50 + */ + signals[CLOSED] = g_signal_new ("closed", + SOUP_TYPE_WEBSOCKET_CONNECTION, + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (SoupWebsocketConnectionClass, closed), + NULL, NULL, g_cclosure_marshal_generic, + G_TYPE_NONE, 0); + + /** + * SoupWebsocketConnection::pong: + * @self: the WebSocket + * @message: the application data (if any) + * + * Emitted when we receive a Pong frame (solicited or + * unsolicited) from the peer. + * + * As a convenience, the @message data will always be + * NUL-terminated, but the NUL byte will not be included in + * the length count. + * + * Since: 2.60 + */ + signals[PONG] = g_signal_new ("pong", + SOUP_TYPE_WEBSOCKET_CONNECTION, + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (SoupWebsocketConnectionClass, pong), + NULL, NULL, g_cclosure_marshal_generic, + G_TYPE_NONE, 1, G_TYPE_BYTES); +} + +/** + * soup_websocket_connection_new: + * @stream: a #GIOStream connected to the WebSocket server + * @uri: the URI of the connection + * @type: the type of connection (client/side) + * @origin: (allow-none): the Origin of the client + * @protocol: (allow-none): the subprotocol in use + * + * Creates a #SoupWebsocketConnection on @stream. This should be + * called after completing the handshake to begin using the WebSocket + * protocol. + * + * Returns: a new #SoupWebsocketConnection + * + * Since: 2.50 + */ +SoupWebsocketConnection * +soup_websocket_connection_new (GIOStream *stream, + SoupURI *uri, + SoupWebsocketConnectionType type, + const char *origin, + const char *protocol) +{ + g_return_val_if_fail (G_IS_IO_STREAM (stream), NULL); + g_return_val_if_fail (uri != NULL, NULL); + g_return_val_if_fail (type != SOUP_WEBSOCKET_CONNECTION_UNKNOWN, NULL); + + return g_object_new (SOUP_TYPE_WEBSOCKET_CONNECTION, + "io-stream", stream, + "uri", uri, + "connection-type", type, + "origin", origin, + "protocol", protocol, + NULL); +} + +/** + * soup_websocket_connection_get_io_stream: + * @self: the WebSocket + * + * Get the I/O stream the WebSocket is communicating over. + * + * Returns: (transfer none): the WebSocket's I/O stream. + * + * Since: 2.50 + */ +GIOStream * +soup_websocket_connection_get_io_stream (SoupWebsocketConnection *self) +{ + g_return_val_if_fail (SOUP_IS_WEBSOCKET_CONNECTION (self), NULL); + + return self->pv->io_stream; +} + +/** + * soup_websocket_connection_get_connection_type: + * @self: the WebSocket + * + * Get the connection type (client/server) of the connection. + * + * Returns: the connection type + * + * Since: 2.50 + */ +SoupWebsocketConnectionType +soup_websocket_connection_get_connection_type (SoupWebsocketConnection *self) +{ + g_return_val_if_fail (SOUP_IS_WEBSOCKET_CONNECTION (self), SOUP_WEBSOCKET_CONNECTION_UNKNOWN); + + return self->pv->connection_type; +} + +/** + * soup_websocket_connection_get_uri: + * @self: the WebSocket + * + * Get the URI of the WebSocket. + * + * For servers this represents the address of the WebSocket, and + * for clients it is the address connected to. + * + * Returns: (transfer none): the URI + * + * Since: 2.50 + */ +SoupURI * +soup_websocket_connection_get_uri (SoupWebsocketConnection *self) +{ + g_return_val_if_fail (SOUP_IS_WEBSOCKET_CONNECTION (self), NULL); + + return self->pv->uri; +} + +/** + * soup_websocket_connection_get_origin: + * @self: the WebSocket + * + * Get the origin of the WebSocket. + * + * Returns: (nullable): the origin, or %NULL + * + * Since: 2.50 + */ +const char * +soup_websocket_connection_get_origin (SoupWebsocketConnection *self) +{ + g_return_val_if_fail (SOUP_IS_WEBSOCKET_CONNECTION (self), NULL); + + return self->pv->origin; +} + +/** + * soup_websocket_connection_get_protocol: + * @self: the WebSocket + * + * Get the protocol chosen via negotiation with the peer. + * + * Returns: (nullable): the chosen protocol, or %NULL + * + * Since: 2.50 + */ +const char * +soup_websocket_connection_get_protocol (SoupWebsocketConnection *self) +{ + g_return_val_if_fail (SOUP_IS_WEBSOCKET_CONNECTION (self), NULL); + + return self->pv->protocol; +} + +/** + * soup_websocket_connection_get_state: + * @self: the WebSocket + * + * Get the current state of the WebSocket. + * + * Returns: the state + * + * Since: 2.50 + */ +SoupWebsocketState +soup_websocket_connection_get_state (SoupWebsocketConnection *self) +{ + g_return_val_if_fail (SOUP_IS_WEBSOCKET_CONNECTION (self), 0); + + if (self->pv->io_closed) + return SOUP_WEBSOCKET_STATE_CLOSED; + else if (self->pv->io_closing || self->pv->close_sent) + return SOUP_WEBSOCKET_STATE_CLOSING; + else + return SOUP_WEBSOCKET_STATE_OPEN; +} + +/** + * soup_websocket_connection_get_close_code: + * @self: the WebSocket + * + * Get the close code received from the WebSocket peer. + * + * This only becomes valid once the WebSocket is in the + * %SOUP_WEBSOCKET_STATE_CLOSED state. The value will often be in the + * #SoupWebsocketCloseCode enumeration, but may also be an application + * defined close code. + * + * Returns: the close code or zero. + * + * Since: 2.50 + */ +gushort +soup_websocket_connection_get_close_code (SoupWebsocketConnection *self) +{ + g_return_val_if_fail (SOUP_IS_WEBSOCKET_CONNECTION (self), 0); + + return self->pv->peer_close_code; +} + +/** + * soup_websocket_connection_get_close_data: + * @self: the WebSocket + * + * Get the close data received from the WebSocket peer. + * + * This only becomes valid once the WebSocket is in the + * %SOUP_WEBSOCKET_STATE_CLOSED state. The data may be freed once + * the main loop is run, so copy it if you need to keep it around. + * + * Returns: the close data or %NULL + * + * Since: 2.50 + */ +const char * +soup_websocket_connection_get_close_data (SoupWebsocketConnection *self) +{ + g_return_val_if_fail (SOUP_IS_WEBSOCKET_CONNECTION (self), NULL); + + return self->pv->peer_close_data; +} + +/** + * soup_websocket_connection_send_text: + * @self: the WebSocket + * @text: the message contents + * + * Send a text (UTF-8) message to the peer. + * + * The message is queued to be sent and will be sent when the main loop + * is run. + * + * Since: 2.50 + */ +void +soup_websocket_connection_send_text (SoupWebsocketConnection *self, + const char *text) +{ + gsize length; + + g_return_if_fail (SOUP_IS_WEBSOCKET_CONNECTION (self)); + g_return_if_fail (soup_websocket_connection_get_state (self) == SOUP_WEBSOCKET_STATE_OPEN); + g_return_if_fail (text != NULL); + + length = strlen (text); + g_return_if_fail (g_utf8_validate (text, length, NULL)); + + send_message (self, SOUP_WEBSOCKET_QUEUE_NORMAL, 0x01, (const guint8 *) text, length); +} + +/** + * soup_websocket_connection_send_binary: + * @self: the WebSocket + * @data: (array length=length) (element-type guint8): the message contents + * @length: the length of @data + * + * Send a binary message to the peer. + * + * The message is queued to be sent and will be sent when the main loop + * is run. + * + * Since: 2.50 + */ +void +soup_websocket_connection_send_binary (SoupWebsocketConnection *self, + gconstpointer data, + gsize length) +{ + g_return_if_fail (SOUP_IS_WEBSOCKET_CONNECTION (self)); + g_return_if_fail (soup_websocket_connection_get_state (self) == SOUP_WEBSOCKET_STATE_OPEN); + g_return_if_fail (data != NULL); + + send_message (self, SOUP_WEBSOCKET_QUEUE_NORMAL, 0x02, data, length); +} + +/** + * soup_websocket_connection_close: + * @self: the WebSocket + * @code: close code + * @data: (allow-none): close data + * + * Close the connection in an orderly fashion. + * + * Note that until the #SoupWebsocketConnection::closed signal fires, the connection + * is not yet completely closed. The close message is not even sent until the + * main loop runs. + * + * The @code and @data are sent to the peer along with the close request. + * Note that the @data must be UTF-8 valid. + * + * Since: 2.50 + */ +void +soup_websocket_connection_close (SoupWebsocketConnection *self, + gushort code, + const char *data) +{ + SoupWebsocketConnectionPrivate *pv; + + g_return_if_fail (SOUP_IS_WEBSOCKET_CONNECTION (self)); + pv = self->pv; + g_return_if_fail (!pv->close_sent); + + g_return_if_fail (code != SOUP_WEBSOCKET_CLOSE_NO_STATUS && + code != SOUP_WEBSOCKET_CLOSE_ABNORMAL && + code != SOUP_WEBSOCKET_CLOSE_TLS_HANDSHAKE); + if (pv->connection_type == SOUP_WEBSOCKET_CONNECTION_SERVER) + g_return_if_fail (code != SOUP_WEBSOCKET_CLOSE_NO_EXTENSION); + else + g_return_if_fail (code != SOUP_WEBSOCKET_CLOSE_SERVER_ERROR); + + close_connection (self, code, data); +} + +/** + * soup_websocket_connection_get_max_incoming_payload_size: + * @self: the WebSocket + * + * Gets the maximum payload size allowed for incoming packets. + * + * Returns: the maximum payload size. + * + * Since: 2.56 + */ +guint64 +soup_websocket_connection_get_max_incoming_payload_size (SoupWebsocketConnection *self) +{ + SoupWebsocketConnectionPrivate *pv; + + g_return_val_if_fail (SOUP_IS_WEBSOCKET_CONNECTION (self), MAX_INCOMING_PAYLOAD_SIZE_DEFAULT); + pv = self->pv; + + return pv->max_incoming_payload_size; +} + +/** + * soup_websocket_connection_set_max_incoming_payload_size: + * @self: the WebSocket + * @max_incoming_payload_size: the maximum payload size + * + * Sets the maximum payload size allowed for incoming packets. It + * does not limit the outgoing packet size. + * + * Since: 2.56 + */ +void +soup_websocket_connection_set_max_incoming_payload_size (SoupWebsocketConnection *self, + guint64 max_incoming_payload_size) +{ + SoupWebsocketConnectionPrivate *pv; + + g_return_if_fail (SOUP_IS_WEBSOCKET_CONNECTION (self)); + pv = self->pv; + + if (pv->max_incoming_payload_size != max_incoming_payload_size) { + pv->max_incoming_payload_size = max_incoming_payload_size; + g_object_notify (G_OBJECT (self), "max-incoming-payload-size"); + } +} + +/** + * soup_websocket_connection_get_keepalive_interval: + * @self: the WebSocket + * + * Gets the keepalive interval in seconds or 0 if disabled. + * + * Returns: the keepalive interval. + * + * Since: 2.58 + */ +guint +soup_websocket_connection_get_keepalive_interval (SoupWebsocketConnection *self) +{ + SoupWebsocketConnectionPrivate *pv; + + g_return_val_if_fail (SOUP_IS_WEBSOCKET_CONNECTION (self), 0); + pv = self->pv; + + return pv->keepalive_interval; +} + +static gboolean +on_queue_ping (gpointer user_data) +{ + SoupWebsocketConnection *self = SOUP_WEBSOCKET_CONNECTION (user_data); + static const char ping_payload[] = "libsoup"; + + g_debug ("sending ping message"); + + send_message (self, SOUP_WEBSOCKET_QUEUE_NORMAL, 0x09, + (guint8 *) ping_payload, strlen(ping_payload)); + + return G_SOURCE_CONTINUE; +} + +/** + * soup_websocket_connection_set_keepalive_interval: + * @self: the WebSocket + * @interval: the interval to send a ping message or 0 to disable it + * + * Sets the interval in seconds on when to send a ping message which will serve + * as a keepalive message. If set to 0 the keepalive message is disabled. + * + * Since: 2.58 + */ +void +soup_websocket_connection_set_keepalive_interval (SoupWebsocketConnection *self, + guint interval) +{ + SoupWebsocketConnectionPrivate *pv; + + g_return_if_fail (SOUP_IS_WEBSOCKET_CONNECTION (self)); + pv = self->pv; + + if (pv->keepalive_interval != interval) { + pv->keepalive_interval = interval; + g_object_notify (G_OBJECT (self), "keepalive-interval"); + + keepalive_stop_timeout (self); + + if (interval > 0) { + pv->keepalive_timeout = g_timeout_source_new_seconds (interval); + g_source_set_callback (pv->keepalive_timeout, on_queue_ping, self, NULL); + g_source_attach (pv->keepalive_timeout, pv->main_context); + } + } +} diff --git a/libsoup/soup-websocket-connection.h b/libsoup/soup-websocket-connection.h new file mode 100644 index 0000000..bbd79e4 --- /dev/null +++ b/libsoup/soup-websocket-connection.h @@ -0,0 +1,127 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-websocket-connection.h: This file was originally part of Cockpit. + * + * Copyright 2013, 2014 Red Hat, Inc. + * + * Cockpit is free software; you can redistribute it 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. + * + * Cockpit is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 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, see . + */ + +#ifndef __SOUP_WEBSOCKET_CONNECTION_H__ +#define __SOUP_WEBSOCKET_CONNECTION_H__ + +#include +#include + +G_BEGIN_DECLS + +#define SOUP_TYPE_WEBSOCKET_CONNECTION (soup_websocket_connection_get_type ()) +#define SOUP_WEBSOCKET_CONNECTION(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), SOUP_TYPE_WEBSOCKET_CONNECTION, SoupWebsocketConnection)) +#define SOUP_IS_WEBSOCKET_CONNECTION(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), SOUP_TYPE_WEBSOCKET_CONNECTION)) +#define SOUP_WEBSOCKET_CONNECTION_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), SOUP_TYPE_WEBSOCKET_CONNECTION, SoupWebsocketConnectionClass)) +#define SOUP_WEBSOCKET_CONNECTION_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), SOUP_TYPE_WEBSOCKET_CONNECTION, SoupWebsocketConnectionClass)) +#define SOUP_IS_WEBSOCKET_CONNECTION_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), SOUP_TYPE_WEBSOCKET_CONNECTION)) + +typedef struct _SoupWebsocketConnectionPrivate SoupWebsocketConnectionPrivate; + +struct _SoupWebsocketConnection { + GObject parent; + + /*< private >*/ + SoupWebsocketConnectionPrivate *pv; +}; + +typedef struct { + GObjectClass parent; + + /* signals */ + void (* message) (SoupWebsocketConnection *self, + SoupWebsocketDataType type, + GBytes *message); + + void (* error) (SoupWebsocketConnection *self, + GError *error); + + void (* closing) (SoupWebsocketConnection *self); + + void (* closed) (SoupWebsocketConnection *self); + + void (* pong) (SoupWebsocketConnection *self, + GBytes *message); +} SoupWebsocketConnectionClass; + +SOUP_AVAILABLE_IN_2_50 +GType soup_websocket_connection_get_type (void) G_GNUC_CONST; + +SOUP_AVAILABLE_IN_2_50 +SoupWebsocketConnection *soup_websocket_connection_new (GIOStream *stream, + SoupURI *uri, + SoupWebsocketConnectionType type, + const char *origin, + const char *protocol); + +SOUP_AVAILABLE_IN_2_50 +GIOStream * soup_websocket_connection_get_io_stream (SoupWebsocketConnection *self); + +SOUP_AVAILABLE_IN_2_50 +SoupWebsocketConnectionType soup_websocket_connection_get_connection_type (SoupWebsocketConnection *self); + +SOUP_AVAILABLE_IN_2_50 +SoupURI * soup_websocket_connection_get_uri (SoupWebsocketConnection *self); + +SOUP_AVAILABLE_IN_2_50 +const char * soup_websocket_connection_get_origin (SoupWebsocketConnection *self); + +SOUP_AVAILABLE_IN_2_50 +const char * soup_websocket_connection_get_protocol (SoupWebsocketConnection *self); + +SOUP_AVAILABLE_IN_2_50 +SoupWebsocketState soup_websocket_connection_get_state (SoupWebsocketConnection *self); + +SOUP_AVAILABLE_IN_2_50 +gushort soup_websocket_connection_get_close_code (SoupWebsocketConnection *self); + +SOUP_AVAILABLE_IN_2_50 +const char * soup_websocket_connection_get_close_data (SoupWebsocketConnection *self); + +SOUP_AVAILABLE_IN_2_50 +void soup_websocket_connection_send_text (SoupWebsocketConnection *self, + const char *text); +SOUP_AVAILABLE_IN_2_50 +void soup_websocket_connection_send_binary (SoupWebsocketConnection *self, + gconstpointer data, + gsize length); + +SOUP_AVAILABLE_IN_2_50 +void soup_websocket_connection_close (SoupWebsocketConnection *self, + gushort code, + const char *data); + +SOUP_AVAILABLE_IN_2_56 +guint64 soup_websocket_connection_get_max_incoming_payload_size (SoupWebsocketConnection *self); + +SOUP_AVAILABLE_IN_2_56 +void soup_websocket_connection_set_max_incoming_payload_size (SoupWebsocketConnection *self, + guint64 max_incoming_payload_size); + +SOUP_AVAILABLE_IN_2_58 +guint soup_websocket_connection_get_keepalive_interval (SoupWebsocketConnection *self); + +SOUP_AVAILABLE_IN_2_58 +void soup_websocket_connection_set_keepalive_interval (SoupWebsocketConnection *self, + guint interval); + +G_END_DECLS + +#endif /* __SOUP_WEBSOCKET_CONNECTION_H__ */ diff --git a/libsoup/soup-websocket.c b/libsoup/soup-websocket.c new file mode 100644 index 0000000..5038041 --- /dev/null +++ b/libsoup/soup-websocket.c @@ -0,0 +1,568 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-websocket.c: This file was originally part of Cockpit. + * + * Copyright 2013, 2014 Red Hat, Inc. + * + * Cockpit is free software; you can redistribute it 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. + * + * Cockpit is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 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, see . + */ + +#include "config.h" + +#include +#include +#include + +#include "soup-websocket.h" +#include "soup-headers.h" +#include "soup-message.h" + +#define FIXED_DIGEST_LEN 20 + +/** + * SECTION:soup-websocket + * @short_description: The WebSocket Protocol + * @see_also: soup_session_websocket_connect_async(), + * soup_server_add_websocket_handler() + * + * #SoupWebsocketConnection provides support for the WebSocket protocol. + * + * To connect to a WebSocket server, create a #SoupSession and call + * soup_session_websocket_connect_async(). To accept WebSocket + * connections, create a #SoupServer and add a handler to it with + * soup_server_add_websocket_handler(). + * + * (Lower-level support is available via + * soup_websocket_client_prepare_handshake() and + * soup_websocket_client_verify_handshake(), for handling the client + * side of the WebSocket handshake, and + * soup_websocket_server_process_handshake() for handling the server + * side.) + * + * #SoupWebsocketConnection handles the details of WebSocket + * communication. You can use soup_websocket_connection_send_text() + * and soup_websocket_connection_send_binary() to send data, and the + * #SoupWebsocketConnection::message signal to receive data. + * (#SoupWebsocketConnection currently only supports asynchronous + * I/O.) + * + * Since: 2.50 + */ + +/** + * SOUP_WEBSOCKET_ERROR: + * + * A #GError domain for WebSocket-related errors. Used with + * #SoupWebsocketError. + * + * Since: 2.50 + */ + +/** + * SoupWebsocketError: + * @SOUP_WEBSOCKET_ERROR_FAILED: a generic error + * @SOUP_WEBSOCKET_ERROR_NOT_WEBSOCKET: attempted to handshake with a + * server that does not appear to understand WebSockets. + * @SOUP_WEBSOCKET_ERROR_BAD_HANDSHAKE: the WebSocket handshake failed + * because some detail was invalid (eg, incorrect accept key). + * @SOUP_WEBSOCKET_ERROR_BAD_ORIGIN: the WebSocket handshake failed + * because the "Origin" header was not an allowed value. + * + * WebSocket-related errors. + * + * Since: 2.50 + */ + +/** + * SoupWebsocketConnectionType: + * @SOUP_WEBSOCKET_CONNECTION_UNKNOWN: unknown/invalid connection + * @SOUP_WEBSOCKET_CONNECTION_CLIENT: a client-side connection + * @SOUP_WEBSOCKET_CONNECTION_SERVER: a server-side connection + * + * The type of a #SoupWebsocketConnection. + * + * Since: 2.50 + */ + +/** + * SoupWebsocketDataType: + * @SOUP_WEBSOCKET_DATA_TEXT: UTF-8 text + * @SOUP_WEBSOCKET_DATA_BINARY: binary data + * + * The type of data contained in a #SoupWebsocketConnection::message + * signal. + * + * Since: 2.50 + */ + +/** + * SoupWebsocketCloseCode: + * @SOUP_WEBSOCKET_CLOSE_NORMAL: a normal, non-error close + * @SOUP_WEBSOCKET_CLOSE_GOING_AWAY: the client/server is going away + * @SOUP_WEBSOCKET_CLOSE_PROTOCOL_ERROR: a protocol error occurred + * @SOUP_WEBSOCKET_CLOSE_UNSUPPORTED_DATA: the endpoint received data + * of a type that it does not support. + * @SOUP_WEBSOCKET_CLOSE_NO_STATUS: reserved value indicating that + * no close code was present; must not be sent. + * @SOUP_WEBSOCKET_CLOSE_ABNORMAL: reserved value indicating that + * the connection was closed abnormally; must not be sent. + * @SOUP_WEBSOCKET_CLOSE_BAD_DATA: the endpoint received data that + * was invalid (eg, non-UTF-8 data in a text message). + * @SOUP_WEBSOCKET_CLOSE_POLICY_VIOLATION: generic error code + * indicating some sort of policy violation. + * @SOUP_WEBSOCKET_CLOSE_TOO_BIG: the endpoint received a message + * that is too big to process. + * @SOUP_WEBSOCKET_CLOSE_NO_EXTENSION: the client is closing the + * connection because the server failed to negotiate a required + * extension. + * @SOUP_WEBSOCKET_CLOSE_SERVER_ERROR: the server is closing the + * connection because it was unable to fulfill the request. + * @SOUP_WEBSOCKET_CLOSE_TLS_HANDSHAKE: reserved value indicating that + * the TLS handshake failed; must not be sent. + * + * Pre-defined close codes that can be passed to + * soup_websocket_connection_close() or received from + * soup_websocket_connection_get_close_code(). (However, other codes + * are also allowed.) + * + * Since: 2.50 + */ + +/** + * SoupWebsocketState: + * @SOUP_WEBSOCKET_STATE_OPEN: the connection is ready to send messages + * @SOUP_WEBSOCKET_STATE_CLOSING: the connection is in the process of + * closing down; messages may be received, but not sent + * @SOUP_WEBSOCKET_STATE_CLOSED: the connection is completely closed down + * + * The state of the WebSocket connection. + * + * Since: 2.50 + */ + +GQuark +soup_websocket_error_get_quark (void) +{ + return g_quark_from_static_string ("web-socket-error-quark"); +} + +static gboolean +validate_key (const char *key) +{ + guchar buf[18]; + int state = 0; + guint save = 0; + + /* The spec requires us to check that the key is "a + * base64-encoded value that, when decoded, is 16 bytes in + * length". + */ + if (strlen (key) != 24) + return FALSE; + if (g_base64_decode_step (key, 24, buf, &state, &save) != 16) + return FALSE; + return TRUE; +} + +static char * +compute_accept_key (const char *key) +{ + gsize digest_len = FIXED_DIGEST_LEN; + guchar digest[FIXED_DIGEST_LEN]; + GChecksum *checksum; + + if (!key) + return NULL; + + checksum = g_checksum_new (G_CHECKSUM_SHA1); + g_return_val_if_fail (checksum != NULL, NULL); + + g_checksum_update (checksum, (guchar *)key, -1); + + /* magic from: http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-17 */ + g_checksum_update (checksum, (guchar *)"258EAFA5-E914-47DA-95CA-C5AB0DC85B11", -1); + + g_checksum_get_digest (checksum, digest, &digest_len); + g_checksum_free (checksum); + + g_assert (digest_len == FIXED_DIGEST_LEN); + + return g_base64_encode (digest, digest_len); +} + +static gboolean +choose_subprotocol (SoupMessage *msg, + const char **server_protocols, + const char **chosen_protocol) +{ + const char *client_protocols_str; + char **client_protocols; + int i, j; + + if (chosen_protocol) + *chosen_protocol = NULL; + + if (!server_protocols) + return TRUE; + + client_protocols_str = soup_message_headers_get_one (msg->request_headers, + "Sec-Websocket-Protocol"); + if (!client_protocols_str) + return TRUE; + + client_protocols = g_strsplit_set (client_protocols_str, ", ", -1); + if (!client_protocols || !client_protocols[0]) { + g_strfreev (client_protocols); + return TRUE; + } + + for (i = 0; server_protocols[i] != NULL; i++) { + for (j = 0; client_protocols[j] != NULL; j++) { + if (g_str_equal (server_protocols[i], client_protocols[j])) { + g_strfreev (client_protocols); + if (chosen_protocol) + *chosen_protocol = server_protocols[i]; + return TRUE; + } + } + } + + g_strfreev (client_protocols); + return FALSE; +} + +/** + * soup_websocket_client_prepare_handshake: + * @msg: a #SoupMessage + * @origin: (allow-none): the "Origin" header to set + * @protocols: (allow-none) (array zero-terminated=1): list of + * protocols to offer + * + * Adds the necessary headers to @msg to request a WebSocket + * handshake. The message body and non-WebSocket-related headers are + * not modified. + * + * This is a low-level function; if you use + * soup_session_websocket_connect_async() to create a WebSocket + * connection, it will call this for you. + * + * Since: 2.50 + */ +void +soup_websocket_client_prepare_handshake (SoupMessage *msg, + const char *origin, + char **protocols) +{ + guint32 raw[4]; + char *key; + + soup_message_headers_replace (msg->request_headers, "Upgrade", "websocket"); + soup_message_headers_append (msg->request_headers, "Connection", "Upgrade"); + + raw[0] = g_random_int (); + raw[1] = g_random_int (); + raw[2] = g_random_int (); + raw[3] = g_random_int (); + key = g_base64_encode ((const guchar *)raw, sizeof (raw)); + soup_message_headers_replace (msg->request_headers, "Sec-WebSocket-Key", key); + g_free (key); + + soup_message_headers_replace (msg->request_headers, "Sec-WebSocket-Version", "13"); + + if (origin) + soup_message_headers_replace (msg->request_headers, "Origin", origin); + + if (protocols) { + char *protocols_str; + + protocols_str = g_strjoinv (", ", protocols); + soup_message_headers_replace (msg->request_headers, + "Sec-WebSocket-Protocol", protocols_str); + g_free (protocols_str); + } +} + +/** + * soup_websocket_server_check_handshake: + * @msg: #SoupMessage containing the client side of a WebSocket handshake + * @origin: (allow-none): expected Origin header + * @protocols: (allow-none) (array zero-terminated=1): allowed WebSocket + * protocols. + * @error: return location for a #GError + * + * Examines the method and request headers in @msg and determines + * whether @msg contains a valid handshake request. + * + * If @origin is non-%NULL, then only requests containing a matching + * "Origin" header will be accepted. If @protocols is non-%NULL, then + * only requests containing a compatible "Sec-WebSocket-Protocols" + * header will be accepted. + * + * Normally soup_websocket_server_process_handshake() will take care + * of this for you, and if you use soup_server_add_websocket_handler() + * to handle accepting WebSocket connections, it will call that for + * you. However, this function may be useful if you need to perform + * more complicated validation; eg, accepting multiple different Origins, + * or handling different protocols depending on the path. + * + * Returns: %TRUE if @msg contained a valid WebSocket handshake, + * %FALSE and an error if not. + * + * Since: 2.50 + */ +gboolean +soup_websocket_server_check_handshake (SoupMessage *msg, + const char *expected_origin, + char **protocols, + GError **error) +{ + const char *origin; + const char *key; + + if (msg->method != SOUP_METHOD_GET) { + g_set_error_literal (error, + SOUP_WEBSOCKET_ERROR, + SOUP_WEBSOCKET_ERROR_NOT_WEBSOCKET, + _("WebSocket handshake expected")); + return FALSE; + } + + if (!soup_message_headers_header_equals (msg->request_headers, "Upgrade", "websocket") || + !soup_message_headers_header_contains (msg->request_headers, "Connection", "upgrade")) { + g_set_error_literal (error, + SOUP_WEBSOCKET_ERROR, + SOUP_WEBSOCKET_ERROR_NOT_WEBSOCKET, + _("WebSocket handshake expected")); + return FALSE; + } + + if (!soup_message_headers_header_equals (msg->request_headers, "Sec-WebSocket-Version", "13")) { + g_set_error_literal (error, + SOUP_WEBSOCKET_ERROR, + SOUP_WEBSOCKET_ERROR_BAD_HANDSHAKE, + _("Unsupported WebSocket version")); + return FALSE; + } + + key = soup_message_headers_get_one (msg->request_headers, "Sec-WebSocket-Key"); + if (key == NULL || !validate_key (key)) { + g_set_error_literal (error, + SOUP_WEBSOCKET_ERROR, + SOUP_WEBSOCKET_ERROR_BAD_HANDSHAKE, + _("Invalid WebSocket key")); + return FALSE; + } + + if (expected_origin) { + origin = soup_message_headers_get_one (msg->request_headers, "Origin"); + if (!origin || g_ascii_strcasecmp (origin, expected_origin) != 0) { + g_set_error (error, + SOUP_WEBSOCKET_ERROR, + SOUP_WEBSOCKET_ERROR_BAD_ORIGIN, + _("Incorrect WebSocket “%s” header"), "Origin"); + return FALSE; + } + } + + if (!choose_subprotocol (msg, (const char **) protocols, NULL)) { + g_set_error_literal (error, + SOUP_WEBSOCKET_ERROR, + SOUP_WEBSOCKET_ERROR_BAD_HANDSHAKE, + _("Unsupported WebSocket subprotocol")); + return FALSE; + } + + return TRUE; +} + +#define RESPONSE_FORBIDDEN "400 Forbidden\r\n" \ + "Received invalid WebSocket request\r\n" + +static void +respond_handshake_forbidden (SoupMessage *msg) +{ + soup_message_set_status (msg, SOUP_STATUS_FORBIDDEN); + soup_message_headers_append (msg->response_headers, "Connection", "close"); + soup_message_set_response (msg, "text/html", SOUP_MEMORY_COPY, + RESPONSE_FORBIDDEN, strlen (RESPONSE_FORBIDDEN)); +} + +#define RESPONSE_BAD "400 Bad Request\r\n" \ + "Received invalid WebSocket request: %s\r\n" + +static void +respond_handshake_bad (SoupMessage *msg, const char *why) +{ + char *text; + + text = g_strdup_printf (RESPONSE_BAD, why); + soup_message_set_status (msg, SOUP_STATUS_BAD_REQUEST); + soup_message_headers_append (msg->response_headers, "Connection", "close"); + soup_message_set_response (msg, "text/html", SOUP_MEMORY_TAKE, + text, strlen (text)); +} + +/** + * soup_websocket_server_process_handshake: + * @msg: #SoupMessage containing the client side of a WebSocket handshake + * @expected_origin: (allow-none): expected Origin header + * @protocols: (allow-none) (array zero-terminated=1): allowed WebSocket + * protocols. + * + * Examines the method and request headers in @msg and (assuming @msg + * contains a valid handshake request), fills in the handshake + * response. + * + * If @expected_origin is non-%NULL, then only requests containing a matching + * "Origin" header will be accepted. If @protocols is non-%NULL, then + * only requests containing a compatible "Sec-WebSocket-Protocols" + * header will be accepted. + * + * This is a low-level function; if you use + * soup_server_add_websocket_handler() to handle accepting WebSocket + * connections, it will call this for you. + * + * Returns: %TRUE if @msg contained a valid WebSocket handshake + * request and was updated to contain a handshake response. %FALSE if not. + * + * Since: 2.50 + */ +gboolean +soup_websocket_server_process_handshake (SoupMessage *msg, + const char *expected_origin, + char **protocols) +{ + const char *chosen_protocol = NULL; + const char *key; + char *accept_key; + GError *error = NULL; + + if (!soup_websocket_server_check_handshake (msg, expected_origin, protocols, &error)) { + if (g_error_matches (error, + SOUP_WEBSOCKET_ERROR, + SOUP_WEBSOCKET_ERROR_BAD_ORIGIN)) + respond_handshake_forbidden (msg); + else + respond_handshake_bad (msg, error->message); + g_error_free (error); + return FALSE; + } + + soup_message_set_status (msg, SOUP_STATUS_SWITCHING_PROTOCOLS); + soup_message_headers_replace (msg->response_headers, "Upgrade", "websocket"); + soup_message_headers_append (msg->response_headers, "Connection", "Upgrade"); + + key = soup_message_headers_get_one (msg->request_headers, "Sec-WebSocket-Key"); + accept_key = compute_accept_key (key); + soup_message_headers_append (msg->response_headers, "Sec-WebSocket-Accept", accept_key); + g_free (accept_key); + + choose_subprotocol (msg, (const char **) protocols, &chosen_protocol); + if (chosen_protocol) + soup_message_headers_append (msg->response_headers, "Sec-WebSocket-Protocol", chosen_protocol); + + return TRUE; +} + +/** + * soup_websocket_client_verify_handshake: + * @msg: #SoupMessage containing both client and server sides of a + * WebSocket handshake + * @error: return location for a #GError + * + * Looks at the response status code and headers in @msg and + * determines if they contain a valid WebSocket handshake response + * (given the handshake request in @msg's request headers). + * + * This is a low-level function; if you use + * soup_session_websocket_connect_async() to create a WebSocket + * connection, it will call this for you. + * + * Returns: %TRUE if @msg contains a completed valid WebSocket + * handshake, %FALSE and an error if not. + * + * Since: 2.50 + */ +gboolean +soup_websocket_client_verify_handshake (SoupMessage *msg, + GError **error) +{ + const char *protocol, *request_protocols, *extensions, *accept_key; + char *expected_accept_key; + gboolean key_ok; + + if (msg->status_code == SOUP_STATUS_BAD_REQUEST) { + g_set_error_literal (error, + SOUP_WEBSOCKET_ERROR, + SOUP_WEBSOCKET_ERROR_BAD_HANDSHAKE, + _("Server rejected WebSocket handshake")); + return FALSE; + } + + if (msg->status_code != SOUP_STATUS_SWITCHING_PROTOCOLS) { + g_set_error_literal (error, + SOUP_WEBSOCKET_ERROR, + SOUP_WEBSOCKET_ERROR_NOT_WEBSOCKET, + _("Server ignored WebSocket handshake")); + return FALSE; + } + + if (!soup_message_headers_header_equals (msg->response_headers, "Upgrade", "websocket") || + !soup_message_headers_header_contains (msg->response_headers, "Connection", "upgrade")) { + g_set_error_literal (error, + SOUP_WEBSOCKET_ERROR, + SOUP_WEBSOCKET_ERROR_NOT_WEBSOCKET, + _("Server ignored WebSocket handshake")); + return FALSE; + } + + protocol = soup_message_headers_get_one (msg->response_headers, "Sec-WebSocket-Protocol"); + if (protocol) { + request_protocols = soup_message_headers_get_one (msg->request_headers, "Sec-WebSocket-Protocol"); + if (!request_protocols || + !soup_header_contains (request_protocols, protocol)) { + g_set_error_literal (error, + SOUP_WEBSOCKET_ERROR, + SOUP_WEBSOCKET_ERROR_BAD_HANDSHAKE, + _("Server requested unsupported protocol")); + return FALSE; + } + } + + extensions = soup_message_headers_get_list (msg->response_headers, "Sec-WebSocket-Extensions"); + if (extensions && *extensions) { + g_set_error_literal (error, + SOUP_WEBSOCKET_ERROR, + SOUP_WEBSOCKET_ERROR_BAD_HANDSHAKE, + _("Server requested unsupported extension")); + return FALSE; + } + + accept_key = soup_message_headers_get_one (msg->response_headers, "Sec-WebSocket-Accept"); + expected_accept_key = compute_accept_key (soup_message_headers_get_one (msg->request_headers, "Sec-WebSocket-Key")); + key_ok = (accept_key && expected_accept_key && + !g_ascii_strcasecmp (accept_key, expected_accept_key)); + g_free (expected_accept_key); + if (!key_ok) { + g_set_error (error, + SOUP_WEBSOCKET_ERROR, + SOUP_WEBSOCKET_ERROR_BAD_HANDSHAKE, + _("Server returned incorrect “%s” key"), + "Sec-WebSocket-Accept"); + return FALSE; + } + + return TRUE; +} diff --git a/libsoup/soup-websocket.h b/libsoup/soup-websocket.h new file mode 100644 index 0000000..2058498 --- /dev/null +++ b/libsoup/soup-websocket.h @@ -0,0 +1,93 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-websocket.h: This file was originally part of Cockpit. + * + * Copyright 2013, 2014 Red Hat, Inc. + * + * Cockpit is free software; you can redistribute it 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. + * + * Cockpit is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 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, see . + */ + +#ifndef __SOUP_WEBSOCKET_H__ +#define __SOUP_WEBSOCKET_H__ + +#include + +G_BEGIN_DECLS + +#define SOUP_WEBSOCKET_ERROR (soup_websocket_error_get_quark ()) +SOUP_AVAILABLE_IN_2_50 +GQuark soup_websocket_error_get_quark (void) G_GNUC_CONST; + +typedef enum { + SOUP_WEBSOCKET_ERROR_FAILED, + SOUP_WEBSOCKET_ERROR_NOT_WEBSOCKET, + SOUP_WEBSOCKET_ERROR_BAD_HANDSHAKE, + SOUP_WEBSOCKET_ERROR_BAD_ORIGIN, +} SoupWebsocketError; + +typedef enum { + SOUP_WEBSOCKET_CONNECTION_UNKNOWN, + SOUP_WEBSOCKET_CONNECTION_CLIENT, + SOUP_WEBSOCKET_CONNECTION_SERVER +} SoupWebsocketConnectionType; + +typedef enum { + SOUP_WEBSOCKET_DATA_TEXT = 0x01, + SOUP_WEBSOCKET_DATA_BINARY = 0x02, +} SoupWebsocketDataType; + +typedef enum { + SOUP_WEBSOCKET_CLOSE_NORMAL = 1000, + SOUP_WEBSOCKET_CLOSE_GOING_AWAY = 1001, + SOUP_WEBSOCKET_CLOSE_PROTOCOL_ERROR = 1002, + SOUP_WEBSOCKET_CLOSE_UNSUPPORTED_DATA = 1003, + SOUP_WEBSOCKET_CLOSE_NO_STATUS = 1005, + SOUP_WEBSOCKET_CLOSE_ABNORMAL = 1006, + SOUP_WEBSOCKET_CLOSE_BAD_DATA = 1007, + SOUP_WEBSOCKET_CLOSE_POLICY_VIOLATION = 1008, + SOUP_WEBSOCKET_CLOSE_TOO_BIG = 1009, + SOUP_WEBSOCKET_CLOSE_NO_EXTENSION = 1010, + SOUP_WEBSOCKET_CLOSE_SERVER_ERROR = 1011, + SOUP_WEBSOCKET_CLOSE_TLS_HANDSHAKE = 1015, +} SoupWebsocketCloseCode; + +typedef enum { + SOUP_WEBSOCKET_STATE_OPEN = 1, + SOUP_WEBSOCKET_STATE_CLOSING = 2, + SOUP_WEBSOCKET_STATE_CLOSED = 3, +} SoupWebsocketState; + +SOUP_AVAILABLE_IN_2_50 +void soup_websocket_client_prepare_handshake (SoupMessage *msg, + const char *origin, + char **protocols); + +SOUP_AVAILABLE_IN_2_50 +gboolean soup_websocket_client_verify_handshake (SoupMessage *msg, + GError **error); + +SOUP_AVAILABLE_IN_2_50 +gboolean soup_websocket_server_check_handshake (SoupMessage *msg, + const char *origin, + char **protocols, + GError **error); + +SOUP_AVAILABLE_IN_2_50 +gboolean soup_websocket_server_process_handshake (SoupMessage *msg, + const char *expected_origin, + char **protocols); + +G_END_DECLS + +#endif /* __SOUP_WEBSOCKET_H__ */ diff --git a/libsoup/soup-xmlrpc-old.c b/libsoup/soup-xmlrpc-old.c new file mode 100644 index 0000000..c57086b --- /dev/null +++ b/libsoup/soup-xmlrpc-old.c @@ -0,0 +1,738 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-xmlrpc.c: XML-RPC parser/generator + * + * Copyright (C) 2007 Red Hat, Inc. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include + +#include "soup-xmlrpc-old.h" +#include "soup.h" + +/** + * SECTION:soup-xmlrpc + * @short_description: XML-RPC support + * + **/ + +/* This whole file is deprecated and replaced by soup-xmlrpc.c */ +G_GNUC_BEGIN_IGNORE_DEPRECATIONS + +static xmlNode *find_real_node (xmlNode *node); + +static gboolean insert_value (xmlNode *parent, GValue *value); + +static gboolean +insert_value (xmlNode *parent, GValue *value) +{ + GType type = G_VALUE_TYPE (value); + xmlNode *xvalue; + char buf[128]; + + xvalue = xmlNewChild (parent, NULL, (const xmlChar *)"value", NULL); + + if (type == G_TYPE_INT) { + g_snprintf (buf, sizeof (buf), "%d", g_value_get_int (value)); + xmlNewChild (xvalue, NULL, + (const xmlChar *)"int", + (const xmlChar *)buf); + } else if (type == G_TYPE_BOOLEAN) { + g_snprintf (buf, sizeof (buf), "%d", g_value_get_boolean (value)); + xmlNewChild (xvalue, NULL, + (const xmlChar *)"boolean", + (const xmlChar *)buf); + } else if (type == G_TYPE_STRING) { + xmlNewTextChild (xvalue, NULL, + (const xmlChar *)"string", + (const xmlChar *)g_value_get_string (value)); + } else if (type == G_TYPE_DOUBLE) { + g_ascii_dtostr (buf, sizeof (buf), g_value_get_double (value)); + xmlNewChild (xvalue, NULL, + (const xmlChar *)"double", + (const xmlChar *)buf); + } else if (type == SOUP_TYPE_DATE) { + SoupDate *date = g_value_get_boxed (value); + char *timestamp = soup_date_to_string (date, SOUP_DATE_ISO8601_XMLRPC); + xmlNewChild (xvalue, NULL, + (const xmlChar *)"dateTime.iso8601", + (const xmlChar *)timestamp); + g_free (timestamp); + } else if (type == SOUP_TYPE_BYTE_ARRAY) { + GByteArray *ba = g_value_get_boxed (value); + char *encoded; + + encoded = g_base64_encode (ba->data, ba->len); + xmlNewChild (xvalue, NULL, + (const xmlChar *)"base64", + (const xmlChar *)encoded); + g_free (encoded); + } else if (type == G_TYPE_HASH_TABLE) { + GHashTable *hash = g_value_get_boxed (value); + GHashTableIter iter; + gpointer mname, mvalue; + xmlNode *struct_node, *member; + + struct_node = xmlNewChild (xvalue, NULL, + (const xmlChar *)"struct", NULL); + + g_hash_table_iter_init (&iter, hash); + + while (g_hash_table_iter_next (&iter, &mname, &mvalue)) { + member = xmlNewChild (struct_node, NULL, + (const xmlChar *)"member", NULL); + xmlNewTextChild (member, NULL, + (const xmlChar *)"name", + (const xmlChar *)mname); + if (!insert_value (member, mvalue)) { + xmlFreeNode (struct_node); + struct_node = NULL; + break; + } + } + + if (!struct_node) + return FALSE; + } else if (type == G_TYPE_VALUE_ARRAY) { + GValueArray *va = g_value_get_boxed (value); + xmlNode *node; + guint i; + + node = xmlNewChild (xvalue, NULL, + (const xmlChar *)"array", NULL); + node = xmlNewChild (node, NULL, + (const xmlChar *)"data", NULL); + for (i = 0; i < va->n_values; i++) { + if (!insert_value (node, &va->values[i])) + return FALSE; + } + } else + return FALSE; + + return TRUE; +} + +/** + * soup_xmlrpc_build_method_call: + * @method_name: the name of the XML-RPC method + * @params: (array length=n_params): arguments to @method + * @n_params: length of @params + * + * This creates an XML-RPC methodCall and returns it as a string. + * This is the low-level method that soup_xmlrpc_request_new() is + * built on. + * + * @params is an array of #GValue representing the parameters to + * @method. (It is *not* a #GValueArray, although if you have a + * #GValueArray, you can just pass its valuesf and + * n_values fields.) + * + * The correspondence between glib types and XML-RPC types is: + * + * int: #int (%G_TYPE_INT) + * boolean: #gboolean (%G_TYPE_BOOLEAN) + * string: #char* (%G_TYPE_STRING) + * double: #double (%G_TYPE_DOUBLE) + * datetime.iso8601: #SoupDate (%SOUP_TYPE_DATE) + * base64: #GByteArray (%SOUP_TYPE_BYTE_ARRAY) + * struct: #GHashTable (%G_TYPE_HASH_TABLE) + * array: #GValueArray (%G_TYPE_VALUE_ARRAY) + * + * For structs, use a #GHashTable that maps strings to #GValue; + * soup_value_hash_new() and related methods can help with this. + * + * Return value: (nullable): the text of the methodCall, or %NULL on + * error + * + * Deprecated: Use soup_xmlrpc_build_request() instead. + **/ +char * +soup_xmlrpc_build_method_call (const char *method_name, + GValue *params, int n_params) +{ + xmlDoc *doc; + xmlNode *node, *param; + xmlChar *xmlbody; + int i, len; + char *body; + + doc = xmlNewDoc ((const xmlChar *)"1.0"); + doc->standalone = FALSE; + doc->encoding = xmlCharStrdup ("UTF-8"); + + node = xmlNewDocNode (doc, NULL, (const xmlChar *)"methodCall", NULL); + xmlDocSetRootElement (doc, node); + xmlNewChild (node, NULL, (const xmlChar *)"methodName", + (const xmlChar *)method_name); + + node = xmlNewChild (node, NULL, (const xmlChar *)"params", NULL); + for (i = 0; i < n_params; i++) { + param = xmlNewChild (node, NULL, + (const xmlChar *)"param", NULL); + if (!insert_value (param, ¶ms[i])) { + xmlFreeDoc (doc); + return NULL; + } + } + + xmlDocDumpMemory (doc, &xmlbody, &len); + body = g_strndup ((char *)xmlbody, len); + xmlFree (xmlbody); + xmlFreeDoc (doc); + return body; +} + +static SoupMessage * +soup_xmlrpc_request_newv (const char *uri, const char *method_name, va_list args) +{ + SoupMessage *msg; + GValueArray *params; + char *body; + + params = soup_value_array_from_args (args); + if (!params) + return NULL; + + body = soup_xmlrpc_build_method_call (method_name, params->values, + params->n_values); + g_value_array_free (params); + + if (!body) + return NULL; + + msg = soup_message_new ("POST", uri); + soup_message_set_request (msg, "text/xml", SOUP_MEMORY_TAKE, + body, strlen (body)); + return msg; +} + +/** + * soup_xmlrpc_request_new: + * @uri: URI of the XML-RPC service + * @method_name: the name of the XML-RPC method to invoke at @uri + * @...: parameters for @method + * + * Creates an XML-RPC methodCall and returns a #SoupMessage, ready + * to send, for that method call. + * + * The parameters are passed as type/value pairs; ie, first a #GType, + * and then a value of the appropriate type, finally terminated by + * %G_TYPE_INVALID. + * + * Return value: (transfer full): a #SoupMessage encoding the + * indicated XML-RPC request. + * + * Deprecated: Use soup_xmlrpc_message_new() instead. + **/ +SoupMessage * +soup_xmlrpc_request_new (const char *uri, const char *method_name, ...) +{ + SoupMessage *msg; + va_list args; + + va_start (args, method_name); + msg = soup_xmlrpc_request_newv (uri, method_name, args); + va_end (args); + return msg; +} + +/** + * soup_xmlrpc_build_method_response: + * @value: the return value + * + * This creates a (successful) XML-RPC methodResponse and returns it + * as a string. To create a fault response, use + * soup_xmlrpc_build_fault(). + * + * The glib type to XML-RPC type mapping is as with + * soup_xmlrpc_build_method_call(), qv. + * + * Return value: (nullable): the text of the methodResponse, or %NULL + * on error + * + * Deprecated: Use soup_xmlrpc_build_response() instead. + **/ +char * +soup_xmlrpc_build_method_response (GValue *value) +{ + xmlDoc *doc; + xmlNode *node; + xmlChar *xmlbody; + char *body; + int len; + + doc = xmlNewDoc ((const xmlChar *)"1.0"); + doc->standalone = FALSE; + doc->encoding = xmlCharStrdup ("UTF-8"); + + node = xmlNewDocNode (doc, NULL, + (const xmlChar *)"methodResponse", NULL); + xmlDocSetRootElement (doc, node); + + node = xmlNewChild (node, NULL, (const xmlChar *)"params", NULL); + node = xmlNewChild (node, NULL, (const xmlChar *)"param", NULL); + if (!insert_value (node, value)) { + xmlFreeDoc (doc); + return NULL; + } + + xmlDocDumpMemory (doc, &xmlbody, &len); + body = g_strndup ((char *)xmlbody, len); + xmlFree (xmlbody); + xmlFreeDoc (doc); + return body; +} + +/** + * soup_xmlrpc_set_response: + * @msg: an XML-RPC request + * @type: the type of the response value + * @...: the response value + * + * Sets the status code and response body of @msg to indicate a + * successful XML-RPC call, with a return value given by @type and the + * following varargs argument, of the type indicated by @type. + * + * Deprecated: Use soup_xmlrpc_message_set_response() instead. + **/ +void +soup_xmlrpc_set_response (SoupMessage *msg, GType type, ...) +{ + va_list args; + GValue value; + char *body; + + va_start (args, type); + SOUP_VALUE_SETV (&value, type, args); + va_end (args); + + body = soup_xmlrpc_build_method_response (&value); + g_value_unset (&value); + soup_message_set_status (msg, SOUP_STATUS_OK); + soup_message_set_response (msg, "text/xml", SOUP_MEMORY_TAKE, + body, strlen (body)); +} + +char *soup_xmlrpc_build_faultv (int fault_code, + const char *fault_format, + va_list args) G_GNUC_PRINTF (2, 0); + +/** + * soup_xmlrpc_set_fault: + * @msg: an XML-RPC request + * @fault_code: the fault code + * @fault_format: a printf()-style format string + * @...: the parameters to @fault_format + * + * Sets the status code and response body of @msg to indicate an + * unsuccessful XML-RPC call, with the error described by @fault_code + * and @fault_format. + * + * Deprecated: Use soup_xmlrpc_message_set_fault() instead. + **/ +void +soup_xmlrpc_set_fault (SoupMessage *msg, int fault_code, + const char *fault_format, ...) +{ + va_list args; + char *body; + + va_start (args, fault_format); + body = soup_xmlrpc_build_faultv (fault_code, fault_format, args); + va_end (args); + + soup_message_set_status (msg, SOUP_STATUS_OK); + soup_message_set_response (msg, "text/xml", SOUP_MEMORY_TAKE, + body, strlen (body)); +} + + + +static gboolean +parse_value (xmlNode *xmlvalue, GValue *value) +{ + xmlNode *typenode; + const char *typename; + xmlChar *content; + + memset (value, 0, sizeof (GValue)); + + typenode = find_real_node (xmlvalue->children); + if (!typenode) { + /* If no type node, it's a string */ + content = xmlNodeGetContent (typenode); + g_value_init (value, G_TYPE_STRING); + g_value_set_string (value, (char *)content); + xmlFree (content); + return TRUE; + } + + typename = (const char *)typenode->name; + + if (!strcmp (typename, "i4") || !strcmp (typename, "int")) { + content = xmlNodeGetContent (typenode); + g_value_init (value, G_TYPE_INT); + g_value_set_int (value, atoi ((char *)content)); + xmlFree (content); + } else if (!strcmp (typename, "boolean")) { + content = xmlNodeGetContent (typenode); + g_value_init (value, G_TYPE_BOOLEAN); + g_value_set_boolean (value, atoi ((char *)content)); + xmlFree (content); + } else if (!strcmp (typename, "string")) { + content = xmlNodeGetContent (typenode); + g_value_init (value, G_TYPE_STRING); + g_value_set_string (value, (char *)content); + xmlFree (content); + } else if (!strcmp (typename, "double")) { + content = xmlNodeGetContent (typenode); + g_value_init (value, G_TYPE_DOUBLE); + g_value_set_double (value, g_ascii_strtod ((char *)content, NULL)); + xmlFree (content); + } else if (!strcmp (typename, "dateTime.iso8601")) { + content = xmlNodeGetContent (typenode); + g_value_init (value, SOUP_TYPE_DATE); + g_value_take_boxed (value, soup_date_new_from_string ((char *)content)); + xmlFree (content); + } else if (!strcmp (typename, "base64")) { + GByteArray *ba; + guchar *decoded; + gsize len; + + content = xmlNodeGetContent (typenode); + decoded = g_base64_decode ((char *)content, &len); + ba = g_byte_array_sized_new (len); + g_byte_array_append (ba, decoded, len); + g_free (decoded); + xmlFree (content); + g_value_init (value, SOUP_TYPE_BYTE_ARRAY); + g_value_take_boxed (value, ba); + } else if (!strcmp (typename, "struct")) { + xmlNode *member, *child, *mname, *mxval; + GHashTable *hash; + GValue mgval; + + hash = soup_value_hash_new (); + for (member = find_real_node (typenode->children); + member; + member = find_real_node (member->next)) { + if (strcmp ((const char *)member->name, "member") != 0) { + g_hash_table_destroy (hash); + return FALSE; + } + mname = mxval = NULL; + memset (&mgval, 0, sizeof (mgval)); + + for (child = find_real_node (member->children); + child; + child = find_real_node (child->next)) { + if (!strcmp ((const char *)child->name, "name")) + mname = child; + else if (!strcmp ((const char *)child->name, "value")) + mxval = child; + else + break; + } + + if (!mname || !mxval || !parse_value (mxval, &mgval)) { + g_hash_table_destroy (hash); + return FALSE; + } + + content = xmlNodeGetContent (mname); + soup_value_hash_insert_value (hash, (char *)content, &mgval); + xmlFree (content); + g_value_unset (&mgval); + } + g_value_init (value, G_TYPE_HASH_TABLE); + g_value_take_boxed (value, hash); + } else if (!strcmp (typename, "array")) { + xmlNode *data, *xval; + GValueArray *array; + GValue gval; + + data = find_real_node (typenode->children); + if (!data || strcmp ((const char *)data->name, "data") != 0) + return FALSE; + + array = g_value_array_new (1); + for (xval = find_real_node (data->children); + xval; + xval = find_real_node (xval->next)) { + memset (&gval, 0, sizeof (gval)); + if (strcmp ((const char *)xval->name, "value") != 0 || + !parse_value (xval, &gval)) { + g_value_array_free (array); + return FALSE; + } + + g_value_array_append (array, &gval); + g_value_unset (&gval); + } + g_value_init (value, G_TYPE_VALUE_ARRAY); + g_value_take_boxed (value, array); + } else + return FALSE; + + return TRUE; +} + +/** + * soup_xmlrpc_parse_method_call: + * @method_call: the XML-RPC methodCall string + * @length: the length of @method_call, or -1 if it is NUL-terminated + * @method_name: (out): on return, the methodName from @method_call + * @params: (out): on return, the parameters from @method_call + * + * Parses @method_call to get the name and parameters, and returns the + * parameter values in a #GValueArray; see also + * soup_xmlrpc_extract_method_call(), which is more convenient if you + * know in advance what the types of the parameters will be. + * + * Return value: success or failure. + * + * Deprecated: Use soup_xmlrpc_parse_request_full() instead. + **/ +gboolean +soup_xmlrpc_parse_method_call (const char *method_call, int length, + char **method_name, GValueArray **params) +{ + xmlDoc *doc; + xmlNode *node, *param, *xval; + xmlChar *xmlMethodName = NULL; + gboolean success = FALSE; + GValue value; + + doc = xmlParseMemory (method_call, + length == -1 ? strlen (method_call) : length); + if (!doc) + return FALSE; + + node = xmlDocGetRootElement (doc); + if (!node || strcmp ((const char *)node->name, "methodCall") != 0) + goto fail; + + node = find_real_node (node->children); + if (!node || strcmp ((const char *)node->name, "methodName") != 0) + goto fail; + xmlMethodName = xmlNodeGetContent (node); + + node = find_real_node (node->next); + if (node) { + if (strcmp ((const char *)node->name, "params") != 0) + goto fail; + + *params = soup_value_array_new (); + param = find_real_node (node->children); + while (param && !strcmp ((const char *)param->name, "param")) { + xval = find_real_node (param->children); + if (!xval || strcmp ((const char *)xval->name, "value") != 0 || + !parse_value (xval, &value)) { + g_value_array_free (*params); + goto fail; + } + g_value_array_append (*params, &value); + g_value_unset (&value); + + param = find_real_node (param->next); + } + } else + *params = soup_value_array_new (); + + success = TRUE; + *method_name = g_strdup ((char *)xmlMethodName); + +fail: + xmlFreeDoc (doc); + if (xmlMethodName) + xmlFree (xmlMethodName); + return success; +} + +/** + * soup_xmlrpc_extract_method_call: + * @method_call: the XML-RPC methodCall string + * @length: the length of @method_call, or -1 if it is NUL-terminated + * @method_name: (out): on return, the methodName from @method_call + * @...: return types and locations for parameters + * + * Parses @method_call to get the name and parameters, and puts + * the parameters into variables of the appropriate types. + * + * The parameters are handled similarly to + * @soup_xmlrpc_build_method_call, with pairs of types and values, + * terminated by %G_TYPE_INVALID, except that values are pointers to + * variables of the indicated type, rather than values of the type. + * + * See also soup_xmlrpc_parse_method_call(), which can be used if + * you don't know the types of the parameters. + * + * Return value: success or failure. + * + * Deprecated: Use soup_xmlrpc_parse_request_full() instead. + **/ +gboolean +soup_xmlrpc_extract_method_call (const char *method_call, int length, + char **method_name, ...) +{ + GValueArray *params; + gboolean success; + va_list args; + + if (!soup_xmlrpc_parse_method_call (method_call, length, + method_name, ¶ms)) + return FALSE; + + va_start (args, method_name); + success = soup_value_array_to_args (params, args); + va_end (args); + + g_value_array_free (params); + + return success; +} + +/** + * soup_xmlrpc_parse_method_response: + * @method_response: the XML-RPC methodResponse string + * @length: the length of @method_response, or -1 if it is NUL-terminated + * @value: (out): on return, the return value from @method_call + * @error: error return value + * + * Parses @method_response and returns the return value in @value. If + * @method_response is a fault, @value will be unchanged, and @error + * will be set to an error of type %SOUP_XMLRPC_FAULT, with the error + * #code containing the fault code, and the error #message containing + * the fault string. (If @method_response cannot be parsed at all, + * soup_xmlrpc_parse_method_response() will return %FALSE, but @error + * will be unset.) + * + * Return value: %TRUE if a return value was parsed, %FALSE if the + * response could not be parsed, or contained a fault. + * + * Deprecated: Use soup_xmlrpc_parse_response() instead. + **/ +gboolean +soup_xmlrpc_parse_method_response (const char *method_response, int length, + GValue *value, GError **error) +{ + xmlDoc *doc; + xmlNode *node; + gboolean success = FALSE; + + doc = xmlParseMemory (method_response, + length == -1 ? strlen (method_response) : length); + if (!doc) + return FALSE; + + node = xmlDocGetRootElement (doc); + if (!node || strcmp ((const char *)node->name, "methodResponse") != 0) + goto fail; + + node = find_real_node (node->children); + if (!node) + goto fail; + + if (!strcmp ((const char *)node->name, "fault") && error) { + int fault_code; + char *fault_string; + GValue fault_val; + GHashTable *fault_hash; + + node = find_real_node (node->children); + if (!node || strcmp ((const char *)node->name, "value") != 0) + goto fail; + if (!parse_value (node, &fault_val)) + goto fail; + if (!G_VALUE_HOLDS (&fault_val, G_TYPE_HASH_TABLE)) { + g_value_unset (&fault_val); + goto fail; + } + fault_hash = g_value_get_boxed (&fault_val); + if (!soup_value_hash_lookup (fault_hash, "faultCode", + G_TYPE_INT, &fault_code) || + !soup_value_hash_lookup (fault_hash, "faultString", + G_TYPE_STRING, &fault_string)) { + g_value_unset (&fault_val); + goto fail; + } + + g_set_error (error, SOUP_XMLRPC_FAULT, + fault_code, "%s", fault_string); + g_value_unset (&fault_val); + } else if (!strcmp ((const char *)node->name, "params")) { + node = find_real_node (node->children); + if (!node || strcmp ((const char *)node->name, "param") != 0) + goto fail; + node = find_real_node (node->children); + if (!node || strcmp ((const char *)node->name, "value") != 0) + goto fail; + if (!parse_value (node, value)) + goto fail; + success = TRUE; + } + +fail: + xmlFreeDoc (doc); + return success; +} + +/** + * soup_xmlrpc_extract_method_response: + * @method_response: the XML-RPC methodResponse string + * @length: the length of @method_response, or -1 if it is NUL-terminated + * @error: error return value + * @type: the expected type of the return value + * @...: location for return value + * + * Parses @method_response and extracts the return value into + * a variable of the correct type. + * + * If @method_response is a fault, the return value will be unset, + * and @error will be set to an error of type %SOUP_XMLRPC_FAULT, with + * the error #code containing the fault code, and the error #message + * containing the fault string. (If @method_response cannot be parsed + * at all, soup_xmlrpc_extract_method_response() will return %FALSE, + * but @error will be unset.) + * + * Return value: %TRUE if a return value was parsed, %FALSE if the + * response was of the wrong type, or contained a fault. + * + * Deprecated: Use soup_xmlrpc_parse_response() instead. + **/ +gboolean +soup_xmlrpc_extract_method_response (const char *method_response, int length, + GError **error, GType type, ...) +{ + GValue value; + va_list args; + + if (!soup_xmlrpc_parse_method_response (method_response, length, + &value, error)) + return FALSE; + if (!G_VALUE_HOLDS (&value, type)) + return FALSE; + + va_start (args, type); + SOUP_VALUE_GETV (&value, type, args); + va_end (args); + + return TRUE; +} + +static xmlNode * +find_real_node (xmlNode *node) +{ + while (node && (node->type == XML_COMMENT_NODE || + xmlIsBlankNode (node))) + node = node->next; + return node; +} + +G_GNUC_END_IGNORE_DEPRECATIONS diff --git a/libsoup/soup-xmlrpc-old.h b/libsoup/soup-xmlrpc-old.h new file mode 100644 index 0000000..1f486ef --- /dev/null +++ b/libsoup/soup-xmlrpc-old.h @@ -0,0 +1,68 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2007 Red Hat, Inc. + */ + +#ifndef SOUP_XMLRPC_OLD_H +#define SOUP_XMLRPC_OLD_H 1 + +#include + +G_BEGIN_DECLS + +/* XML-RPC client */ +SOUP_AVAILABLE_IN_2_4 +SOUP_DEPRECATED_IN_2_52_FOR(soup_xmlrpc_build_request) +char *soup_xmlrpc_build_method_call (const char *method_name, + GValue *params, + int n_params); +SOUP_AVAILABLE_IN_2_4 +SOUP_DEPRECATED_IN_2_52_FOR(soup_xmlrpc_message_new) +SoupMessage *soup_xmlrpc_request_new (const char *uri, + const char *method_name, + ...); +SOUP_AVAILABLE_IN_2_4 +SOUP_DEPRECATED_IN_2_52_FOR(soup_xmlrpc_parse_response) +gboolean soup_xmlrpc_parse_method_response (const char *method_response, + int length, + GValue *value, + GError **error); +SOUP_AVAILABLE_IN_2_4 +SOUP_DEPRECATED_IN_2_52_FOR(soup_xmlrpc_parse_response) +gboolean soup_xmlrpc_extract_method_response (const char *method_response, + int length, + GError **error, + GType type, + ...); + +/* XML-RPC server */ +SOUP_AVAILABLE_IN_2_4 +SOUP_DEPRECATED_IN_2_52_FOR(soup_xmlrpc_parse_request) +gboolean soup_xmlrpc_parse_method_call (const char *method_call, + int length, + char **method_name, + GValueArray **params); +SOUP_AVAILABLE_IN_2_4 +SOUP_DEPRECATED_IN_2_52_FOR(soup_xmlrpc_parse_request) +gboolean soup_xmlrpc_extract_method_call (const char *method_call, + int length, + char **method_name, + ...); +SOUP_AVAILABLE_IN_2_4 +SOUP_DEPRECATED_IN_2_52_FOR(soup_xmlrpc_build_response) +char *soup_xmlrpc_build_method_response (GValue *value); +SOUP_AVAILABLE_IN_2_4 +SOUP_DEPRECATED_IN_2_52_FOR(soup_xmlrpc_message_set_response) +void soup_xmlrpc_set_response (SoupMessage *msg, + GType type, + ...); +SOUP_AVAILABLE_IN_2_4 +SOUP_DEPRECATED_IN_2_52_FOR(soup_xmlrpc_message_set_fault) +void soup_xmlrpc_set_fault (SoupMessage *msg, + int fault_code, + const char *fault_format, + ...) G_GNUC_PRINTF (3, 4); + +G_END_DECLS + +#endif /* SOUP_XMLRPC_OLD_H */ diff --git a/libsoup/soup-xmlrpc.c b/libsoup/soup-xmlrpc.c new file mode 100644 index 0000000..42dcda9 --- /dev/null +++ b/libsoup/soup-xmlrpc.c @@ -0,0 +1,1478 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-xmlrpc.c: XML-RPC parser/generator + * + * Copyright 2007 Red Hat, Inc. + * Copyright 2007 OpenedHand Ltd. + * Copyright 2015 Collabora ltd. + * + * Author: + * Eduardo Lima Mitev + * Xavier Claessens + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include "soup-xmlrpc.h" +#include "soup.h" + +static gboolean insert_value (xmlNode *parent, GVariant *value, GError **error); + +static gboolean +insert_array (xmlNode *parent, GVariant *value, GError **error) +{ + xmlNode *node; + GVariantIter iter; + GVariant *child; + + node = xmlNewChild (parent, NULL, + (const xmlChar *)"array", NULL); + node = xmlNewChild (node, NULL, + (const xmlChar *)"data", NULL); + + g_variant_iter_init (&iter, value); + while ((child = g_variant_iter_next_value (&iter))) { + if (!insert_value (node, child, error)) { + g_variant_unref (child); + return FALSE; + } + g_variant_unref (child); + } + + return TRUE; +} + +static gboolean +insert_struct_member (xmlNode *parent, GVariant *value, GError **error) +{ + xmlNode *member; + GVariant *mname; + GVariant *mvalue; + gboolean ret = FALSE; + + mname = g_variant_get_child_value (value, 0); + mvalue = g_variant_get_child_value (value, 1); + + if (g_variant_classify (mname) != G_VARIANT_CLASS_STRING) { + g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS, + "Only string keys are supported in dictionaries, got %s", + g_variant_get_type_string (mname)); + goto fail; + } + + member = xmlNewChild (parent, NULL, + (const xmlChar *)"member", NULL); + + xmlNewTextChild (member, NULL, + (const xmlChar *)"name", + (const xmlChar *)g_variant_get_string (mname, NULL)); + + ret = insert_value (member, mvalue, error); + +fail: + g_variant_unref (mname); + g_variant_unref (mvalue); + + return ret; +} + +static gboolean +insert_struct (xmlNode *parent, GVariant *value, GError **error) +{ + xmlNode *struct_node; + GVariantIter iter; + GVariant *child; + + struct_node = xmlNewChild (parent, NULL, + (const xmlChar *)"struct", NULL); + + g_variant_iter_init (&iter, value); + while ((child = g_variant_iter_next_value (&iter))) { + if (!insert_struct_member (struct_node, child, error)) { + g_variant_unref (child); + return FALSE; + } + g_variant_unref (child); + } + + return TRUE; +} + +static gboolean +insert_value (xmlNode *parent, GVariant *value, GError **error) +{ + xmlNode *xvalue; + const char *type_str = NULL; + char buf[128]; + + xvalue = xmlNewChild (parent, NULL, (const xmlChar *)"value", NULL); + + switch (g_variant_classify (value)) { + case G_VARIANT_CLASS_BOOLEAN: + g_snprintf (buf, sizeof (buf), "%d", g_variant_get_boolean (value)); + type_str = "boolean"; + break; + case G_VARIANT_CLASS_BYTE: + g_snprintf (buf, sizeof (buf), "%u", g_variant_get_byte (value)); + type_str = "int"; + break; + case G_VARIANT_CLASS_INT16: + g_snprintf (buf, sizeof (buf), "%d", g_variant_get_int16 (value)); + type_str = "int"; + break; + case G_VARIANT_CLASS_UINT16: + g_snprintf (buf, sizeof (buf), "%u", g_variant_get_uint16 (value)); + type_str = "int"; + break; + case G_VARIANT_CLASS_INT32: + g_snprintf (buf, sizeof (buf), "%d", g_variant_get_int32 (value)); + type_str = "int"; + break; + case G_VARIANT_CLASS_UINT32: + g_snprintf (buf, sizeof (buf), "%u", g_variant_get_uint32 (value)); + type_str = "i8"; + break; + case G_VARIANT_CLASS_INT64: + g_snprintf (buf, sizeof (buf), "%"G_GINT64_FORMAT, g_variant_get_int64 (value)); + type_str = "i8"; + break; + case G_VARIANT_CLASS_DOUBLE: + g_ascii_dtostr (buf, sizeof (buf), g_variant_get_double (value)); + type_str = "double"; + break; + case G_VARIANT_CLASS_STRING: + xmlNewTextChild (xvalue, NULL, + (const xmlChar *)"string", + (const xmlChar *)g_variant_get_string (value, NULL)); + break; + case G_VARIANT_CLASS_VARIANT: { + GVariant *child; + + xmlUnlinkNode (xvalue); + xmlFreeNode (xvalue); + + child = g_variant_get_variant (value); + if (!insert_value (parent, child, error)) { + g_variant_unref (child); + return FALSE; + } + g_variant_unref (child); + break; + } + case G_VARIANT_CLASS_ARRAY: { + if (g_variant_is_of_type (value, G_VARIANT_TYPE_BYTESTRING)) { + char *encoded; + + encoded = g_base64_encode (g_variant_get_data (value), + g_variant_get_size (value)); + xmlNewChild (xvalue, NULL, + (const xmlChar *)"base64", + (const xmlChar *)encoded); + g_free (encoded); + } else if (g_variant_is_of_type (value, G_VARIANT_TYPE_DICTIONARY)) { + if (!insert_struct (xvalue, value, error)) + return FALSE; + } else { + if (!insert_array (xvalue, value, error)) + return FALSE; + } + + break; + } + case G_VARIANT_CLASS_TUPLE: { + /* Special case for custom types */ + if (g_variant_is_of_type (value, G_VARIANT_TYPE ("(oss)"))) { + const char *path; + const char *type; + const char *v; + + g_variant_get (value, "(&o&s&s)", &path, &type, &v); + if (g_str_equal (path, "/org/gnome/libsoup/ExtensionType")) { + xmlNewTextChild (xvalue, NULL, + (const xmlChar *)type, + (const xmlChar *)v); + break; + } + } + + if (!insert_array (xvalue, value, error)) + return FALSE; + break; + } + case G_VARIANT_CLASS_DICT_ENTRY: { + xmlNode *node; + + node = xmlNewChild (xvalue, NULL, + (const xmlChar *)"struct", NULL); + if (!insert_struct_member (node, value, error)) + return FALSE; + break; + } + case G_VARIANT_CLASS_HANDLE: + case G_VARIANT_CLASS_MAYBE: + case G_VARIANT_CLASS_UINT64: + case G_VARIANT_CLASS_OBJECT_PATH: + case G_VARIANT_CLASS_SIGNATURE: + default: + g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS, + "Unsupported type: %s", g_variant_get_type_string (value)); + goto fail; + } + + if (type_str != NULL) { + xmlNewTextChild (xvalue, NULL, + (const xmlChar *)type_str, + (const xmlChar *)buf); + } + + return TRUE; + +fail: + return FALSE; +} + +/** + * soup_xmlrpc_build_request: + * @method_name: the name of the XML-RPC method + * @params: a #GVariant tuple + * @error: a #GError, or %NULL + * + * This creates an XML-RPC methodCall and returns it as a string. + * This is the low-level method that soup_xmlrpc_message_new() is + * built on. + * + * @params is a #GVariant tuple representing the method parameters. + * + * Serialization details: + * - "a{s*}" and "{s*}" are serialized as <struct> + * - "ay" is serialized as <base64> + * - Other arrays and tuples are serialized as <array> + * - booleans are serialized as <boolean> + * - byte, int16, uint16 and int32 are serialized as <int> + * - uint32 and int64 are serialized as the nonstandard <i8> type + * - doubles are serialized as <double> + * - Strings are serialized as <string> + * - Variants (i.e. "v" type) are unwrapped and their child is serialized. + * - #GVariants created by soup_xmlrpc_variant_new_datetime() are serialized as + * <dateTime.iso8601> + * - Other types are not supported and will return %NULL and set @error. + * This notably includes: object-paths, signatures, uint64, handles, maybes + * and dictionaries with non-string keys. + * + * If @params is floating, it is consumed. + * + * Return value: the text of the methodCall, or %NULL on error. + * Since: 2.52 + **/ +char * +soup_xmlrpc_build_request (const char *method_name, + GVariant *params, + GError **error) +{ + xmlDoc *doc; + xmlNode *node, *param; + xmlChar *xmlbody; + GVariantIter iter; + GVariant *child; + int len; + char *body = NULL; + + g_return_val_if_fail (g_variant_is_of_type (params, G_VARIANT_TYPE_TUPLE), NULL); + + g_variant_ref_sink (params); + + doc = xmlNewDoc ((const xmlChar *)"1.0"); + doc->standalone = FALSE; + doc->encoding = xmlCharStrdup ("UTF-8"); + + node = xmlNewDocNode (doc, NULL, (const xmlChar *)"methodCall", NULL); + xmlDocSetRootElement (doc, node); + xmlNewChild (node, NULL, (const xmlChar *)"methodName", + (const xmlChar *)method_name); + + node = xmlNewChild (node, NULL, (const xmlChar *)"params", NULL); + g_variant_iter_init (&iter, params); + while ((child = g_variant_iter_next_value (&iter))) { + param = xmlNewChild (node, NULL, + (const xmlChar *)"param", NULL); + if (!insert_value (param, child, error)) { + xmlFreeDoc (doc); + g_variant_unref (child); + g_variant_unref (params); + return NULL; + } + g_variant_unref (child); + } + + xmlDocDumpMemory (doc, &xmlbody, &len); + body = g_strndup ((char *)xmlbody, len); + xmlFree (xmlbody); + + xmlFreeDoc (doc); + g_variant_unref (params); + + return body; +} + +/** + * soup_xmlrpc_message_new: + * @uri: URI of the XML-RPC service + * @method_name: the name of the XML-RPC method to invoke at @uri + * @params: a #GVariant tuple + * @error: a #GError, or %NULL + * + * Creates an XML-RPC methodCall and returns a #SoupMessage, ready + * to send, for that method call. + * + * See soup_xmlrpc_build_request() for serialization details. + * + * If @params is floating, it is consumed. + * + * Returns: (transfer full): a #SoupMessage encoding the + * indicated XML-RPC request, or %NULL on error. + * + * Since: 2.52 + **/ +SoupMessage * +soup_xmlrpc_message_new (const char *uri, + const char *method_name, + GVariant *params, + GError **error) +{ + SoupMessage *msg; + char *body; + + body = soup_xmlrpc_build_request (method_name, params, error); + if (!body) + return NULL; + + msg = soup_message_new ("POST", uri); + soup_message_set_request (msg, "text/xml", SOUP_MEMORY_TAKE, + body, strlen (body)); + return msg; +} + +/** + * soup_xmlrpc_build_response: + * @value: the return value + * @error: a #GError, or %NULL + * + * This creates a (successful) XML-RPC methodResponse and returns it + * as a string. To create a fault response, use soup_xmlrpc_build_fault(). This + * is the low-level method that soup_xmlrpc_message_set_response() is built on. + * + * See soup_xmlrpc_build_request() for serialization details, but note + * that since a method can only have a single return value, @value + * should not be a tuple here (unless the return value is an array). + * + * If @value is floating, it is consumed. + * + * Returns: the text of the methodResponse, or %NULL on error. + * + * Since: 2.52 + **/ +char * +soup_xmlrpc_build_response (GVariant *value, GError **error) +{ + xmlDoc *doc; + xmlNode *node; + xmlChar *xmlbody; + char *body; + int len; + + g_variant_ref_sink (value); + + doc = xmlNewDoc ((const xmlChar *)"1.0"); + doc->standalone = FALSE; + doc->encoding = xmlCharStrdup ("UTF-8"); + + node = xmlNewDocNode (doc, NULL, + (const xmlChar *)"methodResponse", NULL); + xmlDocSetRootElement (doc, node); + + node = xmlNewChild (node, NULL, (const xmlChar *)"params", NULL); + node = xmlNewChild (node, NULL, (const xmlChar *)"param", NULL); + if (!insert_value (node, value, error)) { + xmlFreeDoc (doc); + g_variant_unref (value); + return NULL; + } + + xmlDocDumpMemory (doc, &xmlbody, &len); + body = g_strndup ((char *)xmlbody, len); + xmlFree (xmlbody); + + xmlFreeDoc (doc); + g_variant_unref (value); + + return body; +} + +char * +soup_xmlrpc_build_faultv (int fault_code, + const char *fault_format, + va_list args) G_GNUC_PRINTF (2, 0); + +char * +soup_xmlrpc_build_faultv (int fault_code, const char *fault_format, va_list args) +{ + xmlDoc *doc; + xmlNode *node, *member; + GVariant *value; + xmlChar *xmlbody; + char *fault_string, *body; + int len; + + fault_string = g_strdup_vprintf (fault_format, args); + + doc = xmlNewDoc ((const xmlChar *)"1.0"); + doc->standalone = FALSE; + doc->encoding = xmlCharStrdup ("UTF-8"); + + node = xmlNewDocNode (doc, NULL, + (const xmlChar *)"methodResponse", NULL); + xmlDocSetRootElement (doc, node); + node = xmlNewChild (node, NULL, (const xmlChar *)"fault", NULL); + node = xmlNewChild (node, NULL, (const xmlChar *)"value", NULL); + node = xmlNewChild (node, NULL, (const xmlChar *)"struct", NULL); + + member = xmlNewChild (node, NULL, (const xmlChar *)"member", NULL); + xmlNewChild (member, NULL, + (const xmlChar *)"name", (const xmlChar *)"faultCode"); + value = g_variant_new_int32 (fault_code); + insert_value (member, value, NULL); + g_variant_unref (value); + + member = xmlNewChild (node, NULL, (const xmlChar *)"member", NULL); + xmlNewChild (member, NULL, + (const xmlChar *)"name", (const xmlChar *)"faultString"); + value = g_variant_new_take_string (fault_string); + insert_value (member, value, NULL); + g_variant_unref (value); + + xmlDocDumpMemory (doc, &xmlbody, &len); + body = g_strndup ((char *)xmlbody, len); + xmlFree (xmlbody); + xmlFreeDoc (doc); + + return body; +} + +/** + * soup_xmlrpc_build_fault: + * @fault_code: the fault code + * @fault_format: a printf()-style format string + * @...: the parameters to @fault_format + * + * This creates an XML-RPC fault response and returns it as a string. + * (To create a successful response, use + * soup_xmlrpc_build_method_response().) + * + * Return value: the text of the fault + **/ +char * +soup_xmlrpc_build_fault (int fault_code, const char *fault_format, ...) +{ + va_list args; + char *body; + + va_start (args, fault_format); + body = soup_xmlrpc_build_faultv (fault_code, fault_format, args); + va_end (args); + return body; +} + +/** + * soup_xmlrpc_message_set_fault: + * @msg: an XML-RPC request + * @fault_code: the fault code + * @fault_format: a printf()-style format string + * @...: the parameters to @fault_format + * + * Sets the status code and response body of @msg to indicate an + * unsuccessful XML-RPC call, with the error described by @fault_code + * and @fault_format. + * + * Since: 2.52 + **/ +void +soup_xmlrpc_message_set_fault (SoupMessage *msg, int fault_code, + const char *fault_format, ...) +{ + va_list args; + char *body; + + va_start (args, fault_format); + body = soup_xmlrpc_build_faultv (fault_code, fault_format, args); + va_end (args); + + soup_message_set_status (msg, SOUP_STATUS_OK); + soup_message_set_response (msg, "text/xml", SOUP_MEMORY_TAKE, + body, strlen (body)); +} + +/** + * soup_xmlrpc_message_set_response: + * @msg: an XML-RPC request + * @value: a #GVariant + * @error: a #GError, or %NULL + * + * Sets the status code and response body of @msg to indicate a + * successful XML-RPC call, with a return value given by @value. To set a + * fault response, use soup_xmlrpc_message_set_fault(). + * + * See soup_xmlrpc_build_request() for serialization details. + * + * If @value is floating, it is consumed. + * + * Returns: %TRUE on success, %FALSE otherwise. + * + * Since: 2.52 + **/ +gboolean +soup_xmlrpc_message_set_response (SoupMessage *msg, GVariant *value, GError **error) +{ + char *body; + + body = soup_xmlrpc_build_response (value, error); + if (!body) + return FALSE; + + soup_message_set_status (msg, SOUP_STATUS_OK); + soup_message_set_response (msg, "text/xml", SOUP_MEMORY_TAKE, + body, strlen (body)); + return TRUE; +} + +static GVariant *parse_value (xmlNode *node, const char **signature, GError **error); + +static xmlNode * +find_real_node (xmlNode *node) +{ + while (node && (node->type == XML_COMMENT_NODE || + xmlIsBlankNode (node))) + node = node->next; + return node; +} + +static char * +signature_get_next_complete_type (const char **signature) +{ + GVariantClass class; + const char *initial_signature; + char *result; + + /* here it is assumed that 'signature' is a valid type string */ + + initial_signature = *signature; + class = (*signature)[0]; + + if (class == G_VARIANT_CLASS_TUPLE || class == G_VARIANT_CLASS_DICT_ENTRY) { + char stack[256] = {0}; + guint stack_len = 0; + + do { + if ((*signature)[0] == G_VARIANT_CLASS_TUPLE) { + stack[stack_len] = ')'; + stack_len++; + } + else if ( (*signature)[0] == G_VARIANT_CLASS_DICT_ENTRY) { + stack[stack_len] = '}'; + stack_len++; + } + + (*signature)++; + + if ( (*signature)[0] == stack[stack_len - 1]) + stack_len--; + } while (stack_len > 0); + + (*signature)++; + } else if (class == G_VARIANT_CLASS_ARRAY || class == G_VARIANT_CLASS_MAYBE) { + char *tmp_sig; + + (*signature)++; + tmp_sig = signature_get_next_complete_type (signature); + g_free (tmp_sig); + } else { + (*signature)++; + } + + result = g_strndup (initial_signature, (*signature) - initial_signature); + + return result; +} + +static GVariant * +parse_array (xmlNode *node, const char **signature, GError **error) +{ + GVariant *variant = NULL; + char *child_signature = NULL; + char *array_signature = NULL; + const char *tmp_signature; + gboolean is_tuple = FALSE; + xmlNode *member; + GVariantBuilder builder; + gboolean is_params = FALSE; + + if (signature && *signature[0] == G_VARIANT_CLASS_VARIANT) + signature = NULL; + + if (g_str_equal (node->name, "array")) { + node = find_real_node (node->children); + if (!g_str_equal (node->name, "data")) { + g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS, + " expected but got '%s'", node->name); + goto fail; + } + } else if (g_str_equal (node->name, "params")) { + is_params = TRUE; + } else { + g_assert_not_reached (); + } + + if (signature != NULL) { + if ((*signature)[0] == G_VARIANT_CLASS_TUPLE) { + tmp_signature = *signature; + array_signature = signature_get_next_complete_type (&tmp_signature); + is_tuple = TRUE; + } + (*signature)++; + child_signature = signature_get_next_complete_type (signature); + } else { + child_signature = g_strdup ("v"); + } + + if (!array_signature) + array_signature = g_strdup_printf ("a%s", child_signature); + g_variant_builder_init (&builder, G_VARIANT_TYPE (array_signature)); + + for (member = find_real_node (node->children); + member; + member = find_real_node (member->next)) { + GVariant *child; + xmlNode *xval = member; + + if (is_params) { + if (!g_str_equal (member->name, "param")) { + g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS, + " expected but got '%s'", member->name); + goto fail; + } + xval = find_real_node (member->children); + } + + if (strcmp ((const char *)xval->name, "value") != 0) { + g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS, + " expected but got '%s'", xval->name); + goto fail; + } + + if (is_tuple && child_signature[0] == ')') { + g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS, + "Too many values for tuple"); + goto fail; + } + + tmp_signature = child_signature; + child = parse_value (xval, &tmp_signature, error); + if (child == NULL) + goto fail; + + if (is_tuple) { + g_free (child_signature), + child_signature = signature_get_next_complete_type (signature); + } + + g_variant_builder_add_value (&builder, child); + } + + if (is_tuple && child_signature[0] != ')') { + g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS, + "Too few values for tuple"); + goto fail; + } + + variant = g_variant_builder_end (&builder); + +fail: + g_variant_builder_clear (&builder); + g_free (child_signature); + g_free (array_signature); + + /* compensate the (*signature)++ call at the end of 'recurse()' */ + if (signature) + (*signature)--; + + return variant; +} + +static void +parse_dict_entry_signature (const char **signature, + char **entry_signature, + char **key_signature, + char **value_signature) +{ + const char *tmp_sig; + + if (signature) + *entry_signature = signature_get_next_complete_type (signature); + else + *entry_signature = g_strdup ("{sv}"); + + tmp_sig = (*entry_signature) + 1; + *key_signature = signature_get_next_complete_type (&tmp_sig); + *value_signature = signature_get_next_complete_type (&tmp_sig); +} + +static GVariant * +parse_dictionary (xmlNode *node, const char **signature, GError **error) +{ + GVariant *variant = NULL; + char *dict_signature; + char *entry_signature; + char *key_signature; + char *value_signature; + GVariantBuilder builder; + xmlNode *member; + + if (signature && *signature[0] == G_VARIANT_CLASS_VARIANT) + signature = NULL; + + if (signature) + (*signature)++; + + parse_dict_entry_signature (signature, + &entry_signature, + &key_signature, + &value_signature); + + dict_signature = g_strdup_printf ("a%s", entry_signature); + g_variant_builder_init (&builder, G_VARIANT_TYPE (dict_signature)); + + if (!g_str_equal (key_signature, "s")) { + g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS, + "Dictionary key must be string but got '%s'", key_signature); + goto fail; + } + + for (member = find_real_node (node->children); + member; + member = find_real_node (member->next)) { + xmlNode *child, *mname, *mxval; + const char *tmp_signature; + GVariant *value; + xmlChar *content; + + if (strcmp ((const char *)member->name, "member") != 0) { + g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS, + " expected but got '%s'", member->name); + goto fail; + } + + mname = mxval = NULL; + + for (child = find_real_node (member->children); + child; + child = find_real_node (child->next)) { + if (!strcmp ((const char *)child->name, "name")) + mname = child; + else if (!strcmp ((const char *)child->name, "value")) + mxval = child; + else { + g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS, + " or expected but got '%s'", child->name); + goto fail; + } + } + + if (!mname || !mxval) { + g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS, + "Missing name or value in "); + goto fail; + } + + tmp_signature = value_signature; + value = parse_value (mxval, &tmp_signature, error); + if (!value) + goto fail; + + content = xmlNodeGetContent (mname); + g_variant_builder_open (&builder, G_VARIANT_TYPE (entry_signature)); + g_variant_builder_add (&builder, "s", content); + g_variant_builder_add_value (&builder, value); + g_variant_builder_close (&builder); + xmlFree (content); + } + + variant = g_variant_builder_end (&builder); + +fail: + g_variant_builder_clear (&builder); + g_free (value_signature); + g_free (key_signature); + g_free (entry_signature); + g_free (dict_signature); + + /* compensate the (*signature)++ call at the end of 'recurse()' */ + if (signature != NULL) + (*signature)--; + + return variant; +} + +static GVariant * +parse_number (xmlNode *typenode, GVariantClass class, GError **error) +{ + xmlChar *content; + const char *str; + char *endptr; + gint64 num = 0; + guint64 unum = 0; + GVariant *variant = NULL; + + content = xmlNodeGetContent (typenode); + str = (const char *) content; + + errno = 0; + + if (class == G_VARIANT_CLASS_UINT64) + unum = g_ascii_strtoull (str, &endptr, 10); + else + num = g_ascii_strtoll (str, &endptr, 10); + + if (errno || endptr == str) { + g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS, + "Couldn't parse number '%s'", str); + goto fail; + } + +#define RANGE(v, min, max) \ +G_STMT_START{ \ + if (v < min || v > max) { \ + g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS, \ + "Number out of range '%s'", str); \ + goto fail; \ + } \ +} G_STMT_END + + switch (class) { + case G_VARIANT_CLASS_BOOLEAN: + RANGE (num, 0, 1); + variant = g_variant_new_boolean (num); + break; + case G_VARIANT_CLASS_BYTE: + RANGE (num, 0, G_MAXUINT8); + variant = g_variant_new_byte (num); + break; + case G_VARIANT_CLASS_INT16: + RANGE (num, G_MININT16, G_MAXINT16); + variant = g_variant_new_int16 (num); + break; + case G_VARIANT_CLASS_UINT16: + RANGE (num, 0, G_MAXUINT16); + variant = g_variant_new_uint16 (num); + break; + case G_VARIANT_CLASS_INT32: + RANGE (num, G_MININT32, G_MAXINT32); + variant = g_variant_new_int32 (num); + break; + case G_VARIANT_CLASS_UINT32: + RANGE (num, 0, G_MAXUINT32); + variant = g_variant_new_uint32 (num); + break; + case G_VARIANT_CLASS_INT64: + RANGE (num, G_MININT64, G_MAXINT64); + variant = g_variant_new_int64 (num); + break; + case G_VARIANT_CLASS_UINT64: + RANGE (unum, 0, G_MAXUINT64); + variant = g_variant_new_uint64 (unum); + break; + default: + g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS, + "<%s> node does not match signature", + (const char *)typenode->name); + goto fail; + } + +fail: + xmlFree (content); + + return variant; +} + +static GVariant * +parse_double (xmlNode *typenode, GError **error) +{ + GVariant *variant = NULL; + xmlChar *content; + const char *str; + char *endptr; + gdouble d; + + content = xmlNodeGetContent (typenode); + str = (const char *) content; + + errno = 0; + d = g_ascii_strtod (str, &endptr); + if (errno || endptr == str) { + g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS, + "Couldn't parse double '%s'", str); + goto fail; + } + + variant = g_variant_new_double (d); + +fail: + xmlFree (content); + + return variant; +} + +static GVariant * +parse_base64 (xmlNode *typenode, GError **error) +{ + GVariant *variant; + xmlChar *content; + guchar *decoded; + gsize len; + + content = xmlNodeGetContent (typenode); + decoded = g_base64_decode ((char *)content, &len); + variant = g_variant_new_from_data (G_VARIANT_TYPE ("ay"), + decoded, len, + TRUE, + g_free, decoded); + xmlFree (content); + + return variant; +} + +static GVariant * +soup_xmlrpc_variant_new_custom (const char *type, const char *v) +{ + return g_variant_new ("(oss)", "/org/gnome/libsoup/ExtensionType", + type, v); +} + +static GVariant * +parse_value (xmlNode *node, const char **signature, GError **error) +{ + xmlNode *typenode; + const char *typename; + xmlChar *content = NULL; + GVariant *variant = NULL; + GVariantClass class = G_VARIANT_CLASS_VARIANT; + + if (signature) + class = *signature[0]; + + if (g_str_equal ((const char *)node->name, "value")) { + typenode = find_real_node (node->children); + if (!typenode) { + /* If no typenode, assume value's content is string */ + typename = "string"; + typenode = node; + } else { + typename = (const char *)typenode->name; + } + } else if (g_str_equal ((const char *)node->name, "params")) { + typenode = node; + typename = "params"; + } else { + g_assert_not_reached (); + } + + if (g_str_equal (typename, "boolean")) { + if (class != G_VARIANT_CLASS_VARIANT && class != G_VARIANT_CLASS_BOOLEAN) { + g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS, + " node does not match signature"); + goto fail; + } + variant = parse_number (typenode, G_VARIANT_CLASS_BOOLEAN, error); + } else if (g_str_equal (typename, "int") || g_str_equal (typename, "i4")) { + if (class == G_VARIANT_CLASS_VARIANT) + variant = parse_number (typenode, G_VARIANT_CLASS_INT32, error); + else + variant = parse_number (typenode, class, error); + } else if (g_str_equal (typename, "i8")) { + if (class == G_VARIANT_CLASS_VARIANT) + variant = parse_number (typenode, G_VARIANT_CLASS_INT64, error); + else + variant = parse_number (typenode, class, error); + } else if (g_str_equal (typename, "double")) { + if (class != G_VARIANT_CLASS_VARIANT && class != G_VARIANT_CLASS_DOUBLE) { + g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS, + " node does not match signature"); + goto fail; + } + variant = parse_double (typenode, error); + } else if (g_str_equal (typename, "string")) { + if (class != G_VARIANT_CLASS_VARIANT && class != G_VARIANT_CLASS_STRING) { + g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS, + " node does not match signature"); + goto fail; + } + content = xmlNodeGetContent (typenode); + variant = g_variant_new_string ((const char *)content); + } else if (g_str_equal (typename, "base64")) { + if (class != G_VARIANT_CLASS_VARIANT) { + if (!g_str_has_prefix (*signature, "ay")) { + g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS, + " node does not match signature"); + goto fail; + } + (*signature)++; + } + variant = parse_base64 (typenode, error); + } else if (g_str_equal (typename, "struct")) { + if (class != G_VARIANT_CLASS_VARIANT && + !g_str_has_prefix (*signature, "a{")) { + g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS, + " node does not match signature"); + goto fail; + } + variant = parse_dictionary (typenode, signature, error); + } else if (g_str_equal (typename, "array") || g_str_equal (typename, "params")) { + if (class != G_VARIANT_CLASS_VARIANT && + class != G_VARIANT_CLASS_ARRAY && + class != G_VARIANT_CLASS_TUPLE) { + g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS, + "<%s> node does not match signature", typename); + goto fail; + } + variant = parse_array (typenode, signature, error); + } else if (g_str_equal (typename, "dateTime.iso8601")) { + if (class != G_VARIANT_CLASS_VARIANT) { + g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS, + " node does not match signature"); + goto fail; + } + + content = xmlNodeGetContent (typenode); + variant = soup_xmlrpc_variant_new_custom ("dateTime.iso8601", + (const char *)content); + } else { + g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS, + "Unknown node name %s", typename); + goto fail; + } + + if (variant && signature) { + if (class == G_VARIANT_CLASS_VARIANT) + variant = g_variant_new_variant (variant); + (*signature)++; + } + +fail: + if (content) + xmlFree (content); + + return variant; +} + +/** + * SoupXMLRPCParams: + * + * Opaque structure containing XML-RPC methodCall parameter values. + * Can be parsed using soup_xmlrpc_params_parse() and freed with + * soup_xmlrpc_params_free(). + * + * Since: 2.52 + */ +struct _SoupXMLRPCParams +{ + xmlNode *node; +}; + +/** + * soup_xmlrpc_params_free: + * @self: a SoupXMLRPCParams + * + * Free a #SoupXMLRPCParams returned by soup_xmlrpc_parse_request(). + * + * Since: 2.52 + */ +void +soup_xmlrpc_params_free (SoupXMLRPCParams *self) +{ + g_return_if_fail (self != NULL); + + if (self->node) + xmlFreeDoc (self->node->doc); + g_slice_free (SoupXMLRPCParams, self); +} + +static SoupXMLRPCParams * +soup_xmlrpc_params_new (xmlNode *node) +{ + SoupXMLRPCParams *self; + + self = g_slice_new (SoupXMLRPCParams); + self->node = node; + + return self; +} + +/** + * soup_xmlrpc_params_parse: + * @self: A #SoupXMLRPCParams + * @signature: (allow-none): A valid #GVariant type string, or %NULL + * @error: a #GError, or %NULL + * + * Parse method parameters returned by soup_xmlrpc_parse_request(). + * + * Deserialization details: + * - If @signature is provided, <int> and <i4> can be deserialized + * to byte, int16, uint16, int32, uint32, int64 or uint64. Otherwise + * it will be deserialized to int32. If the value is out of range + * for the target type it will return an error. + * - <struct> will be deserialized to "a{sv}". @signature could define + * another value type (e.g. "a{ss}"). + * - <array> will be deserialized to "av". @signature could define + * another element type (e.g. "as") or could be a tuple (e.g. "(ss)"). + * - <base64> will be deserialized to "ay". + * - <string> will be deserialized to "s". + * - <dateTime.iso8601> will be deserialized to an unspecified variant + * type. If @signature is provided it must have the generic "v" type, which + * means there is no guarantee that it's actually a datetime that has been + * received. soup_xmlrpc_variant_get_datetime() must be used to parse and + * type check this special variant. + * - @signature must not have maybes, otherwise an error is returned. + * - Dictionaries must have string keys, otherwise an error is returned. + * + * Returns: (transfer full): a new (non-floating) #GVariant, or %NULL + * + * Since: 2.52 + */ +GVariant * +soup_xmlrpc_params_parse (SoupXMLRPCParams *self, + const char *signature, + GError **error) +{ + GVariant *value = NULL; + + g_return_val_if_fail (self, NULL); + g_return_val_if_fail (!signature || g_variant_type_string_is_valid (signature), NULL); + + if (!self->node) { + if (!signature || g_variant_type_equal (G_VARIANT_TYPE (signature), G_VARIANT_TYPE ("av"))) + value = g_variant_new_array (G_VARIANT_TYPE_VARIANT, NULL, 0); + else if (g_variant_type_equal (G_VARIANT_TYPE (signature), G_VARIANT_TYPE_UNIT)) + value = g_variant_new_tuple (NULL, 0); + else { + g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS, + "Invalid signature '%s', was expecting '()'", signature); + goto fail; + } + } else { + value = parse_value (self->node, signature ? &signature : NULL, error); + } + +fail: + return value ? g_variant_ref_sink (value) : NULL; +} + +/** + * soup_xmlrpc_parse_request: + * @method_call: the XML-RPC methodCall string + * @length: the length of @method_call, or -1 if it is NUL-terminated + * @params: (out): on success, a new #SoupXMLRPCParams + * @error: a #GError, or %NULL + * + * Parses @method_call and return the method name. Method parameters can be + * parsed later using soup_xmlrpc_params_parse(). + * + * Returns: (transfer full): method's name, or %NULL on error. + * Since: 2.52 + **/ +char * +soup_xmlrpc_parse_request (const char *method_call, + int length, + SoupXMLRPCParams **params, + GError **error) +{ + xmlDoc *doc = NULL; + xmlNode *node; + xmlChar *xmlMethodName = NULL; + char *method_name = NULL; + + doc = xmlParseMemory (method_call, length == -1 ? strlen (method_call) : length); + if (!doc) { + g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS, + "Could not parse XML document"); + goto fail; + } + + node = xmlDocGetRootElement (doc); + if (!node || strcmp ((const char *)node->name, "methodCall") != 0) { + g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS, + " node expected"); + goto fail; + } + + node = find_real_node (node->children); + if (!node || strcmp ((const char *)node->name, "methodName") != 0) { + g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS, + " node expected"); + goto fail; + } + xmlMethodName = xmlNodeGetContent (node); + + if (params) { + node = find_real_node (node->next); + if (node) { + if (strcmp ((const char *)node->name, "params") != 0) { + g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS, + " node expected"); + goto fail; + } + *params = soup_xmlrpc_params_new (node); + doc = NULL; + } else { + *params = soup_xmlrpc_params_new (NULL); + } + } + + method_name = g_strdup ((char *)xmlMethodName); + +fail: + if (doc) + xmlFreeDoc (doc); + if (xmlMethodName) + xmlFree (xmlMethodName); + + return method_name; +} + +/** + * soup_xmlrpc_parse_response: + * @method_response: the XML-RPC methodResponse string + * @length: the length of @method_response, or -1 if it is NUL-terminated + * @signature: (allow-none): A valid #GVariant type string, or %NULL + * @error: a #GError, or %NULL + * + * Parses @method_response and returns the return value. If + * @method_response is a fault, %NULL is returned, and @error + * will be set to an error in the %SOUP_XMLRPC_FAULT domain, with the error + * code containing the fault code, and the error message containing + * the fault string. If @method_response cannot be parsed, %NULL is returned, + * and @error will be set to an error in the %SOUP_XMLRPC_ERROR domain. + * + * See soup_xmlrpc_params_parse() for deserialization details. + * + * Returns: (transfer full): a new (non-floating) #GVariant, or %NULL + * + * Since: 2.52 + **/ +GVariant * +soup_xmlrpc_parse_response (const char *method_response, + int length, + const char *signature, + GError **error) +{ + xmlDoc *doc = NULL; + xmlNode *node; + GVariant *value = NULL; + + g_return_val_if_fail (!signature || g_variant_type_string_is_valid (signature), NULL); + + doc = xmlParseMemory (method_response, + length == -1 ? strlen (method_response) : length); + if (!doc) { + g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS, + "Failed to parse response XML"); + goto fail; + } + + node = xmlDocGetRootElement (doc); + if (!node || strcmp ((const char *)node->name, "methodResponse") != 0) { + g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS, + "Missing 'methodResponse' node"); + goto fail; + } + + node = find_real_node (node->children); + if (!node) { + g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS, + "'methodResponse' has no child"); + goto fail; + } + + if (!strcmp ((const char *)node->name, "fault")) { + int fault_code; + const char *fault_string; + const char *fault_sig = "a{sv}"; + GVariant *fault_val; + + node = find_real_node (node->children); + if (!node || strcmp ((const char *)node->name, "value") != 0) { + g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS, + "'fault' has no 'value' child"); + goto fail; + } + + fault_val = parse_value (node, &fault_sig, error); + if (!fault_val) + goto fail; + + if (!g_variant_lookup (fault_val, "faultCode", "i", &fault_code) || + !g_variant_lookup (fault_val, "faultString", "&s", &fault_string)) { + g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS, + "'fault' missing 'faultCode' or 'faultString'"); + goto fail; + } + g_set_error (error, SOUP_XMLRPC_FAULT, + fault_code, "%s", fault_string); + g_variant_unref (fault_val); + } else if (!strcmp ((const char *)node->name, "params")) { + node = find_real_node (node->children); + if (!node || strcmp ((const char *)node->name, "param") != 0) { + g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS, + "'params' has no 'param' child"); + goto fail; + } + node = find_real_node (node->children); + if (!node || strcmp ((const char *)node->name, "value") != 0) { + g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS, + "'param' has no 'value' child"); + goto fail; + } + value = parse_value (node, signature ? &signature : NULL, error); + } + +fail: + if (doc) + xmlFreeDoc (doc); + return value ? g_variant_ref_sink (value) : NULL; +} + +/** + * soup_xmlrpc_variant_new_datetime: + * @date: a #SoupDate + * + * Construct a special #GVariant used to serialize a <dateTime.iso8601> + * node. See soup_xmlrpc_build_request(). + * + * The actual type of the returned #GVariant is unspecified and "v" or "*" + * should be used in variant format strings. For example: + * + * args = g_variant_new ("(v)", soup_xmlrpc_variant_new_datetime (date)); + * + * + * Returns: a floating #GVariant. + * + * Since: 2.52 + */ +GVariant * +soup_xmlrpc_variant_new_datetime (SoupDate *date) +{ + GVariant *variant; + char *str; + + str = soup_date_to_string (date, SOUP_DATE_ISO8601_XMLRPC); + variant = soup_xmlrpc_variant_new_custom ("dateTime.iso8601", str); + g_free (str); + + return variant; +} + +/** + * soup_xmlrpc_variant_get_datetime: + * @variant: a #GVariant + * @error: a #GError, or %NULL + * + * Get the #SoupDate from special #GVariant created by + * soup_xmlrpc_variant_new_datetime() or by parsing a <dateTime.iso8601> + * node. See soup_xmlrpc_params_parse(). + * + * If @variant does not contain a datetime it will return an error but it is not + * considered a programmer error because it generally means parameters received + * are not in the expected type. + * + * Returns: a new #SoupDate, or %NULL on error. + * + * Since: 2.52 + */ +SoupDate * +soup_xmlrpc_variant_get_datetime (GVariant *variant, GError **error) +{ + SoupDate *date = NULL; + const char *path; + const char *type; + const char *v; + + if (!g_variant_is_of_type (variant, G_VARIANT_TYPE ("(oss)"))) { + g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS, + "Variant is of type '%s' which is not expected for a datetime", + g_variant_get_type_string (variant)); + return NULL; + } + + g_variant_get (variant, "(&o&s&s)", &path, &type, &v); + + if (!g_str_equal (path, "/org/gnome/libsoup/ExtensionType") || + !g_str_equal (type, "dateTime.iso8601")) { + g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS, + "Variant doesn't represent a datetime: %s", + g_variant_get_type_string (variant)); + return NULL; + } + + date = soup_date_new_from_string (v); + + if (date == NULL) { + g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS, + "Can't parse datetime string: %s", v); + return NULL; + } + + return date; + +} + +/** + * SOUP_XMLRPC_FAULT: + * + * A #GError domain representing an XML-RPC fault code. Used with + * #SoupXMLRPCFault (although servers may also return fault codes not + * in that enumeration). + */ + +/** + * SoupXMLRPCFault: + * @SOUP_XMLRPC_FAULT_PARSE_ERROR_NOT_WELL_FORMED: request was not + * well-formed + * @SOUP_XMLRPC_FAULT_PARSE_ERROR_UNSUPPORTED_ENCODING: request was in + * an unsupported encoding + * @SOUP_XMLRPC_FAULT_PARSE_ERROR_INVALID_CHARACTER_FOR_ENCODING: + * request contained an invalid character + * @SOUP_XMLRPC_FAULT_SERVER_ERROR_INVALID_XML_RPC: request was not + * valid XML-RPC + * @SOUP_XMLRPC_FAULT_SERVER_ERROR_REQUESTED_METHOD_NOT_FOUND: method + * not found + * @SOUP_XMLRPC_FAULT_SERVER_ERROR_INVALID_METHOD_PARAMETERS: invalid + * parameters + * @SOUP_XMLRPC_FAULT_SERVER_ERROR_INTERNAL_XML_RPC_ERROR: internal + * error + * @SOUP_XMLRPC_FAULT_APPLICATION_ERROR: start of reserved range for + * application error codes + * @SOUP_XMLRPC_FAULT_SYSTEM_ERROR: start of reserved range for + * system error codes + * @SOUP_XMLRPC_FAULT_TRANSPORT_ERROR: start of reserved range for + * transport error codes + * + * Pre-defined XML-RPC fault codes from http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php. + * These are an extension, not part of the XML-RPC spec; you can't + * assume servers will use them. + */ + +G_DEFINE_QUARK (soup_xmlrpc_fault_quark, soup_xmlrpc_fault); +G_DEFINE_QUARK (soup_xmlrpc_error_quark, soup_xmlrpc_error); diff --git a/libsoup/soup-xmlrpc.h b/libsoup/soup-xmlrpc.h new file mode 100644 index 0000000..1c4634f --- /dev/null +++ b/libsoup/soup-xmlrpc.h @@ -0,0 +1,97 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright 2015 - Collabora Ltd. + */ + +#ifndef SOUP_XMLRPC_H +#define SOUP_XMLRPC_H 1 + +#include +#include + +G_BEGIN_DECLS + +/* XML-RPC client */ +SOUP_AVAILABLE_IN_2_52 +char *soup_xmlrpc_build_request (const char *method_name, + GVariant *params, + GError **error); +SOUP_AVAILABLE_IN_2_52 +SoupMessage *soup_xmlrpc_message_new (const char *uri, + const char *method_name, + GVariant *params, + GError **error); +SOUP_AVAILABLE_IN_2_52 +GVariant *soup_xmlrpc_parse_response (const char *method_response, + int length, + const char *signature, + GError **error); + +/* XML-RPC server */ +typedef struct _SoupXMLRPCParams SoupXMLRPCParams; +SOUP_AVAILABLE_IN_2_52 +void soup_xmlrpc_params_free (SoupXMLRPCParams *self); +SOUP_AVAILABLE_IN_2_52 +GVariant *soup_xmlrpc_params_parse (SoupXMLRPCParams *self, + const char *signature, + GError **error); +SOUP_AVAILABLE_IN_2_52 +char *soup_xmlrpc_parse_request (const char *method_call, + int length, + SoupXMLRPCParams **params, + GError **error); +SOUP_AVAILABLE_IN_2_52 +char *soup_xmlrpc_build_response (GVariant *value, + GError **error); +SOUP_AVAILABLE_IN_2_4 +char *soup_xmlrpc_build_fault (int fault_code, + const char *fault_format, + ...) G_GNUC_PRINTF (2, 3); +SOUP_AVAILABLE_IN_2_52 +gboolean soup_xmlrpc_message_set_response (SoupMessage *msg, + GVariant *value, + GError **error); +SOUP_AVAILABLE_IN_2_52 +void soup_xmlrpc_message_set_fault (SoupMessage *msg, + int fault_code, + const char *fault_format, + ...) G_GNUC_PRINTF (3, 4); + +/* Utils */ +SOUP_AVAILABLE_IN_2_52 +GVariant *soup_xmlrpc_variant_new_datetime (SoupDate *date); + +SOUP_AVAILABLE_IN_2_52 +SoupDate *soup_xmlrpc_variant_get_datetime (GVariant *variant, + GError **error); + +/* Errors */ +#define SOUP_XMLRPC_ERROR soup_xmlrpc_error_quark() +SOUP_AVAILABLE_IN_2_4 +GQuark soup_xmlrpc_error_quark (void); + +typedef enum { + SOUP_XMLRPC_ERROR_ARGUMENTS, + SOUP_XMLRPC_ERROR_RETVAL +} SoupXMLRPCError; + +#define SOUP_XMLRPC_FAULT soup_xmlrpc_fault_quark() +SOUP_AVAILABLE_IN_2_4 +GQuark soup_xmlrpc_fault_quark (void); + +typedef enum { + SOUP_XMLRPC_FAULT_PARSE_ERROR_NOT_WELL_FORMED = -32700, + SOUP_XMLRPC_FAULT_PARSE_ERROR_UNSUPPORTED_ENCODING = -32701, + SOUP_XMLRPC_FAULT_PARSE_ERROR_INVALID_CHARACTER_FOR_ENCODING = -32702, + SOUP_XMLRPC_FAULT_SERVER_ERROR_INVALID_XML_RPC = -32600, + SOUP_XMLRPC_FAULT_SERVER_ERROR_REQUESTED_METHOD_NOT_FOUND = -32601, + SOUP_XMLRPC_FAULT_SERVER_ERROR_INVALID_METHOD_PARAMETERS = -32602, + SOUP_XMLRPC_FAULT_SERVER_ERROR_INTERNAL_XML_RPC_ERROR = -32603, + SOUP_XMLRPC_FAULT_APPLICATION_ERROR = -32500, + SOUP_XMLRPC_FAULT_SYSTEM_ERROR = -32400, + SOUP_XMLRPC_FAULT_TRANSPORT_ERROR = -32300 +} SoupXMLRPCFault; + +G_END_DECLS + +#endif /* SOUP_XMLRPC_H */ diff --git a/libsoup/soup.h b/libsoup/soup.h new file mode 100644 index 0000000..6bedb62 --- /dev/null +++ b/libsoup/soup.h @@ -0,0 +1,68 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2000-2003, Ximian, Inc. + */ + +#ifndef SOUP_H +#define SOUP_H 1 + +#ifdef __cplusplus +extern "C" { +#endif + +#define __SOUP_H_INSIDE__ + +#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 +#include +#include +#include +#include +#include +#include + +#include + +#undef __SOUP_H_INSIDE__ + +#ifdef __cplusplus +} +#endif + +#endif /* SOUP_H */ diff --git a/libsoup/tld-parser.py b/libsoup/tld-parser.py new file mode 100755 index 0000000..a743471 --- /dev/null +++ b/libsoup/tld-parser.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 + +# Generate tld rules +# Copyright (C) 2012 Red Hat, Inc. +# Based on tld-parser.c Copyright (C) 2012 Igalia S.L. + +import sys +import codecs + +SOUP_TLD_RULE_NORMAL = 0 +SOUP_TLD_RULE_MATCH_ALL = 1 << 0 +SOUP_TLD_RULE_EXCEPTION = 1 << 1 + +tlds_file = codecs.open(sys.argv[1], encoding='utf-8') +inc_file = codecs.open(sys.argv[2], 'w', encoding='utf-8') + +first = True +for rule in tlds_file: + rule = rule.strip() + if rule == '' or rule.startswith('//'): + continue + domain = rule + flags = 0 + if rule[0] == '!': + domain = domain[1:] + flags |= SOUP_TLD_RULE_EXCEPTION + + if domain.startswith('*.'): + domain = domain[2:] + flags |= SOUP_TLD_RULE_MATCH_ALL + + if domain.startswith('.'): + domain = domain[1:] + + if not first: + inc_file.write(',\n') + else: + first = False + inc_file.write('{ "%s", %d }' % (domain.strip(), flags)) + +inc_file.write('\n') + +tlds_file.close() +inc_file.close() + diff --git a/ltmain.sh b/ltmain.sh new file mode 100644 index 0000000..a736cf9 --- /dev/null +++ b/ltmain.sh @@ -0,0 +1,11156 @@ +#! /bin/sh +## DO NOT EDIT - This file generated from ./build-aux/ltmain.in +## by inline-source v2014-01-03.01 + +# libtool (GNU libtool) 2.4.6 +# Provide generalized library-building support services. +# Written by Gordon Matzigkeit , 1996 + +# Copyright (C) 1996-2015 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. + +# GNU Libtool 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. +# +# As a special exception to the GNU General Public License, +# if you distribute this file as part of a program or library that +# is built using GNU Libtool, you may include this file under the +# same distribution terms that you use for the rest of that program. +# +# GNU Libtool is distributed in the hope that 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 . + + +PROGRAM=libtool +PACKAGE=libtool +VERSION="2.4.6 Debian-2.4.6-2" +package_revision=2.4.6 + + +## ------ ## +## Usage. ## +## ------ ## + +# Run './libtool --help' for help with using this script from the +# command line. + + +## ------------------------------- ## +## User overridable command paths. ## +## ------------------------------- ## + +# After configure completes, it has a better idea of some of the +# shell tools we need than the defaults used by the functions shared +# with bootstrap, so set those here where they can still be over- +# ridden by the user, but otherwise take precedence. + +: ${AUTOCONF="autoconf"} +: ${AUTOMAKE="automake"} + + +## -------------------------- ## +## Source external libraries. ## +## -------------------------- ## + +# Much of our low-level functionality needs to be sourced from external +# libraries, which are installed to $pkgauxdir. + +# Set a version string for this script. +scriptversion=2015-01-20.17; # UTC + +# General shell script boiler plate, and helper functions. +# Written by Gary V. Vaughan, 2004 + +# Copyright (C) 2004-2015 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. + +# 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 3 of the License, or +# (at your option) any later version. + +# As a special exception to the GNU General Public License, if you distribute +# this file as part of a program or library that is built using GNU Libtool, +# you may include this file under the same distribution terms that you use +# for the rest of that program. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNES 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 . + +# Please report bugs or propose patches to gary@gnu.org. + + +## ------ ## +## Usage. ## +## ------ ## + +# Evaluate this file near the top of your script to gain access to +# the functions and variables defined here: +# +# . `echo "$0" | ${SED-sed} 's|[^/]*$||'`/build-aux/funclib.sh +# +# If you need to override any of the default environment variable +# settings, do that before evaluating this file. + + +## -------------------- ## +## Shell normalisation. ## +## -------------------- ## + +# Some shells need a little help to be as Bourne compatible as possible. +# Before doing anything else, make sure all that help has been provided! + +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 + +# NLS nuisances: We save the old values in case they are required later. +_G_user_locale= +_G_safe_locale= +for _G_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES +do + eval "if test set = \"\${$_G_var+set}\"; then + save_$_G_var=\$$_G_var + $_G_var=C + export $_G_var + _G_user_locale=\"$_G_var=\\\$save_\$_G_var; \$_G_user_locale\" + _G_safe_locale=\"$_G_var=C; \$_G_safe_locale\" + fi" +done + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# Make sure IFS has a sensible default +sp=' ' +nl=' +' +IFS="$sp $nl" + +# There are apparently some retarded systems that use ';' as a PATH separator! +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 + + + +## ------------------------- ## +## Locate command utilities. ## +## ------------------------- ## + + +# func_executable_p FILE +# ---------------------- +# Check that FILE is an executable regular file. +func_executable_p () +{ + test -f "$1" && test -x "$1" +} + + +# func_path_progs PROGS_LIST CHECK_FUNC [PATH] +# -------------------------------------------- +# Search for either a program that responds to --version with output +# containing "GNU", or else returned by CHECK_FUNC otherwise, by +# trying all the directories in PATH with each of the elements of +# PROGS_LIST. +# +# CHECK_FUNC should accept the path to a candidate program, and +# set $func_check_prog_result if it truncates its output less than +# $_G_path_prog_max characters. +func_path_progs () +{ + _G_progs_list=$1 + _G_check_func=$2 + _G_PATH=${3-"$PATH"} + + _G_path_prog_max=0 + _G_path_prog_found=false + _G_save_IFS=$IFS; IFS=${PATH_SEPARATOR-:} + for _G_dir in $_G_PATH; do + IFS=$_G_save_IFS + test -z "$_G_dir" && _G_dir=. + for _G_prog_name in $_G_progs_list; do + for _exeext in '' .EXE; do + _G_path_prog=$_G_dir/$_G_prog_name$_exeext + func_executable_p "$_G_path_prog" || continue + case `"$_G_path_prog" --version 2>&1` in + *GNU*) func_path_progs_result=$_G_path_prog _G_path_prog_found=: ;; + *) $_G_check_func $_G_path_prog + func_path_progs_result=$func_check_prog_result + ;; + esac + $_G_path_prog_found && break 3 + done + done + done + IFS=$_G_save_IFS + test -z "$func_path_progs_result" && { + echo "no acceptable sed could be found in \$PATH" >&2 + exit 1 + } +} + + +# We want to be able to use the functions in this file before configure +# has figured out where the best binaries are kept, which means we have +# to search for them ourselves - except when the results are already set +# where we skip the searches. + +# Unless the user overrides by setting SED, search the path for either GNU +# sed, or the sed that truncates its output the least. +test -z "$SED" && { + _G_sed_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ + for _G_i in 1 2 3 4 5 6 7; do + _G_sed_script=$_G_sed_script$nl$_G_sed_script + done + echo "$_G_sed_script" 2>/dev/null | sed 99q >conftest.sed + _G_sed_script= + + func_check_prog_sed () + { + _G_path_prog=$1 + + _G_count=0 + printf 0123456789 >conftest.in + while : + do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo '' >> conftest.nl + "$_G_path_prog" -f conftest.sed conftest.out 2>/dev/null || break + diff conftest.out conftest.nl >/dev/null 2>&1 || break + _G_count=`expr $_G_count + 1` + if test "$_G_count" -gt "$_G_path_prog_max"; then + # Best one so far, save it but keep looking for a better one + func_check_prog_result=$_G_path_prog + _G_path_prog_max=$_G_count + fi + # 10*(2^10) chars as input seems more than enough + test 10 -lt "$_G_count" && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out + } + + func_path_progs "sed gsed" func_check_prog_sed $PATH:/usr/xpg4/bin + rm -f conftest.sed + SED=$func_path_progs_result +} + + +# Unless the user overrides by setting GREP, search the path for either GNU +# grep, or the grep that truncates its output the least. +test -z "$GREP" && { + func_check_prog_grep () + { + _G_path_prog=$1 + + _G_count=0 + _G_path_prog_max=0 + printf 0123456789 >conftest.in + while : + do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo 'GREP' >> conftest.nl + "$_G_path_prog" -e 'GREP$' -e '-(cannot match)-' conftest.out 2>/dev/null || break + diff conftest.out conftest.nl >/dev/null 2>&1 || break + _G_count=`expr $_G_count + 1` + if test "$_G_count" -gt "$_G_path_prog_max"; then + # Best one so far, save it but keep looking for a better one + func_check_prog_result=$_G_path_prog + _G_path_prog_max=$_G_count + fi + # 10*(2^10) chars as input seems more than enough + test 10 -lt "$_G_count" && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out + } + + func_path_progs "grep ggrep" func_check_prog_grep $PATH:/usr/xpg4/bin + GREP=$func_path_progs_result +} + + +## ------------------------------- ## +## User overridable command paths. ## +## ------------------------------- ## + +# All uppercase variable names are used for environment variables. These +# variables can be overridden by the user before calling a script that +# uses them if a suitable command of that name is not already available +# in the command search PATH. + +: ${CP="cp -f"} +: ${ECHO="printf %s\n"} +: ${EGREP="$GREP -E"} +: ${FGREP="$GREP -F"} +: ${LN_S="ln -s"} +: ${MAKE="make"} +: ${MKDIR="mkdir"} +: ${MV="mv -f"} +: ${RM="rm -f"} +: ${SHELL="${CONFIG_SHELL-/bin/sh}"} + + +## -------------------- ## +## Useful sed snippets. ## +## -------------------- ## + +sed_dirname='s|/[^/]*$||' +sed_basename='s|^.*/||' + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +sed_quote_subst='s|\([`"$\\]\)|\\\1|g' + +# Same as above, but do not quote variable references. +sed_double_quote_subst='s/\(["`\\]\)/\\\1/g' + +# Sed substitution that turns a string into a regex matching for the +# string literally. +sed_make_literal_regex='s|[].[^$\\*\/]|\\&|g' + +# Sed substitution that converts a w32 file name or path +# that contains forward slashes, into one that contains +# (escaped) backslashes. A very naive implementation. +sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' + +# Re-'\' parameter expansions in output of sed_double_quote_subst that +# were '\'-ed in input to the same. If an odd number of '\' preceded a +# '$' in input to sed_double_quote_subst, that '$' was protected from +# expansion. Since each input '\' is now two '\'s, look for any number +# of runs of four '\'s followed by two '\'s and then a '$'. '\' that '$'. +_G_bs='\\' +_G_bs2='\\\\' +_G_bs4='\\\\\\\\' +_G_dollar='\$' +sed_double_backslash="\ + s/$_G_bs4/&\\ +/g + s/^$_G_bs2$_G_dollar/$_G_bs&/ + s/\\([^$_G_bs]\\)$_G_bs2$_G_dollar/\\1$_G_bs2$_G_bs$_G_dollar/g + s/\n//g" + + +## ----------------- ## +## Global variables. ## +## ----------------- ## + +# Except for the global variables explicitly listed below, the following +# functions in the '^func_' namespace, and the '^require_' namespace +# variables initialised in the 'Resource management' section, sourcing +# this file will not pollute your global namespace with anything +# else. There's no portable way to scope variables in Bourne shell +# though, so actually running these functions will sometimes place +# results into a variable named after the function, and often use +# temporary variables in the '^_G_' namespace. If you are careful to +# avoid using those namespaces casually in your sourcing script, things +# should continue to work as you expect. And, of course, you can freely +# overwrite any of the functions or variables defined here before +# calling anything to customize them. + +EXIT_SUCCESS=0 +EXIT_FAILURE=1 +EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. +EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. + +# Allow overriding, eg assuming that you follow the convention of +# putting '$debug_cmd' at the start of all your functions, you can get +# bash to show function call trace with: +# +# debug_cmd='eval echo "${FUNCNAME[0]} $*" >&2' bash your-script-name +debug_cmd=${debug_cmd-":"} +exit_cmd=: + +# By convention, finish your script with: +# +# exit $exit_status +# +# so that you can set exit_status to non-zero if you want to indicate +# something went wrong during execution without actually bailing out at +# the point of failure. +exit_status=$EXIT_SUCCESS + +# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh +# is ksh but when the shell is invoked as "sh" and the current value of +# the _XPG environment variable is not equal to 1 (one), the special +# positional parameter $0, within a function call, is the name of the +# function. +progpath=$0 + +# The name of this program. +progname=`$ECHO "$progpath" |$SED "$sed_basename"` + +# Make sure we have an absolute progpath for reexecution: +case $progpath in + [\\/]*|[A-Za-z]:\\*) ;; + *[\\/]*) + progdir=`$ECHO "$progpath" |$SED "$sed_dirname"` + progdir=`cd "$progdir" && pwd` + progpath=$progdir/$progname + ;; + *) + _G_IFS=$IFS + IFS=${PATH_SEPARATOR-:} + for progdir in $PATH; do + IFS=$_G_IFS + test -x "$progdir/$progname" && break + done + IFS=$_G_IFS + test -n "$progdir" || progdir=`pwd` + progpath=$progdir/$progname + ;; +esac + + +## ----------------- ## +## Standard options. ## +## ----------------- ## + +# The following options affect the operation of the functions defined +# below, and should be set appropriately depending on run-time para- +# meters passed on the command line. + +opt_dry_run=false +opt_quiet=false +opt_verbose=false + +# Categories 'all' and 'none' are always available. Append any others +# you will pass as the first argument to func_warning from your own +# code. +warning_categories= + +# By default, display warnings according to 'opt_warning_types'. Set +# 'warning_func' to ':' to elide all warnings, or func_fatal_error to +# treat the next displayed warning as a fatal error. +warning_func=func_warn_and_continue + +# Set to 'all' to display all warnings, 'none' to suppress all +# warnings, or a space delimited list of some subset of +# 'warning_categories' to display only the listed warnings. +opt_warning_types=all + + +## -------------------- ## +## Resource management. ## +## -------------------- ## + +# This section contains definitions for functions that each ensure a +# particular resource (a file, or a non-empty configuration variable for +# example) is available, and if appropriate to extract default values +# from pertinent package files. Call them using their associated +# 'require_*' variable to ensure that they are executed, at most, once. +# +# It's entirely deliberate that calling these functions can set +# variables that don't obey the namespace limitations obeyed by the rest +# of this file, in order that that they be as useful as possible to +# callers. + + +# require_term_colors +# ------------------- +# Allow display of bold text on terminals that support it. +require_term_colors=func_require_term_colors +func_require_term_colors () +{ + $debug_cmd + + test -t 1 && { + # COLORTERM and USE_ANSI_COLORS environment variables take + # precedence, because most terminfo databases neglect to describe + # whether color sequences are supported. + test -n "${COLORTERM+set}" && : ${USE_ANSI_COLORS="1"} + + if test 1 = "$USE_ANSI_COLORS"; then + # Standard ANSI escape sequences + tc_reset='' + tc_bold=''; tc_standout='' + tc_red=''; tc_green='' + tc_blue=''; tc_cyan='' + else + # Otherwise trust the terminfo database after all. + test -n "`tput sgr0 2>/dev/null`" && { + tc_reset=`tput sgr0` + test -n "`tput bold 2>/dev/null`" && tc_bold=`tput bold` + tc_standout=$tc_bold + test -n "`tput smso 2>/dev/null`" && tc_standout=`tput smso` + test -n "`tput setaf 1 2>/dev/null`" && tc_red=`tput setaf 1` + test -n "`tput setaf 2 2>/dev/null`" && tc_green=`tput setaf 2` + test -n "`tput setaf 4 2>/dev/null`" && tc_blue=`tput setaf 4` + test -n "`tput setaf 5 2>/dev/null`" && tc_cyan=`tput setaf 5` + } + fi + } + + require_term_colors=: +} + + +## ----------------- ## +## Function library. ## +## ----------------- ## + +# This section contains a variety of useful functions to call in your +# scripts. Take note of the portable wrappers for features provided by +# some modern shells, which will fall back to slower equivalents on +# less featureful shells. + + +# func_append VAR VALUE +# --------------------- +# Append VALUE onto the existing contents of VAR. + + # We should try to minimise forks, especially on Windows where they are + # unreasonably slow, so skip the feature probes when bash or zsh are + # being used: + if test set = "${BASH_VERSION+set}${ZSH_VERSION+set}"; then + : ${_G_HAVE_ARITH_OP="yes"} + : ${_G_HAVE_XSI_OPS="yes"} + # The += operator was introduced in bash 3.1 + case $BASH_VERSION in + [12].* | 3.0 | 3.0*) ;; + *) + : ${_G_HAVE_PLUSEQ_OP="yes"} + ;; + esac + fi + + # _G_HAVE_PLUSEQ_OP + # Can be empty, in which case the shell is probed, "yes" if += is + # useable or anything else if it does not work. + test -z "$_G_HAVE_PLUSEQ_OP" \ + && (eval 'x=a; x+=" b"; test "a b" = "$x"') 2>/dev/null \ + && _G_HAVE_PLUSEQ_OP=yes + +if test yes = "$_G_HAVE_PLUSEQ_OP" +then + # This is an XSI compatible shell, allowing a faster implementation... + eval 'func_append () + { + $debug_cmd + + eval "$1+=\$2" + }' +else + # ...otherwise fall back to using expr, which is often a shell builtin. + func_append () + { + $debug_cmd + + eval "$1=\$$1\$2" + } +fi + + +# func_append_quoted VAR VALUE +# ---------------------------- +# Quote VALUE and append to the end of shell variable VAR, separated +# by a space. +if test yes = "$_G_HAVE_PLUSEQ_OP"; then + eval 'func_append_quoted () + { + $debug_cmd + + func_quote_for_eval "$2" + eval "$1+=\\ \$func_quote_for_eval_result" + }' +else + func_append_quoted () + { + $debug_cmd + + func_quote_for_eval "$2" + eval "$1=\$$1\\ \$func_quote_for_eval_result" + } +fi + + +# func_append_uniq VAR VALUE +# -------------------------- +# Append unique VALUE onto the existing contents of VAR, assuming +# entries are delimited by the first character of VALUE. For example: +# +# func_append_uniq options " --another-option option-argument" +# +# will only append to $options if " --another-option option-argument " +# is not already present somewhere in $options already (note spaces at +# each end implied by leading space in second argument). +func_append_uniq () +{ + $debug_cmd + + eval _G_current_value='`$ECHO $'$1'`' + _G_delim=`expr "$2" : '\(.\)'` + + case $_G_delim$_G_current_value$_G_delim in + *"$2$_G_delim"*) ;; + *) func_append "$@" ;; + esac +} + + +# func_arith TERM... +# ------------------ +# Set func_arith_result to the result of evaluating TERMs. + test -z "$_G_HAVE_ARITH_OP" \ + && (eval 'test 2 = $(( 1 + 1 ))') 2>/dev/null \ + && _G_HAVE_ARITH_OP=yes + +if test yes = "$_G_HAVE_ARITH_OP"; then + eval 'func_arith () + { + $debug_cmd + + func_arith_result=$(( $* )) + }' +else + func_arith () + { + $debug_cmd + + func_arith_result=`expr "$@"` + } +fi + + +# func_basename FILE +# ------------------ +# Set func_basename_result to FILE with everything up to and including +# the last / stripped. +if test yes = "$_G_HAVE_XSI_OPS"; then + # If this shell supports suffix pattern removal, then use it to avoid + # forking. Hide the definitions single quotes in case the shell chokes + # on unsupported syntax... + _b='func_basename_result=${1##*/}' + _d='case $1 in + */*) func_dirname_result=${1%/*}$2 ;; + * ) func_dirname_result=$3 ;; + esac' + +else + # ...otherwise fall back to using sed. + _b='func_basename_result=`$ECHO "$1" |$SED "$sed_basename"`' + _d='func_dirname_result=`$ECHO "$1" |$SED "$sed_dirname"` + if test "X$func_dirname_result" = "X$1"; then + func_dirname_result=$3 + else + func_append func_dirname_result "$2" + fi' +fi + +eval 'func_basename () +{ + $debug_cmd + + '"$_b"' +}' + + +# func_dirname FILE APPEND NONDIR_REPLACEMENT +# ------------------------------------------- +# Compute the dirname of FILE. If nonempty, add APPEND to the result, +# otherwise set result to NONDIR_REPLACEMENT. +eval 'func_dirname () +{ + $debug_cmd + + '"$_d"' +}' + + +# func_dirname_and_basename FILE APPEND NONDIR_REPLACEMENT +# -------------------------------------------------------- +# Perform func_basename and func_dirname in a single function +# call: +# dirname: Compute the dirname of FILE. If nonempty, +# add APPEND to the result, otherwise set result +# to NONDIR_REPLACEMENT. +# value returned in "$func_dirname_result" +# basename: Compute filename of FILE. +# value retuned in "$func_basename_result" +# For efficiency, we do not delegate to the functions above but instead +# duplicate the functionality here. +eval 'func_dirname_and_basename () +{ + $debug_cmd + + '"$_b"' + '"$_d"' +}' + + +# func_echo ARG... +# ---------------- +# Echo program name prefixed message. +func_echo () +{ + $debug_cmd + + _G_message=$* + + func_echo_IFS=$IFS + IFS=$nl + for _G_line in $_G_message; do + IFS=$func_echo_IFS + $ECHO "$progname: $_G_line" + done + IFS=$func_echo_IFS +} + + +# func_echo_all ARG... +# -------------------- +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "$*" +} + + +# func_echo_infix_1 INFIX ARG... +# ------------------------------ +# Echo program name, followed by INFIX on the first line, with any +# additional lines not showing INFIX. +func_echo_infix_1 () +{ + $debug_cmd + + $require_term_colors + + _G_infix=$1; shift + _G_indent=$_G_infix + _G_prefix="$progname: $_G_infix: " + _G_message=$* + + # Strip color escape sequences before counting printable length + for _G_tc in "$tc_reset" "$tc_bold" "$tc_standout" "$tc_red" "$tc_green" "$tc_blue" "$tc_cyan" + do + test -n "$_G_tc" && { + _G_esc_tc=`$ECHO "$_G_tc" | $SED "$sed_make_literal_regex"` + _G_indent=`$ECHO "$_G_indent" | $SED "s|$_G_esc_tc||g"` + } + done + _G_indent="$progname: "`echo "$_G_indent" | $SED 's|.| |g'`" " ## exclude from sc_prohibit_nested_quotes + + func_echo_infix_1_IFS=$IFS + IFS=$nl + for _G_line in $_G_message; do + IFS=$func_echo_infix_1_IFS + $ECHO "$_G_prefix$tc_bold$_G_line$tc_reset" >&2 + _G_prefix=$_G_indent + done + IFS=$func_echo_infix_1_IFS +} + + +# func_error ARG... +# ----------------- +# Echo program name prefixed message to standard error. +func_error () +{ + $debug_cmd + + $require_term_colors + + func_echo_infix_1 " $tc_standout${tc_red}error$tc_reset" "$*" >&2 +} + + +# func_fatal_error ARG... +# ----------------------- +# Echo program name prefixed message to standard error, and exit. +func_fatal_error () +{ + $debug_cmd + + func_error "$*" + exit $EXIT_FAILURE +} + + +# func_grep EXPRESSION FILENAME +# ----------------------------- +# Check whether EXPRESSION matches any line of FILENAME, without output. +func_grep () +{ + $debug_cmd + + $GREP "$1" "$2" >/dev/null 2>&1 +} + + +# func_len STRING +# --------------- +# Set func_len_result to the length of STRING. STRING may not +# start with a hyphen. + test -z "$_G_HAVE_XSI_OPS" \ + && (eval 'x=a/b/c; + test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ + && _G_HAVE_XSI_OPS=yes + +if test yes = "$_G_HAVE_XSI_OPS"; then + eval 'func_len () + { + $debug_cmd + + func_len_result=${#1} + }' +else + func_len () + { + $debug_cmd + + func_len_result=`expr "$1" : ".*" 2>/dev/null || echo $max_cmd_len` + } +fi + + +# func_mkdir_p DIRECTORY-PATH +# --------------------------- +# Make sure the entire path to DIRECTORY-PATH is available. +func_mkdir_p () +{ + $debug_cmd + + _G_directory_path=$1 + _G_dir_list= + + if test -n "$_G_directory_path" && test : != "$opt_dry_run"; then + + # Protect directory names starting with '-' + case $_G_directory_path in + -*) _G_directory_path=./$_G_directory_path ;; + esac + + # While some portion of DIR does not yet exist... + while test ! -d "$_G_directory_path"; do + # ...make a list in topmost first order. Use a colon delimited + # list incase some portion of path contains whitespace. + _G_dir_list=$_G_directory_path:$_G_dir_list + + # If the last portion added has no slash in it, the list is done + case $_G_directory_path in */*) ;; *) break ;; esac + + # ...otherwise throw away the child directory and loop + _G_directory_path=`$ECHO "$_G_directory_path" | $SED -e "$sed_dirname"` + done + _G_dir_list=`$ECHO "$_G_dir_list" | $SED 's|:*$||'` + + func_mkdir_p_IFS=$IFS; IFS=: + for _G_dir in $_G_dir_list; do + IFS=$func_mkdir_p_IFS + # mkdir can fail with a 'File exist' error if two processes + # try to create one of the directories concurrently. Don't + # stop in that case! + $MKDIR "$_G_dir" 2>/dev/null || : + done + IFS=$func_mkdir_p_IFS + + # Bail out if we (or some other process) failed to create a directory. + test -d "$_G_directory_path" || \ + func_fatal_error "Failed to create '$1'" + fi +} + + +# func_mktempdir [BASENAME] +# ------------------------- +# Make a temporary directory that won't clash with other running +# libtool processes, and avoids race conditions if possible. If +# given, BASENAME is the basename for that directory. +func_mktempdir () +{ + $debug_cmd + + _G_template=${TMPDIR-/tmp}/${1-$progname} + + if test : = "$opt_dry_run"; then + # Return a directory name, but don't create it in dry-run mode + _G_tmpdir=$_G_template-$$ + else + + # If mktemp works, use that first and foremost + _G_tmpdir=`mktemp -d "$_G_template-XXXXXXXX" 2>/dev/null` + + if test ! -d "$_G_tmpdir"; then + # Failing that, at least try and use $RANDOM to avoid a race + _G_tmpdir=$_G_template-${RANDOM-0}$$ + + func_mktempdir_umask=`umask` + umask 0077 + $MKDIR "$_G_tmpdir" + umask $func_mktempdir_umask + fi + + # If we're not in dry-run mode, bomb out on failure + test -d "$_G_tmpdir" || \ + func_fatal_error "cannot create temporary directory '$_G_tmpdir'" + fi + + $ECHO "$_G_tmpdir" +} + + +# func_normal_abspath PATH +# ------------------------ +# Remove doubled-up and trailing slashes, "." path components, +# and cancel out any ".." path components in PATH after making +# it an absolute path. +func_normal_abspath () +{ + $debug_cmd + + # These SED scripts presuppose an absolute path with a trailing slash. + _G_pathcar='s|^/\([^/]*\).*$|\1|' + _G_pathcdr='s|^/[^/]*||' + _G_removedotparts=':dotsl + s|/\./|/|g + t dotsl + s|/\.$|/|' + _G_collapseslashes='s|/\{1,\}|/|g' + _G_finalslash='s|/*$|/|' + + # Start from root dir and reassemble the path. + func_normal_abspath_result= + func_normal_abspath_tpath=$1 + func_normal_abspath_altnamespace= + case $func_normal_abspath_tpath in + "") + # Empty path, that just means $cwd. + func_stripname '' '/' "`pwd`" + func_normal_abspath_result=$func_stripname_result + return + ;; + # The next three entries are used to spot a run of precisely + # two leading slashes without using negated character classes; + # we take advantage of case's first-match behaviour. + ///*) + # Unusual form of absolute path, do nothing. + ;; + //*) + # Not necessarily an ordinary path; POSIX reserves leading '//' + # and for example Cygwin uses it to access remote file shares + # over CIFS/SMB, so we conserve a leading double slash if found. + func_normal_abspath_altnamespace=/ + ;; + /*) + # Absolute path, do nothing. + ;; + *) + # Relative path, prepend $cwd. + func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath + ;; + esac + + # Cancel out all the simple stuff to save iterations. We also want + # the path to end with a slash for ease of parsing, so make sure + # there is one (and only one) here. + func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$_G_removedotparts" -e "$_G_collapseslashes" -e "$_G_finalslash"` + while :; do + # Processed it all yet? + if test / = "$func_normal_abspath_tpath"; then + # If we ascended to the root using ".." the result may be empty now. + if test -z "$func_normal_abspath_result"; then + func_normal_abspath_result=/ + fi + break + fi + func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$_G_pathcar"` + func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$_G_pathcdr"` + # Figure out what to do with it + case $func_normal_abspath_tcomponent in + "") + # Trailing empty path component, ignore it. + ;; + ..) + # Parent dir; strip last assembled component from result. + func_dirname "$func_normal_abspath_result" + func_normal_abspath_result=$func_dirname_result + ;; + *) + # Actual path component, append it. + func_append func_normal_abspath_result "/$func_normal_abspath_tcomponent" + ;; + esac + done + # Restore leading double-slash if one was found on entry. + func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result +} + + +# func_notquiet ARG... +# -------------------- +# Echo program name prefixed message only when not in quiet mode. +func_notquiet () +{ + $debug_cmd + + $opt_quiet || func_echo ${1+"$@"} + + # A bug in bash halts the script if the last line of a function + # fails when set -e is in force, so we need another command to + # work around that: + : +} + + +# func_relative_path SRCDIR DSTDIR +# -------------------------------- +# Set func_relative_path_result to the relative path from SRCDIR to DSTDIR. +func_relative_path () +{ + $debug_cmd + + func_relative_path_result= + func_normal_abspath "$1" + func_relative_path_tlibdir=$func_normal_abspath_result + func_normal_abspath "$2" + func_relative_path_tbindir=$func_normal_abspath_result + + # Ascend the tree starting from libdir + while :; do + # check if we have found a prefix of bindir + case $func_relative_path_tbindir in + $func_relative_path_tlibdir) + # found an exact match + func_relative_path_tcancelled= + break + ;; + $func_relative_path_tlibdir*) + # found a matching prefix + func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir" + func_relative_path_tcancelled=$func_stripname_result + if test -z "$func_relative_path_result"; then + func_relative_path_result=. + fi + break + ;; + *) + func_dirname $func_relative_path_tlibdir + func_relative_path_tlibdir=$func_dirname_result + if test -z "$func_relative_path_tlibdir"; then + # Have to descend all the way to the root! + func_relative_path_result=../$func_relative_path_result + func_relative_path_tcancelled=$func_relative_path_tbindir + break + fi + func_relative_path_result=../$func_relative_path_result + ;; + esac + done + + # Now calculate path; take care to avoid doubling-up slashes. + func_stripname '' '/' "$func_relative_path_result" + func_relative_path_result=$func_stripname_result + func_stripname '/' '/' "$func_relative_path_tcancelled" + if test -n "$func_stripname_result"; then + func_append func_relative_path_result "/$func_stripname_result" + fi + + # Normalisation. If bindir is libdir, return '.' else relative path. + if test -n "$func_relative_path_result"; then + func_stripname './' '' "$func_relative_path_result" + func_relative_path_result=$func_stripname_result + fi + + test -n "$func_relative_path_result" || func_relative_path_result=. + + : +} + + +# func_quote_for_eval ARG... +# -------------------------- +# Aesthetically quote ARGs to be evaled later. +# This function returns two values: +# i) func_quote_for_eval_result +# double-quoted, suitable for a subsequent eval +# ii) func_quote_for_eval_unquoted_result +# has all characters that are still active within double +# quotes backslashified. +func_quote_for_eval () +{ + $debug_cmd + + func_quote_for_eval_unquoted_result= + func_quote_for_eval_result= + while test 0 -lt $#; do + case $1 in + *[\\\`\"\$]*) + _G_unquoted_arg=`printf '%s\n' "$1" |$SED "$sed_quote_subst"` ;; + *) + _G_unquoted_arg=$1 ;; + esac + if test -n "$func_quote_for_eval_unquoted_result"; then + func_append func_quote_for_eval_unquoted_result " $_G_unquoted_arg" + else + func_append func_quote_for_eval_unquoted_result "$_G_unquoted_arg" + fi + + case $_G_unquoted_arg in + # Double-quote args containing shell metacharacters to delay + # word splitting, command substitution and variable expansion + # for a subsequent eval. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + _G_quoted_arg=\"$_G_unquoted_arg\" + ;; + *) + _G_quoted_arg=$_G_unquoted_arg + ;; + esac + + if test -n "$func_quote_for_eval_result"; then + func_append func_quote_for_eval_result " $_G_quoted_arg" + else + func_append func_quote_for_eval_result "$_G_quoted_arg" + fi + shift + done +} + + +# func_quote_for_expand ARG +# ------------------------- +# Aesthetically quote ARG to be evaled later; same as above, +# but do not quote variable references. +func_quote_for_expand () +{ + $debug_cmd + + case $1 in + *[\\\`\"]*) + _G_arg=`$ECHO "$1" | $SED \ + -e "$sed_double_quote_subst" -e "$sed_double_backslash"` ;; + *) + _G_arg=$1 ;; + esac + + case $_G_arg in + # Double-quote args containing shell metacharacters to delay + # word splitting and command substitution for a subsequent eval. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + _G_arg=\"$_G_arg\" + ;; + esac + + func_quote_for_expand_result=$_G_arg +} + + +# func_stripname PREFIX SUFFIX NAME +# --------------------------------- +# strip PREFIX and SUFFIX from NAME, and store in func_stripname_result. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +if test yes = "$_G_HAVE_XSI_OPS"; then + eval 'func_stripname () + { + $debug_cmd + + # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are + # positional parameters, so assign one to ordinary variable first. + func_stripname_result=$3 + func_stripname_result=${func_stripname_result#"$1"} + func_stripname_result=${func_stripname_result%"$2"} + }' +else + func_stripname () + { + $debug_cmd + + case $2 in + .*) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%\\\\$2\$%%"`;; + *) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%$2\$%%"`;; + esac + } +fi + + +# func_show_eval CMD [FAIL_EXP] +# ----------------------------- +# Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. +func_show_eval () +{ + $debug_cmd + + _G_cmd=$1 + _G_fail_exp=${2-':'} + + func_quote_for_expand "$_G_cmd" + eval "func_notquiet $func_quote_for_expand_result" + + $opt_dry_run || { + eval "$_G_cmd" + _G_status=$? + if test 0 -ne "$_G_status"; then + eval "(exit $_G_status); $_G_fail_exp" + fi + } +} + + +# func_show_eval_locale CMD [FAIL_EXP] +# ------------------------------------ +# Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. Use the saved locale for evaluation. +func_show_eval_locale () +{ + $debug_cmd + + _G_cmd=$1 + _G_fail_exp=${2-':'} + + $opt_quiet || { + func_quote_for_expand "$_G_cmd" + eval "func_echo $func_quote_for_expand_result" + } + + $opt_dry_run || { + eval "$_G_user_locale + $_G_cmd" + _G_status=$? + eval "$_G_safe_locale" + if test 0 -ne "$_G_status"; then + eval "(exit $_G_status); $_G_fail_exp" + fi + } +} + + +# func_tr_sh +# ---------- +# Turn $1 into a string suitable for a shell variable name. +# Result is stored in $func_tr_sh_result. All characters +# not in the set a-zA-Z0-9_ are replaced with '_'. Further, +# if $1 begins with a digit, a '_' is prepended as well. +func_tr_sh () +{ + $debug_cmd + + case $1 in + [0-9]* | *[!a-zA-Z0-9_]*) + func_tr_sh_result=`$ECHO "$1" | $SED -e 's/^\([0-9]\)/_\1/' -e 's/[^a-zA-Z0-9_]/_/g'` + ;; + * ) + func_tr_sh_result=$1 + ;; + esac +} + + +# func_verbose ARG... +# ------------------- +# Echo program name prefixed message in verbose mode only. +func_verbose () +{ + $debug_cmd + + $opt_verbose && func_echo "$*" + + : +} + + +# func_warn_and_continue ARG... +# ----------------------------- +# Echo program name prefixed warning message to standard error. +func_warn_and_continue () +{ + $debug_cmd + + $require_term_colors + + func_echo_infix_1 "${tc_red}warning$tc_reset" "$*" >&2 +} + + +# func_warning CATEGORY ARG... +# ---------------------------- +# Echo program name prefixed warning message to standard error. Warning +# messages can be filtered according to CATEGORY, where this function +# elides messages where CATEGORY is not listed in the global variable +# 'opt_warning_types'. +func_warning () +{ + $debug_cmd + + # CATEGORY must be in the warning_categories list! + case " $warning_categories " in + *" $1 "*) ;; + *) func_internal_error "invalid warning category '$1'" ;; + esac + + _G_category=$1 + shift + + case " $opt_warning_types " in + *" $_G_category "*) $warning_func ${1+"$@"} ;; + esac +} + + +# func_sort_ver VER1 VER2 +# ----------------------- +# 'sort -V' is not generally available. +# Note this deviates from the version comparison in automake +# in that it treats 1.5 < 1.5.0, and treats 1.4.4a < 1.4-p3a +# but this should suffice as we won't be specifying old +# version formats or redundant trailing .0 in bootstrap.conf. +# If we did want full compatibility then we should probably +# use m4_version_compare from autoconf. +func_sort_ver () +{ + $debug_cmd + + printf '%s\n%s\n' "$1" "$2" \ + | sort -t. -k 1,1n -k 2,2n -k 3,3n -k 4,4n -k 5,5n -k 6,6n -k 7,7n -k 8,8n -k 9,9n +} + +# func_lt_ver PREV CURR +# --------------------- +# Return true if PREV and CURR are in the correct order according to +# func_sort_ver, otherwise false. Use it like this: +# +# func_lt_ver "$prev_ver" "$proposed_ver" || func_fatal_error "..." +func_lt_ver () +{ + $debug_cmd + + test "x$1" = x`func_sort_ver "$1" "$2" | $SED 1q` +} + + +# Local variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC" +# time-stamp-time-zone: "UTC" +# End: +#! /bin/sh + +# Set a version string for this script. +scriptversion=2014-01-07.03; # UTC + +# A portable, pluggable option parser for Bourne shell. +# Written by Gary V. Vaughan, 2010 + +# Copyright (C) 2010-2015 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. + +# 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 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 . + +# Please report bugs or propose patches to gary@gnu.org. + + +## ------ ## +## Usage. ## +## ------ ## + +# This file is a library for parsing options in your shell scripts along +# with assorted other useful supporting features that you can make use +# of too. +# +# For the simplest scripts you might need only: +# +# #!/bin/sh +# . relative/path/to/funclib.sh +# . relative/path/to/options-parser +# scriptversion=1.0 +# func_options ${1+"$@"} +# eval set dummy "$func_options_result"; shift +# ...rest of your script... +# +# In order for the '--version' option to work, you will need to have a +# suitably formatted comment like the one at the top of this file +# starting with '# Written by ' and ending with '# warranty; '. +# +# For '-h' and '--help' to work, you will also need a one line +# description of your script's purpose in a comment directly above the +# '# Written by ' line, like the one at the top of this file. +# +# The default options also support '--debug', which will turn on shell +# execution tracing (see the comment above debug_cmd below for another +# use), and '--verbose' and the func_verbose function to allow your script +# to display verbose messages only when your user has specified +# '--verbose'. +# +# After sourcing this file, you can plug processing for additional +# options by amending the variables from the 'Configuration' section +# below, and following the instructions in the 'Option parsing' +# section further down. + +## -------------- ## +## Configuration. ## +## -------------- ## + +# You should override these variables in your script after sourcing this +# file so that they reflect the customisations you have added to the +# option parser. + +# The usage line for option parsing errors and the start of '-h' and +# '--help' output messages. You can embed shell variables for delayed +# expansion at the time the message is displayed, but you will need to +# quote other shell meta-characters carefully to prevent them being +# expanded when the contents are evaled. +usage='$progpath [OPTION]...' + +# Short help message in response to '-h' and '--help'. Add to this or +# override it after sourcing this library to reflect the full set of +# options your script accepts. +usage_message="\ + --debug enable verbose shell tracing + -W, --warnings=CATEGORY + report the warnings falling in CATEGORY [all] + -v, --verbose verbosely report processing + --version print version information and exit + -h, --help print short or long help message and exit +" + +# Additional text appended to 'usage_message' in response to '--help'. +long_help_message=" +Warning categories include: + 'all' show all warnings + 'none' turn off all the warnings + 'error' warnings are treated as fatal errors" + +# Help message printed before fatal option parsing errors. +fatal_help="Try '\$progname --help' for more information." + + + +## ------------------------- ## +## Hook function management. ## +## ------------------------- ## + +# This section contains functions for adding, removing, and running hooks +# to the main code. A hook is just a named list of of function, that can +# be run in order later on. + +# func_hookable FUNC_NAME +# ----------------------- +# Declare that FUNC_NAME will run hooks added with +# 'func_add_hook FUNC_NAME ...'. +func_hookable () +{ + $debug_cmd + + func_append hookable_fns " $1" +} + + +# func_add_hook FUNC_NAME HOOK_FUNC +# --------------------------------- +# Request that FUNC_NAME call HOOK_FUNC before it returns. FUNC_NAME must +# first have been declared "hookable" by a call to 'func_hookable'. +func_add_hook () +{ + $debug_cmd + + case " $hookable_fns " in + *" $1 "*) ;; + *) func_fatal_error "'$1' does not accept hook functions." ;; + esac + + eval func_append ${1}_hooks '" $2"' +} + + +# func_remove_hook FUNC_NAME HOOK_FUNC +# ------------------------------------ +# Remove HOOK_FUNC from the list of functions called by FUNC_NAME. +func_remove_hook () +{ + $debug_cmd + + eval ${1}_hooks='`$ECHO "\$'$1'_hooks" |$SED "s| '$2'||"`' +} + + +# func_run_hooks FUNC_NAME [ARG]... +# --------------------------------- +# Run all hook functions registered to FUNC_NAME. +# It is assumed that the list of hook functions contains nothing more +# than a whitespace-delimited list of legal shell function names, and +# no effort is wasted trying to catch shell meta-characters or preserve +# whitespace. +func_run_hooks () +{ + $debug_cmd + + case " $hookable_fns " in + *" $1 "*) ;; + *) func_fatal_error "'$1' does not support hook funcions.n" ;; + esac + + eval _G_hook_fns=\$$1_hooks; shift + + for _G_hook in $_G_hook_fns; do + eval $_G_hook '"$@"' + + # store returned options list back into positional + # parameters for next 'cmd' execution. + eval _G_hook_result=\$${_G_hook}_result + eval set dummy "$_G_hook_result"; shift + done + + func_quote_for_eval ${1+"$@"} + func_run_hooks_result=$func_quote_for_eval_result +} + + + +## --------------- ## +## Option parsing. ## +## --------------- ## + +# In order to add your own option parsing hooks, you must accept the +# full positional parameter list in your hook function, remove any +# options that you action, and then pass back the remaining unprocessed +# options in '_result', escaped suitably for +# 'eval'. Like this: +# +# my_options_prep () +# { +# $debug_cmd +# +# # Extend the existing usage message. +# usage_message=$usage_message' +# -s, --silent don'\''t print informational messages +# ' +# +# func_quote_for_eval ${1+"$@"} +# my_options_prep_result=$func_quote_for_eval_result +# } +# func_add_hook func_options_prep my_options_prep +# +# +# my_silent_option () +# { +# $debug_cmd +# +# # Note that for efficiency, we parse as many options as we can +# # recognise in a loop before passing the remainder back to the +# # caller on the first unrecognised argument we encounter. +# while test $# -gt 0; do +# opt=$1; shift +# case $opt in +# --silent|-s) opt_silent=: ;; +# # Separate non-argument short options: +# -s*) func_split_short_opt "$_G_opt" +# set dummy "$func_split_short_opt_name" \ +# "-$func_split_short_opt_arg" ${1+"$@"} +# shift +# ;; +# *) set dummy "$_G_opt" "$*"; shift; break ;; +# esac +# done +# +# func_quote_for_eval ${1+"$@"} +# my_silent_option_result=$func_quote_for_eval_result +# } +# func_add_hook func_parse_options my_silent_option +# +# +# my_option_validation () +# { +# $debug_cmd +# +# $opt_silent && $opt_verbose && func_fatal_help "\ +# '--silent' and '--verbose' options are mutually exclusive." +# +# func_quote_for_eval ${1+"$@"} +# my_option_validation_result=$func_quote_for_eval_result +# } +# func_add_hook func_validate_options my_option_validation +# +# You'll alse need to manually amend $usage_message to reflect the extra +# options you parse. It's preferable to append if you can, so that +# multiple option parsing hooks can be added safely. + + +# func_options [ARG]... +# --------------------- +# All the functions called inside func_options are hookable. See the +# individual implementations for details. +func_hookable func_options +func_options () +{ + $debug_cmd + + func_options_prep ${1+"$@"} + eval func_parse_options \ + ${func_options_prep_result+"$func_options_prep_result"} + eval func_validate_options \ + ${func_parse_options_result+"$func_parse_options_result"} + + eval func_run_hooks func_options \ + ${func_validate_options_result+"$func_validate_options_result"} + + # save modified positional parameters for caller + func_options_result=$func_run_hooks_result +} + + +# func_options_prep [ARG]... +# -------------------------- +# All initialisations required before starting the option parse loop. +# Note that when calling hook functions, we pass through the list of +# positional parameters. If a hook function modifies that list, and +# needs to propogate that back to rest of this script, then the complete +# modified list must be put in 'func_run_hooks_result' before +# returning. +func_hookable func_options_prep +func_options_prep () +{ + $debug_cmd + + # Option defaults: + opt_verbose=false + opt_warning_types= + + func_run_hooks func_options_prep ${1+"$@"} + + # save modified positional parameters for caller + func_options_prep_result=$func_run_hooks_result +} + + +# func_parse_options [ARG]... +# --------------------------- +# The main option parsing loop. +func_hookable func_parse_options +func_parse_options () +{ + $debug_cmd + + func_parse_options_result= + + # this just eases exit handling + while test $# -gt 0; do + # Defer to hook functions for initial option parsing, so they + # get priority in the event of reusing an option name. + func_run_hooks func_parse_options ${1+"$@"} + + # Adjust func_parse_options positional parameters to match + eval set dummy "$func_run_hooks_result"; shift + + # Break out of the loop if we already parsed every option. + test $# -gt 0 || break + + _G_opt=$1 + shift + case $_G_opt in + --debug|-x) debug_cmd='set -x' + func_echo "enabling shell trace mode" + $debug_cmd + ;; + + --no-warnings|--no-warning|--no-warn) + set dummy --warnings none ${1+"$@"} + shift + ;; + + --warnings|--warning|-W) + test $# = 0 && func_missing_arg $_G_opt && break + case " $warning_categories $1" in + *" $1 "*) + # trailing space prevents matching last $1 above + func_append_uniq opt_warning_types " $1" + ;; + *all) + opt_warning_types=$warning_categories + ;; + *none) + opt_warning_types=none + warning_func=: + ;; + *error) + opt_warning_types=$warning_categories + warning_func=func_fatal_error + ;; + *) + func_fatal_error \ + "unsupported warning category: '$1'" + ;; + esac + shift + ;; + + --verbose|-v) opt_verbose=: ;; + --version) func_version ;; + -\?|-h) func_usage ;; + --help) func_help ;; + + # Separate optargs to long options (plugins may need this): + --*=*) func_split_equals "$_G_opt" + set dummy "$func_split_equals_lhs" \ + "$func_split_equals_rhs" ${1+"$@"} + shift + ;; + + # Separate optargs to short options: + -W*) + func_split_short_opt "$_G_opt" + set dummy "$func_split_short_opt_name" \ + "$func_split_short_opt_arg" ${1+"$@"} + shift + ;; + + # Separate non-argument short options: + -\?*|-h*|-v*|-x*) + func_split_short_opt "$_G_opt" + set dummy "$func_split_short_opt_name" \ + "-$func_split_short_opt_arg" ${1+"$@"} + shift + ;; + + --) break ;; + -*) func_fatal_help "unrecognised option: '$_G_opt'" ;; + *) set dummy "$_G_opt" ${1+"$@"}; shift; break ;; + esac + done + + # save modified positional parameters for caller + func_quote_for_eval ${1+"$@"} + func_parse_options_result=$func_quote_for_eval_result +} + + +# func_validate_options [ARG]... +# ------------------------------ +# Perform any sanity checks on option settings and/or unconsumed +# arguments. +func_hookable func_validate_options +func_validate_options () +{ + $debug_cmd + + # Display all warnings if -W was not given. + test -n "$opt_warning_types" || opt_warning_types=" $warning_categories" + + func_run_hooks func_validate_options ${1+"$@"} + + # Bail if the options were screwed! + $exit_cmd $EXIT_FAILURE + + # save modified positional parameters for caller + func_validate_options_result=$func_run_hooks_result +} + + + +## ----------------- ## +## Helper functions. ## +## ----------------- ## + +# This section contains the helper functions used by the rest of the +# hookable option parser framework in ascii-betical order. + + +# func_fatal_help ARG... +# ---------------------- +# Echo program name prefixed message to standard error, followed by +# a help hint, and exit. +func_fatal_help () +{ + $debug_cmd + + eval \$ECHO \""Usage: $usage"\" + eval \$ECHO \""$fatal_help"\" + func_error ${1+"$@"} + exit $EXIT_FAILURE +} + + +# func_help +# --------- +# Echo long help message to standard output and exit. +func_help () +{ + $debug_cmd + + func_usage_message + $ECHO "$long_help_message" + exit 0 +} + + +# func_missing_arg ARGNAME +# ------------------------ +# Echo program name prefixed message to standard error and set global +# exit_cmd. +func_missing_arg () +{ + $debug_cmd + + func_error "Missing argument for '$1'." + exit_cmd=exit +} + + +# func_split_equals STRING +# ------------------------ +# Set func_split_equals_lhs and func_split_equals_rhs shell variables after +# splitting STRING at the '=' sign. +test -z "$_G_HAVE_XSI_OPS" \ + && (eval 'x=a/b/c; + test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ + && _G_HAVE_XSI_OPS=yes + +if test yes = "$_G_HAVE_XSI_OPS" +then + # This is an XSI compatible shell, allowing a faster implementation... + eval 'func_split_equals () + { + $debug_cmd + + func_split_equals_lhs=${1%%=*} + func_split_equals_rhs=${1#*=} + test "x$func_split_equals_lhs" = "x$1" \ + && func_split_equals_rhs= + }' +else + # ...otherwise fall back to using expr, which is often a shell builtin. + func_split_equals () + { + $debug_cmd + + func_split_equals_lhs=`expr "x$1" : 'x\([^=]*\)'` + func_split_equals_rhs= + test "x$func_split_equals_lhs" = "x$1" \ + || func_split_equals_rhs=`expr "x$1" : 'x[^=]*=\(.*\)$'` + } +fi #func_split_equals + + +# func_split_short_opt SHORTOPT +# ----------------------------- +# Set func_split_short_opt_name and func_split_short_opt_arg shell +# variables after splitting SHORTOPT after the 2nd character. +if test yes = "$_G_HAVE_XSI_OPS" +then + # This is an XSI compatible shell, allowing a faster implementation... + eval 'func_split_short_opt () + { + $debug_cmd + + func_split_short_opt_arg=${1#??} + func_split_short_opt_name=${1%"$func_split_short_opt_arg"} + }' +else + # ...otherwise fall back to using expr, which is often a shell builtin. + func_split_short_opt () + { + $debug_cmd + + func_split_short_opt_name=`expr "x$1" : 'x-\(.\)'` + func_split_short_opt_arg=`expr "x$1" : 'x-.\(.*\)$'` + } +fi #func_split_short_opt + + +# func_usage +# ---------- +# Echo short help message to standard output and exit. +func_usage () +{ + $debug_cmd + + func_usage_message + $ECHO "Run '$progname --help |${PAGER-more}' for full usage" + exit 0 +} + + +# func_usage_message +# ------------------ +# Echo short help message to standard output. +func_usage_message () +{ + $debug_cmd + + eval \$ECHO \""Usage: $usage"\" + echo + $SED -n 's|^# || + /^Written by/{ + x;p;x + } + h + /^Written by/q' < "$progpath" + echo + eval \$ECHO \""$usage_message"\" +} + + +# func_version +# ------------ +# Echo version message to standard output and exit. +func_version () +{ + $debug_cmd + + printf '%s\n' "$progname $scriptversion" + $SED -n ' + /(C)/!b go + :more + /\./!{ + N + s|\n# | | + b more + } + :go + /^# Written by /,/# warranty; / { + s|^# || + s|^# *$|| + s|\((C)\)[ 0-9,-]*[ ,-]\([1-9][0-9]* \)|\1 \2| + p + } + /^# Written by / { + s|^# || + p + } + /^warranty; /q' < "$progpath" + + exit $? +} + + +# Local variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC" +# time-stamp-time-zone: "UTC" +# End: + +# Set a version string. +scriptversion='(GNU libtool) 2.4.6' + + +# func_echo ARG... +# ---------------- +# Libtool also displays the current mode in messages, so override +# funclib.sh func_echo with this custom definition. +func_echo () +{ + $debug_cmd + + _G_message=$* + + func_echo_IFS=$IFS + IFS=$nl + for _G_line in $_G_message; do + IFS=$func_echo_IFS + $ECHO "$progname${opt_mode+: $opt_mode}: $_G_line" + done + IFS=$func_echo_IFS +} + + +# func_warning ARG... +# ------------------- +# Libtool warnings are not categorized, so override funclib.sh +# func_warning with this simpler definition. +func_warning () +{ + $debug_cmd + + $warning_func ${1+"$@"} +} + + +## ---------------- ## +## Options parsing. ## +## ---------------- ## + +# Hook in the functions to make sure our own options are parsed during +# the option parsing loop. + +usage='$progpath [OPTION]... [MODE-ARG]...' + +# Short help message in response to '-h'. +usage_message="Options: + --config show all configuration variables + --debug enable verbose shell tracing + -n, --dry-run display commands without modifying any files + --features display basic configuration information and exit + --mode=MODE use operation mode MODE + --no-warnings equivalent to '-Wnone' + --preserve-dup-deps don't remove duplicate dependency libraries + --quiet, --silent don't print informational messages + --tag=TAG use configuration variables from tag TAG + -v, --verbose print more informational messages than default + --version print version information + -W, --warnings=CATEGORY report the warnings falling in CATEGORY [all] + -h, --help, --help-all print short, long, or detailed help message +" + +# Additional text appended to 'usage_message' in response to '--help'. +func_help () +{ + $debug_cmd + + func_usage_message + $ECHO "$long_help_message + +MODE must be one of the following: + + clean remove files from the build directory + compile compile a source file into a libtool object + execute automatically set library path, then run a program + finish complete the installation of libtool libraries + install install libraries or executables + link create a library or an executable + uninstall remove libraries from an installed directory + +MODE-ARGS vary depending on the MODE. When passed as first option, +'--mode=MODE' may be abbreviated as 'MODE' or a unique abbreviation of that. +Try '$progname --help --mode=MODE' for a more detailed description of MODE. + +When reporting a bug, please describe a test case to reproduce it and +include the following information: + + host-triplet: $host + shell: $SHELL + compiler: $LTCC + compiler flags: $LTCFLAGS + linker: $LD (gnu? $with_gnu_ld) + version: $progname $scriptversion Debian-2.4.6-2 + automake: `($AUTOMAKE --version) 2>/dev/null |$SED 1q` + autoconf: `($AUTOCONF --version) 2>/dev/null |$SED 1q` + +Report bugs to . +GNU libtool home page: . +General help using GNU software: ." + exit 0 +} + + +# func_lo2o OBJECT-NAME +# --------------------- +# Transform OBJECT-NAME from a '.lo' suffix to the platform specific +# object suffix. + +lo2o=s/\\.lo\$/.$objext/ +o2lo=s/\\.$objext\$/.lo/ + +if test yes = "$_G_HAVE_XSI_OPS"; then + eval 'func_lo2o () + { + case $1 in + *.lo) func_lo2o_result=${1%.lo}.$objext ;; + * ) func_lo2o_result=$1 ;; + esac + }' + + # func_xform LIBOBJ-OR-SOURCE + # --------------------------- + # Transform LIBOBJ-OR-SOURCE from a '.o' or '.c' (or otherwise) + # suffix to a '.lo' libtool-object suffix. + eval 'func_xform () + { + func_xform_result=${1%.*}.lo + }' +else + # ...otherwise fall back to using sed. + func_lo2o () + { + func_lo2o_result=`$ECHO "$1" | $SED "$lo2o"` + } + + func_xform () + { + func_xform_result=`$ECHO "$1" | $SED 's|\.[^.]*$|.lo|'` + } +fi + + +# func_fatal_configuration ARG... +# ------------------------------- +# Echo program name prefixed message to standard error, followed by +# a configuration failure hint, and exit. +func_fatal_configuration () +{ + func__fatal_error ${1+"$@"} \ + "See the $PACKAGE documentation for more information." \ + "Fatal configuration error." +} + + +# func_config +# ----------- +# Display the configuration for all the tags in this script. +func_config () +{ + re_begincf='^# ### BEGIN LIBTOOL' + re_endcf='^# ### END LIBTOOL' + + # Default configuration. + $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath" + + # Now print the configurations for the tags. + for tagname in $taglist; do + $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath" + done + + exit $? +} + + +# func_features +# ------------- +# Display the features supported by this script. +func_features () +{ + echo "host: $host" + if test yes = "$build_libtool_libs"; then + echo "enable shared libraries" + else + echo "disable shared libraries" + fi + if test yes = "$build_old_libs"; then + echo "enable static libraries" + else + echo "disable static libraries" + fi + + exit $? +} + + +# func_enable_tag TAGNAME +# ----------------------- +# Verify that TAGNAME is valid, and either flag an error and exit, or +# enable the TAGNAME tag. We also add TAGNAME to the global $taglist +# variable here. +func_enable_tag () +{ + # Global variable: + tagname=$1 + + re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$" + re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$" + sed_extractcf=/$re_begincf/,/$re_endcf/p + + # Validate tagname. + case $tagname in + *[!-_A-Za-z0-9,/]*) + func_fatal_error "invalid tag name: $tagname" + ;; + esac + + # Don't test for the "default" C tag, as we know it's + # there but not specially marked. + case $tagname in + CC) ;; + *) + if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then + taglist="$taglist $tagname" + + # Evaluate the configuration. Be careful to quote the path + # and the sed script, to avoid splitting on whitespace, but + # also don't use non-portable quotes within backquotes within + # quotes we have to do it in 2 steps: + extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` + eval "$extractedcf" + else + func_error "ignoring unknown tag $tagname" + fi + ;; + esac +} + + +# func_check_version_match +# ------------------------ +# Ensure that we are using m4 macros, and libtool script from the same +# release of libtool. +func_check_version_match () +{ + if test "$package_revision" != "$macro_revision"; then + if test "$VERSION" != "$macro_version"; then + if test -z "$macro_version"; then + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, but the +$progname: definition of this LT_INIT comes from an older release. +$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION +$progname: and run autoconf again. +_LT_EOF + else + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, but the +$progname: definition of this LT_INIT comes from $PACKAGE $macro_version. +$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION +$progname: and run autoconf again. +_LT_EOF + fi + else + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision, +$progname: but the definition of this LT_INIT comes from revision $macro_revision. +$progname: You should recreate aclocal.m4 with macros from revision $package_revision +$progname: of $PACKAGE $VERSION and run autoconf again. +_LT_EOF + fi + + exit $EXIT_MISMATCH + fi +} + + +# libtool_options_prep [ARG]... +# ----------------------------- +# Preparation for options parsed by libtool. +libtool_options_prep () +{ + $debug_mode + + # Option defaults: + opt_config=false + opt_dlopen= + opt_dry_run=false + opt_help=false + opt_mode= + opt_preserve_dup_deps=false + opt_quiet=false + + nonopt= + preserve_args= + + # Shorthand for --mode=foo, only valid as the first argument + case $1 in + clean|clea|cle|cl) + shift; set dummy --mode clean ${1+"$@"}; shift + ;; + compile|compil|compi|comp|com|co|c) + shift; set dummy --mode compile ${1+"$@"}; shift + ;; + execute|execut|execu|exec|exe|ex|e) + shift; set dummy --mode execute ${1+"$@"}; shift + ;; + finish|finis|fini|fin|fi|f) + shift; set dummy --mode finish ${1+"$@"}; shift + ;; + install|instal|insta|inst|ins|in|i) + shift; set dummy --mode install ${1+"$@"}; shift + ;; + link|lin|li|l) + shift; set dummy --mode link ${1+"$@"}; shift + ;; + uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) + shift; set dummy --mode uninstall ${1+"$@"}; shift + ;; + esac + + # Pass back the list of options. + func_quote_for_eval ${1+"$@"} + libtool_options_prep_result=$func_quote_for_eval_result +} +func_add_hook func_options_prep libtool_options_prep + + +# libtool_parse_options [ARG]... +# --------------------------------- +# Provide handling for libtool specific options. +libtool_parse_options () +{ + $debug_cmd + + # Perform our own loop to consume as many options as possible in + # each iteration. + while test $# -gt 0; do + _G_opt=$1 + shift + case $_G_opt in + --dry-run|--dryrun|-n) + opt_dry_run=: + ;; + + --config) func_config ;; + + --dlopen|-dlopen) + opt_dlopen="${opt_dlopen+$opt_dlopen +}$1" + shift + ;; + + --preserve-dup-deps) + opt_preserve_dup_deps=: ;; + + --features) func_features ;; + + --finish) set dummy --mode finish ${1+"$@"}; shift ;; + + --help) opt_help=: ;; + + --help-all) opt_help=': help-all' ;; + + --mode) test $# = 0 && func_missing_arg $_G_opt && break + opt_mode=$1 + case $1 in + # Valid mode arguments: + clean|compile|execute|finish|install|link|relink|uninstall) ;; + + # Catch anything else as an error + *) func_error "invalid argument for $_G_opt" + exit_cmd=exit + break + ;; + esac + shift + ;; + + --no-silent|--no-quiet) + opt_quiet=false + func_append preserve_args " $_G_opt" + ;; + + --no-warnings|--no-warning|--no-warn) + opt_warning=false + func_append preserve_args " $_G_opt" + ;; + + --no-verbose) + opt_verbose=false + func_append preserve_args " $_G_opt" + ;; + + --silent|--quiet) + opt_quiet=: + opt_verbose=false + func_append preserve_args " $_G_opt" + ;; + + --tag) test $# = 0 && func_missing_arg $_G_opt && break + opt_tag=$1 + func_append preserve_args " $_G_opt $1" + func_enable_tag "$1" + shift + ;; + + --verbose|-v) opt_quiet=false + opt_verbose=: + func_append preserve_args " $_G_opt" + ;; + + # An option not handled by this hook function: + *) set dummy "$_G_opt" ${1+"$@"}; shift; break ;; + esac + done + + + # save modified positional parameters for caller + func_quote_for_eval ${1+"$@"} + libtool_parse_options_result=$func_quote_for_eval_result +} +func_add_hook func_parse_options libtool_parse_options + + + +# libtool_validate_options [ARG]... +# --------------------------------- +# Perform any sanity checks on option settings and/or unconsumed +# arguments. +libtool_validate_options () +{ + # save first non-option argument + if test 0 -lt $#; then + nonopt=$1 + shift + fi + + # preserve --debug + test : = "$debug_cmd" || func_append preserve_args " --debug" + + case $host in + # Solaris2 added to fix http://debbugs.gnu.org/cgi/bugreport.cgi?bug=16452 + # see also: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59788 + *cygwin* | *mingw* | *pw32* | *cegcc* | *solaris2* | *os2*) + # don't eliminate duplications in $postdeps and $predeps + opt_duplicate_compiler_generated_deps=: + ;; + *) + opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps + ;; + esac + + $opt_help || { + # Sanity checks first: + func_check_version_match + + test yes != "$build_libtool_libs" \ + && test yes != "$build_old_libs" \ + && func_fatal_configuration "not configured to build any kind of library" + + # Darwin sucks + eval std_shrext=\"$shrext_cmds\" + + # Only execute mode is allowed to have -dlopen flags. + if test -n "$opt_dlopen" && test execute != "$opt_mode"; then + func_error "unrecognized option '-dlopen'" + $ECHO "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Change the help message to a mode-specific one. + generic_help=$help + help="Try '$progname --help --mode=$opt_mode' for more information." + } + + # Pass back the unparsed argument list + func_quote_for_eval ${1+"$@"} + libtool_validate_options_result=$func_quote_for_eval_result +} +func_add_hook func_validate_options libtool_validate_options + + +# Process options as early as possible so that --help and --version +# can return quickly. +func_options ${1+"$@"} +eval set dummy "$func_options_result"; shift + + + +## ----------- ## +## Main. ## +## ----------- ## + +magic='%%%MAGIC variable%%%' +magic_exe='%%%MAGIC EXE variable%%%' + +# Global variables. +extracted_archives= +extracted_serial=0 + +# If this variable is set in any of the actions, the command in it +# will be execed at the end. This prevents here-documents from being +# left over by shells. +exec_cmd= + + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' +} + +# func_generated_by_libtool +# True iff stdin has been generated by Libtool. This function is only +# a basic sanity check; it will hardly flush out determined imposters. +func_generated_by_libtool_p () +{ + $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 +} + +# func_lalib_p file +# True iff FILE is a libtool '.la' library or '.lo' object file. +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_lalib_p () +{ + test -f "$1" && + $SED -e 4q "$1" 2>/dev/null | func_generated_by_libtool_p +} + +# func_lalib_unsafe_p file +# True iff FILE is a libtool '.la' library or '.lo' object file. +# This function implements the same check as func_lalib_p without +# resorting to external programs. To this end, it redirects stdin and +# closes it afterwards, without saving the original file descriptor. +# As a safety measure, use it only where a negative result would be +# fatal anyway. Works if 'file' does not exist. +func_lalib_unsafe_p () +{ + lalib_p=no + if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then + for lalib_p_l in 1 2 3 4 + do + read lalib_p_line + case $lalib_p_line in + \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;; + esac + done + exec 0<&5 5<&- + fi + test yes = "$lalib_p" +} + +# func_ltwrapper_script_p file +# True iff FILE is a libtool wrapper script +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_script_p () +{ + test -f "$1" && + $lt_truncate_bin < "$1" 2>/dev/null | func_generated_by_libtool_p +} + +# func_ltwrapper_executable_p file +# True iff FILE is a libtool wrapper executable +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_executable_p () +{ + func_ltwrapper_exec_suffix= + case $1 in + *.exe) ;; + *) func_ltwrapper_exec_suffix=.exe ;; + esac + $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1 +} + +# func_ltwrapper_scriptname file +# Assumes file is an ltwrapper_executable +# uses $file to determine the appropriate filename for a +# temporary ltwrapper_script. +func_ltwrapper_scriptname () +{ + func_dirname_and_basename "$1" "" "." + func_stripname '' '.exe' "$func_basename_result" + func_ltwrapper_scriptname_result=$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper +} + +# func_ltwrapper_p file +# True iff FILE is a libtool wrapper script or wrapper executable +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_p () +{ + func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1" +} + + +# func_execute_cmds commands fail_cmd +# Execute tilde-delimited COMMANDS. +# If FAIL_CMD is given, eval that upon failure. +# FAIL_CMD may read-access the current command in variable CMD! +func_execute_cmds () +{ + $debug_cmd + + save_ifs=$IFS; IFS='~' + for cmd in $1; do + IFS=$sp$nl + eval cmd=\"$cmd\" + IFS=$save_ifs + func_show_eval "$cmd" "${2-:}" + done + IFS=$save_ifs +} + + +# func_source file +# Source FILE, adding directory component if necessary. +# Note that it is not necessary on cygwin/mingw to append a dot to +# FILE even if both FILE and FILE.exe exist: automatic-append-.exe +# behavior happens only for exec(3), not for open(2)! Also, sourcing +# 'FILE.' does not work on cygwin managed mounts. +func_source () +{ + $debug_cmd + + case $1 in + */* | *\\*) . "$1" ;; + *) . "./$1" ;; + esac +} + + +# func_resolve_sysroot PATH +# Replace a leading = in PATH with a sysroot. Store the result into +# func_resolve_sysroot_result +func_resolve_sysroot () +{ + func_resolve_sysroot_result=$1 + case $func_resolve_sysroot_result in + =*) + func_stripname '=' '' "$func_resolve_sysroot_result" + func_resolve_sysroot_result=$lt_sysroot$func_stripname_result + ;; + esac +} + +# func_replace_sysroot PATH +# If PATH begins with the sysroot, replace it with = and +# store the result into func_replace_sysroot_result. +func_replace_sysroot () +{ + case $lt_sysroot:$1 in + ?*:"$lt_sysroot"*) + func_stripname "$lt_sysroot" '' "$1" + func_replace_sysroot_result='='$func_stripname_result + ;; + *) + # Including no sysroot. + func_replace_sysroot_result=$1 + ;; + esac +} + +# func_infer_tag arg +# Infer tagged configuration to use if any are available and +# if one wasn't chosen via the "--tag" command line option. +# Only attempt this if the compiler in the base compile +# command doesn't match the default compiler. +# arg is usually of the form 'gcc ...' +func_infer_tag () +{ + $debug_cmd + + if test -n "$available_tags" && test -z "$tagname"; then + CC_quoted= + for arg in $CC; do + func_append_quoted CC_quoted "$arg" + done + CC_expanded=`func_echo_all $CC` + CC_quoted_expanded=`func_echo_all $CC_quoted` + case $@ in + # Blanks in the command may have been stripped by the calling shell, + # but not from the CC environment variable when configure was run. + " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ + " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;; + # Blanks at the start of $base_compile will cause this to fail + # if we don't check for them as well. + *) + for z in $available_tags; do + if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then + # Evaluate the configuration. + eval "`$SED -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" + CC_quoted= + for arg in $CC; do + # Double-quote args containing other shell metacharacters. + func_append_quoted CC_quoted "$arg" + done + CC_expanded=`func_echo_all $CC` + CC_quoted_expanded=`func_echo_all $CC_quoted` + case "$@ " in + " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ + " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) + # The compiler in the base compile command matches + # the one in the tagged configuration. + # Assume this is the tagged configuration we want. + tagname=$z + break + ;; + esac + fi + done + # If $tagname still isn't set, then no tagged configuration + # was found and let the user know that the "--tag" command + # line option must be used. + if test -z "$tagname"; then + func_echo "unable to infer tagged configuration" + func_fatal_error "specify a tag with '--tag'" +# else +# func_verbose "using $tagname tagged configuration" + fi + ;; + esac + fi +} + + + +# func_write_libtool_object output_name pic_name nonpic_name +# Create a libtool object file (analogous to a ".la" file), +# but don't create it if we're doing a dry run. +func_write_libtool_object () +{ + write_libobj=$1 + if test yes = "$build_libtool_libs"; then + write_lobj=\'$2\' + else + write_lobj=none + fi + + if test yes = "$build_old_libs"; then + write_oldobj=\'$3\' + else + write_oldobj=none + fi + + $opt_dry_run || { + cat >${write_libobj}T </dev/null` + if test "$?" -eq 0 && test -n "$func_convert_core_file_wine_to_w32_tmp"; then + func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" | + $SED -e "$sed_naive_backslashify"` + else + func_convert_core_file_wine_to_w32_result= + fi + fi +} +# end: func_convert_core_file_wine_to_w32 + + +# func_convert_core_path_wine_to_w32 ARG +# Helper function used by path conversion functions when $build is *nix, and +# $host is mingw, cygwin, or some other w32 environment. Relies on a correctly +# configured wine environment available, with the winepath program in $build's +# $PATH. Assumes ARG has no leading or trailing path separator characters. +# +# ARG is path to be converted from $build format to win32. +# Result is available in $func_convert_core_path_wine_to_w32_result. +# Unconvertible file (directory) names in ARG are skipped; if no directory names +# are convertible, then the result may be empty. +func_convert_core_path_wine_to_w32 () +{ + $debug_cmd + + # unfortunately, winepath doesn't convert paths, only file names + func_convert_core_path_wine_to_w32_result= + if test -n "$1"; then + oldIFS=$IFS + IFS=: + for func_convert_core_path_wine_to_w32_f in $1; do + IFS=$oldIFS + func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f" + if test -n "$func_convert_core_file_wine_to_w32_result"; then + if test -z "$func_convert_core_path_wine_to_w32_result"; then + func_convert_core_path_wine_to_w32_result=$func_convert_core_file_wine_to_w32_result + else + func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result" + fi + fi + done + IFS=$oldIFS + fi +} +# end: func_convert_core_path_wine_to_w32 + + +# func_cygpath ARGS... +# Wrapper around calling the cygpath program via LT_CYGPATH. This is used when +# when (1) $build is *nix and Cygwin is hosted via a wine environment; or (2) +# $build is MSYS and $host is Cygwin, or (3) $build is Cygwin. In case (1) or +# (2), returns the Cygwin file name or path in func_cygpath_result (input +# file name or path is assumed to be in w32 format, as previously converted +# from $build's *nix or MSYS format). In case (3), returns the w32 file name +# or path in func_cygpath_result (input file name or path is assumed to be in +# Cygwin format). Returns an empty string on error. +# +# ARGS are passed to cygpath, with the last one being the file name or path to +# be converted. +# +# Specify the absolute *nix (or w32) name to cygpath in the LT_CYGPATH +# environment variable; do not put it in $PATH. +func_cygpath () +{ + $debug_cmd + + if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then + func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null` + if test "$?" -ne 0; then + # on failure, ensure result is empty + func_cygpath_result= + fi + else + func_cygpath_result= + func_error "LT_CYGPATH is empty or specifies non-existent file: '$LT_CYGPATH'" + fi +} +#end: func_cygpath + + +# func_convert_core_msys_to_w32 ARG +# Convert file name or path ARG from MSYS format to w32 format. Return +# result in func_convert_core_msys_to_w32_result. +func_convert_core_msys_to_w32 () +{ + $debug_cmd + + # awkward: cmd appends spaces to result + func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null | + $SED -e 's/[ ]*$//' -e "$sed_naive_backslashify"` +} +#end: func_convert_core_msys_to_w32 + + +# func_convert_file_check ARG1 ARG2 +# Verify that ARG1 (a file name in $build format) was converted to $host +# format in ARG2. Otherwise, emit an error message, but continue (resetting +# func_to_host_file_result to ARG1). +func_convert_file_check () +{ + $debug_cmd + + if test -z "$2" && test -n "$1"; then + func_error "Could not determine host file name corresponding to" + func_error " '$1'" + func_error "Continuing, but uninstalled executables may not work." + # Fallback: + func_to_host_file_result=$1 + fi +} +# end func_convert_file_check + + +# func_convert_path_check FROM_PATHSEP TO_PATHSEP FROM_PATH TO_PATH +# Verify that FROM_PATH (a path in $build format) was converted to $host +# format in TO_PATH. Otherwise, emit an error message, but continue, resetting +# func_to_host_file_result to a simplistic fallback value (see below). +func_convert_path_check () +{ + $debug_cmd + + if test -z "$4" && test -n "$3"; then + func_error "Could not determine the host path corresponding to" + func_error " '$3'" + func_error "Continuing, but uninstalled executables may not work." + # Fallback. This is a deliberately simplistic "conversion" and + # should not be "improved". See libtool.info. + if test "x$1" != "x$2"; then + lt_replace_pathsep_chars="s|$1|$2|g" + func_to_host_path_result=`echo "$3" | + $SED -e "$lt_replace_pathsep_chars"` + else + func_to_host_path_result=$3 + fi + fi +} +# end func_convert_path_check + + +# func_convert_path_front_back_pathsep FRONTPAT BACKPAT REPL ORIG +# Modifies func_to_host_path_result by prepending REPL if ORIG matches FRONTPAT +# and appending REPL if ORIG matches BACKPAT. +func_convert_path_front_back_pathsep () +{ + $debug_cmd + + case $4 in + $1 ) func_to_host_path_result=$3$func_to_host_path_result + ;; + esac + case $4 in + $2 ) func_append func_to_host_path_result "$3" + ;; + esac +} +# end func_convert_path_front_back_pathsep + + +################################################## +# $build to $host FILE NAME CONVERSION FUNCTIONS # +################################################## +# invoked via '$to_host_file_cmd ARG' +# +# In each case, ARG is the path to be converted from $build to $host format. +# Result will be available in $func_to_host_file_result. + + +# func_to_host_file ARG +# Converts the file name ARG from $build format to $host format. Return result +# in func_to_host_file_result. +func_to_host_file () +{ + $debug_cmd + + $to_host_file_cmd "$1" +} +# end func_to_host_file + + +# func_to_tool_file ARG LAZY +# converts the file name ARG from $build format to toolchain format. Return +# result in func_to_tool_file_result. If the conversion in use is listed +# in (the comma separated) LAZY, no conversion takes place. +func_to_tool_file () +{ + $debug_cmd + + case ,$2, in + *,"$to_tool_file_cmd",*) + func_to_tool_file_result=$1 + ;; + *) + $to_tool_file_cmd "$1" + func_to_tool_file_result=$func_to_host_file_result + ;; + esac +} +# end func_to_tool_file + + +# func_convert_file_noop ARG +# Copy ARG to func_to_host_file_result. +func_convert_file_noop () +{ + func_to_host_file_result=$1 +} +# end func_convert_file_noop + + +# func_convert_file_msys_to_w32 ARG +# Convert file name ARG from (mingw) MSYS to (mingw) w32 format; automatic +# conversion to w32 is not available inside the cwrapper. Returns result in +# func_to_host_file_result. +func_convert_file_msys_to_w32 () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + func_convert_core_msys_to_w32 "$1" + func_to_host_file_result=$func_convert_core_msys_to_w32_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_msys_to_w32 + + +# func_convert_file_cygwin_to_w32 ARG +# Convert file name ARG from Cygwin to w32 format. Returns result in +# func_to_host_file_result. +func_convert_file_cygwin_to_w32 () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + # because $build is cygwin, we call "the" cygpath in $PATH; no need to use + # LT_CYGPATH in this case. + func_to_host_file_result=`cygpath -m "$1"` + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_cygwin_to_w32 + + +# func_convert_file_nix_to_w32 ARG +# Convert file name ARG from *nix to w32 format. Requires a wine environment +# and a working winepath. Returns result in func_to_host_file_result. +func_convert_file_nix_to_w32 () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + func_convert_core_file_wine_to_w32 "$1" + func_to_host_file_result=$func_convert_core_file_wine_to_w32_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_nix_to_w32 + + +# func_convert_file_msys_to_cygwin ARG +# Convert file name ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. +# Returns result in func_to_host_file_result. +func_convert_file_msys_to_cygwin () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + func_convert_core_msys_to_w32 "$1" + func_cygpath -u "$func_convert_core_msys_to_w32_result" + func_to_host_file_result=$func_cygpath_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_msys_to_cygwin + + +# func_convert_file_nix_to_cygwin ARG +# Convert file name ARG from *nix to Cygwin format. Requires Cygwin installed +# in a wine environment, working winepath, and LT_CYGPATH set. Returns result +# in func_to_host_file_result. +func_convert_file_nix_to_cygwin () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + # convert from *nix to w32, then use cygpath to convert from w32 to cygwin. + func_convert_core_file_wine_to_w32 "$1" + func_cygpath -u "$func_convert_core_file_wine_to_w32_result" + func_to_host_file_result=$func_cygpath_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_nix_to_cygwin + + +############################################# +# $build to $host PATH CONVERSION FUNCTIONS # +############################################# +# invoked via '$to_host_path_cmd ARG' +# +# In each case, ARG is the path to be converted from $build to $host format. +# The result will be available in $func_to_host_path_result. +# +# Path separators are also converted from $build format to $host format. If +# ARG begins or ends with a path separator character, it is preserved (but +# converted to $host format) on output. +# +# All path conversion functions are named using the following convention: +# file name conversion function : func_convert_file_X_to_Y () +# path conversion function : func_convert_path_X_to_Y () +# where, for any given $build/$host combination the 'X_to_Y' value is the +# same. If conversion functions are added for new $build/$host combinations, +# the two new functions must follow this pattern, or func_init_to_host_path_cmd +# will break. + + +# func_init_to_host_path_cmd +# Ensures that function "pointer" variable $to_host_path_cmd is set to the +# appropriate value, based on the value of $to_host_file_cmd. +to_host_path_cmd= +func_init_to_host_path_cmd () +{ + $debug_cmd + + if test -z "$to_host_path_cmd"; then + func_stripname 'func_convert_file_' '' "$to_host_file_cmd" + to_host_path_cmd=func_convert_path_$func_stripname_result + fi +} + + +# func_to_host_path ARG +# Converts the path ARG from $build format to $host format. Return result +# in func_to_host_path_result. +func_to_host_path () +{ + $debug_cmd + + func_init_to_host_path_cmd + $to_host_path_cmd "$1" +} +# end func_to_host_path + + +# func_convert_path_noop ARG +# Copy ARG to func_to_host_path_result. +func_convert_path_noop () +{ + func_to_host_path_result=$1 +} +# end func_convert_path_noop + + +# func_convert_path_msys_to_w32 ARG +# Convert path ARG from (mingw) MSYS to (mingw) w32 format; automatic +# conversion to w32 is not available inside the cwrapper. Returns result in +# func_to_host_path_result. +func_convert_path_msys_to_w32 () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # Remove leading and trailing path separator characters from ARG. MSYS + # behavior is inconsistent here; cygpath turns them into '.;' and ';.'; + # and winepath ignores them completely. + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" + func_to_host_path_result=$func_convert_core_msys_to_w32_result + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_msys_to_w32 + + +# func_convert_path_cygwin_to_w32 ARG +# Convert path ARG from Cygwin to w32 format. Returns result in +# func_to_host_file_result. +func_convert_path_cygwin_to_w32 () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_to_host_path_result=`cygpath -m -p "$func_to_host_path_tmp1"` + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_cygwin_to_w32 + + +# func_convert_path_nix_to_w32 ARG +# Convert path ARG from *nix to w32 format. Requires a wine environment and +# a working winepath. Returns result in func_to_host_file_result. +func_convert_path_nix_to_w32 () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" + func_to_host_path_result=$func_convert_core_path_wine_to_w32_result + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_nix_to_w32 + + +# func_convert_path_msys_to_cygwin ARG +# Convert path ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. +# Returns result in func_to_host_file_result. +func_convert_path_msys_to_cygwin () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" + func_cygpath -u -p "$func_convert_core_msys_to_w32_result" + func_to_host_path_result=$func_cygpath_result + func_convert_path_check : : \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" : "$1" + fi +} +# end func_convert_path_msys_to_cygwin + + +# func_convert_path_nix_to_cygwin ARG +# Convert path ARG from *nix to Cygwin format. Requires Cygwin installed in a +# a wine environment, working winepath, and LT_CYGPATH set. Returns result in +# func_to_host_file_result. +func_convert_path_nix_to_cygwin () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # Remove leading and trailing path separator characters from + # ARG. msys behavior is inconsistent here, cygpath turns them + # into '.;' and ';.', and winepath ignores them completely. + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" + func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result" + func_to_host_path_result=$func_cygpath_result + func_convert_path_check : : \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" : "$1" + fi +} +# end func_convert_path_nix_to_cygwin + + +# func_dll_def_p FILE +# True iff FILE is a Windows DLL '.def' file. +# Keep in sync with _LT_DLL_DEF_P in libtool.m4 +func_dll_def_p () +{ + $debug_cmd + + func_dll_def_p_tmp=`$SED -n \ + -e 's/^[ ]*//' \ + -e '/^\(;.*\)*$/d' \ + -e 's/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p' \ + -e q \ + "$1"` + test DEF = "$func_dll_def_p_tmp" +} + + +# func_mode_compile arg... +func_mode_compile () +{ + $debug_cmd + + # Get the compilation command and the source file. + base_compile= + srcfile=$nonopt # always keep a non-empty value in "srcfile" + suppress_opt=yes + suppress_output= + arg_mode=normal + libobj= + later= + pie_flag= + + for arg + do + case $arg_mode in + arg ) + # do not "continue". Instead, add this to base_compile + lastarg=$arg + arg_mode=normal + ;; + + target ) + libobj=$arg + arg_mode=normal + continue + ;; + + normal ) + # Accept any command-line options. + case $arg in + -o) + test -n "$libobj" && \ + func_fatal_error "you cannot specify '-o' more than once" + arg_mode=target + continue + ;; + + -pie | -fpie | -fPIE) + func_append pie_flag " $arg" + continue + ;; + + -shared | -static | -prefer-pic | -prefer-non-pic) + func_append later " $arg" + continue + ;; + + -no-suppress) + suppress_opt=no + continue + ;; + + -Xcompiler) + arg_mode=arg # the next one goes into the "base_compile" arg list + continue # The current "srcfile" will either be retained or + ;; # replaced later. I would guess that would be a bug. + + -Wc,*) + func_stripname '-Wc,' '' "$arg" + args=$func_stripname_result + lastarg= + save_ifs=$IFS; IFS=, + for arg in $args; do + IFS=$save_ifs + func_append_quoted lastarg "$arg" + done + IFS=$save_ifs + func_stripname ' ' '' "$lastarg" + lastarg=$func_stripname_result + + # Add the arguments to base_compile. + func_append base_compile " $lastarg" + continue + ;; + + *) + # Accept the current argument as the source file. + # The previous "srcfile" becomes the current argument. + # + lastarg=$srcfile + srcfile=$arg + ;; + esac # case $arg + ;; + esac # case $arg_mode + + # Aesthetically quote the previous argument. + func_append_quoted base_compile "$lastarg" + done # for arg + + case $arg_mode in + arg) + func_fatal_error "you must specify an argument for -Xcompile" + ;; + target) + func_fatal_error "you must specify a target with '-o'" + ;; + *) + # Get the name of the library object. + test -z "$libobj" && { + func_basename "$srcfile" + libobj=$func_basename_result + } + ;; + esac + + # Recognize several different file suffixes. + # If the user specifies -o file.o, it is replaced with file.lo + case $libobj in + *.[cCFSifmso] | \ + *.ada | *.adb | *.ads | *.asm | \ + *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \ + *.[fF][09]? | *.for | *.java | *.go | *.obj | *.sx | *.cu | *.cup) + func_xform "$libobj" + libobj=$func_xform_result + ;; + esac + + case $libobj in + *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;; + *) + func_fatal_error "cannot determine name of library object from '$libobj'" + ;; + esac + + func_infer_tag $base_compile + + for arg in $later; do + case $arg in + -shared) + test yes = "$build_libtool_libs" \ + || func_fatal_configuration "cannot build a shared library" + build_old_libs=no + continue + ;; + + -static) + build_libtool_libs=no + build_old_libs=yes + continue + ;; + + -prefer-pic) + pic_mode=yes + continue + ;; + + -prefer-non-pic) + pic_mode=no + continue + ;; + esac + done + + func_quote_for_eval "$libobj" + test "X$libobj" != "X$func_quote_for_eval_result" \ + && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"' &()|`$[]' \ + && func_warning "libobj name '$libobj' may not contain shell special characters." + func_dirname_and_basename "$obj" "/" "" + objname=$func_basename_result + xdir=$func_dirname_result + lobj=$xdir$objdir/$objname + + test -z "$base_compile" && \ + func_fatal_help "you must specify a compilation command" + + # Delete any leftover library objects. + if test yes = "$build_old_libs"; then + removelist="$obj $lobj $libobj ${libobj}T" + else + removelist="$lobj $libobj ${libobj}T" + fi + + # On Cygwin there's no "real" PIC flag so we must build both object types + case $host_os in + cygwin* | mingw* | pw32* | os2* | cegcc*) + pic_mode=default + ;; + esac + if test no = "$pic_mode" && test pass_all != "$deplibs_check_method"; then + # non-PIC code in shared libraries is not supported + pic_mode=default + fi + + # Calculate the filename of the output object if compiler does + # not support -o with -c + if test no = "$compiler_c_o"; then + output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.$objext + lockfile=$output_obj.lock + else + output_obj= + need_locks=no + lockfile= + fi + + # Lock this critical section if it is needed + # We use this script file to make the link, it avoids creating a new file + if test yes = "$need_locks"; then + until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do + func_echo "Waiting for $lockfile to be removed" + sleep 2 + done + elif test warn = "$need_locks"; then + if test -f "$lockfile"; then + $ECHO "\ +*** ERROR, $lockfile exists and contains: +`cat $lockfile 2>/dev/null` + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support '-c' and '-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + func_append removelist " $output_obj" + $ECHO "$srcfile" > "$lockfile" + fi + + $opt_dry_run || $RM $removelist + func_append removelist " $lockfile" + trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15 + + func_to_tool_file "$srcfile" func_convert_file_msys_to_w32 + srcfile=$func_to_tool_file_result + func_quote_for_eval "$srcfile" + qsrcfile=$func_quote_for_eval_result + + # Only build a PIC object if we are building libtool libraries. + if test yes = "$build_libtool_libs"; then + # Without this assignment, base_compile gets emptied. + fbsd_hideous_sh_bug=$base_compile + + if test no != "$pic_mode"; then + command="$base_compile $qsrcfile $pic_flag" + else + # Don't build PIC code + command="$base_compile $qsrcfile" + fi + + func_mkdir_p "$xdir$objdir" + + if test -z "$output_obj"; then + # Place PIC objects in $objdir + func_append command " -o $lobj" + fi + + func_show_eval_locale "$command" \ + 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE' + + if test warn = "$need_locks" && + test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then + $ECHO "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support '-c' and '-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed, then go on to compile the next one + if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then + func_show_eval '$MV "$output_obj" "$lobj"' \ + 'error=$?; $opt_dry_run || $RM $removelist; exit $error' + fi + + # Allow error messages only from the first compilation. + if test yes = "$suppress_opt"; then + suppress_output=' >/dev/null 2>&1' + fi + fi + + # Only build a position-dependent object if we build old libraries. + if test yes = "$build_old_libs"; then + if test yes != "$pic_mode"; then + # Don't build PIC code + command="$base_compile $qsrcfile$pie_flag" + else + command="$base_compile $qsrcfile $pic_flag" + fi + if test yes = "$compiler_c_o"; then + func_append command " -o $obj" + fi + + # Suppress compiler output if we already did a PIC compilation. + func_append command "$suppress_output" + func_show_eval_locale "$command" \ + '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' + + if test warn = "$need_locks" && + test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then + $ECHO "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support '-c' and '-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed + if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then + func_show_eval '$MV "$output_obj" "$obj"' \ + 'error=$?; $opt_dry_run || $RM $removelist; exit $error' + fi + fi + + $opt_dry_run || { + func_write_libtool_object "$libobj" "$objdir/$objname" "$objname" + + # Unlock the critical section if it was locked + if test no != "$need_locks"; then + removelist=$lockfile + $RM "$lockfile" + fi + } + + exit $EXIT_SUCCESS +} + +$opt_help || { + test compile = "$opt_mode" && func_mode_compile ${1+"$@"} +} + +func_mode_help () +{ + # We need to display help for each of the modes. + case $opt_mode in + "") + # Generic help is extracted from the usage comments + # at the start of this file. + func_help + ;; + + clean) + $ECHO \ +"Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE... + +Remove files from the build directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed +to RM. + +If FILE is a libtool library, object or program, all the files associated +with it are deleted. Otherwise, only FILE itself is deleted using RM." + ;; + + compile) + $ECHO \ +"Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE + +Compile a source file into a libtool library object. + +This mode accepts the following additional options: + + -o OUTPUT-FILE set the output file name to OUTPUT-FILE + -no-suppress do not suppress compiler output for multiple passes + -prefer-pic try to build PIC objects only + -prefer-non-pic try to build non-PIC objects only + -shared do not build a '.o' file suitable for static linking + -static only build a '.o' file suitable for static linking + -Wc,FLAG pass FLAG directly to the compiler + +COMPILE-COMMAND is a command to be used in creating a 'standard' object file +from the given SOURCEFILE. + +The output file name is determined by removing the directory component from +SOURCEFILE, then substituting the C source code suffix '.c' with the +library object suffix, '.lo'." + ;; + + execute) + $ECHO \ +"Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]... + +Automatically set library path, then run a program. + +This mode accepts the following additional options: + + -dlopen FILE add the directory containing FILE to the library path + +This mode sets the library path environment variable according to '-dlopen' +flags. + +If any of the ARGS are libtool executable wrappers, then they are translated +into their corresponding uninstalled binary, and any of their required library +directories are added to the library path. + +Then, COMMAND is executed, with ARGS as arguments." + ;; + + finish) + $ECHO \ +"Usage: $progname [OPTION]... --mode=finish [LIBDIR]... + +Complete the installation of libtool libraries. + +Each LIBDIR is a directory that contains libtool libraries. + +The commands that this mode executes may require superuser privileges. Use +the '--dry-run' option if you just want to see what would be executed." + ;; + + install) + $ECHO \ +"Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND... + +Install executables or libraries. + +INSTALL-COMMAND is the installation command. The first component should be +either the 'install' or 'cp' program. + +The following components of INSTALL-COMMAND are treated specially: + + -inst-prefix-dir PREFIX-DIR Use PREFIX-DIR as a staging area for installation + +The rest of the components are interpreted as arguments to that command (only +BSD-compatible install options are recognized)." + ;; + + link) + $ECHO \ +"Usage: $progname [OPTION]... --mode=link LINK-COMMAND... + +Link object files or libraries together to form another library, or to +create an executable program. + +LINK-COMMAND is a command using the C compiler that you would use to create +a program from several object files. + +The following components of LINK-COMMAND are treated specially: + + -all-static do not do any dynamic linking at all + -avoid-version do not add a version suffix if possible + -bindir BINDIR specify path to binaries directory (for systems where + libraries must be found in the PATH setting at runtime) + -dlopen FILE '-dlpreopen' FILE if it cannot be dlopened at runtime + -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols + -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) + -export-symbols SYMFILE + try to export only the symbols listed in SYMFILE + -export-symbols-regex REGEX + try to export only the symbols matching REGEX + -LLIBDIR search LIBDIR for required installed libraries + -lNAME OUTPUT-FILE requires the installed library libNAME + -module build a library that can dlopened + -no-fast-install disable the fast-install mode + -no-install link a not-installable executable + -no-undefined declare that a library does not refer to external symbols + -o OUTPUT-FILE create OUTPUT-FILE from the specified objects + -objectlist FILE use a list of object files found in FILE to specify objects + -os2dllname NAME force a short DLL name on OS/2 (no effect on other OSes) + -precious-files-regex REGEX + don't remove output files matching REGEX + -release RELEASE specify package release information + -rpath LIBDIR the created library will eventually be installed in LIBDIR + -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries + -shared only do dynamic linking of libtool libraries + -shrext SUFFIX override the standard shared library file extension + -static do not do any dynamic linking of uninstalled libtool libraries + -static-libtool-libs + do not do any dynamic linking of libtool libraries + -version-info CURRENT[:REVISION[:AGE]] + specify library version info [each variable defaults to 0] + -weak LIBNAME declare that the target provides the LIBNAME interface + -Wc,FLAG + -Xcompiler FLAG pass linker-specific FLAG directly to the compiler + -Wl,FLAG + -Xlinker FLAG pass linker-specific FLAG directly to the linker + -XCClinker FLAG pass link-specific FLAG to the compiler driver (CC) + +All other options (arguments beginning with '-') are ignored. + +Every other argument is treated as a filename. Files ending in '.la' are +treated as uninstalled libtool libraries, other files are standard or library +object files. + +If the OUTPUT-FILE ends in '.la', then a libtool library is created, +only library objects ('.lo' files) may be specified, and '-rpath' is +required, except when creating a convenience library. + +If OUTPUT-FILE ends in '.a' or '.lib', then a standard library is created +using 'ar' and 'ranlib', or on Windows using 'lib'. + +If OUTPUT-FILE ends in '.lo' or '.$objext', then a reloadable object file +is created, otherwise an executable program is created." + ;; + + uninstall) + $ECHO \ +"Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... + +Remove libraries from an installation directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed +to RM. + +If FILE is a libtool library, all the files associated with it are deleted. +Otherwise, only FILE itself is deleted using RM." + ;; + + *) + func_fatal_help "invalid operation mode '$opt_mode'" + ;; + esac + + echo + $ECHO "Try '$progname --help' for more information about other modes." +} + +# Now that we've collected a possible --mode arg, show help if necessary +if $opt_help; then + if test : = "$opt_help"; then + func_mode_help + else + { + func_help noexit + for opt_mode in compile link execute install finish uninstall clean; do + func_mode_help + done + } | $SED -n '1p; 2,$s/^Usage:/ or: /p' + { + func_help noexit + for opt_mode in compile link execute install finish uninstall clean; do + echo + func_mode_help + done + } | + $SED '1d + /^When reporting/,/^Report/{ + H + d + } + $x + /information about other modes/d + /more detailed .*MODE/d + s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/' + fi + exit $? +fi + + +# func_mode_execute arg... +func_mode_execute () +{ + $debug_cmd + + # The first argument is the command name. + cmd=$nonopt + test -z "$cmd" && \ + func_fatal_help "you must specify a COMMAND" + + # Handle -dlopen flags immediately. + for file in $opt_dlopen; do + test -f "$file" \ + || func_fatal_help "'$file' is not a file" + + dir= + case $file in + *.la) + func_resolve_sysroot "$file" + file=$func_resolve_sysroot_result + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$file" \ + || func_fatal_help "'$lib' is not a valid libtool archive" + + # Read the libtool library. + dlname= + library_names= + func_source "$file" + + # Skip this library if it cannot be dlopened. + if test -z "$dlname"; then + # Warn if it was a shared library. + test -n "$library_names" && \ + func_warning "'$file' was not linked with '-export-dynamic'" + continue + fi + + func_dirname "$file" "" "." + dir=$func_dirname_result + + if test -f "$dir/$objdir/$dlname"; then + func_append dir "/$objdir" + else + if test ! -f "$dir/$dlname"; then + func_fatal_error "cannot find '$dlname' in '$dir' or '$dir/$objdir'" + fi + fi + ;; + + *.lo) + # Just add the directory containing the .lo file. + func_dirname "$file" "" "." + dir=$func_dirname_result + ;; + + *) + func_warning "'-dlopen' is ignored for non-libtool libraries and objects" + continue + ;; + esac + + # Get the absolute pathname. + absdir=`cd "$dir" && pwd` + test -n "$absdir" && dir=$absdir + + # Now add the directory to shlibpath_var. + if eval "test -z \"\$$shlibpath_var\""; then + eval "$shlibpath_var=\"\$dir\"" + else + eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" + fi + done + + # This variable tells wrapper scripts just to set shlibpath_var + # rather than running their programs. + libtool_execute_magic=$magic + + # Check if any of the arguments is a wrapper script. + args= + for file + do + case $file in + -* | *.la | *.lo ) ;; + *) + # Do a test to see if this is really a libtool program. + if func_ltwrapper_script_p "$file"; then + func_source "$file" + # Transform arg to wrapped name. + file=$progdir/$program + elif func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + func_source "$func_ltwrapper_scriptname_result" + # Transform arg to wrapped name. + file=$progdir/$program + fi + ;; + esac + # Quote arguments (to preserve shell metacharacters). + func_append_quoted args "$file" + done + + if $opt_dry_run; then + # Display what would be done. + if test -n "$shlibpath_var"; then + eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" + echo "export $shlibpath_var" + fi + $ECHO "$cmd$args" + exit $EXIT_SUCCESS + else + if test -n "$shlibpath_var"; then + # Export the shlibpath_var. + eval "export $shlibpath_var" + fi + + # Restore saved environment variables + for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES + do + eval "if test \"\${save_$lt_var+set}\" = set; then + $lt_var=\$save_$lt_var; export $lt_var + else + $lt_unset $lt_var + fi" + done + + # Now prepare to actually exec the command. + exec_cmd=\$cmd$args + fi +} + +test execute = "$opt_mode" && func_mode_execute ${1+"$@"} + + +# func_mode_finish arg... +func_mode_finish () +{ + $debug_cmd + + libs= + libdirs= + admincmds= + + for opt in "$nonopt" ${1+"$@"} + do + if test -d "$opt"; then + func_append libdirs " $opt" + + elif test -f "$opt"; then + if func_lalib_unsafe_p "$opt"; then + func_append libs " $opt" + else + func_warning "'$opt' is not a valid libtool archive" + fi + + else + func_fatal_error "invalid argument '$opt'" + fi + done + + if test -n "$libs"; then + if test -n "$lt_sysroot"; then + sysroot_regex=`$ECHO "$lt_sysroot" | $SED "$sed_make_literal_regex"` + sysroot_cmd="s/\([ ']\)$sysroot_regex/\1/g;" + else + sysroot_cmd= + fi + + # Remove sysroot references + if $opt_dry_run; then + for lib in $libs; do + echo "removing references to $lt_sysroot and '=' prefixes from $lib" + done + else + tmpdir=`func_mktempdir` + for lib in $libs; do + $SED -e "$sysroot_cmd s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \ + > $tmpdir/tmp-la + mv -f $tmpdir/tmp-la $lib + done + ${RM}r "$tmpdir" + fi + fi + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + for libdir in $libdirs; do + if test -n "$finish_cmds"; then + # Do each command in the finish commands. + func_execute_cmds "$finish_cmds" 'admincmds="$admincmds +'"$cmd"'"' + fi + if test -n "$finish_eval"; then + # Do the single finish_eval. + eval cmds=\"$finish_eval\" + $opt_dry_run || eval "$cmds" || func_append admincmds " + $cmds" + fi + done + fi + + # Exit here if they wanted silent mode. + $opt_quiet && exit $EXIT_SUCCESS + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + echo "----------------------------------------------------------------------" + echo "Libraries have been installed in:" + for libdir in $libdirs; do + $ECHO " $libdir" + done + echo + echo "If you ever happen to want to link against installed libraries" + echo "in a given directory, LIBDIR, you must either use libtool, and" + echo "specify the full pathname of the library, or use the '-LLIBDIR'" + echo "flag during linking and do at least one of the following:" + if test -n "$shlibpath_var"; then + echo " - add LIBDIR to the '$shlibpath_var' environment variable" + echo " during execution" + fi + if test -n "$runpath_var"; then + echo " - add LIBDIR to the '$runpath_var' environment variable" + echo " during linking" + fi + if test -n "$hardcode_libdir_flag_spec"; then + libdir=LIBDIR + eval flag=\"$hardcode_libdir_flag_spec\" + + $ECHO " - use the '$flag' linker flag" + fi + if test -n "$admincmds"; then + $ECHO " - have your system administrator run these commands:$admincmds" + fi + if test -f /etc/ld.so.conf; then + echo " - have your system administrator add LIBDIR to '/etc/ld.so.conf'" + fi + echo + + echo "See any operating system documentation about shared libraries for" + case $host in + solaris2.[6789]|solaris2.1[0-9]) + echo "more information, such as the ld(1), crle(1) and ld.so(8) manual" + echo "pages." + ;; + *) + echo "more information, such as the ld(1) and ld.so(8) manual pages." + ;; + esac + echo "----------------------------------------------------------------------" + fi + exit $EXIT_SUCCESS +} + +test finish = "$opt_mode" && func_mode_finish ${1+"$@"} + + +# func_mode_install arg... +func_mode_install () +{ + $debug_cmd + + # There may be an optional sh(1) argument at the beginning of + # install_prog (especially on Windows NT). + if test "$SHELL" = "$nonopt" || test /bin/sh = "$nonopt" || + # Allow the use of GNU shtool's install command. + case $nonopt in *shtool*) :;; *) false;; esac + then + # Aesthetically quote it. + func_quote_for_eval "$nonopt" + install_prog="$func_quote_for_eval_result " + arg=$1 + shift + else + install_prog= + arg=$nonopt + fi + + # The real first argument should be the name of the installation program. + # Aesthetically quote it. + func_quote_for_eval "$arg" + func_append install_prog "$func_quote_for_eval_result" + install_shared_prog=$install_prog + case " $install_prog " in + *[\\\ /]cp\ *) install_cp=: ;; + *) install_cp=false ;; + esac + + # We need to accept at least all the BSD install flags. + dest= + files= + opts= + prev= + install_type= + isdir=false + stripme= + no_mode=: + for arg + do + arg2= + if test -n "$dest"; then + func_append files " $dest" + dest=$arg + continue + fi + + case $arg in + -d) isdir=: ;; + -f) + if $install_cp; then :; else + prev=$arg + fi + ;; + -g | -m | -o) + prev=$arg + ;; + -s) + stripme=" -s" + continue + ;; + -*) + ;; + *) + # If the previous option needed an argument, then skip it. + if test -n "$prev"; then + if test X-m = "X$prev" && test -n "$install_override_mode"; then + arg2=$install_override_mode + no_mode=false + fi + prev= + else + dest=$arg + continue + fi + ;; + esac + + # Aesthetically quote the argument. + func_quote_for_eval "$arg" + func_append install_prog " $func_quote_for_eval_result" + if test -n "$arg2"; then + func_quote_for_eval "$arg2" + fi + func_append install_shared_prog " $func_quote_for_eval_result" + done + + test -z "$install_prog" && \ + func_fatal_help "you must specify an install program" + + test -n "$prev" && \ + func_fatal_help "the '$prev' option requires an argument" + + if test -n "$install_override_mode" && $no_mode; then + if $install_cp; then :; else + func_quote_for_eval "$install_override_mode" + func_append install_shared_prog " -m $func_quote_for_eval_result" + fi + fi + + if test -z "$files"; then + if test -z "$dest"; then + func_fatal_help "no file or destination specified" + else + func_fatal_help "you must specify a destination" + fi + fi + + # Strip any trailing slash from the destination. + func_stripname '' '/' "$dest" + dest=$func_stripname_result + + # Check to see that the destination is a directory. + test -d "$dest" && isdir=: + if $isdir; then + destdir=$dest + destname= + else + func_dirname_and_basename "$dest" "" "." + destdir=$func_dirname_result + destname=$func_basename_result + + # Not a directory, so check to see that there is only one file specified. + set dummy $files; shift + test "$#" -gt 1 && \ + func_fatal_help "'$dest' is not a directory" + fi + case $destdir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + for file in $files; do + case $file in + *.lo) ;; + *) + func_fatal_help "'$destdir' must be an absolute directory name" + ;; + esac + done + ;; + esac + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic=$magic + + staticlibs= + future_libdirs= + current_libdirs= + for file in $files; do + + # Do each installation. + case $file in + *.$libext) + # Do the static libraries later. + func_append staticlibs " $file" + ;; + + *.la) + func_resolve_sysroot "$file" + file=$func_resolve_sysroot_result + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$file" \ + || func_fatal_help "'$file' is not a valid libtool archive" + + library_names= + old_library= + relink_command= + func_source "$file" + + # Add the libdir to current_libdirs if it is the destination. + if test "X$destdir" = "X$libdir"; then + case "$current_libdirs " in + *" $libdir "*) ;; + *) func_append current_libdirs " $libdir" ;; + esac + else + # Note the libdir as a future libdir. + case "$future_libdirs " in + *" $libdir "*) ;; + *) func_append future_libdirs " $libdir" ;; + esac + fi + + func_dirname "$file" "/" "" + dir=$func_dirname_result + func_append dir "$objdir" + + if test -n "$relink_command"; then + # Determine the prefix the user has applied to our future dir. + inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"` + + # Don't allow the user to place us outside of our expected + # location b/c this prevents finding dependent libraries that + # are installed to the same prefix. + # At present, this check doesn't affect windows .dll's that + # are installed into $libdir/../bin (currently, that works fine) + # but it's something to keep an eye on. + test "$inst_prefix_dir" = "$destdir" && \ + func_fatal_error "error: cannot install '$file' to a directory not ending in $libdir" + + if test -n "$inst_prefix_dir"; then + # Stick the inst_prefix_dir data into the link command. + relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` + else + relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"` + fi + + func_warning "relinking '$file'" + func_show_eval "$relink_command" \ + 'func_fatal_error "error: relink '\''$file'\'' with the above command before installing it"' + fi + + # See the names of the shared library. + set dummy $library_names; shift + if test -n "$1"; then + realname=$1 + shift + + srcname=$realname + test -n "$relink_command" && srcname=${realname}T + + # Install the shared library and build the symlinks. + func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \ + 'exit $?' + tstripme=$stripme + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + case $realname in + *.dll.a) + tstripme= + ;; + esac + ;; + os2*) + case $realname in + *_dll.a) + tstripme= + ;; + esac + ;; + esac + if test -n "$tstripme" && test -n "$striplib"; then + func_show_eval "$striplib $destdir/$realname" 'exit $?' + fi + + if test "$#" -gt 0; then + # Delete the old symlinks, and create new ones. + # Try 'ln -sf' first, because the 'ln' binary might depend on + # the symlink we replace! Solaris /bin/ln does not understand -f, + # so we also need to try rm && ln -s. + for linkname + do + test "$linkname" != "$realname" \ + && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })" + done + fi + + # Do each command in the postinstall commands. + lib=$destdir/$realname + func_execute_cmds "$postinstall_cmds" 'exit $?' + fi + + # Install the pseudo-library for information purposes. + func_basename "$file" + name=$func_basename_result + instname=$dir/${name}i + func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' + + # Maybe install the static library, too. + test -n "$old_library" && func_append staticlibs " $dir/$old_library" + ;; + + *.lo) + # Install (i.e. copy) a libtool object. + + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile=$destdir/$destname + else + func_basename "$file" + destfile=$func_basename_result + destfile=$destdir/$destfile + fi + + # Deduce the name of the destination old-style object file. + case $destfile in + *.lo) + func_lo2o "$destfile" + staticdest=$func_lo2o_result + ;; + *.$objext) + staticdest=$destfile + destfile= + ;; + *) + func_fatal_help "cannot copy a libtool object to '$destfile'" + ;; + esac + + # Install the libtool object if requested. + test -n "$destfile" && \ + func_show_eval "$install_prog $file $destfile" 'exit $?' + + # Install the old object if enabled. + if test yes = "$build_old_libs"; then + # Deduce the name of the old-style object file. + func_lo2o "$file" + staticobj=$func_lo2o_result + func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?' + fi + exit $EXIT_SUCCESS + ;; + + *) + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile=$destdir/$destname + else + func_basename "$file" + destfile=$func_basename_result + destfile=$destdir/$destfile + fi + + # If the file is missing, and there is a .exe on the end, strip it + # because it is most likely a libtool script we actually want to + # install + stripped_ext= + case $file in + *.exe) + if test ! -f "$file"; then + func_stripname '' '.exe' "$file" + file=$func_stripname_result + stripped_ext=.exe + fi + ;; + esac + + # Do a test to see if this is really a libtool program. + case $host in + *cygwin* | *mingw*) + if func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + wrapper=$func_ltwrapper_scriptname_result + else + func_stripname '' '.exe' "$file" + wrapper=$func_stripname_result + fi + ;; + *) + wrapper=$file + ;; + esac + if func_ltwrapper_script_p "$wrapper"; then + notinst_deplibs= + relink_command= + + func_source "$wrapper" + + # Check the variables that should have been set. + test -z "$generated_by_libtool_version" && \ + func_fatal_error "invalid libtool wrapper script '$wrapper'" + + finalize=: + for lib in $notinst_deplibs; do + # Check to see that each library is installed. + libdir= + if test -f "$lib"; then + func_source "$lib" + fi + libfile=$libdir/`$ECHO "$lib" | $SED 's%^.*/%%g'` + if test -n "$libdir" && test ! -f "$libfile"; then + func_warning "'$lib' has not been installed in '$libdir'" + finalize=false + fi + done + + relink_command= + func_source "$wrapper" + + outputname= + if test no = "$fast_install" && test -n "$relink_command"; then + $opt_dry_run || { + if $finalize; then + tmpdir=`func_mktempdir` + func_basename "$file$stripped_ext" + file=$func_basename_result + outputname=$tmpdir/$file + # Replace the output file specification. + relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'` + + $opt_quiet || { + func_quote_for_expand "$relink_command" + eval "func_echo $func_quote_for_expand_result" + } + if eval "$relink_command"; then : + else + func_error "error: relink '$file' with the above command before installing it" + $opt_dry_run || ${RM}r "$tmpdir" + continue + fi + file=$outputname + else + func_warning "cannot relink '$file'" + fi + } + else + # Install the binary that we compiled earlier. + file=`$ECHO "$file$stripped_ext" | $SED "s%\([^/]*\)$%$objdir/\1%"` + fi + fi + + # remove .exe since cygwin /usr/bin/install will append another + # one anyway + case $install_prog,$host in + */usr/bin/install*,*cygwin*) + case $file:$destfile in + *.exe:*.exe) + # this is ok + ;; + *.exe:*) + destfile=$destfile.exe + ;; + *:*.exe) + func_stripname '' '.exe' "$destfile" + destfile=$func_stripname_result + ;; + esac + ;; + esac + func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?' + $opt_dry_run || if test -n "$outputname"; then + ${RM}r "$tmpdir" + fi + ;; + esac + done + + for file in $staticlibs; do + func_basename "$file" + name=$func_basename_result + + # Set up the ranlib parameters. + oldlib=$destdir/$name + func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 + tool_oldlib=$func_to_tool_file_result + + func_show_eval "$install_prog \$file \$oldlib" 'exit $?' + + if test -n "$stripme" && test -n "$old_striplib"; then + func_show_eval "$old_striplib $tool_oldlib" 'exit $?' + fi + + # Do each command in the postinstall commands. + func_execute_cmds "$old_postinstall_cmds" 'exit $?' + done + + test -n "$future_libdirs" && \ + func_warning "remember to run '$progname --finish$future_libdirs'" + + if test -n "$current_libdirs"; then + # Maybe just do a dry run. + $opt_dry_run && current_libdirs=" -n$current_libdirs" + exec_cmd='$SHELL "$progpath" $preserve_args --finish$current_libdirs' + else + exit $EXIT_SUCCESS + fi +} + +test install = "$opt_mode" && func_mode_install ${1+"$@"} + + +# func_generate_dlsyms outputname originator pic_p +# Extract symbols from dlprefiles and create ${outputname}S.o with +# a dlpreopen symbol table. +func_generate_dlsyms () +{ + $debug_cmd + + my_outputname=$1 + my_originator=$2 + my_pic_p=${3-false} + my_prefix=`$ECHO "$my_originator" | $SED 's%[^a-zA-Z0-9]%_%g'` + my_dlsyms= + + if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then + if test -n "$NM" && test -n "$global_symbol_pipe"; then + my_dlsyms=${my_outputname}S.c + else + func_error "not configured to extract global symbols from dlpreopened files" + fi + fi + + if test -n "$my_dlsyms"; then + case $my_dlsyms in + "") ;; + *.c) + # Discover the nlist of each of the dlfiles. + nlist=$output_objdir/$my_outputname.nm + + func_show_eval "$RM $nlist ${nlist}S ${nlist}T" + + # Parse the name list into a source file. + func_verbose "creating $output_objdir/$my_dlsyms" + + $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\ +/* $my_dlsyms - symbol resolution table for '$my_outputname' dlsym emulation. */ +/* Generated by $PROGRAM (GNU $PACKAGE) $VERSION */ + +#ifdef __cplusplus +extern \"C\" { +#endif + +#if defined __GNUC__ && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4)) +#pragma GCC diagnostic ignored \"-Wstrict-prototypes\" +#endif + +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE +/* DATA imports from DLLs on WIN32 can't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT_DLSYM_CONST +#elif defined __osf__ +/* This system does not cope well with relocations in const data. */ +# define LT_DLSYM_CONST +#else +# define LT_DLSYM_CONST const +#endif + +#define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0) + +/* External symbol declarations for the compiler. */\ +" + + if test yes = "$dlself"; then + func_verbose "generating symbol list for '$output'" + + $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" + + # Add our own program objects to the symbol list. + progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP` + for progfile in $progfiles; do + func_to_tool_file "$progfile" func_convert_file_msys_to_w32 + func_verbose "extracting global C symbols from '$func_to_tool_file_result'" + $opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'" + done + + if test -n "$exclude_expsyms"; then + $opt_dry_run || { + eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + } + fi + + if test -n "$export_symbols_regex"; then + $opt_dry_run || { + eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + } + fi + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + export_symbols=$output_objdir/$outputname.exp + $opt_dry_run || { + $RM $export_symbols + eval "$SED -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' + case $host in + *cygwin* | *mingw* | *cegcc* ) + eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' + ;; + esac + } + else + $opt_dry_run || { + eval "$SED -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' + eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + case $host in + *cygwin* | *mingw* | *cegcc* ) + eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' + ;; + esac + } + fi + fi + + for dlprefile in $dlprefiles; do + func_verbose "extracting global C symbols from '$dlprefile'" + func_basename "$dlprefile" + name=$func_basename_result + case $host in + *cygwin* | *mingw* | *cegcc* ) + # if an import library, we need to obtain dlname + if func_win32_import_lib_p "$dlprefile"; then + func_tr_sh "$dlprefile" + eval "curr_lafile=\$libfile_$func_tr_sh_result" + dlprefile_dlbasename= + if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then + # Use subshell, to avoid clobbering current variable values + dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"` + if test -n "$dlprefile_dlname"; then + func_basename "$dlprefile_dlname" + dlprefile_dlbasename=$func_basename_result + else + # no lafile. user explicitly requested -dlpreopen . + $sharedlib_from_linklib_cmd "$dlprefile" + dlprefile_dlbasename=$sharedlib_from_linklib_result + fi + fi + $opt_dry_run || { + if test -n "$dlprefile_dlbasename"; then + eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"' + else + func_warning "Could not compute DLL name from $name" + eval '$ECHO ": $name " >> "$nlist"' + fi + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe | + $SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' >> '$nlist'" + } + else # not an import lib + $opt_dry_run || { + eval '$ECHO ": $name " >> "$nlist"' + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" + } + fi + ;; + *) + $opt_dry_run || { + eval '$ECHO ": $name " >> "$nlist"' + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" + } + ;; + esac + done + + $opt_dry_run || { + # Make sure we have at least an empty file. + test -f "$nlist" || : > "$nlist" + + if test -n "$exclude_expsyms"; then + $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T + $MV "$nlist"T "$nlist" + fi + + # Try sorting and uniquifying the output. + if $GREP -v "^: " < "$nlist" | + if sort -k 3 /dev/null 2>&1; then + sort -k 3 + else + sort +2 + fi | + uniq > "$nlist"S; then + : + else + $GREP -v "^: " < "$nlist" > "$nlist"S + fi + + if test -f "$nlist"S; then + eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"' + else + echo '/* NONE */' >> "$output_objdir/$my_dlsyms" + fi + + func_show_eval '$RM "${nlist}I"' + if test -n "$global_symbol_to_import"; then + eval "$global_symbol_to_import"' < "$nlist"S > "$nlist"I' + fi + + echo >> "$output_objdir/$my_dlsyms" "\ + +/* The mapping between symbol names and symbols. */ +typedef struct { + const char *name; + void *address; +} lt_dlsymlist; +extern LT_DLSYM_CONST lt_dlsymlist +lt_${my_prefix}_LTX_preloaded_symbols[];\ +" + + if test -s "$nlist"I; then + echo >> "$output_objdir/$my_dlsyms" "\ +static void lt_syminit(void) +{ + LT_DLSYM_CONST lt_dlsymlist *symbol = lt_${my_prefix}_LTX_preloaded_symbols; + for (; symbol->name; ++symbol) + {" + $SED 's/.*/ if (STREQ (symbol->name, \"&\")) symbol->address = (void *) \&&;/' < "$nlist"I >> "$output_objdir/$my_dlsyms" + echo >> "$output_objdir/$my_dlsyms" "\ + } +}" + fi + echo >> "$output_objdir/$my_dlsyms" "\ +LT_DLSYM_CONST lt_dlsymlist +lt_${my_prefix}_LTX_preloaded_symbols[] = +{ {\"$my_originator\", (void *) 0}," + + if test -s "$nlist"I; then + echo >> "$output_objdir/$my_dlsyms" "\ + {\"@INIT@\", (void *) <_syminit}," + fi + + case $need_lib_prefix in + no) + eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms" + ;; + *) + eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms" + ;; + esac + echo >> "$output_objdir/$my_dlsyms" "\ + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt_${my_prefix}_LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif\ +" + } # !$opt_dry_run + + pic_flag_for_symtable= + case "$compile_command " in + *" -static "*) ;; + *) + case $host in + # compiling the symbol table file with pic_flag works around + # a FreeBSD bug that causes programs to crash when -lm is + # linked before any other PIC object. But we must not use + # pic_flag when linking with -static. The problem exists in + # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. + *-*-freebsd2.*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) + pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;; + *-*-hpux*) + pic_flag_for_symtable=" $pic_flag" ;; + *) + $my_pic_p && pic_flag_for_symtable=" $pic_flag" + ;; + esac + ;; + esac + symtab_cflags= + for arg in $LTCFLAGS; do + case $arg in + -pie | -fpie | -fPIE) ;; + *) func_append symtab_cflags " $arg" ;; + esac + done + + # Now compile the dynamic symbol file. + func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' + + # Clean up the generated files. + func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T" "${nlist}I"' + + # Transform the symbol file into the correct name. + symfileobj=$output_objdir/${my_outputname}S.$objext + case $host in + *cygwin* | *mingw* | *cegcc* ) + if test -f "$output_objdir/$my_outputname.def"; then + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` + else + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` + fi + ;; + *) + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` + ;; + esac + ;; + *) + func_fatal_error "unknown suffix for '$my_dlsyms'" + ;; + esac + else + # We keep going just in case the user didn't refer to + # lt_preloaded_symbols. The linker will fail if global_symbol_pipe + # really was required. + + # Nullify the symbol file. + compile_command=`$ECHO "$compile_command" | $SED "s% @SYMFILE@%%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"` + fi +} + +# func_cygming_gnu_implib_p ARG +# This predicate returns with zero status (TRUE) if +# ARG is a GNU/binutils-style import library. Returns +# with nonzero status (FALSE) otherwise. +func_cygming_gnu_implib_p () +{ + $debug_cmd + + func_to_tool_file "$1" func_convert_file_msys_to_w32 + func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'` + test -n "$func_cygming_gnu_implib_tmp" +} + +# func_cygming_ms_implib_p ARG +# This predicate returns with zero status (TRUE) if +# ARG is an MS-style import library. Returns +# with nonzero status (FALSE) otherwise. +func_cygming_ms_implib_p () +{ + $debug_cmd + + func_to_tool_file "$1" func_convert_file_msys_to_w32 + func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'` + test -n "$func_cygming_ms_implib_tmp" +} + +# func_win32_libid arg +# return the library type of file 'arg' +# +# Need a lot of goo to handle *both* DLLs and import libs +# Has to be a shell function in order to 'eat' the argument +# that is supplied when $file_magic_command is called. +# Despite the name, also deal with 64 bit binaries. +func_win32_libid () +{ + $debug_cmd + + win32_libid_type=unknown + win32_fileres=`file -L $1 2>/dev/null` + case $win32_fileres in + *ar\ archive\ import\ library*) # definitely import + win32_libid_type="x86 archive import" + ;; + *ar\ archive*) # could be an import, or static + # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD. + if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | + $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then + case $nm_interface in + "MS dumpbin") + if func_cygming_ms_implib_p "$1" || + func_cygming_gnu_implib_p "$1" + then + win32_nmres=import + else + win32_nmres= + fi + ;; + *) + func_to_tool_file "$1" func_convert_file_msys_to_w32 + win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" | + $SED -n -e ' + 1,100{ + / I /{ + s|.*|import| + p + q + } + }'` + ;; + esac + case $win32_nmres in + import*) win32_libid_type="x86 archive import";; + *) win32_libid_type="x86 archive static";; + esac + fi + ;; + *DLL*) + win32_libid_type="x86 DLL" + ;; + *executable*) # but shell scripts are "executable" too... + case $win32_fileres in + *MS\ Windows\ PE\ Intel*) + win32_libid_type="x86 DLL" + ;; + esac + ;; + esac + $ECHO "$win32_libid_type" +} + +# func_cygming_dll_for_implib ARG +# +# Platform-specific function to extract the +# name of the DLL associated with the specified +# import library ARG. +# Invoked by eval'ing the libtool variable +# $sharedlib_from_linklib_cmd +# Result is available in the variable +# $sharedlib_from_linklib_result +func_cygming_dll_for_implib () +{ + $debug_cmd + + sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"` +} + +# func_cygming_dll_for_implib_fallback_core SECTION_NAME LIBNAMEs +# +# The is the core of a fallback implementation of a +# platform-specific function to extract the name of the +# DLL associated with the specified import library LIBNAME. +# +# SECTION_NAME is either .idata$6 or .idata$7, depending +# on the platform and compiler that created the implib. +# +# Echos the name of the DLL associated with the +# specified import library. +func_cygming_dll_for_implib_fallback_core () +{ + $debug_cmd + + match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"` + $OBJDUMP -s --section "$1" "$2" 2>/dev/null | + $SED '/^Contents of section '"$match_literal"':/{ + # Place marker at beginning of archive member dllname section + s/.*/====MARK====/ + p + d + } + # These lines can sometimes be longer than 43 characters, but + # are always uninteresting + /:[ ]*file format pe[i]\{,1\}-/d + /^In archive [^:]*:/d + # Ensure marker is printed + /^====MARK====/p + # Remove all lines with less than 43 characters + /^.\{43\}/!d + # From remaining lines, remove first 43 characters + s/^.\{43\}//' | + $SED -n ' + # Join marker and all lines until next marker into a single line + /^====MARK====/ b para + H + $ b para + b + :para + x + s/\n//g + # Remove the marker + s/^====MARK====// + # Remove trailing dots and whitespace + s/[\. \t]*$// + # Print + /./p' | + # we now have a list, one entry per line, of the stringified + # contents of the appropriate section of all members of the + # archive that possess that section. Heuristic: eliminate + # all those that have a first or second character that is + # a '.' (that is, objdump's representation of an unprintable + # character.) This should work for all archives with less than + # 0x302f exports -- but will fail for DLLs whose name actually + # begins with a literal '.' or a single character followed by + # a '.'. + # + # Of those that remain, print the first one. + $SED -e '/^\./d;/^.\./d;q' +} + +# func_cygming_dll_for_implib_fallback ARG +# Platform-specific function to extract the +# name of the DLL associated with the specified +# import library ARG. +# +# This fallback implementation is for use when $DLLTOOL +# does not support the --identify-strict option. +# Invoked by eval'ing the libtool variable +# $sharedlib_from_linklib_cmd +# Result is available in the variable +# $sharedlib_from_linklib_result +func_cygming_dll_for_implib_fallback () +{ + $debug_cmd + + if func_cygming_gnu_implib_p "$1"; then + # binutils import library + sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"` + elif func_cygming_ms_implib_p "$1"; then + # ms-generated import library + sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"` + else + # unknown + sharedlib_from_linklib_result= + fi +} + + +# func_extract_an_archive dir oldlib +func_extract_an_archive () +{ + $debug_cmd + + f_ex_an_ar_dir=$1; shift + f_ex_an_ar_oldlib=$1 + if test yes = "$lock_old_archive_extraction"; then + lockfile=$f_ex_an_ar_oldlib.lock + until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do + func_echo "Waiting for $lockfile to be removed" + sleep 2 + done + fi + func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \ + 'stat=$?; rm -f "$lockfile"; exit $stat' + if test yes = "$lock_old_archive_extraction"; then + $opt_dry_run || rm -f "$lockfile" + fi + if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then + : + else + func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" + fi +} + + +# func_extract_archives gentop oldlib ... +func_extract_archives () +{ + $debug_cmd + + my_gentop=$1; shift + my_oldlibs=${1+"$@"} + my_oldobjs= + my_xlib= + my_xabs= + my_xdir= + + for my_xlib in $my_oldlibs; do + # Extract the objects. + case $my_xlib in + [\\/]* | [A-Za-z]:[\\/]*) my_xabs=$my_xlib ;; + *) my_xabs=`pwd`"/$my_xlib" ;; + esac + func_basename "$my_xlib" + my_xlib=$func_basename_result + my_xlib_u=$my_xlib + while :; do + case " $extracted_archives " in + *" $my_xlib_u "*) + func_arith $extracted_serial + 1 + extracted_serial=$func_arith_result + my_xlib_u=lt$extracted_serial-$my_xlib ;; + *) break ;; + esac + done + extracted_archives="$extracted_archives $my_xlib_u" + my_xdir=$my_gentop/$my_xlib_u + + func_mkdir_p "$my_xdir" + + case $host in + *-darwin*) + func_verbose "Extracting $my_xabs" + # Do not bother doing anything if just a dry run + $opt_dry_run || { + darwin_orig_dir=`pwd` + cd $my_xdir || exit $? + darwin_archive=$my_xabs + darwin_curdir=`pwd` + func_basename "$darwin_archive" + darwin_base_archive=$func_basename_result + darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` + if test -n "$darwin_arches"; then + darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` + darwin_arch= + func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" + for darwin_arch in $darwin_arches; do + func_mkdir_p "unfat-$$/$darwin_base_archive-$darwin_arch" + $LIPO -thin $darwin_arch -output "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" "$darwin_archive" + cd "unfat-$$/$darwin_base_archive-$darwin_arch" + func_extract_an_archive "`pwd`" "$darwin_base_archive" + cd "$darwin_curdir" + $RM "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" + done # $darwin_arches + ## Okay now we've a bunch of thin objects, gotta fatten them up :) + darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$sed_basename" | sort -u` + darwin_file= + darwin_files= + for darwin_file in $darwin_filelist; do + darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP` + $LIPO -create -output "$darwin_file" $darwin_files + done # $darwin_filelist + $RM -rf unfat-$$ + cd "$darwin_orig_dir" + else + cd $darwin_orig_dir + func_extract_an_archive "$my_xdir" "$my_xabs" + fi # $darwin_arches + } # !$opt_dry_run + ;; + *) + func_extract_an_archive "$my_xdir" "$my_xabs" + ;; + esac + my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP` + done + + func_extract_archives_result=$my_oldobjs +} + + +# func_emit_wrapper [arg=no] +# +# Emit a libtool wrapper script on stdout. +# Don't directly open a file because we may want to +# incorporate the script contents within a cygwin/mingw +# wrapper executable. Must ONLY be called from within +# func_mode_link because it depends on a number of variables +# set therein. +# +# ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR +# variable will take. If 'yes', then the emitted script +# will assume that the directory where it is stored is +# the $objdir directory. This is a cygwin/mingw-specific +# behavior. +func_emit_wrapper () +{ + func_emit_wrapper_arg1=${1-no} + + $ECHO "\ +#! $SHELL + +# $output - temporary wrapper script for $objdir/$outputname +# Generated by $PROGRAM (GNU $PACKAGE) $VERSION +# +# The $output program cannot be directly executed until all the libtool +# libraries that it depends on are installed. +# +# This wrapper script should never be moved out of the build directory. +# If it is, it will not operate correctly. + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +sed_quote_subst='$sed_quote_subst' + +# Be Bourne compatible +if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs 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 +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +relink_command=\"$relink_command\" + +# This environment variable determines our operation mode. +if test \"\$libtool_install_magic\" = \"$magic\"; then + # install mode needs the following variables: + generated_by_libtool_version='$macro_version' + notinst_deplibs='$notinst_deplibs' +else + # When we are sourced in execute mode, \$file and \$ECHO are already set. + if test \"\$libtool_execute_magic\" != \"$magic\"; then + file=\"\$0\"" + + qECHO=`$ECHO "$ECHO" | $SED "$sed_quote_subst"` + $ECHO "\ + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$1 +_LTECHO_EOF' +} + ECHO=\"$qECHO\" + fi + +# Very basic option parsing. These options are (a) specific to +# the libtool wrapper, (b) are identical between the wrapper +# /script/ and the wrapper /executable/ that is used only on +# windows platforms, and (c) all begin with the string "--lt-" +# (application programs are unlikely to have options that match +# this pattern). +# +# There are only two supported options: --lt-debug and +# --lt-dump-script. There is, deliberately, no --lt-help. +# +# The first argument to this parsing function should be the +# script's $0 value, followed by "$@". +lt_option_debug= +func_parse_lt_options () +{ + lt_script_arg0=\$0 + shift + for lt_opt + do + case \"\$lt_opt\" in + --lt-debug) lt_option_debug=1 ;; + --lt-dump-script) + lt_dump_D=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%/[^/]*$%%'\` + test \"X\$lt_dump_D\" = \"X\$lt_script_arg0\" && lt_dump_D=. + lt_dump_F=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%^.*/%%'\` + cat \"\$lt_dump_D/\$lt_dump_F\" + exit 0 + ;; + --lt-*) + \$ECHO \"Unrecognized --lt- option: '\$lt_opt'\" 1>&2 + exit 1 + ;; + esac + done + + # Print the debug banner immediately: + if test -n \"\$lt_option_debug\"; then + echo \"$outputname:$output:\$LINENO: libtool wrapper (GNU $PACKAGE) $VERSION\" 1>&2 + fi +} + +# Used when --lt-debug. Prints its arguments to stdout +# (redirection is the responsibility of the caller) +func_lt_dump_args () +{ + lt_dump_args_N=1; + for lt_arg + do + \$ECHO \"$outputname:$output:\$LINENO: newargv[\$lt_dump_args_N]: \$lt_arg\" + lt_dump_args_N=\`expr \$lt_dump_args_N + 1\` + done +} + +# Core function for launching the target application +func_exec_program_core () +{ +" + case $host in + # Backslashes separate directories on plain windows + *-*-mingw | *-*-os2* | *-cegcc*) + $ECHO "\ + if test -n \"\$lt_option_debug\"; then + \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir\\\\\$program\" 1>&2 + func_lt_dump_args \${1+\"\$@\"} 1>&2 + fi + exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} +" + ;; + + *) + $ECHO "\ + if test -n \"\$lt_option_debug\"; then + \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir/\$program\" 1>&2 + func_lt_dump_args \${1+\"\$@\"} 1>&2 + fi + exec \"\$progdir/\$program\" \${1+\"\$@\"} +" + ;; + esac + $ECHO "\ + \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 + exit 1 +} + +# A function to encapsulate launching the target application +# Strips options in the --lt-* namespace from \$@ and +# launches target application with the remaining arguments. +func_exec_program () +{ + case \" \$* \" in + *\\ --lt-*) + for lt_wr_arg + do + case \$lt_wr_arg in + --lt-*) ;; + *) set x \"\$@\" \"\$lt_wr_arg\"; shift;; + esac + shift + done ;; + esac + func_exec_program_core \${1+\"\$@\"} +} + + # Parse options + func_parse_lt_options \"\$0\" \${1+\"\$@\"} + + # Find the directory that this script lives in. + thisdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*$%%'\` + test \"x\$thisdir\" = \"x\$file\" && thisdir=. + + # Follow symbolic links until we get to the real thisdir. + file=\`ls -ld \"\$file\" | $SED -n 's/.*-> //p'\` + while test -n \"\$file\"; do + destdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*\$%%'\` + + # If there was a directory component, then change thisdir. + if test \"x\$destdir\" != \"x\$file\"; then + case \"\$destdir\" in + [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; + *) thisdir=\"\$thisdir/\$destdir\" ;; + esac + fi + + file=\`\$ECHO \"\$file\" | $SED 's%^.*/%%'\` + file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\` + done + + # Usually 'no', except on cygwin/mingw when embedded into + # the cwrapper. + WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1 + if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then + # special case for '.' + if test \"\$thisdir\" = \".\"; then + thisdir=\`pwd\` + fi + # remove .libs from thisdir + case \"\$thisdir\" in + *[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;; + $objdir ) thisdir=. ;; + esac + fi + + # Try to get the absolute directory name. + absdir=\`cd \"\$thisdir\" && pwd\` + test -n \"\$absdir\" && thisdir=\"\$absdir\" +" + + if test yes = "$fast_install"; then + $ECHO "\ + program=lt-'$outputname'$exeext + progdir=\"\$thisdir/$objdir\" + + if test ! -f \"\$progdir/\$program\" || + { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | $SED 1q\`; \\ + test \"X\$file\" != \"X\$progdir/\$program\"; }; then + + file=\"\$\$-\$program\" + + if test ! -d \"\$progdir\"; then + $MKDIR \"\$progdir\" + else + $RM \"\$progdir/\$file\" + fi" + + $ECHO "\ + + # relink executable if necessary + if test -n \"\$relink_command\"; then + if relink_command_output=\`eval \$relink_command 2>&1\`; then : + else + \$ECHO \"\$relink_command_output\" >&2 + $RM \"\$progdir/\$file\" + exit 1 + fi + fi + + $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || + { $RM \"\$progdir/\$program\"; + $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; } + $RM \"\$progdir/\$file\" + fi" + else + $ECHO "\ + program='$outputname' + progdir=\"\$thisdir/$objdir\" +" + fi + + $ECHO "\ + + if test -f \"\$progdir/\$program\"; then" + + # fixup the dll searchpath if we need to. + # + # Fix the DLL searchpath if we need to. Do this before prepending + # to shlibpath, because on Windows, both are PATH and uninstalled + # libraries must come first. + if test -n "$dllsearchpath"; then + $ECHO "\ + # Add the dll search path components to the executable PATH + PATH=$dllsearchpath:\$PATH +" + fi + + # Export our shlibpath_var if we have one. + if test yes = "$shlibpath_overrides_runpath" && test -n "$shlibpath_var" && test -n "$temp_rpath"; then + $ECHO "\ + # Add our own library path to $shlibpath_var + $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" + + # Some systems cannot cope with colon-terminated $shlibpath_var + # The second colon is a workaround for a bug in BeOS R4 sed + $shlibpath_var=\`\$ECHO \"\$$shlibpath_var\" | $SED 's/::*\$//'\` + + export $shlibpath_var +" + fi + + $ECHO "\ + if test \"\$libtool_execute_magic\" != \"$magic\"; then + # Run the actual program with our arguments. + func_exec_program \${1+\"\$@\"} + fi + else + # The program doesn't exist. + \$ECHO \"\$0: error: '\$progdir/\$program' does not exist\" 1>&2 + \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 + \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 + exit 1 + fi +fi\ +" +} + + +# func_emit_cwrapperexe_src +# emit the source code for a wrapper executable on stdout +# Must ONLY be called from within func_mode_link because +# it depends on a number of variable set therein. +func_emit_cwrapperexe_src () +{ + cat < +#include +#ifdef _MSC_VER +# include +# include +# include +#else +# include +# include +# ifdef __CYGWIN__ +# include +# endif +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +#define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0) + +/* declarations of non-ANSI functions */ +#if defined __MINGW32__ +# ifdef __STRICT_ANSI__ +int _putenv (const char *); +# endif +#elif defined __CYGWIN__ +# ifdef __STRICT_ANSI__ +char *realpath (const char *, char *); +int putenv (char *); +int setenv (const char *, const char *, int); +# endif +/* #elif defined other_platform || defined ... */ +#endif + +/* portability defines, excluding path handling macros */ +#if defined _MSC_VER +# define setmode _setmode +# define stat _stat +# define chmod _chmod +# define getcwd _getcwd +# define putenv _putenv +# define S_IXUSR _S_IEXEC +#elif defined __MINGW32__ +# define setmode _setmode +# define stat _stat +# define chmod _chmod +# define getcwd _getcwd +# define putenv _putenv +#elif defined __CYGWIN__ +# define HAVE_SETENV +# define FOPEN_WB "wb" +/* #elif defined other platforms ... */ +#endif + +#if defined PATH_MAX +# define LT_PATHMAX PATH_MAX +#elif defined MAXPATHLEN +# define LT_PATHMAX MAXPATHLEN +#else +# define LT_PATHMAX 1024 +#endif + +#ifndef S_IXOTH +# define S_IXOTH 0 +#endif +#ifndef S_IXGRP +# define S_IXGRP 0 +#endif + +/* path handling portability macros */ +#ifndef DIR_SEPARATOR +# define DIR_SEPARATOR '/' +# define PATH_SEPARATOR ':' +#endif + +#if defined _WIN32 || defined __MSDOS__ || defined __DJGPP__ || \ + defined __OS2__ +# define HAVE_DOS_BASED_FILE_SYSTEM +# define FOPEN_WB "wb" +# ifndef DIR_SEPARATOR_2 +# define DIR_SEPARATOR_2 '\\' +# endif +# ifndef PATH_SEPARATOR_2 +# define PATH_SEPARATOR_2 ';' +# endif +#endif + +#ifndef DIR_SEPARATOR_2 +# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) +#else /* DIR_SEPARATOR_2 */ +# define IS_DIR_SEPARATOR(ch) \ + (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) +#endif /* DIR_SEPARATOR_2 */ + +#ifndef PATH_SEPARATOR_2 +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) +#else /* PATH_SEPARATOR_2 */ +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) +#endif /* PATH_SEPARATOR_2 */ + +#ifndef FOPEN_WB +# define FOPEN_WB "w" +#endif +#ifndef _O_BINARY +# define _O_BINARY 0 +#endif + +#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) +#define XFREE(stale) do { \ + if (stale) { free (stale); stale = 0; } \ +} while (0) + +#if defined LT_DEBUGWRAPPER +static int lt_debug = 1; +#else +static int lt_debug = 0; +#endif + +const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */ + +void *xmalloc (size_t num); +char *xstrdup (const char *string); +const char *base_name (const char *name); +char *find_executable (const char *wrapper); +char *chase_symlinks (const char *pathspec); +int make_executable (const char *path); +int check_executable (const char *path); +char *strendzap (char *str, const char *pat); +void lt_debugprintf (const char *file, int line, const char *fmt, ...); +void lt_fatal (const char *file, int line, const char *message, ...); +static const char *nonnull (const char *s); +static const char *nonempty (const char *s); +void lt_setenv (const char *name, const char *value); +char *lt_extend_str (const char *orig_value, const char *add, int to_end); +void lt_update_exe_path (const char *name, const char *value); +void lt_update_lib_path (const char *name, const char *value); +char **prepare_spawn (char **argv); +void lt_dump_script (FILE *f); +EOF + + cat <= 0) + && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) + return 1; + else + return 0; +} + +int +make_executable (const char *path) +{ + int rval = 0; + struct stat st; + + lt_debugprintf (__FILE__, __LINE__, "(make_executable): %s\n", + nonempty (path)); + if ((!path) || (!*path)) + return 0; + + if (stat (path, &st) >= 0) + { + rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR); + } + return rval; +} + +/* Searches for the full path of the wrapper. Returns + newly allocated full path name if found, NULL otherwise + Does not chase symlinks, even on platforms that support them. +*/ +char * +find_executable (const char *wrapper) +{ + int has_slash = 0; + const char *p; + const char *p_next; + /* static buffer for getcwd */ + char tmp[LT_PATHMAX + 1]; + size_t tmp_len; + char *concat_name; + + lt_debugprintf (__FILE__, __LINE__, "(find_executable): %s\n", + nonempty (wrapper)); + + if ((wrapper == NULL) || (*wrapper == '\0')) + return NULL; + + /* Absolute path? */ +#if defined HAVE_DOS_BASED_FILE_SYSTEM + if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':') + { + concat_name = xstrdup (wrapper); + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } + else + { +#endif + if (IS_DIR_SEPARATOR (wrapper[0])) + { + concat_name = xstrdup (wrapper); + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } +#if defined HAVE_DOS_BASED_FILE_SYSTEM + } +#endif + + for (p = wrapper; *p; p++) + if (*p == '/') + { + has_slash = 1; + break; + } + if (!has_slash) + { + /* no slashes; search PATH */ + const char *path = getenv ("PATH"); + if (path != NULL) + { + for (p = path; *p; p = p_next) + { + const char *q; + size_t p_len; + for (q = p; *q; q++) + if (IS_PATH_SEPARATOR (*q)) + break; + p_len = (size_t) (q - p); + p_next = (*q == '\0' ? q : q + 1); + if (p_len == 0) + { + /* empty path: current directory */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", + nonnull (strerror (errno))); + tmp_len = strlen (tmp); + concat_name = + XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + } + else + { + concat_name = + XMALLOC (char, p_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, p, p_len); + concat_name[p_len] = '/'; + strcpy (concat_name + p_len + 1, wrapper); + } + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } + } + /* not found in PATH; assume curdir */ + } + /* Relative path | not found in path: prepend cwd */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", + nonnull (strerror (errno))); + tmp_len = strlen (tmp); + concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + return NULL; +} + +char * +chase_symlinks (const char *pathspec) +{ +#ifndef S_ISLNK + return xstrdup (pathspec); +#else + char buf[LT_PATHMAX]; + struct stat s; + char *tmp_pathspec = xstrdup (pathspec); + char *p; + int has_symlinks = 0; + while (strlen (tmp_pathspec) && !has_symlinks) + { + lt_debugprintf (__FILE__, __LINE__, + "checking path component for symlinks: %s\n", + tmp_pathspec); + if (lstat (tmp_pathspec, &s) == 0) + { + if (S_ISLNK (s.st_mode) != 0) + { + has_symlinks = 1; + break; + } + + /* search backwards for last DIR_SEPARATOR */ + p = tmp_pathspec + strlen (tmp_pathspec) - 1; + while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) + p--; + if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) + { + /* no more DIR_SEPARATORS left */ + break; + } + *p = '\0'; + } + else + { + lt_fatal (__FILE__, __LINE__, + "error accessing file \"%s\": %s", + tmp_pathspec, nonnull (strerror (errno))); + } + } + XFREE (tmp_pathspec); + + if (!has_symlinks) + { + return xstrdup (pathspec); + } + + tmp_pathspec = realpath (pathspec, buf); + if (tmp_pathspec == 0) + { + lt_fatal (__FILE__, __LINE__, + "could not follow symlinks for %s", pathspec); + } + return xstrdup (tmp_pathspec); +#endif +} + +char * +strendzap (char *str, const char *pat) +{ + size_t len, patlen; + + assert (str != NULL); + assert (pat != NULL); + + len = strlen (str); + patlen = strlen (pat); + + if (patlen <= len) + { + str += len - patlen; + if (STREQ (str, pat)) + *str = '\0'; + } + return str; +} + +void +lt_debugprintf (const char *file, int line, const char *fmt, ...) +{ + va_list args; + if (lt_debug) + { + (void) fprintf (stderr, "%s:%s:%d: ", program_name, file, line); + va_start (args, fmt); + (void) vfprintf (stderr, fmt, args); + va_end (args); + } +} + +static void +lt_error_core (int exit_status, const char *file, + int line, const char *mode, + const char *message, va_list ap) +{ + fprintf (stderr, "%s:%s:%d: %s: ", program_name, file, line, mode); + vfprintf (stderr, message, ap); + fprintf (stderr, ".\n"); + + if (exit_status >= 0) + exit (exit_status); +} + +void +lt_fatal (const char *file, int line, const char *message, ...) +{ + va_list ap; + va_start (ap, message); + lt_error_core (EXIT_FAILURE, file, line, "FATAL", message, ap); + va_end (ap); +} + +static const char * +nonnull (const char *s) +{ + return s ? s : "(null)"; +} + +static const char * +nonempty (const char *s) +{ + return (s && !*s) ? "(empty)" : nonnull (s); +} + +void +lt_setenv (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_setenv) setting '%s' to '%s'\n", + nonnull (name), nonnull (value)); + { +#ifdef HAVE_SETENV + /* always make a copy, for consistency with !HAVE_SETENV */ + char *str = xstrdup (value); + setenv (name, str, 1); +#else + size_t len = strlen (name) + 1 + strlen (value) + 1; + char *str = XMALLOC (char, len); + sprintf (str, "%s=%s", name, value); + if (putenv (str) != EXIT_SUCCESS) + { + XFREE (str); + } +#endif + } +} + +char * +lt_extend_str (const char *orig_value, const char *add, int to_end) +{ + char *new_value; + if (orig_value && *orig_value) + { + size_t orig_value_len = strlen (orig_value); + size_t add_len = strlen (add); + new_value = XMALLOC (char, add_len + orig_value_len + 1); + if (to_end) + { + strcpy (new_value, orig_value); + strcpy (new_value + orig_value_len, add); + } + else + { + strcpy (new_value, add); + strcpy (new_value + add_len, orig_value); + } + } + else + { + new_value = xstrdup (add); + } + return new_value; +} + +void +lt_update_exe_path (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_update_exe_path) modifying '%s' by prepending '%s'\n", + nonnull (name), nonnull (value)); + + if (name && *name && value && *value) + { + char *new_value = lt_extend_str (getenv (name), value, 0); + /* some systems can't cope with a ':'-terminated path #' */ + size_t len = strlen (new_value); + while ((len > 0) && IS_PATH_SEPARATOR (new_value[len-1])) + { + new_value[--len] = '\0'; + } + lt_setenv (name, new_value); + XFREE (new_value); + } +} + +void +lt_update_lib_path (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_update_lib_path) modifying '%s' by prepending '%s'\n", + nonnull (name), nonnull (value)); + + if (name && *name && value && *value) + { + char *new_value = lt_extend_str (getenv (name), value, 0); + lt_setenv (name, new_value); + XFREE (new_value); + } +} + +EOF + case $host_os in + mingw*) + cat <<"EOF" + +/* Prepares an argument vector before calling spawn(). + Note that spawn() does not by itself call the command interpreter + (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") : + ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&v); + v.dwPlatformId == VER_PLATFORM_WIN32_NT; + }) ? "cmd.exe" : "command.com"). + Instead it simply concatenates the arguments, separated by ' ', and calls + CreateProcess(). We must quote the arguments since Win32 CreateProcess() + interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a + special way: + - Space and tab are interpreted as delimiters. They are not treated as + delimiters if they are surrounded by double quotes: "...". + - Unescaped double quotes are removed from the input. Their only effect is + that within double quotes, space and tab are treated like normal + characters. + - Backslashes not followed by double quotes are not special. + - But 2*n+1 backslashes followed by a double quote become + n backslashes followed by a double quote (n >= 0): + \" -> " + \\\" -> \" + \\\\\" -> \\" + */ +#define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" +#define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" +char ** +prepare_spawn (char **argv) +{ + size_t argc; + char **new_argv; + size_t i; + + /* Count number of arguments. */ + for (argc = 0; argv[argc] != NULL; argc++) + ; + + /* Allocate new argument vector. */ + new_argv = XMALLOC (char *, argc + 1); + + /* Put quoted arguments into the new argument vector. */ + for (i = 0; i < argc; i++) + { + const char *string = argv[i]; + + if (string[0] == '\0') + new_argv[i] = xstrdup ("\"\""); + else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL) + { + int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL); + size_t length; + unsigned int backslashes; + const char *s; + char *quoted_string; + char *p; + + length = 0; + backslashes = 0; + if (quote_around) + length++; + for (s = string; *s != '\0'; s++) + { + char c = *s; + if (c == '"') + length += backslashes + 1; + length++; + if (c == '\\') + backslashes++; + else + backslashes = 0; + } + if (quote_around) + length += backslashes + 1; + + quoted_string = XMALLOC (char, length + 1); + + p = quoted_string; + backslashes = 0; + if (quote_around) + *p++ = '"'; + for (s = string; *s != '\0'; s++) + { + char c = *s; + if (c == '"') + { + unsigned int j; + for (j = backslashes + 1; j > 0; j--) + *p++ = '\\'; + } + *p++ = c; + if (c == '\\') + backslashes++; + else + backslashes = 0; + } + if (quote_around) + { + unsigned int j; + for (j = backslashes; j > 0; j--) + *p++ = '\\'; + *p++ = '"'; + } + *p = '\0'; + + new_argv[i] = quoted_string; + } + else + new_argv[i] = (char *) string; + } + new_argv[argc] = NULL; + + return new_argv; +} +EOF + ;; + esac + + cat <<"EOF" +void lt_dump_script (FILE* f) +{ +EOF + func_emit_wrapper yes | + $SED -n -e ' +s/^\(.\{79\}\)\(..*\)/\1\ +\2/ +h +s/\([\\"]\)/\\\1/g +s/$/\\n/ +s/\([^\n]*\).*/ fputs ("\1", f);/p +g +D' + cat <<"EOF" +} +EOF +} +# end: func_emit_cwrapperexe_src + +# func_win32_import_lib_p ARG +# True if ARG is an import lib, as indicated by $file_magic_cmd +func_win32_import_lib_p () +{ + $debug_cmd + + case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in + *import*) : ;; + *) false ;; + esac +} + +# func_suncc_cstd_abi +# !!ONLY CALL THIS FOR SUN CC AFTER $compile_command IS FULLY EXPANDED!! +# Several compiler flags select an ABI that is incompatible with the +# Cstd library. Avoid specifying it if any are in CXXFLAGS. +func_suncc_cstd_abi () +{ + $debug_cmd + + case " $compile_command " in + *" -compat=g "*|*\ -std=c++[0-9][0-9]\ *|*" -library=stdcxx4 "*|*" -library=stlport4 "*) + suncc_use_cstd_abi=no + ;; + *) + suncc_use_cstd_abi=yes + ;; + esac +} + +# func_mode_link arg... +func_mode_link () +{ + $debug_cmd + + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + # It is impossible to link a dll without this setting, and + # we shouldn't force the makefile maintainer to figure out + # what system we are compiling for in order to pass an extra + # flag for every libtool invocation. + # allow_undefined=no + + # FIXME: Unfortunately, there are problems with the above when trying + # to make a dll that has undefined symbols, in which case not + # even a static library is built. For now, we need to specify + # -no-undefined on the libtool link line when we can be certain + # that all symbols are satisfied, otherwise we get a static library. + allow_undefined=yes + ;; + *) + allow_undefined=yes + ;; + esac + libtool_args=$nonopt + base_compile="$nonopt $@" + compile_command=$nonopt + finalize_command=$nonopt + + compile_rpath= + finalize_rpath= + compile_shlibpath= + finalize_shlibpath= + convenience= + old_convenience= + deplibs= + old_deplibs= + compiler_flags= + linker_flags= + dllsearchpath= + lib_search_path=`pwd` + inst_prefix_dir= + new_inherited_linker_flags= + + avoid_version=no + bindir= + dlfiles= + dlprefiles= + dlself=no + export_dynamic=no + export_symbols= + export_symbols_regex= + generated= + libobjs= + ltlibs= + module=no + no_install=no + objs= + os2dllname= + non_pic_objects= + precious_files_regex= + prefer_static_libs=no + preload=false + prev= + prevarg= + release= + rpath= + xrpath= + perm_rpath= + temp_rpath= + thread_safe=no + vinfo= + vinfo_number=no + weak_libs= + single_module=$wl-single_module + func_infer_tag $base_compile + + # We need to know -static, to get the right output filenames. + for arg + do + case $arg in + -shared) + test yes != "$build_libtool_libs" \ + && func_fatal_configuration "cannot build a shared library" + build_old_libs=no + break + ;; + -all-static | -static | -static-libtool-libs) + case $arg in + -all-static) + if test yes = "$build_libtool_libs" && test -z "$link_static_flag"; then + func_warning "complete static linking is impossible in this configuration" + fi + if test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + ;; + -static) + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=built + ;; + -static-libtool-libs) + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + ;; + esac + build_libtool_libs=no + build_old_libs=yes + break + ;; + esac + done + + # See if our shared archives depend on static archives. + test -n "$old_archive_from_new_cmds" && build_old_libs=yes + + # Go through the arguments, transforming them on the way. + while test "$#" -gt 0; do + arg=$1 + shift + func_quote_for_eval "$arg" + qarg=$func_quote_for_eval_unquoted_result + func_append libtool_args " $func_quote_for_eval_result" + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case $prev in + output) + func_append compile_command " @OUTPUT@" + func_append finalize_command " @OUTPUT@" + ;; + esac + + case $prev in + bindir) + bindir=$arg + prev= + continue + ;; + dlfiles|dlprefiles) + $preload || { + # Add the symbol object into the linking commands. + func_append compile_command " @SYMFILE@" + func_append finalize_command " @SYMFILE@" + preload=: + } + case $arg in + *.la | *.lo) ;; # We handle these cases below. + force) + if test no = "$dlself"; then + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + self) + if test dlprefiles = "$prev"; then + dlself=yes + elif test dlfiles = "$prev" && test yes != "$dlopen_self"; then + dlself=yes + else + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + *) + if test dlfiles = "$prev"; then + func_append dlfiles " $arg" + else + func_append dlprefiles " $arg" + fi + prev= + continue + ;; + esac + ;; + expsyms) + export_symbols=$arg + test -f "$arg" \ + || func_fatal_error "symbol file '$arg' does not exist" + prev= + continue + ;; + expsyms_regex) + export_symbols_regex=$arg + prev= + continue + ;; + framework) + case $host in + *-*-darwin*) + case "$deplibs " in + *" $qarg.ltframework "*) ;; + *) func_append deplibs " $qarg.ltframework" # this is fixed later + ;; + esac + ;; + esac + prev= + continue + ;; + inst_prefix) + inst_prefix_dir=$arg + prev= + continue + ;; + mllvm) + # Clang does not use LLVM to link, so we can simply discard any + # '-mllvm $arg' options when doing the link step. + prev= + continue + ;; + objectlist) + if test -f "$arg"; then + save_arg=$arg + moreargs= + for fil in `cat "$save_arg"` + do +# func_append moreargs " $fil" + arg=$fil + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if func_lalib_unsafe_p "$arg"; then + pic_object= + non_pic_object= + + # Read the .lo file + func_source "$arg" + + if test -z "$pic_object" || + test -z "$non_pic_object" || + test none = "$pic_object" && + test none = "$non_pic_object"; then + func_fatal_error "cannot find name of object for '$arg'" + fi + + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + if test none != "$pic_object"; then + # Prepend the subdirectory the object is found in. + pic_object=$xdir$pic_object + + if test dlfiles = "$prev"; then + if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then + func_append dlfiles " $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test dlprefiles = "$prev"; then + # Preload the old-style object. + func_append dlprefiles " $pic_object" + prev= + fi + + # A PIC object. + func_append libobjs " $pic_object" + arg=$pic_object + fi + + # Non-PIC object. + if test none != "$non_pic_object"; then + # Prepend the subdirectory the object is found in. + non_pic_object=$xdir$non_pic_object + + # A standard non-PIC object + func_append non_pic_objects " $non_pic_object" + if test -z "$pic_object" || test none = "$pic_object"; then + arg=$non_pic_object + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object=$pic_object + func_append non_pic_objects " $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if $opt_dry_run; then + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + func_lo2o "$arg" + pic_object=$xdir$objdir/$func_lo2o_result + non_pic_object=$xdir$func_lo2o_result + func_append libobjs " $pic_object" + func_append non_pic_objects " $non_pic_object" + else + func_fatal_error "'$arg' is not a valid libtool object" + fi + fi + done + else + func_fatal_error "link input file '$arg' does not exist" + fi + arg=$save_arg + prev= + continue + ;; + os2dllname) + os2dllname=$arg + prev= + continue + ;; + precious_regex) + precious_files_regex=$arg + prev= + continue + ;; + release) + release=-$arg + prev= + continue + ;; + rpath | xrpath) + # We need an absolute path. + case $arg in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + func_fatal_error "only absolute run-paths are allowed" + ;; + esac + if test rpath = "$prev"; then + case "$rpath " in + *" $arg "*) ;; + *) func_append rpath " $arg" ;; + esac + else + case "$xrpath " in + *" $arg "*) ;; + *) func_append xrpath " $arg" ;; + esac + fi + prev= + continue + ;; + shrext) + shrext_cmds=$arg + prev= + continue + ;; + weak) + func_append weak_libs " $arg" + prev= + continue + ;; + xcclinker) + func_append linker_flags " $qarg" + func_append compiler_flags " $qarg" + prev= + func_append compile_command " $qarg" + func_append finalize_command " $qarg" + continue + ;; + xcompiler) + func_append compiler_flags " $qarg" + prev= + func_append compile_command " $qarg" + func_append finalize_command " $qarg" + continue + ;; + xlinker) + func_append linker_flags " $qarg" + func_append compiler_flags " $wl$qarg" + prev= + func_append compile_command " $wl$qarg" + func_append finalize_command " $wl$qarg" + continue + ;; + *) + eval "$prev=\"\$arg\"" + prev= + continue + ;; + esac + fi # test -n "$prev" + + prevarg=$arg + + case $arg in + -all-static) + if test -n "$link_static_flag"; then + # See comment for -static flag below, for more details. + func_append compile_command " $link_static_flag" + func_append finalize_command " $link_static_flag" + fi + continue + ;; + + -allow-undefined) + # FIXME: remove this flag sometime in the future. + func_fatal_error "'-allow-undefined' must not be used because it is the default" + ;; + + -avoid-version) + avoid_version=yes + continue + ;; + + -bindir) + prev=bindir + continue + ;; + + -dlopen) + prev=dlfiles + continue + ;; + + -dlpreopen) + prev=dlprefiles + continue + ;; + + -export-dynamic) + export_dynamic=yes + continue + ;; + + -export-symbols | -export-symbols-regex) + if test -n "$export_symbols" || test -n "$export_symbols_regex"; then + func_fatal_error "more than one -exported-symbols argument is not allowed" + fi + if test X-export-symbols = "X$arg"; then + prev=expsyms + else + prev=expsyms_regex + fi + continue + ;; + + -framework) + prev=framework + continue + ;; + + -inst-prefix-dir) + prev=inst_prefix + continue + ;; + + # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* + # so, if we see these flags be careful not to treat them like -L + -L[A-Z][A-Z]*:*) + case $with_gcc/$host in + no/*-*-irix* | /*-*-irix*) + func_append compile_command " $arg" + func_append finalize_command " $arg" + ;; + esac + continue + ;; + + -L*) + func_stripname "-L" '' "$arg" + if test -z "$func_stripname_result"; then + if test "$#" -gt 0; then + func_fatal_error "require no space between '-L' and '$1'" + else + func_fatal_error "need path for '-L' option" + fi + fi + func_resolve_sysroot "$func_stripname_result" + dir=$func_resolve_sysroot_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + absdir=`cd "$dir" && pwd` + test -z "$absdir" && \ + func_fatal_error "cannot determine absolute directory name of '$dir'" + dir=$absdir + ;; + esac + case "$deplibs " in + *" -L$dir "* | *" $arg "*) + # Will only happen for absolute or sysroot arguments + ;; + *) + # Preserve sysroot, but never include relative directories + case $dir in + [\\/]* | [A-Za-z]:[\\/]* | =*) func_append deplibs " $arg" ;; + *) func_append deplibs " -L$dir" ;; + esac + func_append lib_search_path " $dir" + ;; + esac + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$dir:"*) ;; + ::) dllsearchpath=$dir;; + *) func_append dllsearchpath ":$dir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + ::) dllsearchpath=$testbindir;; + *) func_append dllsearchpath ":$testbindir";; + esac + ;; + esac + continue + ;; + + -l*) + if test X-lc = "X$arg" || test X-lm = "X$arg"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*) + # These systems don't actually have a C or math library (as such) + continue + ;; + *-*-os2*) + # These systems don't actually have a C library (as such) + test X-lc = "X$arg" && continue + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*) + # Do not include libc due to us having libc/libc_r. + test X-lc = "X$arg" && continue + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C and math libraries are in the System framework + func_append deplibs " System.ltframework" + continue + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + test X-lc = "X$arg" && continue + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + test X-lc = "X$arg" && continue + ;; + esac + elif test X-lc_r = "X$arg"; then + case $host in + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*) + # Do not include libc_r directly, use -pthread flag. + continue + ;; + esac + fi + func_append deplibs " $arg" + continue + ;; + + -mllvm) + prev=mllvm + continue + ;; + + -module) + module=yes + continue + ;; + + # Tru64 UNIX uses -model [arg] to determine the layout of C++ + # classes, name mangling, and exception handling. + # Darwin uses the -arch flag to determine output architecture. + -model|-arch|-isysroot|--sysroot) + func_append compiler_flags " $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + prev=xcompiler + continue + ;; + + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ + |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) + func_append compiler_flags " $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + case "$new_inherited_linker_flags " in + *" $arg "*) ;; + * ) func_append new_inherited_linker_flags " $arg" ;; + esac + continue + ;; + + -multi_module) + single_module=$wl-multi_module + continue + ;; + + -no-fast-install) + fast_install=no + continue + ;; + + -no-install) + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) + # The PATH hackery in wrapper scripts is required on Windows + # and Darwin in order for the loader to find any dlls it needs. + func_warning "'-no-install' is ignored for $host" + func_warning "assuming '-no-fast-install' instead" + fast_install=no + ;; + *) no_install=yes ;; + esac + continue + ;; + + -no-undefined) + allow_undefined=no + continue + ;; + + -objectlist) + prev=objectlist + continue + ;; + + -os2dllname) + prev=os2dllname + continue + ;; + + -o) prev=output ;; + + -precious-files-regex) + prev=precious_regex + continue + ;; + + -release) + prev=release + continue + ;; + + -rpath) + prev=rpath + continue + ;; + + -R) + prev=xrpath + continue + ;; + + -R*) + func_stripname '-R' '' "$arg" + dir=$func_stripname_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + =*) + func_stripname '=' '' "$dir" + dir=$lt_sysroot$func_stripname_result + ;; + *) + func_fatal_error "only absolute run-paths are allowed" + ;; + esac + case "$xrpath " in + *" $dir "*) ;; + *) func_append xrpath " $dir" ;; + esac + continue + ;; + + -shared) + # The effects of -shared are defined in a previous loop. + continue + ;; + + -shrext) + prev=shrext + continue + ;; + + -static | -static-libtool-libs) + # The effects of -static are defined in a previous loop. + # We used to do the same as -all-static on platforms that + # didn't have a PIC flag, but the assumption that the effects + # would be equivalent was wrong. It would break on at least + # Digital Unix and AIX. + continue + ;; + + -thread-safe) + thread_safe=yes + continue + ;; + + -version-info) + prev=vinfo + continue + ;; + + -version-number) + prev=vinfo + vinfo_number=yes + continue + ;; + + -weak) + prev=weak + continue + ;; + + -Wc,*) + func_stripname '-Wc,' '' "$arg" + args=$func_stripname_result + arg= + save_ifs=$IFS; IFS=, + for flag in $args; do + IFS=$save_ifs + func_quote_for_eval "$flag" + func_append arg " $func_quote_for_eval_result" + func_append compiler_flags " $func_quote_for_eval_result" + done + IFS=$save_ifs + func_stripname ' ' '' "$arg" + arg=$func_stripname_result + ;; + + -Wl,*) + func_stripname '-Wl,' '' "$arg" + args=$func_stripname_result + arg= + save_ifs=$IFS; IFS=, + for flag in $args; do + IFS=$save_ifs + func_quote_for_eval "$flag" + func_append arg " $wl$func_quote_for_eval_result" + func_append compiler_flags " $wl$func_quote_for_eval_result" + func_append linker_flags " $func_quote_for_eval_result" + done + IFS=$save_ifs + func_stripname ' ' '' "$arg" + arg=$func_stripname_result + ;; + + -Xcompiler) + prev=xcompiler + continue + ;; + + -Xlinker) + prev=xlinker + continue + ;; + + -XCClinker) + prev=xcclinker + continue + ;; + + # -msg_* for osf cc + -msg_*) + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + ;; + + # Flags to be passed through unchanged, with rationale: + # -64, -mips[0-9] enable 64-bit mode for the SGI compiler + # -r[0-9][0-9]* specify processor for the SGI compiler + # -xarch=*, -xtarget=* enable 64-bit mode for the Sun compiler + # +DA*, +DD* enable 64-bit mode for the HP compiler + # -q* compiler args for the IBM compiler + # -m*, -t[45]*, -txscale* architecture-specific flags for GCC + # -F/path path to uninstalled frameworks, gcc on darwin + # -p, -pg, --coverage, -fprofile-* profiling flags for GCC + # -fstack-protector* stack protector flags for GCC + # @file GCC response files + # -tp=* Portland pgcc target processor selection + # --sysroot=* for sysroot support + # -O*, -g*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization + # -specs=* GCC specs files + # -stdlib=* select c++ std lib with clang + # -fsanitize=* Clang/GCC memory and address sanitizer + -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ + -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \ + -O*|-g*|-flto*|-fwhopr*|-fuse-linker-plugin|-fstack-protector*|-stdlib=*| \ + -specs=*|-fsanitize=*) + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + func_append compile_command " $arg" + func_append finalize_command " $arg" + func_append compiler_flags " $arg" + continue + ;; + + -Z*) + if test os2 = "`expr $host : '.*\(os2\)'`"; then + # OS/2 uses -Zxxx to specify OS/2-specific options + compiler_flags="$compiler_flags $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + case $arg in + -Zlinker | -Zstack) + prev=xcompiler + ;; + esac + continue + else + # Otherwise treat like 'Some other compiler flag' below + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + fi + ;; + + # Some other compiler flag. + -* | +*) + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + ;; + + *.$objext) + # A standard object. + func_append objs " $arg" + ;; + + *.lo) + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if func_lalib_unsafe_p "$arg"; then + pic_object= + non_pic_object= + + # Read the .lo file + func_source "$arg" + + if test -z "$pic_object" || + test -z "$non_pic_object" || + test none = "$pic_object" && + test none = "$non_pic_object"; then + func_fatal_error "cannot find name of object for '$arg'" + fi + + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + test none = "$pic_object" || { + # Prepend the subdirectory the object is found in. + pic_object=$xdir$pic_object + + if test dlfiles = "$prev"; then + if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then + func_append dlfiles " $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test dlprefiles = "$prev"; then + # Preload the old-style object. + func_append dlprefiles " $pic_object" + prev= + fi + + # A PIC object. + func_append libobjs " $pic_object" + arg=$pic_object + } + + # Non-PIC object. + if test none != "$non_pic_object"; then + # Prepend the subdirectory the object is found in. + non_pic_object=$xdir$non_pic_object + + # A standard non-PIC object + func_append non_pic_objects " $non_pic_object" + if test -z "$pic_object" || test none = "$pic_object"; then + arg=$non_pic_object + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object=$pic_object + func_append non_pic_objects " $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if $opt_dry_run; then + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + func_lo2o "$arg" + pic_object=$xdir$objdir/$func_lo2o_result + non_pic_object=$xdir$func_lo2o_result + func_append libobjs " $pic_object" + func_append non_pic_objects " $non_pic_object" + else + func_fatal_error "'$arg' is not a valid libtool object" + fi + fi + ;; + + *.$libext) + # An archive. + func_append deplibs " $arg" + func_append old_deplibs " $arg" + continue + ;; + + *.la) + # A libtool-controlled library. + + func_resolve_sysroot "$arg" + if test dlfiles = "$prev"; then + # This library was specified with -dlopen. + func_append dlfiles " $func_resolve_sysroot_result" + prev= + elif test dlprefiles = "$prev"; then + # The library was specified with -dlpreopen. + func_append dlprefiles " $func_resolve_sysroot_result" + prev= + else + func_append deplibs " $func_resolve_sysroot_result" + fi + continue + ;; + + # Some other compiler argument. + *) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + ;; + esac # arg + + # Now actually substitute the argument into the commands. + if test -n "$arg"; then + func_append compile_command " $arg" + func_append finalize_command " $arg" + fi + done # argument parsing loop + + test -n "$prev" && \ + func_fatal_help "the '$prevarg' option requires an argument" + + if test yes = "$export_dynamic" && test -n "$export_dynamic_flag_spec"; then + eval arg=\"$export_dynamic_flag_spec\" + func_append compile_command " $arg" + func_append finalize_command " $arg" + fi + + oldlibs= + # calculate the name of the file, without its directory + func_basename "$output" + outputname=$func_basename_result + libobjs_save=$libobjs + + if test -n "$shlibpath_var"; then + # get the directories listed in $shlibpath_var + eval shlib_search_path=\`\$ECHO \"\$$shlibpath_var\" \| \$SED \'s/:/ /g\'\` + else + shlib_search_path= + fi + eval sys_lib_search_path=\"$sys_lib_search_path_spec\" + eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" + + # Definition is injected by LT_CONFIG during libtool generation. + func_munge_path_list sys_lib_dlsearch_path "$LT_SYS_LIBRARY_PATH" + + func_dirname "$output" "/" "" + output_objdir=$func_dirname_result$objdir + func_to_tool_file "$output_objdir/" + tool_output_objdir=$func_to_tool_file_result + # Create the object directory. + func_mkdir_p "$output_objdir" + + # Determine the type of output + case $output in + "") + func_fatal_help "you must specify an output file" + ;; + *.$libext) linkmode=oldlib ;; + *.lo | *.$objext) linkmode=obj ;; + *.la) linkmode=lib ;; + *) linkmode=prog ;; # Anything else should be a program. + esac + + specialdeplibs= + + libs= + # Find all interdependent deplibs by searching for libraries + # that are linked more than once (e.g. -la -lb -la) + for deplib in $deplibs; do + if $opt_preserve_dup_deps; then + case "$libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append libs " $deplib" + done + + if test lib = "$linkmode"; then + libs="$predeps $libs $compiler_lib_search_path $postdeps" + + # Compute libraries that are listed more than once in $predeps + # $postdeps and mark them as special (i.e., whose duplicates are + # not to be eliminated). + pre_post_deps= + if $opt_duplicate_compiler_generated_deps; then + for pre_post_dep in $predeps $postdeps; do + case "$pre_post_deps " in + *" $pre_post_dep "*) func_append specialdeplibs " $pre_post_deps" ;; + esac + func_append pre_post_deps " $pre_post_dep" + done + fi + pre_post_deps= + fi + + deplibs= + newdependency_libs= + newlib_search_path= + need_relink=no # whether we're linking any uninstalled libtool libraries + notinst_deplibs= # not-installed libtool libraries + notinst_path= # paths that contain not-installed libtool libraries + + case $linkmode in + lib) + passes="conv dlpreopen link" + for file in $dlfiles $dlprefiles; do + case $file in + *.la) ;; + *) + func_fatal_help "libraries can '-dlopen' only libtool libraries: $file" + ;; + esac + done + ;; + prog) + compile_deplibs= + finalize_deplibs= + alldeplibs=false + newdlfiles= + newdlprefiles= + passes="conv scan dlopen dlpreopen link" + ;; + *) passes="conv" + ;; + esac + + for pass in $passes; do + # The preopen pass in lib mode reverses $deplibs; put it back here + # so that -L comes before libs that need it for instance... + if test lib,link = "$linkmode,$pass"; then + ## FIXME: Find the place where the list is rebuilt in the wrong + ## order, and fix it there properly + tmp_deplibs= + for deplib in $deplibs; do + tmp_deplibs="$deplib $tmp_deplibs" + done + deplibs=$tmp_deplibs + fi + + if test lib,link = "$linkmode,$pass" || + test prog,scan = "$linkmode,$pass"; then + libs=$deplibs + deplibs= + fi + if test prog = "$linkmode"; then + case $pass in + dlopen) libs=$dlfiles ;; + dlpreopen) libs=$dlprefiles ;; + link) + libs="$deplibs %DEPLIBS%" + test "X$link_all_deplibs" != Xno && libs="$libs $dependency_libs" + ;; + esac + fi + if test lib,dlpreopen = "$linkmode,$pass"; then + # Collect and forward deplibs of preopened libtool libs + for lib in $dlprefiles; do + # Ignore non-libtool-libs + dependency_libs= + func_resolve_sysroot "$lib" + case $lib in + *.la) func_source "$func_resolve_sysroot_result" ;; + esac + + # Collect preopened libtool deplibs, except any this library + # has declared as weak libs + for deplib in $dependency_libs; do + func_basename "$deplib" + deplib_base=$func_basename_result + case " $weak_libs " in + *" $deplib_base "*) ;; + *) func_append deplibs " $deplib" ;; + esac + done + done + libs=$dlprefiles + fi + if test dlopen = "$pass"; then + # Collect dlpreopened libraries + save_deplibs=$deplibs + deplibs= + fi + + for deplib in $libs; do + lib= + found=false + case $deplib in + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ + |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + func_append compiler_flags " $deplib" + if test lib = "$linkmode"; then + case "$new_inherited_linker_flags " in + *" $deplib "*) ;; + * ) func_append new_inherited_linker_flags " $deplib" ;; + esac + fi + fi + continue + ;; + -l*) + if test lib != "$linkmode" && test prog != "$linkmode"; then + func_warning "'-l' is ignored for archives/objects" + continue + fi + func_stripname '-l' '' "$deplib" + name=$func_stripname_result + if test lib = "$linkmode"; then + searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" + else + searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" + fi + for searchdir in $searchdirs; do + for search_ext in .la $std_shrext .so .a; do + # Search the libtool library + lib=$searchdir/lib$name$search_ext + if test -f "$lib"; then + if test .la = "$search_ext"; then + found=: + else + found=false + fi + break 2 + fi + done + done + if $found; then + # deplib is a libtool library + # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, + # We need to do some special things here, and not later. + if test yes = "$allow_libtool_libs_with_static_runtimes"; then + case " $predeps $postdeps " in + *" $deplib "*) + if func_lalib_p "$lib"; then + library_names= + old_library= + func_source "$lib" + for l in $old_library $library_names; do + ll=$l + done + if test "X$ll" = "X$old_library"; then # only static version available + found=false + func_dirname "$lib" "" "." + ladir=$func_dirname_result + lib=$ladir/$old_library + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs" + fi + continue + fi + fi + ;; + *) ;; + esac + fi + else + # deplib doesn't seem to be a libtool library + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs" + fi + continue + fi + ;; # -l + *.ltframework) + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + if test lib = "$linkmode"; then + case "$new_inherited_linker_flags " in + *" $deplib "*) ;; + * ) func_append new_inherited_linker_flags " $deplib" ;; + esac + fi + fi + continue + ;; + -L*) + case $linkmode in + lib) + deplibs="$deplib $deplibs" + test conv = "$pass" && continue + newdependency_libs="$deplib $newdependency_libs" + func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + prog) + if test conv = "$pass"; then + deplibs="$deplib $deplibs" + continue + fi + if test scan = "$pass"; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + *) + func_warning "'-L' is ignored for archives/objects" + ;; + esac # linkmode + continue + ;; # -L + -R*) + if test link = "$pass"; then + func_stripname '-R' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + dir=$func_resolve_sysroot_result + # Make sure the xrpath contains only unique directories. + case "$xrpath " in + *" $dir "*) ;; + *) func_append xrpath " $dir" ;; + esac + fi + deplibs="$deplib $deplibs" + continue + ;; + *.la) + func_resolve_sysroot "$deplib" + lib=$func_resolve_sysroot_result + ;; + *.$libext) + if test conv = "$pass"; then + deplibs="$deplib $deplibs" + continue + fi + case $linkmode in + lib) + # Linking convenience modules into shared libraries is allowed, + # but linking other static libraries is non-portable. + case " $dlpreconveniencelibs " in + *" $deplib "*) ;; + *) + valid_a_lib=false + case $deplibs_check_method in + match_pattern*) + set dummy $deplibs_check_method; shift + match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` + if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \ + | $EGREP "$match_pattern_regex" > /dev/null; then + valid_a_lib=: + fi + ;; + pass_all) + valid_a_lib=: + ;; + esac + if $valid_a_lib; then + echo + $ECHO "*** Warning: Linking the shared library $output against the" + $ECHO "*** static library $deplib is not portable!" + deplibs="$deplib $deplibs" + else + echo + $ECHO "*** Warning: Trying to link with static lib archive $deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because the file extensions .$libext of this argument makes me believe" + echo "*** that it is just a static archive that I should not use here." + fi + ;; + esac + continue + ;; + prog) + if test link != "$pass"; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + continue + ;; + esac # linkmode + ;; # *.$libext + *.lo | *.$objext) + if test conv = "$pass"; then + deplibs="$deplib $deplibs" + elif test prog = "$linkmode"; then + if test dlpreopen = "$pass" || test yes != "$dlopen_support" || test no = "$build_libtool_libs"; then + # If there is no dlopen support or we're linking statically, + # we need to preload. + func_append newdlprefiles " $deplib" + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + func_append newdlfiles " $deplib" + fi + fi + continue + ;; + %DEPLIBS%) + alldeplibs=: + continue + ;; + esac # case $deplib + + $found || test -f "$lib" \ + || func_fatal_error "cannot find the library '$lib' or unhandled argument '$deplib'" + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$lib" \ + || func_fatal_error "'$lib' is not a valid libtool archive" + + func_dirname "$lib" "" "." + ladir=$func_dirname_result + + dlname= + dlopen= + dlpreopen= + libdir= + library_names= + old_library= + inherited_linker_flags= + # If the library was installed with an old release of libtool, + # it will not redefine variables installed, or shouldnotlink + installed=yes + shouldnotlink=no + avoidtemprpath= + + + # Read the .la file + func_source "$lib" + + # Convert "-framework foo" to "foo.ltframework" + if test -n "$inherited_linker_flags"; then + tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'` + for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do + case " $new_inherited_linker_flags " in + *" $tmp_inherited_linker_flag "*) ;; + *) func_append new_inherited_linker_flags " $tmp_inherited_linker_flag";; + esac + done + fi + dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + if test lib,link = "$linkmode,$pass" || + test prog,scan = "$linkmode,$pass" || + { test prog != "$linkmode" && test lib != "$linkmode"; }; then + test -n "$dlopen" && func_append dlfiles " $dlopen" + test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen" + fi + + if test conv = "$pass"; then + # Only check for convenience libraries + deplibs="$lib $deplibs" + if test -z "$libdir"; then + if test -z "$old_library"; then + func_fatal_error "cannot find name of link library for '$lib'" + fi + # It is a libtool convenience library, so add in its objects. + func_append convenience " $ladir/$objdir/$old_library" + func_append old_convenience " $ladir/$objdir/$old_library" + tmp_libs= + for deplib in $dependency_libs; do + deplibs="$deplib $deplibs" + if $opt_preserve_dup_deps; then + case "$tmp_libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append tmp_libs " $deplib" + done + elif test prog != "$linkmode" && test lib != "$linkmode"; then + func_fatal_error "'$lib' is not a convenience library" + fi + continue + fi # $pass = conv + + + # Get the name of the library we link against. + linklib= + if test -n "$old_library" && + { test yes = "$prefer_static_libs" || + test built,no = "$prefer_static_libs,$installed"; }; then + linklib=$old_library + else + for l in $old_library $library_names; do + linklib=$l + done + fi + if test -z "$linklib"; then + func_fatal_error "cannot find name of link library for '$lib'" + fi + + # This library was specified with -dlopen. + if test dlopen = "$pass"; then + test -z "$libdir" \ + && func_fatal_error "cannot -dlopen a convenience library: '$lib'" + if test -z "$dlname" || + test yes != "$dlopen_support" || + test no = "$build_libtool_libs" + then + # If there is no dlname, no dlopen support or we're linking + # statically, we need to preload. We also need to preload any + # dependent libraries so libltdl's deplib preloader doesn't + # bomb out in the load deplibs phase. + func_append dlprefiles " $lib $dependency_libs" + else + func_append newdlfiles " $lib" + fi + continue + fi # $pass = dlopen + + # We need an absolute path. + case $ladir in + [\\/]* | [A-Za-z]:[\\/]*) abs_ladir=$ladir ;; + *) + abs_ladir=`cd "$ladir" && pwd` + if test -z "$abs_ladir"; then + func_warning "cannot determine absolute directory name of '$ladir'" + func_warning "passing it literally to the linker, although it might fail" + abs_ladir=$ladir + fi + ;; + esac + func_basename "$lib" + laname=$func_basename_result + + # Find the relevant object directory and library name. + if test yes = "$installed"; then + if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then + func_warning "library '$lib' was moved." + dir=$ladir + absdir=$abs_ladir + libdir=$abs_ladir + else + dir=$lt_sysroot$libdir + absdir=$lt_sysroot$libdir + fi + test yes = "$hardcode_automatic" && avoidtemprpath=yes + else + if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then + dir=$ladir + absdir=$abs_ladir + # Remove this search path later + func_append notinst_path " $abs_ladir" + else + dir=$ladir/$objdir + absdir=$abs_ladir/$objdir + # Remove this search path later + func_append notinst_path " $abs_ladir" + fi + fi # $installed = yes + func_stripname 'lib' '.la' "$laname" + name=$func_stripname_result + + # This library was specified with -dlpreopen. + if test dlpreopen = "$pass"; then + if test -z "$libdir" && test prog = "$linkmode"; then + func_fatal_error "only libraries may -dlpreopen a convenience library: '$lib'" + fi + case $host in + # special handling for platforms with PE-DLLs. + *cygwin* | *mingw* | *cegcc* ) + # Linker will automatically link against shared library if both + # static and shared are present. Therefore, ensure we extract + # symbols from the import library if a shared library is present + # (otherwise, the dlopen module name will be incorrect). We do + # this by putting the import library name into $newdlprefiles. + # We recover the dlopen module name by 'saving' the la file + # name in a special purpose variable, and (later) extracting the + # dlname from the la file. + if test -n "$dlname"; then + func_tr_sh "$dir/$linklib" + eval "libfile_$func_tr_sh_result=\$abs_ladir/\$laname" + func_append newdlprefiles " $dir/$linklib" + else + func_append newdlprefiles " $dir/$old_library" + # Keep a list of preopened convenience libraries to check + # that they are being used correctly in the link pass. + test -z "$libdir" && \ + func_append dlpreconveniencelibs " $dir/$old_library" + fi + ;; + * ) + # Prefer using a static library (so that no silly _DYNAMIC symbols + # are required to link). + if test -n "$old_library"; then + func_append newdlprefiles " $dir/$old_library" + # Keep a list of preopened convenience libraries to check + # that they are being used correctly in the link pass. + test -z "$libdir" && \ + func_append dlpreconveniencelibs " $dir/$old_library" + # Otherwise, use the dlname, so that lt_dlopen finds it. + elif test -n "$dlname"; then + func_append newdlprefiles " $dir/$dlname" + else + func_append newdlprefiles " $dir/$linklib" + fi + ;; + esac + fi # $pass = dlpreopen + + if test -z "$libdir"; then + # Link the convenience library + if test lib = "$linkmode"; then + deplibs="$dir/$old_library $deplibs" + elif test prog,link = "$linkmode,$pass"; then + compile_deplibs="$dir/$old_library $compile_deplibs" + finalize_deplibs="$dir/$old_library $finalize_deplibs" + else + deplibs="$lib $deplibs" # used for prog,scan pass + fi + continue + fi + + + if test prog = "$linkmode" && test link != "$pass"; then + func_append newlib_search_path " $ladir" + deplibs="$lib $deplibs" + + linkalldeplibs=false + if test no != "$link_all_deplibs" || test -z "$library_names" || + test no = "$build_libtool_libs"; then + linkalldeplibs=: + fi + + tmp_libs= + for deplib in $dependency_libs; do + case $deplib in + -L*) func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + esac + # Need to link against all dependency_libs? + if $linkalldeplibs; then + deplibs="$deplib $deplibs" + else + # Need to hardcode shared library paths + # or/and link against static libraries + newdependency_libs="$deplib $newdependency_libs" + fi + if $opt_preserve_dup_deps; then + case "$tmp_libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append tmp_libs " $deplib" + done # for deplib + continue + fi # $linkmode = prog... + + if test prog,link = "$linkmode,$pass"; then + if test -n "$library_names" && + { { test no = "$prefer_static_libs" || + test built,yes = "$prefer_static_libs,$installed"; } || + test -z "$old_library"; }; then + # We need to hardcode the library path + if test -n "$shlibpath_var" && test -z "$avoidtemprpath"; then + # Make sure the rpath contains only unique directories. + case $temp_rpath: in + *"$absdir:"*) ;; + *) func_append temp_rpath "$absdir:" ;; + esac + fi + + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) func_append compile_rpath " $absdir" ;; + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + ;; + esac + fi # $linkmode,$pass = prog,link... + + if $alldeplibs && + { test pass_all = "$deplibs_check_method" || + { test yes = "$build_libtool_libs" && + test -n "$library_names"; }; }; then + # We only need to search for static libraries + continue + fi + fi + + link_static=no # Whether the deplib will be linked statically + use_static_libs=$prefer_static_libs + if test built = "$use_static_libs" && test yes = "$installed"; then + use_static_libs=no + fi + if test -n "$library_names" && + { test no = "$use_static_libs" || test -z "$old_library"; }; then + case $host in + *cygwin* | *mingw* | *cegcc* | *os2*) + # No point in relinking DLLs because paths are not encoded + func_append notinst_deplibs " $lib" + need_relink=no + ;; + *) + if test no = "$installed"; then + func_append notinst_deplibs " $lib" + need_relink=yes + fi + ;; + esac + # This is a shared library + + # Warn about portability, can't link against -module's on some + # systems (darwin). Don't bleat about dlopened modules though! + dlopenmodule= + for dlpremoduletest in $dlprefiles; do + if test "X$dlpremoduletest" = "X$lib"; then + dlopenmodule=$dlpremoduletest + break + fi + done + if test -z "$dlopenmodule" && test yes = "$shouldnotlink" && test link = "$pass"; then + echo + if test prog = "$linkmode"; then + $ECHO "*** Warning: Linking the executable $output against the loadable module" + else + $ECHO "*** Warning: Linking the shared library $output against the loadable module" + fi + $ECHO "*** $linklib is not portable!" + fi + if test lib = "$linkmode" && + test yes = "$hardcode_into_libs"; then + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) func_append compile_rpath " $absdir" ;; + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + ;; + esac + fi + + if test -n "$old_archive_from_expsyms_cmds"; then + # figure out the soname + set dummy $library_names + shift + realname=$1 + shift + libname=`eval "\\$ECHO \"$libname_spec\""` + # use dlname if we got it. it's perfectly good, no? + if test -n "$dlname"; then + soname=$dlname + elif test -n "$soname_spec"; then + # bleh windows + case $host in + *cygwin* | mingw* | *cegcc* | *os2*) + func_arith $current - $age + major=$func_arith_result + versuffix=-$major + ;; + esac + eval soname=\"$soname_spec\" + else + soname=$realname + fi + + # Make a new name for the extract_expsyms_cmds to use + soroot=$soname + func_basename "$soroot" + soname=$func_basename_result + func_stripname 'lib' '.dll' "$soname" + newlib=libimp-$func_stripname_result.a + + # If the library has no export list, then create one now + if test -f "$output_objdir/$soname-def"; then : + else + func_verbose "extracting exported symbol list from '$soname'" + func_execute_cmds "$extract_expsyms_cmds" 'exit $?' + fi + + # Create $newlib + if test -f "$output_objdir/$newlib"; then :; else + func_verbose "generating import library for '$soname'" + func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' + fi + # make sure the library variables are pointing to the new library + dir=$output_objdir + linklib=$newlib + fi # test -n "$old_archive_from_expsyms_cmds" + + if test prog = "$linkmode" || test relink != "$opt_mode"; then + add_shlibpath= + add_dir= + add= + lib_linked=yes + case $hardcode_action in + immediate | unsupported) + if test no = "$hardcode_direct"; then + add=$dir/$linklib + case $host in + *-*-sco3.2v5.0.[024]*) add_dir=-L$dir ;; + *-*-sysv4*uw2*) add_dir=-L$dir ;; + *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ + *-*-unixware7*) add_dir=-L$dir ;; + *-*-darwin* ) + # if the lib is a (non-dlopened) module then we cannot + # link against it, someone is ignoring the earlier warnings + if /usr/bin/file -L $add 2> /dev/null | + $GREP ": [^:]* bundle" >/dev/null; then + if test "X$dlopenmodule" != "X$lib"; then + $ECHO "*** Warning: lib $linklib is a module, not a shared library" + if test -z "$old_library"; then + echo + echo "*** And there doesn't seem to be a static archive available" + echo "*** The link will probably fail, sorry" + else + add=$dir/$old_library + fi + elif test -n "$old_library"; then + add=$dir/$old_library + fi + fi + esac + elif test no = "$hardcode_minus_L"; then + case $host in + *-*-sunos*) add_shlibpath=$dir ;; + esac + add_dir=-L$dir + add=-l$name + elif test no = "$hardcode_shlibpath_var"; then + add_shlibpath=$dir + add=-l$name + else + lib_linked=no + fi + ;; + relink) + if test yes = "$hardcode_direct" && + test no = "$hardcode_direct_absolute"; then + add=$dir/$linklib + elif test yes = "$hardcode_minus_L"; then + add_dir=-L$absdir + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + func_append add_dir " -L$inst_prefix_dir$libdir" + ;; + esac + fi + add=-l$name + elif test yes = "$hardcode_shlibpath_var"; then + add_shlibpath=$dir + add=-l$name + else + lib_linked=no + fi + ;; + *) lib_linked=no ;; + esac + + if test yes != "$lib_linked"; then + func_fatal_configuration "unsupported hardcode properties" + fi + + if test -n "$add_shlibpath"; then + case :$compile_shlibpath: in + *":$add_shlibpath:"*) ;; + *) func_append compile_shlibpath "$add_shlibpath:" ;; + esac + fi + if test prog = "$linkmode"; then + test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" + test -n "$add" && compile_deplibs="$add $compile_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + if test yes != "$hardcode_direct" && + test yes != "$hardcode_minus_L" && + test yes = "$hardcode_shlibpath_var"; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) func_append finalize_shlibpath "$libdir:" ;; + esac + fi + fi + fi + + if test prog = "$linkmode" || test relink = "$opt_mode"; then + add_shlibpath= + add_dir= + add= + # Finalize command for both is simple: just hardcode it. + if test yes = "$hardcode_direct" && + test no = "$hardcode_direct_absolute"; then + add=$libdir/$linklib + elif test yes = "$hardcode_minus_L"; then + add_dir=-L$libdir + add=-l$name + elif test yes = "$hardcode_shlibpath_var"; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) func_append finalize_shlibpath "$libdir:" ;; + esac + add=-l$name + elif test yes = "$hardcode_automatic"; then + if test -n "$inst_prefix_dir" && + test -f "$inst_prefix_dir$libdir/$linklib"; then + add=$inst_prefix_dir$libdir/$linklib + else + add=$libdir/$linklib + fi + else + # We cannot seem to hardcode it, guess we'll fake it. + add_dir=-L$libdir + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + func_append add_dir " -L$inst_prefix_dir$libdir" + ;; + esac + fi + add=-l$name + fi + + if test prog = "$linkmode"; then + test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" + test -n "$add" && finalize_deplibs="$add $finalize_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + fi + fi + elif test prog = "$linkmode"; then + # Here we assume that one of hardcode_direct or hardcode_minus_L + # is not unsupported. This is valid on all known static and + # shared platforms. + if test unsupported != "$hardcode_direct"; then + test -n "$old_library" && linklib=$old_library + compile_deplibs="$dir/$linklib $compile_deplibs" + finalize_deplibs="$dir/$linklib $finalize_deplibs" + else + compile_deplibs="-l$name -L$dir $compile_deplibs" + finalize_deplibs="-l$name -L$dir $finalize_deplibs" + fi + elif test yes = "$build_libtool_libs"; then + # Not a shared library + if test pass_all != "$deplibs_check_method"; then + # We're trying link a shared library against a static one + # but the system doesn't support it. + + # Just print a warning and add the library to dependency_libs so + # that the program can be linked against the static library. + echo + $ECHO "*** Warning: This system cannot link to static lib archive $lib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have." + if test yes = "$module"; then + echo "*** But as you try to build a module library, libtool will still create " + echo "*** a static module, that should work as long as the dlopening application" + echo "*** is linked with the -dlopen flag to resolve symbols at runtime." + if test -z "$global_symbol_pipe"; then + echo + echo "*** However, this would only work if libtool was able to extract symbol" + echo "*** lists from a program, using 'nm' or equivalent, but libtool could" + echo "*** not find such a program. So, this module is probably useless." + echo "*** 'nm' from GNU binutils and a full rebuild may help." + fi + if test no = "$build_old_libs"; then + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + else + deplibs="$dir/$old_library $deplibs" + link_static=yes + fi + fi # link shared/static library? + + if test lib = "$linkmode"; then + if test -n "$dependency_libs" && + { test yes != "$hardcode_into_libs" || + test yes = "$build_old_libs" || + test yes = "$link_static"; }; then + # Extract -R from dependency_libs + temp_deplibs= + for libdir in $dependency_libs; do + case $libdir in + -R*) func_stripname '-R' '' "$libdir" + temp_xrpath=$func_stripname_result + case " $xrpath " in + *" $temp_xrpath "*) ;; + *) func_append xrpath " $temp_xrpath";; + esac;; + *) func_append temp_deplibs " $libdir";; + esac + done + dependency_libs=$temp_deplibs + fi + + func_append newlib_search_path " $absdir" + # Link against this library + test no = "$link_static" && newdependency_libs="$abs_ladir/$laname $newdependency_libs" + # ... and its dependency_libs + tmp_libs= + for deplib in $dependency_libs; do + newdependency_libs="$deplib $newdependency_libs" + case $deplib in + -L*) func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result";; + *) func_resolve_sysroot "$deplib" ;; + esac + if $opt_preserve_dup_deps; then + case "$tmp_libs " in + *" $func_resolve_sysroot_result "*) + func_append specialdeplibs " $func_resolve_sysroot_result" ;; + esac + fi + func_append tmp_libs " $func_resolve_sysroot_result" + done + + if test no != "$link_all_deplibs"; then + # Add the search paths of all dependency libraries + for deplib in $dependency_libs; do + path= + case $deplib in + -L*) path=$deplib ;; + *.la) + func_resolve_sysroot "$deplib" + deplib=$func_resolve_sysroot_result + func_dirname "$deplib" "" "." + dir=$func_dirname_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) absdir=$dir ;; + *) + absdir=`cd "$dir" && pwd` + if test -z "$absdir"; then + func_warning "cannot determine absolute directory name of '$dir'" + absdir=$dir + fi + ;; + esac + if $GREP "^installed=no" $deplib > /dev/null; then + case $host in + *-*-darwin*) + depdepl= + eval deplibrary_names=`$SED -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` + if test -n "$deplibrary_names"; then + for tmp in $deplibrary_names; do + depdepl=$tmp + done + if test -f "$absdir/$objdir/$depdepl"; then + depdepl=$absdir/$objdir/$depdepl + darwin_install_name=`$OTOOL -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + if test -z "$darwin_install_name"; then + darwin_install_name=`$OTOOL64 -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + fi + func_append compiler_flags " $wl-dylib_file $wl$darwin_install_name:$depdepl" + func_append linker_flags " -dylib_file $darwin_install_name:$depdepl" + path= + fi + fi + ;; + *) + path=-L$absdir/$objdir + ;; + esac + else + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + test -z "$libdir" && \ + func_fatal_error "'$deplib' is not a valid libtool archive" + test "$absdir" != "$libdir" && \ + func_warning "'$deplib' seems to be moved" + + path=-L$absdir + fi + ;; + esac + case " $deplibs " in + *" $path "*) ;; + *) deplibs="$path $deplibs" ;; + esac + done + fi # link_all_deplibs != no + fi # linkmode = lib + done # for deplib in $libs + if test link = "$pass"; then + if test prog = "$linkmode"; then + compile_deplibs="$new_inherited_linker_flags $compile_deplibs" + finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" + else + compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + fi + fi + dependency_libs=$newdependency_libs + if test dlpreopen = "$pass"; then + # Link the dlpreopened libraries before other libraries + for deplib in $save_deplibs; do + deplibs="$deplib $deplibs" + done + fi + if test dlopen != "$pass"; then + test conv = "$pass" || { + # Make sure lib_search_path contains only unique directories. + lib_search_path= + for dir in $newlib_search_path; do + case "$lib_search_path " in + *" $dir "*) ;; + *) func_append lib_search_path " $dir" ;; + esac + done + newlib_search_path= + } + + if test prog,link = "$linkmode,$pass"; then + vars="compile_deplibs finalize_deplibs" + else + vars=deplibs + fi + for var in $vars dependency_libs; do + # Add libraries to $var in reverse order + eval tmp_libs=\"\$$var\" + new_libs= + for deplib in $tmp_libs; do + # FIXME: Pedantically, this is the right thing to do, so + # that some nasty dependency loop isn't accidentally + # broken: + #new_libs="$deplib $new_libs" + # Pragmatically, this seems to cause very few problems in + # practice: + case $deplib in + -L*) new_libs="$deplib $new_libs" ;; + -R*) ;; + *) + # And here is the reason: when a library appears more + # than once as an explicit dependence of a library, or + # is implicitly linked in more than once by the + # compiler, it is considered special, and multiple + # occurrences thereof are not removed. Compare this + # with having the same library being listed as a + # dependency of multiple other libraries: in this case, + # we know (pedantically, we assume) the library does not + # need to be listed more than once, so we keep only the + # last copy. This is not always right, but it is rare + # enough that we require users that really mean to play + # such unportable linking tricks to link the library + # using -Wl,-lname, so that libtool does not consider it + # for duplicate removal. + case " $specialdeplibs " in + *" $deplib "*) new_libs="$deplib $new_libs" ;; + *) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$deplib $new_libs" ;; + esac + ;; + esac + ;; + esac + done + tmp_libs= + for deplib in $new_libs; do + case $deplib in + -L*) + case " $tmp_libs " in + *" $deplib "*) ;; + *) func_append tmp_libs " $deplib" ;; + esac + ;; + *) func_append tmp_libs " $deplib" ;; + esac + done + eval $var=\"$tmp_libs\" + done # for var + fi + + # Add Sun CC postdeps if required: + test CXX = "$tagname" && { + case $host_os in + linux*) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C++ 5.9 + func_suncc_cstd_abi + + if test no != "$suncc_use_cstd_abi"; then + func_append postdeps ' -library=Cstd -library=Crun' + fi + ;; + esac + ;; + + solaris*) + func_cc_basename "$CC" + case $func_cc_basename_result in + CC* | sunCC*) + func_suncc_cstd_abi + + if test no != "$suncc_use_cstd_abi"; then + func_append postdeps ' -library=Cstd -library=Crun' + fi + ;; + esac + ;; + esac + } + + # Last step: remove runtime libs from dependency_libs + # (they stay in deplibs) + tmp_libs= + for i in $dependency_libs; do + case " $predeps $postdeps $compiler_lib_search_path " in + *" $i "*) + i= + ;; + esac + if test -n "$i"; then + func_append tmp_libs " $i" + fi + done + dependency_libs=$tmp_libs + done # for pass + if test prog = "$linkmode"; then + dlfiles=$newdlfiles + fi + if test prog = "$linkmode" || test lib = "$linkmode"; then + dlprefiles=$newdlprefiles + fi + + case $linkmode in + oldlib) + if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then + func_warning "'-dlopen' is ignored for archives" + fi + + case " $deplibs" in + *\ -l* | *\ -L*) + func_warning "'-l' and '-L' are ignored for archives" ;; + esac + + test -n "$rpath" && \ + func_warning "'-rpath' is ignored for archives" + + test -n "$xrpath" && \ + func_warning "'-R' is ignored for archives" + + test -n "$vinfo" && \ + func_warning "'-version-info/-version-number' is ignored for archives" + + test -n "$release" && \ + func_warning "'-release' is ignored for archives" + + test -n "$export_symbols$export_symbols_regex" && \ + func_warning "'-export-symbols' is ignored for archives" + + # Now set the variables for building old libraries. + build_libtool_libs=no + oldlibs=$output + func_append objs "$old_deplibs" + ;; + + lib) + # Make sure we only generate libraries of the form 'libNAME.la'. + case $outputname in + lib*) + func_stripname 'lib' '.la' "$outputname" + name=$func_stripname_result + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + ;; + *) + test no = "$module" \ + && func_fatal_help "libtool library '$output' must begin with 'lib'" + + if test no != "$need_lib_prefix"; then + # Add the "lib" prefix for modules if required + func_stripname '' '.la' "$outputname" + name=$func_stripname_result + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + else + func_stripname '' '.la' "$outputname" + libname=$func_stripname_result + fi + ;; + esac + + if test -n "$objs"; then + if test pass_all != "$deplibs_check_method"; then + func_fatal_error "cannot build libtool library '$output' from non-libtool objects on this host:$objs" + else + echo + $ECHO "*** Warning: Linking the shared library $output against the non-libtool" + $ECHO "*** objects $objs is not portable!" + func_append libobjs " $objs" + fi + fi + + test no = "$dlself" \ + || func_warning "'-dlopen self' is ignored for libtool libraries" + + set dummy $rpath + shift + test 1 -lt "$#" \ + && func_warning "ignoring multiple '-rpath's for a libtool library" + + install_libdir=$1 + + oldlibs= + if test -z "$rpath"; then + if test yes = "$build_libtool_libs"; then + # Building a libtool convenience library. + # Some compilers have problems with a '.al' extension so + # convenience libraries should have the same extension an + # archive normally would. + oldlibs="$output_objdir/$libname.$libext $oldlibs" + build_libtool_libs=convenience + build_old_libs=yes + fi + + test -n "$vinfo" && \ + func_warning "'-version-info/-version-number' is ignored for convenience libraries" + + test -n "$release" && \ + func_warning "'-release' is ignored for convenience libraries" + else + + # Parse the version information argument. + save_ifs=$IFS; IFS=: + set dummy $vinfo 0 0 0 + shift + IFS=$save_ifs + + test -n "$7" && \ + func_fatal_help "too many parameters to '-version-info'" + + # convert absolute version numbers to libtool ages + # this retains compatibility with .la files and attempts + # to make the code below a bit more comprehensible + + case $vinfo_number in + yes) + number_major=$1 + number_minor=$2 + number_revision=$3 + # + # There are really only two kinds -- those that + # use the current revision as the major version + # and those that subtract age and use age as + # a minor version. But, then there is irix + # that has an extra 1 added just for fun + # + case $version_type in + # correct linux to gnu/linux during the next big refactor + darwin|freebsd-elf|linux|osf|windows|none) + func_arith $number_major + $number_minor + current=$func_arith_result + age=$number_minor + revision=$number_revision + ;; + freebsd-aout|qnx|sunos) + current=$number_major + revision=$number_minor + age=0 + ;; + irix|nonstopux) + func_arith $number_major + $number_minor + current=$func_arith_result + age=$number_minor + revision=$number_minor + lt_irix_increment=no + ;; + *) + func_fatal_configuration "$modename: unknown library version type '$version_type'" + ;; + esac + ;; + no) + current=$1 + revision=$2 + age=$3 + ;; + esac + + # Check that each of the things are valid numbers. + case $current in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "CURRENT '$current' must be a nonnegative integer" + func_fatal_error "'$vinfo' is not valid version information" + ;; + esac + + case $revision in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "REVISION '$revision' must be a nonnegative integer" + func_fatal_error "'$vinfo' is not valid version information" + ;; + esac + + case $age in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "AGE '$age' must be a nonnegative integer" + func_fatal_error "'$vinfo' is not valid version information" + ;; + esac + + if test "$age" -gt "$current"; then + func_error "AGE '$age' is greater than the current interface number '$current'" + func_fatal_error "'$vinfo' is not valid version information" + fi + + # Calculate the version variables. + major= + versuffix= + verstring= + case $version_type in + none) ;; + + darwin) + # Like Linux, but with the current version available in + # verstring for coding it into the library header + func_arith $current - $age + major=.$func_arith_result + versuffix=$major.$age.$revision + # Darwin ld doesn't like 0 for these options... + func_arith $current + 1 + minor_current=$func_arith_result + xlcverstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" + verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" + # On Darwin other compilers + case $CC in + nagfor*) + verstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" + ;; + *) + verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" + ;; + esac + ;; + + freebsd-aout) + major=.$current + versuffix=.$current.$revision + ;; + + freebsd-elf) + func_arith $current - $age + major=.$func_arith_result + versuffix=$major.$age.$revision + ;; + + irix | nonstopux) + if test no = "$lt_irix_increment"; then + func_arith $current - $age + else + func_arith $current - $age + 1 + fi + major=$func_arith_result + + case $version_type in + nonstopux) verstring_prefix=nonstopux ;; + *) verstring_prefix=sgi ;; + esac + verstring=$verstring_prefix$major.$revision + + # Add in all the interfaces that we are compatible with. + loop=$revision + while test 0 -ne "$loop"; do + func_arith $revision - $loop + iface=$func_arith_result + func_arith $loop - 1 + loop=$func_arith_result + verstring=$verstring_prefix$major.$iface:$verstring + done + + # Before this point, $major must not contain '.'. + major=.$major + versuffix=$major.$revision + ;; + + linux) # correct to gnu/linux during the next big refactor + func_arith $current - $age + major=.$func_arith_result + versuffix=$major.$age.$revision + ;; + + osf) + func_arith $current - $age + major=.$func_arith_result + versuffix=.$current.$age.$revision + verstring=$current.$age.$revision + + # Add in all the interfaces that we are compatible with. + loop=$age + while test 0 -ne "$loop"; do + func_arith $current - $loop + iface=$func_arith_result + func_arith $loop - 1 + loop=$func_arith_result + verstring=$verstring:$iface.0 + done + + # Make executables depend on our current version. + func_append verstring ":$current.0" + ;; + + qnx) + major=.$current + versuffix=.$current + ;; + + sco) + major=.$current + versuffix=.$current + ;; + + sunos) + major=.$current + versuffix=.$current.$revision + ;; + + windows) + # Use '-' rather than '.', since we only want one + # extension on DOS 8.3 file systems. + func_arith $current - $age + major=$func_arith_result + versuffix=-$major + ;; + + *) + func_fatal_configuration "unknown library version type '$version_type'" + ;; + esac + + # Clear the version info if we defaulted, and they specified a release. + if test -z "$vinfo" && test -n "$release"; then + major= + case $version_type in + darwin) + # we can't check for "0.0" in archive_cmds due to quoting + # problems, so we reset it completely + verstring= + ;; + *) + verstring=0.0 + ;; + esac + if test no = "$need_version"; then + versuffix= + else + versuffix=.0.0 + fi + fi + + # Remove version info from name if versioning should be avoided + if test yes,no = "$avoid_version,$need_version"; then + major= + versuffix= + verstring= + fi + + # Check to see if the archive will have undefined symbols. + if test yes = "$allow_undefined"; then + if test unsupported = "$allow_undefined_flag"; then + if test yes = "$build_old_libs"; then + func_warning "undefined symbols not allowed in $host shared libraries; building static only" + build_libtool_libs=no + else + func_fatal_error "can't build $host shared library unless -no-undefined is specified" + fi + fi + else + # Don't allow undefined symbols. + allow_undefined_flag=$no_undefined_flag + fi + + fi + + func_generate_dlsyms "$libname" "$libname" : + func_append libobjs " $symfileobj" + test " " = "$libobjs" && libobjs= + + if test relink != "$opt_mode"; then + # Remove our outputs, but don't remove object files since they + # may have been created when compiling PIC objects. + removelist= + tempremovelist=`$ECHO "$output_objdir/*"` + for p in $tempremovelist; do + case $p in + *.$objext | *.gcno) + ;; + $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/$libname$release.*) + if test -n "$precious_files_regex"; then + if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 + then + continue + fi + fi + func_append removelist " $p" + ;; + *) ;; + esac + done + test -n "$removelist" && \ + func_show_eval "${RM}r \$removelist" + fi + + # Now set the variables for building old libraries. + if test yes = "$build_old_libs" && test convenience != "$build_libtool_libs"; then + func_append oldlibs " $output_objdir/$libname.$libext" + + # Transform .lo files to .o files. + oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; $lo2o" | $NL2SP` + fi + + # Eliminate all temporary directories. + #for path in $notinst_path; do + # lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"` + # deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"` + # dependency_libs=`$ECHO "$dependency_libs " | $SED "s% -L$path % %g"` + #done + + if test -n "$xrpath"; then + # If the user specified any rpath flags, then add them. + temp_xrpath= + for libdir in $xrpath; do + func_replace_sysroot "$libdir" + func_append temp_xrpath " -R$func_replace_sysroot_result" + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + done + if test yes != "$hardcode_into_libs" || test yes = "$build_old_libs"; then + dependency_libs="$temp_xrpath $dependency_libs" + fi + fi + + # Make sure dlfiles contains only unique files that won't be dlpreopened + old_dlfiles=$dlfiles + dlfiles= + for lib in $old_dlfiles; do + case " $dlprefiles $dlfiles " in + *" $lib "*) ;; + *) func_append dlfiles " $lib" ;; + esac + done + + # Make sure dlprefiles contains only unique files + old_dlprefiles=$dlprefiles + dlprefiles= + for lib in $old_dlprefiles; do + case "$dlprefiles " in + *" $lib "*) ;; + *) func_append dlprefiles " $lib" ;; + esac + done + + if test yes = "$build_libtool_libs"; then + if test -n "$rpath"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*) + # these systems don't actually have a c library (as such)! + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C library is in the System framework + func_append deplibs " System.ltframework" + ;; + *-*-netbsd*) + # Don't link with libc until the a.out ld.so is fixed. + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc due to us having libc/libc_r. + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + ;; + *) + # Add libc to deplibs on all other systems if necessary. + if test yes = "$build_libtool_need_lc"; then + func_append deplibs " -lc" + fi + ;; + esac + fi + + # Transform deplibs into only deplibs that can be linked in shared. + name_save=$name + libname_save=$libname + release_save=$release + versuffix_save=$versuffix + major_save=$major + # I'm not sure if I'm treating the release correctly. I think + # release should show up in the -l (ie -lgmp5) so we don't want to + # add it in twice. Is that correct? + release= + versuffix= + major= + newdeplibs= + droppeddeps=no + case $deplibs_check_method in + pass_all) + # Don't check for shared/static. Everything works. + # This might be a little naive. We might want to check + # whether the library exists or not. But this is on + # osf3 & osf4 and I'm not really sure... Just + # implementing what was already the behavior. + newdeplibs=$deplibs + ;; + test_compile) + # This code stresses the "libraries are programs" paradigm to its + # limits. Maybe even breaks it. We compile a program, linking it + # against the deplibs as a proxy for the library. Then we can check + # whether they linked in statically or dynamically with ldd. + $opt_dry_run || $RM conftest.c + cat > conftest.c </dev/null` + $nocaseglob + else + potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null` + fi + for potent_lib in $potential_libs; do + # Follow soft links. + if ls -lLd "$potent_lib" 2>/dev/null | + $GREP " -> " >/dev/null; then + continue + fi + # The statement above tries to avoid entering an + # endless loop below, in case of cyclic links. + # We might still enter an endless loop, since a link + # loop can be closed while we follow links, + # but so what? + potlib=$potent_lib + while test -h "$potlib" 2>/dev/null; do + potliblink=`ls -ld $potlib | $SED 's/.* -> //'` + case $potliblink in + [\\/]* | [A-Za-z]:[\\/]*) potlib=$potliblink;; + *) potlib=`$ECHO "$potlib" | $SED 's|[^/]*$||'`"$potliblink";; + esac + done + if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | + $SED -e 10q | + $EGREP "$file_magic_regex" > /dev/null; then + func_append newdeplibs " $a_deplib" + a_deplib= + break 2 + fi + done + done + fi + if test -n "$a_deplib"; then + droppeddeps=yes + echo + $ECHO "*** Warning: linker path does not have real file for library $a_deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib"; then + $ECHO "*** with $libname but no candidates were found. (...for file magic test)" + else + $ECHO "*** with $libname and none of the candidates passed a file format test" + $ECHO "*** using a file magic. Last file checked: $potlib" + fi + fi + ;; + *) + # Add a -L argument. + func_append newdeplibs " $a_deplib" + ;; + esac + done # Gone through all deplibs. + ;; + match_pattern*) + set dummy $deplibs_check_method; shift + match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` + for a_deplib in $deplibs; do + case $a_deplib in + -l*) + func_stripname -l '' "$a_deplib" + name=$func_stripname_result + if test yes = "$allow_libtool_libs_with_static_runtimes"; then + case " $predeps $postdeps " in + *" $a_deplib "*) + func_append newdeplibs " $a_deplib" + a_deplib= + ;; + esac + fi + if test -n "$a_deplib"; then + libname=`eval "\\$ECHO \"$libname_spec\""` + for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do + potential_libs=`ls $i/$libname[.-]* 2>/dev/null` + for potent_lib in $potential_libs; do + potlib=$potent_lib # see symlink-check above in file_magic test + if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \ + $EGREP "$match_pattern_regex" > /dev/null; then + func_append newdeplibs " $a_deplib" + a_deplib= + break 2 + fi + done + done + fi + if test -n "$a_deplib"; then + droppeddeps=yes + echo + $ECHO "*** Warning: linker path does not have real file for library $a_deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib"; then + $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" + else + $ECHO "*** with $libname and none of the candidates passed a file format test" + $ECHO "*** using a regex pattern. Last file checked: $potlib" + fi + fi + ;; + *) + # Add a -L argument. + func_append newdeplibs " $a_deplib" + ;; + esac + done # Gone through all deplibs. + ;; + none | unknown | *) + newdeplibs= + tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'` + if test yes = "$allow_libtool_libs_with_static_runtimes"; then + for i in $predeps $postdeps; do + # can't use Xsed below, because $i might contain '/' + tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s|$i||"` + done + fi + case $tmp_deplibs in + *[!\ \ ]*) + echo + if test none = "$deplibs_check_method"; then + echo "*** Warning: inter-library dependencies are not supported in this platform." + else + echo "*** Warning: inter-library dependencies are not known to be supported." + fi + echo "*** All declared inter-library dependencies are being dropped." + droppeddeps=yes + ;; + esac + ;; + esac + versuffix=$versuffix_save + major=$major_save + release=$release_save + libname=$libname_save + name=$name_save + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library with the System framework + newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'` + ;; + esac + + if test yes = "$droppeddeps"; then + if test yes = "$module"; then + echo + echo "*** Warning: libtool could not satisfy all declared inter-library" + $ECHO "*** dependencies of module $libname. Therefore, libtool will create" + echo "*** a static module, that should work as long as the dlopening" + echo "*** application is linked with the -dlopen flag." + if test -z "$global_symbol_pipe"; then + echo + echo "*** However, this would only work if libtool was able to extract symbol" + echo "*** lists from a program, using 'nm' or equivalent, but libtool could" + echo "*** not find such a program. So, this module is probably useless." + echo "*** 'nm' from GNU binutils and a full rebuild may help." + fi + if test no = "$build_old_libs"; then + oldlibs=$output_objdir/$libname.$libext + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + else + echo "*** The inter-library dependencies that have been dropped here will be" + echo "*** automatically added whenever a program is linked with this library" + echo "*** or is declared to -dlopen it." + + if test no = "$allow_undefined"; then + echo + echo "*** Since this library must not contain undefined symbols," + echo "*** because either the platform does not support them or" + echo "*** it was explicitly requested with -no-undefined," + echo "*** libtool will only create a static version of it." + if test no = "$build_old_libs"; then + oldlibs=$output_objdir/$libname.$libext + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + fi + fi + # Done checking deplibs! + deplibs=$newdeplibs + fi + # Time to change all our "foo.ltframework" stuff back to "-framework foo" + case $host in + *-*-darwin*) + newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + ;; + esac + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $deplibs " in + *" -L$path/$objdir "*) + func_append new_libs " -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) func_append new_libs " $deplib" ;; + esac + ;; + *) func_append new_libs " $deplib" ;; + esac + done + deplibs=$new_libs + + # All the library-specific variables (install_libdir is set above). + library_names= + old_library= + dlname= + + # Test again, we may have decided not to build it any more + if test yes = "$build_libtool_libs"; then + # Remove $wl instances when linking with ld. + # FIXME: should test the right _cmds variable. + case $archive_cmds in + *\$LD\ *) wl= ;; + esac + if test yes = "$hardcode_into_libs"; then + # Hardcode the library paths + hardcode_libdirs= + dep_rpath= + rpath=$finalize_rpath + test relink = "$opt_mode" || rpath=$compile_rpath$rpath + for libdir in $rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + func_replace_sysroot "$libdir" + libdir=$func_replace_sysroot_result + if test -z "$hardcode_libdirs"; then + hardcode_libdirs=$libdir + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append dep_rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) func_append perm_rpath " $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir=$hardcode_libdirs + eval "dep_rpath=\"$hardcode_libdir_flag_spec\"" + fi + if test -n "$runpath_var" && test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + func_append rpath "$dir:" + done + eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" + fi + test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" + fi + + shlibpath=$finalize_shlibpath + test relink = "$opt_mode" || shlibpath=$compile_shlibpath$shlibpath + if test -n "$shlibpath"; then + eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" + fi + + # Get the real and link names of the library. + eval shared_ext=\"$shrext_cmds\" + eval library_names=\"$library_names_spec\" + set dummy $library_names + shift + realname=$1 + shift + + if test -n "$soname_spec"; then + eval soname=\"$soname_spec\" + else + soname=$realname + fi + if test -z "$dlname"; then + dlname=$soname + fi + + lib=$output_objdir/$realname + linknames= + for link + do + func_append linknames " $link" + done + + # Use standard objects if they are pic + test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP` + test "X$libobjs" = "X " && libobjs= + + delfiles= + if test -n "$export_symbols" && test -n "$include_expsyms"; then + $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" + export_symbols=$output_objdir/$libname.uexp + func_append delfiles " $export_symbols" + fi + + orig_export_symbols= + case $host_os in + cygwin* | mingw* | cegcc*) + if test -n "$export_symbols" && test -z "$export_symbols_regex"; then + # exporting using user supplied symfile + func_dll_def_p "$export_symbols" || { + # and it's NOT already a .def file. Must figure out + # which of the given symbols are data symbols and tag + # them as such. So, trigger use of export_symbols_cmds. + # export_symbols gets reassigned inside the "prepare + # the list of exported symbols" if statement, so the + # include_expsyms logic still works. + orig_export_symbols=$export_symbols + export_symbols= + always_export_symbols=yes + } + fi + ;; + esac + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + if test yes = "$always_export_symbols" || test -n "$export_symbols_regex"; then + func_verbose "generating symbol list for '$libname.la'" + export_symbols=$output_objdir/$libname.exp + $opt_dry_run || $RM $export_symbols + cmds=$export_symbols_cmds + save_ifs=$IFS; IFS='~' + for cmd1 in $cmds; do + IFS=$save_ifs + # Take the normal branch if the nm_file_list_spec branch + # doesn't work or if tool conversion is not needed. + case $nm_file_list_spec~$to_tool_file_cmd in + *~func_convert_file_noop | *~func_convert_file_msys_to_w32 | ~*) + try_normal_branch=yes + eval cmd=\"$cmd1\" + func_len " $cmd" + len=$func_len_result + ;; + *) + try_normal_branch=no + ;; + esac + if test yes = "$try_normal_branch" \ + && { test "$len" -lt "$max_cmd_len" \ + || test "$max_cmd_len" -le -1; } + then + func_show_eval "$cmd" 'exit $?' + skipped_export=false + elif test -n "$nm_file_list_spec"; then + func_basename "$output" + output_la=$func_basename_result + save_libobjs=$libobjs + save_output=$output + output=$output_objdir/$output_la.nm + func_to_tool_file "$output" + libobjs=$nm_file_list_spec$func_to_tool_file_result + func_append delfiles " $output" + func_verbose "creating $NM input file list: $output" + for obj in $save_libobjs; do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" + done > "$output" + eval cmd=\"$cmd1\" + func_show_eval "$cmd" 'exit $?' + output=$save_output + libobjs=$save_libobjs + skipped_export=false + else + # The command line is too long to execute in one step. + func_verbose "using reloadable object file for export list..." + skipped_export=: + # Break out early, otherwise skipped_export may be + # set to false by a later but shorter cmd. + break + fi + done + IFS=$save_ifs + if test -n "$export_symbols_regex" && test : != "$skipped_export"; then + func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + func_show_eval '$MV "${export_symbols}T" "$export_symbols"' + fi + fi + fi + + if test -n "$export_symbols" && test -n "$include_expsyms"; then + tmp_export_symbols=$export_symbols + test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols + $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' + fi + + if test : != "$skipped_export" && test -n "$orig_export_symbols"; then + # The given exports_symbols file has to be filtered, so filter it. + func_verbose "filter symbol list for '$libname.la' to tag DATA exports" + # FIXME: $output_objdir/$libname.filter potentially contains lots of + # 's' commands, which not all seds can handle. GNU sed should be fine + # though. Also, the filter scales superlinearly with the number of + # global variables. join(1) would be nice here, but unfortunately + # isn't a blessed tool. + $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter + func_append delfiles " $export_symbols $output_objdir/$libname.filter" + export_symbols=$output_objdir/$libname.def + $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols + fi + + tmp_deplibs= + for test_deplib in $deplibs; do + case " $convenience " in + *" $test_deplib "*) ;; + *) + func_append tmp_deplibs " $test_deplib" + ;; + esac + done + deplibs=$tmp_deplibs + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec" && + test yes = "$compiler_needs_object" && + test -z "$libobjs"; then + # extract the archives, so we have objects to list. + # TODO: could optimize this to just extract one archive. + whole_archive_flag_spec= + fi + if test -n "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + test "X$libobjs" = "X " && libobjs= + else + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $convenience + func_append libobjs " $func_extract_archives_result" + test "X$libobjs" = "X " && libobjs= + fi + fi + + if test yes = "$thread_safe" && test -n "$thread_safe_flag_spec"; then + eval flag=\"$thread_safe_flag_spec\" + func_append linker_flags " $flag" + fi + + # Make a backup of the uninstalled library when relinking + if test relink = "$opt_mode"; then + $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? + fi + + # Do each of the archive commands. + if test yes = "$module" && test -n "$module_cmds"; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + eval test_cmds=\"$module_expsym_cmds\" + cmds=$module_expsym_cmds + else + eval test_cmds=\"$module_cmds\" + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + eval test_cmds=\"$archive_expsym_cmds\" + cmds=$archive_expsym_cmds + else + eval test_cmds=\"$archive_cmds\" + cmds=$archive_cmds + fi + fi + + if test : != "$skipped_export" && + func_len " $test_cmds" && + len=$func_len_result && + test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + : + else + # The command line is too long to link in one step, link piecewise + # or, if using GNU ld and skipped_export is not :, use a linker + # script. + + # Save the value of $output and $libobjs because we want to + # use them later. If we have whole_archive_flag_spec, we + # want to use save_libobjs as it was before + # whole_archive_flag_spec was expanded, because we can't + # assume the linker understands whole_archive_flag_spec. + # This may have to be revisited, in case too many + # convenience libraries get linked in and end up exceeding + # the spec. + if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + fi + save_output=$output + func_basename "$output" + output_la=$func_basename_result + + # Clear the reloadable object creation command queue and + # initialize k to one. + test_cmds= + concat_cmds= + objlist= + last_robj= + k=1 + + if test -n "$save_libobjs" && test : != "$skipped_export" && test yes = "$with_gnu_ld"; then + output=$output_objdir/$output_la.lnkscript + func_verbose "creating GNU ld script: $output" + echo 'INPUT (' > $output + for obj in $save_libobjs + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" >> $output + done + echo ')' >> $output + func_append delfiles " $output" + func_to_tool_file "$output" + output=$func_to_tool_file_result + elif test -n "$save_libobjs" && test : != "$skipped_export" && test -n "$file_list_spec"; then + output=$output_objdir/$output_la.lnk + func_verbose "creating linker input file list: $output" + : > $output + set x $save_libobjs + shift + firstobj= + if test yes = "$compiler_needs_object"; then + firstobj="$1 " + shift + fi + for obj + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" >> $output + done + func_append delfiles " $output" + func_to_tool_file "$output" + output=$firstobj\"$file_list_spec$func_to_tool_file_result\" + else + if test -n "$save_libobjs"; then + func_verbose "creating reloadable object files..." + output=$output_objdir/$output_la-$k.$objext + eval test_cmds=\"$reload_cmds\" + func_len " $test_cmds" + len0=$func_len_result + len=$len0 + + # Loop over the list of objects to be linked. + for obj in $save_libobjs + do + func_len " $obj" + func_arith $len + $func_len_result + len=$func_arith_result + if test -z "$objlist" || + test "$len" -lt "$max_cmd_len"; then + func_append objlist " $obj" + else + # The command $test_cmds is almost too long, add a + # command to the queue. + if test 1 -eq "$k"; then + # The first file doesn't have a previous command to add. + reload_objs=$objlist + eval concat_cmds=\"$reload_cmds\" + else + # All subsequent reloadable object files will link in + # the last one created. + reload_objs="$objlist $last_robj" + eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\" + fi + last_robj=$output_objdir/$output_la-$k.$objext + func_arith $k + 1 + k=$func_arith_result + output=$output_objdir/$output_la-$k.$objext + objlist=" $obj" + func_len " $last_robj" + func_arith $len0 + $func_len_result + len=$func_arith_result + fi + done + # Handle the remaining objects by creating one last + # reloadable object file. All subsequent reloadable object + # files will link in the last one created. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + reload_objs="$objlist $last_robj" + eval concat_cmds=\"\$concat_cmds$reload_cmds\" + if test -n "$last_robj"; then + eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" + fi + func_append delfiles " $output" + + else + output= + fi + + ${skipped_export-false} && { + func_verbose "generating symbol list for '$libname.la'" + export_symbols=$output_objdir/$libname.exp + $opt_dry_run || $RM $export_symbols + libobjs=$output + # Append the command to create the export file. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\" + if test -n "$last_robj"; then + eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" + fi + } + + test -n "$save_libobjs" && + func_verbose "creating a temporary reloadable object file: $output" + + # Loop through the commands generated above and execute them. + save_ifs=$IFS; IFS='~' + for cmd in $concat_cmds; do + IFS=$save_ifs + $opt_quiet || { + func_quote_for_expand "$cmd" + eval "func_echo $func_quote_for_expand_result" + } + $opt_dry_run || eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test relink = "$opt_mode"; then + ( cd "$output_objdir" && \ + $RM "${realname}T" && \ + $MV "${realname}U" "$realname" ) + fi + + exit $lt_exit + } + done + IFS=$save_ifs + + if test -n "$export_symbols_regex" && ${skipped_export-false}; then + func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + func_show_eval '$MV "${export_symbols}T" "$export_symbols"' + fi + fi + + ${skipped_export-false} && { + if test -n "$export_symbols" && test -n "$include_expsyms"; then + tmp_export_symbols=$export_symbols + test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols + $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' + fi + + if test -n "$orig_export_symbols"; then + # The given exports_symbols file has to be filtered, so filter it. + func_verbose "filter symbol list for '$libname.la' to tag DATA exports" + # FIXME: $output_objdir/$libname.filter potentially contains lots of + # 's' commands, which not all seds can handle. GNU sed should be fine + # though. Also, the filter scales superlinearly with the number of + # global variables. join(1) would be nice here, but unfortunately + # isn't a blessed tool. + $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter + func_append delfiles " $export_symbols $output_objdir/$libname.filter" + export_symbols=$output_objdir/$libname.def + $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols + fi + } + + libobjs=$output + # Restore the value of output. + output=$save_output + + if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + test "X$libobjs" = "X " && libobjs= + fi + # Expand the library linking commands again to reset the + # value of $libobjs for piecewise linking. + + # Do each of the archive commands. + if test yes = "$module" && test -n "$module_cmds"; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + cmds=$module_expsym_cmds + else + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + cmds=$archive_expsym_cmds + else + cmds=$archive_cmds + fi + fi + fi + + if test -n "$delfiles"; then + # Append the command to remove temporary files to $cmds. + eval cmds=\"\$cmds~\$RM $delfiles\" + fi + + # Add any objects from preloaded convenience libraries + if test -n "$dlprefiles"; then + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $dlprefiles + func_append libobjs " $func_extract_archives_result" + test "X$libobjs" = "X " && libobjs= + fi + + save_ifs=$IFS; IFS='~' + for cmd in $cmds; do + IFS=$sp$nl + eval cmd=\"$cmd\" + IFS=$save_ifs + $opt_quiet || { + func_quote_for_expand "$cmd" + eval "func_echo $func_quote_for_expand_result" + } + $opt_dry_run || eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test relink = "$opt_mode"; then + ( cd "$output_objdir" && \ + $RM "${realname}T" && \ + $MV "${realname}U" "$realname" ) + fi + + exit $lt_exit + } + done + IFS=$save_ifs + + # Restore the uninstalled library and exit + if test relink = "$opt_mode"; then + $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $? + + if test -n "$convenience"; then + if test -z "$whole_archive_flag_spec"; then + func_show_eval '${RM}r "$gentop"' + fi + fi + + exit $EXIT_SUCCESS + fi + + # Create links to the real library. + for linkname in $linknames; do + if test "$realname" != "$linkname"; then + func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?' + fi + done + + # If -module or -export-dynamic was specified, set the dlname. + if test yes = "$module" || test yes = "$export_dynamic"; then + # On all known operating systems, these are identical. + dlname=$soname + fi + fi + ;; + + obj) + if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then + func_warning "'-dlopen' is ignored for objects" + fi + + case " $deplibs" in + *\ -l* | *\ -L*) + func_warning "'-l' and '-L' are ignored for objects" ;; + esac + + test -n "$rpath" && \ + func_warning "'-rpath' is ignored for objects" + + test -n "$xrpath" && \ + func_warning "'-R' is ignored for objects" + + test -n "$vinfo" && \ + func_warning "'-version-info' is ignored for objects" + + test -n "$release" && \ + func_warning "'-release' is ignored for objects" + + case $output in + *.lo) + test -n "$objs$old_deplibs" && \ + func_fatal_error "cannot build library object '$output' from non-libtool objects" + + libobj=$output + func_lo2o "$libobj" + obj=$func_lo2o_result + ;; + *) + libobj= + obj=$output + ;; + esac + + # Delete the old objects. + $opt_dry_run || $RM $obj $libobj + + # Objects from convenience libraries. This assumes + # single-version convenience libraries. Whenever we create + # different ones for PIC/non-PIC, this we'll have to duplicate + # the extraction. + reload_conv_objs= + gentop= + # if reload_cmds runs $LD directly, get rid of -Wl from + # whole_archive_flag_spec and hope we can get by with turning comma + # into space. + case $reload_cmds in + *\$LD[\ \$]*) wl= ;; + esac + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec"; then + eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" + test -n "$wl" || tmp_whole_archive_flags=`$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'` + reload_conv_objs=$reload_objs\ $tmp_whole_archive_flags + else + gentop=$output_objdir/${obj}x + func_append generated " $gentop" + + func_extract_archives $gentop $convenience + reload_conv_objs="$reload_objs $func_extract_archives_result" + fi + fi + + # If we're not building shared, we need to use non_pic_objs + test yes = "$build_libtool_libs" || libobjs=$non_pic_objects + + # Create the old-style object. + reload_objs=$objs$old_deplibs' '`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; /\.lib$/d; $lo2o" | $NL2SP`' '$reload_conv_objs + + output=$obj + func_execute_cmds "$reload_cmds" 'exit $?' + + # Exit if we aren't doing a library object file. + if test -z "$libobj"; then + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + exit $EXIT_SUCCESS + fi + + test yes = "$build_libtool_libs" || { + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + # Create an invalid libtool object if no PIC, so that we don't + # accidentally link it into a program. + # $show "echo timestamp > $libobj" + # $opt_dry_run || eval "echo timestamp > $libobj" || exit $? + exit $EXIT_SUCCESS + } + + if test -n "$pic_flag" || test default != "$pic_mode"; then + # Only do commands if we really have different PIC objects. + reload_objs="$libobjs $reload_conv_objs" + output=$libobj + func_execute_cmds "$reload_cmds" 'exit $?' + fi + + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + exit $EXIT_SUCCESS + ;; + + prog) + case $host in + *cygwin*) func_stripname '' '.exe' "$output" + output=$func_stripname_result.exe;; + esac + test -n "$vinfo" && \ + func_warning "'-version-info' is ignored for programs" + + test -n "$release" && \ + func_warning "'-release' is ignored for programs" + + $preload \ + && test unknown,unknown,unknown = "$dlopen_support,$dlopen_self,$dlopen_self_static" \ + && func_warning "'LT_INIT([dlopen])' not used. Assuming no dlopen support." + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library is the System framework + compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'` + finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'` + ;; + esac + + case $host in + *-*-darwin*) + # Don't allow lazy linking, it breaks C++ global constructors + # But is supposedly fixed on 10.4 or later (yay!). + if test CXX = "$tagname"; then + case ${MACOSX_DEPLOYMENT_TARGET-10.0} in + 10.[0123]) + func_append compile_command " $wl-bind_at_load" + func_append finalize_command " $wl-bind_at_load" + ;; + esac + fi + # Time to change all our "foo.ltframework" stuff back to "-framework foo" + compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + ;; + esac + + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $compile_deplibs " in + *" -L$path/$objdir "*) + func_append new_libs " -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $compile_deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) func_append new_libs " $deplib" ;; + esac + ;; + *) func_append new_libs " $deplib" ;; + esac + done + compile_deplibs=$new_libs + + + func_append compile_command " $compile_deplibs" + func_append finalize_command " $finalize_deplibs" + + if test -n "$rpath$xrpath"; then + # If the user specified any rpath flags, then add them. + for libdir in $rpath $xrpath; do + # This is the magic to use -rpath. + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + done + fi + + # Now hardcode the library paths + rpath= + hardcode_libdirs= + for libdir in $compile_rpath $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs=$libdir + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) func_append perm_rpath " $libdir" ;; + esac + fi + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + testbindir=`$ECHO "$libdir" | $SED -e 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$libdir:"*) ;; + ::) dllsearchpath=$libdir;; + *) func_append dllsearchpath ":$libdir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + ::) dllsearchpath=$testbindir;; + *) func_append dllsearchpath ":$testbindir";; + esac + ;; + esac + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir=$hardcode_libdirs + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + compile_rpath=$rpath + + rpath= + hardcode_libdirs= + for libdir in $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs=$libdir + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$finalize_perm_rpath " in + *" $libdir "*) ;; + *) func_append finalize_perm_rpath " $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir=$hardcode_libdirs + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + finalize_rpath=$rpath + + if test -n "$libobjs" && test yes = "$build_old_libs"; then + # Transform all the library objects into standard objects. + compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP` + finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP` + fi + + func_generate_dlsyms "$outputname" "@PROGRAM@" false + + # template prelinking step + if test -n "$prelink_cmds"; then + func_execute_cmds "$prelink_cmds" 'exit $?' + fi + + wrappers_required=: + case $host in + *cegcc* | *mingw32ce*) + # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway. + wrappers_required=false + ;; + *cygwin* | *mingw* ) + test yes = "$build_libtool_libs" || wrappers_required=false + ;; + *) + if test no = "$need_relink" || test yes != "$build_libtool_libs"; then + wrappers_required=false + fi + ;; + esac + $wrappers_required || { + # Replace the output file specification. + compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'` + link_command=$compile_command$compile_rpath + + # We have no uninstalled library dependencies, so finalize right now. + exit_status=0 + func_show_eval "$link_command" 'exit_status=$?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + # Delete the generated files. + if test -f "$output_objdir/${outputname}S.$objext"; then + func_show_eval '$RM "$output_objdir/${outputname}S.$objext"' + fi + + exit $exit_status + } + + if test -n "$compile_shlibpath$finalize_shlibpath"; then + compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" + fi + if test -n "$finalize_shlibpath"; then + finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" + fi + + compile_var= + finalize_var= + if test -n "$runpath_var"; then + if test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + func_append rpath "$dir:" + done + compile_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + if test -n "$finalize_perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $finalize_perm_rpath; do + func_append rpath "$dir:" + done + finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + fi + + if test yes = "$no_install"; then + # We don't need to create a wrapper script. + link_command=$compile_var$compile_command$compile_rpath + # Replace the output file specification. + link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'` + # Delete the old output file. + $opt_dry_run || $RM $output + # Link the executable and exit + func_show_eval "$link_command" 'exit $?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + exit $EXIT_SUCCESS + fi + + case $hardcode_action,$fast_install in + relink,*) + # Fast installation is not supported + link_command=$compile_var$compile_command$compile_rpath + relink_command=$finalize_var$finalize_command$finalize_rpath + + func_warning "this platform does not like uninstalled shared libraries" + func_warning "'$output' will be relinked during installation" + ;; + *,yes) + link_command=$finalize_var$compile_command$finalize_rpath + relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'` + ;; + *,no) + link_command=$compile_var$compile_command$compile_rpath + relink_command=$finalize_var$finalize_command$finalize_rpath + ;; + *,needless) + link_command=$finalize_var$compile_command$finalize_rpath + relink_command= + ;; + esac + + # Replace the output file specification. + link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` + + # Delete the old output files. + $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname + + func_show_eval "$link_command" 'exit $?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output_objdir/$outputname" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + # Now create the wrapper script. + func_verbose "creating $output" + + # Quote the relink command for shipping. + if test -n "$relink_command"; then + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + func_quote_for_eval "$var_value" + relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" + fi + done + relink_command="(cd `pwd`; $relink_command)" + relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` + fi + + # Only actually do things if not in dry run mode. + $opt_dry_run || { + # win32 will think the script is a binary if it has + # a .exe suffix, so we strip it off here. + case $output in + *.exe) func_stripname '' '.exe' "$output" + output=$func_stripname_result ;; + esac + # test for cygwin because mv fails w/o .exe extensions + case $host in + *cygwin*) + exeext=.exe + func_stripname '' '.exe' "$outputname" + outputname=$func_stripname_result ;; + *) exeext= ;; + esac + case $host in + *cygwin* | *mingw* ) + func_dirname_and_basename "$output" "" "." + output_name=$func_basename_result + output_path=$func_dirname_result + cwrappersource=$output_path/$objdir/lt-$output_name.c + cwrapper=$output_path/$output_name.exe + $RM $cwrappersource $cwrapper + trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 + + func_emit_cwrapperexe_src > $cwrappersource + + # The wrapper executable is built using the $host compiler, + # because it contains $host paths and files. If cross- + # compiling, it, like the target executable, must be + # executed on the $host or under an emulation environment. + $opt_dry_run || { + $LTCC $LTCFLAGS -o $cwrapper $cwrappersource + $STRIP $cwrapper + } + + # Now, create the wrapper script for func_source use: + func_ltwrapper_scriptname $cwrapper + $RM $func_ltwrapper_scriptname_result + trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 + $opt_dry_run || { + # note: this script will not be executed, so do not chmod. + if test "x$build" = "x$host"; then + $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result + else + func_emit_wrapper no > $func_ltwrapper_scriptname_result + fi + } + ;; + * ) + $RM $output + trap "$RM $output; exit $EXIT_FAILURE" 1 2 15 + + func_emit_wrapper no > $output + chmod +x $output + ;; + esac + } + exit $EXIT_SUCCESS + ;; + esac + + # See if we need to build an old-fashioned archive. + for oldlib in $oldlibs; do + + case $build_libtool_libs in + convenience) + oldobjs="$libobjs_save $symfileobj" + addlibs=$convenience + build_libtool_libs=no + ;; + module) + oldobjs=$libobjs_save + addlibs=$old_convenience + build_libtool_libs=no + ;; + *) + oldobjs="$old_deplibs $non_pic_objects" + $preload && test -f "$symfileobj" \ + && func_append oldobjs " $symfileobj" + addlibs=$old_convenience + ;; + esac + + if test -n "$addlibs"; then + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $addlibs + func_append oldobjs " $func_extract_archives_result" + fi + + # Do each command in the archive commands. + if test -n "$old_archive_from_new_cmds" && test yes = "$build_libtool_libs"; then + cmds=$old_archive_from_new_cmds + else + + # Add any objects from preloaded convenience libraries + if test -n "$dlprefiles"; then + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $dlprefiles + func_append oldobjs " $func_extract_archives_result" + fi + + # POSIX demands no paths to be encoded in archives. We have + # to avoid creating archives with duplicate basenames if we + # might have to extract them afterwards, e.g., when creating a + # static archive out of a convenience library, or when linking + # the entirety of a libtool archive into another (currently + # not supported by libtool). + if (for obj in $oldobjs + do + func_basename "$obj" + $ECHO "$func_basename_result" + done | sort | sort -uc >/dev/null 2>&1); then + : + else + echo "copying selected object files to avoid basename conflicts..." + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + func_mkdir_p "$gentop" + save_oldobjs=$oldobjs + oldobjs= + counter=1 + for obj in $save_oldobjs + do + func_basename "$obj" + objbase=$func_basename_result + case " $oldobjs " in + " ") oldobjs=$obj ;; + *[\ /]"$objbase "*) + while :; do + # Make sure we don't pick an alternate name that also + # overlaps. + newobj=lt$counter-$objbase + func_arith $counter + 1 + counter=$func_arith_result + case " $oldobjs " in + *[\ /]"$newobj "*) ;; + *) if test ! -f "$gentop/$newobj"; then break; fi ;; + esac + done + func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" + func_append oldobjs " $gentop/$newobj" + ;; + *) func_append oldobjs " $obj" ;; + esac + done + fi + func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 + tool_oldlib=$func_to_tool_file_result + eval cmds=\"$old_archive_cmds\" + + func_len " $cmds" + len=$func_len_result + if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + cmds=$old_archive_cmds + elif test -n "$archiver_list_spec"; then + func_verbose "using command file archive linking..." + for obj in $oldobjs + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" + done > $output_objdir/$libname.libcmd + func_to_tool_file "$output_objdir/$libname.libcmd" + oldobjs=" $archiver_list_spec$func_to_tool_file_result" + cmds=$old_archive_cmds + else + # the command line is too long to link in one step, link in parts + func_verbose "using piecewise archive linking..." + save_RANLIB=$RANLIB + RANLIB=: + objlist= + concat_cmds= + save_oldobjs=$oldobjs + oldobjs= + # Is there a better way of finding the last object in the list? + for obj in $save_oldobjs + do + last_oldobj=$obj + done + eval test_cmds=\"$old_archive_cmds\" + func_len " $test_cmds" + len0=$func_len_result + len=$len0 + for obj in $save_oldobjs + do + func_len " $obj" + func_arith $len + $func_len_result + len=$func_arith_result + func_append objlist " $obj" + if test "$len" -lt "$max_cmd_len"; then + : + else + # the above command should be used before it gets too long + oldobjs=$objlist + if test "$obj" = "$last_oldobj"; then + RANLIB=$save_RANLIB + fi + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\$concat_cmds$old_archive_cmds\" + objlist= + len=$len0 + fi + done + RANLIB=$save_RANLIB + oldobjs=$objlist + if test -z "$oldobjs"; then + eval cmds=\"\$concat_cmds\" + else + eval cmds=\"\$concat_cmds~\$old_archive_cmds\" + fi + fi + fi + func_execute_cmds "$cmds" 'exit $?' + done + + test -n "$generated" && \ + func_show_eval "${RM}r$generated" + + # Now create the libtool archive. + case $output in + *.la) + old_library= + test yes = "$build_old_libs" && old_library=$libname.$libext + func_verbose "creating $output" + + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + func_quote_for_eval "$var_value" + relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" + fi + done + # Quote the link command for shipping. + relink_command="(cd `pwd`; $SHELL \"$progpath\" $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" + relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` + if test yes = "$hardcode_automatic"; then + relink_command= + fi + + # Only create the output if not a dry run. + $opt_dry_run || { + for installed in no yes; do + if test yes = "$installed"; then + if test -z "$install_libdir"; then + break + fi + output=$output_objdir/${outputname}i + # Replace all uninstalled libtool libraries with the installed ones + newdependency_libs= + for deplib in $dependency_libs; do + case $deplib in + *.la) + func_basename "$deplib" + name=$func_basename_result + func_resolve_sysroot "$deplib" + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $func_resolve_sysroot_result` + test -z "$libdir" && \ + func_fatal_error "'$deplib' is not a valid libtool archive" + func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name" + ;; + -L*) + func_stripname -L '' "$deplib" + func_replace_sysroot "$func_stripname_result" + func_append newdependency_libs " -L$func_replace_sysroot_result" + ;; + -R*) + func_stripname -R '' "$deplib" + func_replace_sysroot "$func_stripname_result" + func_append newdependency_libs " -R$func_replace_sysroot_result" + ;; + *) func_append newdependency_libs " $deplib" ;; + esac + done + dependency_libs=$newdependency_libs + newdlfiles= + + for lib in $dlfiles; do + case $lib in + *.la) + func_basename "$lib" + name=$func_basename_result + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + test -z "$libdir" && \ + func_fatal_error "'$lib' is not a valid libtool archive" + func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name" + ;; + *) func_append newdlfiles " $lib" ;; + esac + done + dlfiles=$newdlfiles + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + *.la) + # Only pass preopened files to the pseudo-archive (for + # eventual linking with the app. that links it) if we + # didn't already link the preopened objects directly into + # the library: + func_basename "$lib" + name=$func_basename_result + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + test -z "$libdir" && \ + func_fatal_error "'$lib' is not a valid libtool archive" + func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name" + ;; + esac + done + dlprefiles=$newdlprefiles + else + newdlfiles= + for lib in $dlfiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; + *) abs=`pwd`"/$lib" ;; + esac + func_append newdlfiles " $abs" + done + dlfiles=$newdlfiles + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; + *) abs=`pwd`"/$lib" ;; + esac + func_append newdlprefiles " $abs" + done + dlprefiles=$newdlprefiles + fi + $RM $output + # place dlname in correct position for cygwin + # In fact, it would be nice if we could use this code for all target + # systems that can't hard-code library paths into their executables + # and that have no shared library path variable independent of PATH, + # but it turns out we can't easily determine that from inspecting + # libtool variables, so we have to hard-code the OSs to which it + # applies here; at the moment, that means platforms that use the PE + # object format with DLL files. See the long comment at the top of + # tests/bindir.at for full details. + tdlname=$dlname + case $host,$output,$installed,$module,$dlname in + *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) + # If a -bindir argument was supplied, place the dll there. + if test -n "$bindir"; then + func_relative_path "$install_libdir" "$bindir" + tdlname=$func_relative_path_result/$dlname + else + # Otherwise fall back on heuristic. + tdlname=../bin/$dlname + fi + ;; + esac + $ECHO > $output "\ +# $outputname - a libtool library file +# Generated by $PROGRAM (GNU $PACKAGE) $VERSION +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='$tdlname' + +# Names of this library. +library_names='$library_names' + +# The name of the static archive. +old_library='$old_library' + +# Linker flags that cannot go in dependency_libs. +inherited_linker_flags='$new_inherited_linker_flags' + +# Libraries that this one depends upon. +dependency_libs='$dependency_libs' + +# Names of additional weak libraries provided by this library +weak_library_names='$weak_libs' + +# Version information for $libname. +current=$current +age=$age +revision=$revision + +# Is this an already installed library? +installed=$installed + +# Should we warn about portability when linking against -modules? +shouldnotlink=$module + +# Files to dlopen/dlpreopen +dlopen='$dlfiles' +dlpreopen='$dlprefiles' + +# Directory that this library needs to be installed in: +libdir='$install_libdir'" + if test no,yes = "$installed,$need_relink"; then + $ECHO >> $output "\ +relink_command=\"$relink_command\"" + fi + done + } + + # Do a symbolic link so that the libtool archive can be found in + # LD_LIBRARY_PATH before the program is installed. + func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?' + ;; + esac + exit $EXIT_SUCCESS +} + +if test link = "$opt_mode" || test relink = "$opt_mode"; then + func_mode_link ${1+"$@"} +fi + + +# func_mode_uninstall arg... +func_mode_uninstall () +{ + $debug_cmd + + RM=$nonopt + files= + rmforce=false + exit_status=0 + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic=$magic + + for arg + do + case $arg in + -f) func_append RM " $arg"; rmforce=: ;; + -*) func_append RM " $arg" ;; + *) func_append files " $arg" ;; + esac + done + + test -z "$RM" && \ + func_fatal_help "you must specify an RM program" + + rmdirs= + + for file in $files; do + func_dirname "$file" "" "." + dir=$func_dirname_result + if test . = "$dir"; then + odir=$objdir + else + odir=$dir/$objdir + fi + func_basename "$file" + name=$func_basename_result + test uninstall = "$opt_mode" && odir=$dir + + # Remember odir for removal later, being careful to avoid duplicates + if test clean = "$opt_mode"; then + case " $rmdirs " in + *" $odir "*) ;; + *) func_append rmdirs " $odir" ;; + esac + fi + + # Don't error if the file doesn't exist and rm -f was used. + if { test -L "$file"; } >/dev/null 2>&1 || + { test -h "$file"; } >/dev/null 2>&1 || + test -f "$file"; then + : + elif test -d "$file"; then + exit_status=1 + continue + elif $rmforce; then + continue + fi + + rmfiles=$file + + case $name in + *.la) + # Possibly a libtool archive, so verify it. + if func_lalib_p "$file"; then + func_source $dir/$name + + # Delete the libtool libraries and symlinks. + for n in $library_names; do + func_append rmfiles " $odir/$n" + done + test -n "$old_library" && func_append rmfiles " $odir/$old_library" + + case $opt_mode in + clean) + case " $library_names " in + *" $dlname "*) ;; + *) test -n "$dlname" && func_append rmfiles " $odir/$dlname" ;; + esac + test -n "$libdir" && func_append rmfiles " $odir/$name $odir/${name}i" + ;; + uninstall) + if test -n "$library_names"; then + # Do each command in the postuninstall commands. + func_execute_cmds "$postuninstall_cmds" '$rmforce || exit_status=1' + fi + + if test -n "$old_library"; then + # Do each command in the old_postuninstall commands. + func_execute_cmds "$old_postuninstall_cmds" '$rmforce || exit_status=1' + fi + # FIXME: should reinstall the best remaining shared library. + ;; + esac + fi + ;; + + *.lo) + # Possibly a libtool object, so verify it. + if func_lalib_p "$file"; then + + # Read the .lo file + func_source $dir/$name + + # Add PIC object to the list of files to remove. + if test -n "$pic_object" && test none != "$pic_object"; then + func_append rmfiles " $dir/$pic_object" + fi + + # Add non-PIC object to the list of files to remove. + if test -n "$non_pic_object" && test none != "$non_pic_object"; then + func_append rmfiles " $dir/$non_pic_object" + fi + fi + ;; + + *) + if test clean = "$opt_mode"; then + noexename=$name + case $file in + *.exe) + func_stripname '' '.exe' "$file" + file=$func_stripname_result + func_stripname '' '.exe' "$name" + noexename=$func_stripname_result + # $file with .exe has already been added to rmfiles, + # add $file without .exe + func_append rmfiles " $file" + ;; + esac + # Do a test to see if this is a libtool program. + if func_ltwrapper_p "$file"; then + if func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + relink_command= + func_source $func_ltwrapper_scriptname_result + func_append rmfiles " $func_ltwrapper_scriptname_result" + else + relink_command= + func_source $dir/$noexename + fi + + # note $name still contains .exe if it was in $file originally + # as does the version of $file that was added into $rmfiles + func_append rmfiles " $odir/$name $odir/${name}S.$objext" + if test yes = "$fast_install" && test -n "$relink_command"; then + func_append rmfiles " $odir/lt-$name" + fi + if test "X$noexename" != "X$name"; then + func_append rmfiles " $odir/lt-$noexename.c" + fi + fi + fi + ;; + esac + func_show_eval "$RM $rmfiles" 'exit_status=1' + done + + # Try to remove the $objdir's in the directories where we deleted files + for dir in $rmdirs; do + if test -d "$dir"; then + func_show_eval "rmdir $dir >/dev/null 2>&1" + fi + done + + exit $exit_status +} + +if test uninstall = "$opt_mode" || test clean = "$opt_mode"; then + func_mode_uninstall ${1+"$@"} +fi + +test -z "$opt_mode" && { + help=$generic_help + func_fatal_help "you must specify a MODE" +} + +test -z "$exec_cmd" && \ + func_fatal_help "invalid operation mode '$opt_mode'" + +if test -n "$exec_cmd"; then + eval exec "$exec_cmd" + exit $EXIT_FAILURE +fi + +exit $exit_status + + +# The TAGs below are defined such that we never get into a situation +# where we disable both kinds of libraries. Given conflicting +# choices, we go for a static library, that is the most portable, +# since we can't tell whether shared libraries were disabled because +# the user asked for that or because the platform doesn't support +# them. This is particularly important on AIX, because we don't +# support having both static and shared libraries enabled at the same +# time on that platform, so we default to a shared-only configuration. +# If a disable-shared tag is given, we'll fallback to a static-only +# configuration. But we'll never go from static-only to shared-only. + +# ### BEGIN LIBTOOL TAG CONFIG: disable-shared +build_libtool_libs=no +build_old_libs=yes +# ### END LIBTOOL TAG CONFIG: disable-shared + +# ### BEGIN LIBTOOL TAG CONFIG: disable-static +build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` +# ### END LIBTOOL TAG CONFIG: disable-static + +# Local Variables: +# mode:shell-script +# sh-indentation:2 +# End: diff --git a/m4/ax_code_coverage.m4 b/m4/ax_code_coverage.m4 new file mode 100644 index 0000000..93dfce3 --- /dev/null +++ b/m4/ax_code_coverage.m4 @@ -0,0 +1,274 @@ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_code_coverage.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_CODE_COVERAGE() +# +# DESCRIPTION +# +# Defines CODE_COVERAGE_CPPFLAGS, CODE_COVERAGE_CFLAGS, +# CODE_COVERAGE_CXXFLAGS and CODE_COVERAGE_LDFLAGS which should be +# included in the CPPFLAGS, CFLAGS CXXFLAGS and LIBS/LDFLAGS variables of +# every build target (program or library) which should be built with code +# coverage support. Also defines CODE_COVERAGE_RULES which should be +# substituted in your Makefile; and $enable_code_coverage which can be +# used in subsequent configure output. CODE_COVERAGE_ENABLED is defined +# and substituted, and corresponds to the value of the +# --enable-code-coverage option, which defaults to being disabled. +# +# Test also for gcov program and create GCOV variable that could be +# substituted. +# +# Note that all optimisation flags in CFLAGS must be disabled when code +# coverage is enabled. +# +# Usage example: +# +# configure.ac: +# +# AX_CODE_COVERAGE +# +# Makefile.am: +# +# @CODE_COVERAGE_RULES@ +# my_program_LIBS = ... $(CODE_COVERAGE_LDFLAGS) ... +# my_program_CPPFLAGS = ... $(CODE_COVERAGE_CPPFLAGS) ... +# my_program_CFLAGS = ... $(CODE_COVERAGE_CFLAGS) ... +# my_program_CXXFLAGS = ... $(CODE_COVERAGE_CXXFLAGS) ... +# +# This results in a "check-code-coverage" rule being added to any +# Makefile.am which includes "@CODE_COVERAGE_RULES@" (assuming the module +# has been configured with --enable-code-coverage). Running `make +# check-code-coverage` in that directory will run the module's test suite +# (`make check`) and build a code coverage report detailing the code which +# was touched, then print the URI for the report. +# +# This code was derived from Makefile.decl in GLib, originally licenced +# under LGPLv2.1+. +# +# LICENSE +# +# Copyright (c) 2012, 2016 Philip Withnall +# Copyright (c) 2012 Xan Lopez +# Copyright (c) 2012 Christian Persch +# Copyright (c) 2012 Paolo Borelli +# Copyright (c) 2012 Dan Winship +# Copyright (c) 2015 Bastien ROUCARIES +# +# 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 program. If not, see . + +#serial 16 + +AC_DEFUN([AX_CODE_COVERAGE],[ + dnl Check for --enable-code-coverage + AC_REQUIRE([AC_PROG_SED]) + + # allow to override gcov location + AC_ARG_WITH([gcov], + [AS_HELP_STRING([--with-gcov[=GCOV]], [use given GCOV for coverage (GCOV=gcov).])], + [_AX_CODE_COVERAGE_GCOV_PROG_WITH=$with_gcov], + [_AX_CODE_COVERAGE_GCOV_PROG_WITH=gcov]) + + AC_MSG_CHECKING([whether to build with code coverage support]) + AC_ARG_ENABLE([code-coverage], + AS_HELP_STRING([--enable-code-coverage], + [Whether to enable code coverage support]),, + enable_code_coverage=no) + + AM_CONDITIONAL([CODE_COVERAGE_ENABLED], [test x$enable_code_coverage = xyes]) + AC_SUBST([CODE_COVERAGE_ENABLED], [$enable_code_coverage]) + AC_MSG_RESULT($enable_code_coverage) + + AS_IF([ test "$enable_code_coverage" = "yes" ], [ + # check for gcov + AC_CHECK_TOOL([GCOV], + [$_AX_CODE_COVERAGE_GCOV_PROG_WITH], + [:]) + AS_IF([test "X$GCOV" = "X:"], + [AC_MSG_ERROR([gcov is needed to do coverage])]) + AC_SUBST([GCOV]) + + dnl Check if gcc is being used + AS_IF([ test "$GCC" = "no" ], [ + AC_MSG_ERROR([not compiling with gcc, which is required for gcov code coverage]) + ]) + + # List of supported lcov versions. + lcov_version_list="1.6 1.7 1.8 1.9 1.10 1.11 1.12" + + AC_CHECK_PROG([LCOV], [lcov], [lcov]) + AC_CHECK_PROG([GENHTML], [genhtml], [genhtml]) + + AS_IF([ test "$LCOV" ], [ + AC_CACHE_CHECK([for lcov version], ax_cv_lcov_version, [ + ax_cv_lcov_version=invalid + lcov_version=`$LCOV -v 2>/dev/null | $SED -e 's/^.* //'` + for lcov_check_version in $lcov_version_list; do + if test "$lcov_version" = "$lcov_check_version"; then + ax_cv_lcov_version="$lcov_check_version (ok)" + fi + done + ]) + ], [ + lcov_msg="To enable code coverage reporting you must have one of the following lcov versions installed: $lcov_version_list" + AC_MSG_ERROR([$lcov_msg]) + ]) + + case $ax_cv_lcov_version in + ""|invalid[)] + lcov_msg="You must have one of the following versions of lcov: $lcov_version_list (found: $lcov_version)." + AC_MSG_ERROR([$lcov_msg]) + LCOV="exit 0;" + ;; + esac + + AS_IF([ test -z "$GENHTML" ], [ + AC_MSG_ERROR([Could not find genhtml from the lcov package]) + ]) + + dnl Build the code coverage flags + CODE_COVERAGE_CPPFLAGS="-DNDEBUG" + CODE_COVERAGE_CFLAGS="-O0 -g -fprofile-arcs -ftest-coverage" + CODE_COVERAGE_CXXFLAGS="-O0 -g -fprofile-arcs -ftest-coverage" + CODE_COVERAGE_LDFLAGS="-lgcov" + + AC_SUBST([CODE_COVERAGE_CPPFLAGS]) + AC_SUBST([CODE_COVERAGE_CFLAGS]) + AC_SUBST([CODE_COVERAGE_CXXFLAGS]) + AC_SUBST([CODE_COVERAGE_LDFLAGS]) + ]) + +[CODE_COVERAGE_RULES=' +# Code coverage +# +# Optional: +# - CODE_COVERAGE_DIRECTORY: Top-level directory for code coverage reporting. +# Multiple directories may be specified, separated by whitespace. +# (Default: $(top_builddir)) +# - CODE_COVERAGE_OUTPUT_FILE: Filename and path for the .info file generated +# by lcov for code coverage. (Default: +# $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage.info) +# - CODE_COVERAGE_OUTPUT_DIRECTORY: Directory for generated code coverage +# reports to be created. (Default: +# $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage) +# - CODE_COVERAGE_BRANCH_COVERAGE: Set to 1 to enforce branch coverage, +# set to 0 to disable it and leave empty to stay with the default. +# (Default: empty) +# - CODE_COVERAGE_LCOV_SHOPTS_DEFAULT: Extra options shared between both lcov +# instances. (Default: based on $CODE_COVERAGE_BRANCH_COVERAGE) +# - CODE_COVERAGE_LCOV_SHOPTS: Extra options to shared between both lcov +# instances. (Default: $CODE_COVERAGE_LCOV_SHOPTS_DEFAULT) +# - CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH: --gcov-tool pathtogcov +# - CODE_COVERAGE_LCOV_OPTIONS_DEFAULT: Extra options to pass to the +# collecting lcov instance. (Default: $CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH) +# - CODE_COVERAGE_LCOV_OPTIONS: Extra options to pass to the collecting lcov +# instance. (Default: $CODE_COVERAGE_LCOV_OPTIONS_DEFAULT) +# - CODE_COVERAGE_LCOV_RMOPTS_DEFAULT: Extra options to pass to the filtering +# lcov instance. (Default: empty) +# - CODE_COVERAGE_LCOV_RMOPTS: Extra options to pass to the filtering lcov +# instance. (Default: $CODE_COVERAGE_LCOV_RMOPTS_DEFAULT) +# - CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT: Extra options to pass to the +# genhtml instance. (Default: based on $CODE_COVERAGE_BRANCH_COVERAGE) +# - CODE_COVERAGE_GENHTML_OPTIONS: Extra options to pass to the genhtml +# instance. (Default: $CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT) +# - CODE_COVERAGE_IGNORE_PATTERN: Extra glob pattern of files to ignore +# +# The generated report will be titled using the $(PACKAGE_NAME) and +# $(PACKAGE_VERSION). In order to add the current git hash to the title, +# use the git-version-gen script, available online. + +# Optional variables +CODE_COVERAGE_DIRECTORY ?= $(top_builddir) +CODE_COVERAGE_OUTPUT_FILE ?= $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage.info +CODE_COVERAGE_OUTPUT_DIRECTORY ?= $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage +CODE_COVERAGE_BRANCH_COVERAGE ?= +CODE_COVERAGE_LCOV_SHOPTS_DEFAULT ?= $(if $(CODE_COVERAGE_BRANCH_COVERAGE),\ +--rc lcov_branch_coverage=$(CODE_COVERAGE_BRANCH_COVERAGE)) +CODE_COVERAGE_LCOV_SHOPTS ?= $(CODE_COVERAGE_LCOV_SHOPTS_DEFAULT) +CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH ?= --gcov-tool "$(GCOV)" +CODE_COVERAGE_LCOV_OPTIONS_DEFAULT ?= $(CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH) +CODE_COVERAGE_LCOV_OPTIONS ?= $(CODE_COVERAGE_LCOV_OPTIONS_DEFAULT) +CODE_COVERAGE_LCOV_RMOPTS_DEFAULT ?= +CODE_COVERAGE_LCOV_RMOPTS ?= $(CODE_COVERAGE_LCOV_RMOPTS_DEFAULT) +CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT ?=\ +$(if $(CODE_COVERAGE_BRANCH_COVERAGE),\ +--rc genhtml_branch_coverage=$(CODE_COVERAGE_BRANCH_COVERAGE)) +CODE_COVERAGE_GENHTML_OPTIONS ?= $(CODE_COVERAGE_GENHTML_OPTIONS_DEFAULTS) +CODE_COVERAGE_IGNORE_PATTERN ?= + +code_coverage_v_lcov_cap = $(code_coverage_v_lcov_cap_$(V)) +code_coverage_v_lcov_cap_ = $(code_coverage_v_lcov_cap_$(AM_DEFAULT_VERBOSITY)) +code_coverage_v_lcov_cap_0 = @echo " LCOV --capture"\ + $(CODE_COVERAGE_OUTPUT_FILE); +code_coverage_v_lcov_ign = $(code_coverage_v_lcov_ign_$(V)) +code_coverage_v_lcov_ign_ = $(code_coverage_v_lcov_ign_$(AM_DEFAULT_VERBOSITY)) +code_coverage_v_lcov_ign_0 = @echo " LCOV --remove /tmp/*"\ + $(CODE_COVERAGE_IGNORE_PATTERN); +code_coverage_v_genhtml = $(code_coverage_v_genhtml_$(V)) +code_coverage_v_genhtml_ = $(code_coverage_v_genhtml_$(AM_DEFAULT_VERBOSITY)) +code_coverage_v_genhtml_0 = @echo " GEN " $(CODE_COVERAGE_OUTPUT_DIRECTORY); +code_coverage_quiet = $(code_coverage_quiet_$(V)) +code_coverage_quiet_ = $(code_coverage_quiet_$(AM_DEFAULT_VERBOSITY)) +code_coverage_quiet_0 = --quiet + +# sanitizes the test-name: replaces with underscores: dashes and dots +code_coverage_sanitize = $(subst -,_,$(subst .,_,$(1))) + +# Use recursive makes in order to ignore errors during check +check-code-coverage: +ifeq ($(CODE_COVERAGE_ENABLED),yes) + -$(A''M_V_at)$(MAKE) $(AM_MAKEFLAGS) -k check + $(A''M_V_at)$(MAKE) $(AM_MAKEFLAGS) code-coverage-capture +else + @echo "Need to reconfigure with --enable-code-coverage" +endif + +# Capture code coverage data +code-coverage-capture: code-coverage-capture-hook +ifeq ($(CODE_COVERAGE_ENABLED),yes) + $(code_coverage_v_lcov_cap)$(LCOV) $(code_coverage_quiet) $(addprefix --directory ,$(CODE_COVERAGE_DIRECTORY)) --capture --output-file "$(CODE_COVERAGE_OUTPUT_FILE).tmp" --test-name "$(call code_coverage_sanitize,$(PACKAGE_NAME)-$(PACKAGE_VERSION))" --no-checksum --compat-libtool $(CODE_COVERAGE_LCOV_SHOPTS) $(CODE_COVERAGE_LCOV_OPTIONS) + $(code_coverage_v_lcov_ign)$(LCOV) $(code_coverage_quiet) $(addprefix --directory ,$(CODE_COVERAGE_DIRECTORY)) --remove "$(CODE_COVERAGE_OUTPUT_FILE).tmp" "/tmp/*" $(CODE_COVERAGE_IGNORE_PATTERN) --output-file "$(CODE_COVERAGE_OUTPUT_FILE)" $(CODE_COVERAGE_LCOV_SHOPTS) $(CODE_COVERAGE_LCOV_RMOPTS) + -@rm -f $(CODE_COVERAGE_OUTPUT_FILE).tmp + $(code_coverage_v_genhtml)LANG=C $(GENHTML) $(code_coverage_quiet) $(addprefix --prefix ,$(CODE_COVERAGE_DIRECTORY)) --output-directory "$(CODE_COVERAGE_OUTPUT_DIRECTORY)" --title "$(PACKAGE_NAME)-$(PACKAGE_VERSION) Code Coverage" --legend --show-details "$(CODE_COVERAGE_OUTPUT_FILE)" $(CODE_COVERAGE_GENHTML_OPTIONS) + @echo "file://$(abs_builddir)/$(CODE_COVERAGE_OUTPUT_DIRECTORY)/index.html" +else + @echo "Need to reconfigure with --enable-code-coverage" +endif + +# Hook rule executed before code-coverage-capture, overridable by the user +code-coverage-capture-hook: + +ifeq ($(CODE_COVERAGE_ENABLED),yes) +clean: code-coverage-clean +distclean: code-coverage-clean +code-coverage-clean: + -$(LCOV) --directory $(top_builddir) -z + -rm -rf $(CODE_COVERAGE_OUTPUT_FILE) $(CODE_COVERAGE_OUTPUT_FILE).tmp $(CODE_COVERAGE_OUTPUT_DIRECTORY) + -find . \( -name "*.gcda" -o -name "*.gcno" -o -name "*.gcov" \) -delete +endif + +GITIGNOREFILES ?= +GITIGNOREFILES += $(CODE_COVERAGE_OUTPUT_FILE) $(CODE_COVERAGE_OUTPUT_DIRECTORY) + +A''M_DISTCHECK_CONFIGURE_FLAGS ?= +A''M_DISTCHECK_CONFIGURE_FLAGS += --disable-code-coverage + +.PHONY: check-code-coverage code-coverage-capture code-coverage-capture-hook code-coverage-clean +'] + + AC_SUBST([CODE_COVERAGE_RULES]) + m4_ifdef([_AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE([CODE_COVERAGE_RULES])]) +]) diff --git a/m4/glibtests.m4 b/m4/glibtests.m4 new file mode 100644 index 0000000..7d5920a --- /dev/null +++ b/m4/glibtests.m4 @@ -0,0 +1,28 @@ +dnl GLIB_TESTS +dnl + +AC_DEFUN([GLIB_TESTS], +[ + AC_ARG_ENABLE(installed-tests, + AS_HELP_STRING([--enable-installed-tests], + [Enable installation of some test cases]), + [case ${enableval} in + yes) ENABLE_INSTALLED_TESTS="1" ;; + no) ENABLE_INSTALLED_TESTS="" ;; + *) AC_MSG_ERROR([bad value ${enableval} for --enable-installed-tests]) ;; + esac]) + AM_CONDITIONAL([ENABLE_INSTALLED_TESTS], test "$ENABLE_INSTALLED_TESTS" = "1") + AC_ARG_ENABLE(always-build-tests, + AS_HELP_STRING([--enable-always-build-tests], + [Enable always building tests during 'make all']), + [case ${enableval} in + yes) ENABLE_ALWAYS_BUILD_TESTS="1" ;; + no) ENABLE_ALWAYS_BUILD_TESTS="" ;; + *) AC_MSG_ERROR([bad value ${enableval} for --enable-always-build-tests]) ;; + esac]) + AM_CONDITIONAL([ENABLE_ALWAYS_BUILD_TESTS], test "$ENABLE_ALWAYS_BUILD_TESTS" = "1") + if test "$ENABLE_INSTALLED_TESTS" = "1"; then + AC_SUBST(installed_test_metadir, [${datadir}/installed-tests/]AC_PACKAGE_NAME) + AC_SUBST(installed_testdir, [${libexecdir}/installed-tests/]AC_PACKAGE_NAME) + fi +]) diff --git a/m4/gtk-doc.m4 b/m4/gtk-doc.m4 new file mode 100644 index 0000000..2d12f01 --- /dev/null +++ b/m4/gtk-doc.m4 @@ -0,0 +1,113 @@ +# -*- mode: autoconf -*- +# +# gtk-doc.m4 - configure macro to check for gtk-doc +# Copyright (C) 2003 James Henstridge +# 2007-2017 Stefan Sauer +# +# 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 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, the above copyright owner gives unlimited +# permission to copy, distribute and modify the configure scripts that +# are the output of Autoconf when processing the Macro. You need not +# follow the terms of the GNU General Public License when using or +# distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. + +# serial 2 + +dnl Usage: +dnl GTK_DOC_CHECK([minimum-gtk-doc-version]) +AC_DEFUN([GTK_DOC_CHECK], +[ + AC_REQUIRE([PKG_PROG_PKG_CONFIG]) + AC_BEFORE([AC_PROG_LIBTOOL],[$0])dnl setup libtool first + AC_BEFORE([AM_PROG_LIBTOOL],[$0])dnl setup libtool first + + ifelse([$1],[],[gtk_doc_requires="gtk-doc"],[gtk_doc_requires="gtk-doc >= $1"]) + AC_MSG_CHECKING([for gtk-doc]) + PKG_CHECK_EXISTS([$gtk_doc_requires],[have_gtk_doc=yes],[have_gtk_doc=no]) + AC_MSG_RESULT($have_gtk_doc) + + if test "$have_gtk_doc" = "no"; then + AC_MSG_WARN([ + You will not be able to create source packages with 'make dist' + because $gtk_doc_requires is not found.]) + fi + + dnl check for tools we added during development + dnl Use AC_CHECK_PROG to avoid the check target using an absolute path that + dnl may not be writable by the user. Currently, automake requires that the + dnl test name must end in '.test'. + dnl https://bugzilla.gnome.org/show_bug.cgi?id=701638 + AC_CHECK_PROG([GTKDOC_CHECK],[gtkdoc-check],[gtkdoc-check.test]) + AC_PATH_PROG([GTKDOC_CHECK_PATH],[gtkdoc-check]) + AC_PATH_PROGS([GTKDOC_REBASE],[gtkdoc-rebase],[true]) + AC_PATH_PROG([GTKDOC_MKPDF],[gtkdoc-mkpdf]) + + dnl for overriding the documentation installation directory + AC_ARG_WITH([html-dir], + AS_HELP_STRING([--with-html-dir=PATH], [path to installed docs]),, + [with_html_dir='${datadir}/gtk-doc/html']) + HTML_DIR="$with_html_dir" + AC_SUBST([HTML_DIR]) + + dnl enable/disable documentation building + AC_ARG_ENABLE([gtk-doc], + AS_HELP_STRING([--enable-gtk-doc], + [use gtk-doc to build documentation [[default=no]]]),, + [enable_gtk_doc=no]) + + AC_MSG_CHECKING([whether to build gtk-doc documentation]) + AC_MSG_RESULT($enable_gtk_doc) + + if test "x$enable_gtk_doc" = "xyes" && test "$have_gtk_doc" = "no"; then + AC_MSG_ERROR([ + You must have $gtk_doc_requires installed to build documentation for + $PACKAGE_NAME. Please install gtk-doc or disable building the + documentation by adding '--disable-gtk-doc' to '[$]0'.]) + fi + + dnl don't check for glib if we build glib + if test "x$PACKAGE_NAME" != "xglib"; then + dnl don't fail if someone does not have glib + PKG_CHECK_MODULES(GTKDOC_DEPS, glib-2.0 >= 2.10.0 gobject-2.0 >= 2.10.0,,[:]) + fi + + dnl enable/disable output formats + AC_ARG_ENABLE([gtk-doc-html], + AS_HELP_STRING([--enable-gtk-doc-html], + [build documentation in html format [[default=yes]]]),, + [enable_gtk_doc_html=yes]) + AC_ARG_ENABLE([gtk-doc-pdf], + AS_HELP_STRING([--enable-gtk-doc-pdf], + [build documentation in pdf format [[default=no]]]),, + [enable_gtk_doc_pdf=no]) + + if test -z "$GTKDOC_MKPDF"; then + enable_gtk_doc_pdf=no + fi + + if test -z "$AM_DEFAULT_VERBOSITY"; then + AM_DEFAULT_VERBOSITY=1 + fi + AC_SUBST([AM_DEFAULT_VERBOSITY]) + + AM_CONDITIONAL([HAVE_GTK_DOC], [test x$have_gtk_doc = xyes]) + AM_CONDITIONAL([ENABLE_GTK_DOC], [test x$enable_gtk_doc = xyes]) + AM_CONDITIONAL([GTK_DOC_BUILD_HTML], [test x$enable_gtk_doc_html = xyes]) + AM_CONDITIONAL([GTK_DOC_BUILD_PDF], [test x$enable_gtk_doc_pdf = xyes]) + AM_CONDITIONAL([GTK_DOC_USE_LIBTOOL], [test -n "$LIBTOOL"]) + AM_CONDITIONAL([GTK_DOC_USE_REBASE], [test -n "$GTKDOC_REBASE"]) +]) diff --git a/m4/intltool.m4 b/m4/intltool.m4 new file mode 100644 index 0000000..c25b7b1 --- /dev/null +++ b/m4/intltool.m4 @@ -0,0 +1,212 @@ +## intltool.m4 - Configure intltool for the target system. -*-Shell-script-*- +## Copyright (C) 2001 Eazel, Inc. +## Author: Maciej Stachowiak +## Kenneth Christiansen +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +## +## 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. + +dnl IT_PROG_INTLTOOL([MINIMUM-VERSION], [no-xml]) +# serial 42 IT_PROG_INTLTOOL +AC_DEFUN([IT_PROG_INTLTOOL], [ +AC_PREREQ([2.50])dnl +AC_REQUIRE([AM_NLS])dnl + +case "$am__api_version" in + 1.[01234]) + AC_MSG_ERROR([Automake 1.5 or newer is required to use intltool]) + ;; + *) + ;; +esac + +INTLTOOL_REQUIRED_VERSION_AS_INT=`echo $1 | awk -F. '{ print $ 1 * 1000 + $ 2 * 100 + $ 3; }'` +INTLTOOL_APPLIED_VERSION=`intltool-update --version | head -1 | cut -d" " -f3` +INTLTOOL_APPLIED_VERSION_AS_INT=`echo $INTLTOOL_APPLIED_VERSION | awk -F. '{ print $ 1 * 1000 + $ 2 * 100 + $ 3; }'` +if test -n "$1"; then + AC_MSG_CHECKING([for intltool >= $1]) + AC_MSG_RESULT([$INTLTOOL_APPLIED_VERSION found]) + test "$INTLTOOL_APPLIED_VERSION_AS_INT" -ge "$INTLTOOL_REQUIRED_VERSION_AS_INT" || + AC_MSG_ERROR([Your intltool is too old. You need intltool $1 or later.]) +fi + +AC_PATH_PROG(INTLTOOL_UPDATE, [intltool-update]) +AC_PATH_PROG(INTLTOOL_MERGE, [intltool-merge]) +AC_PATH_PROG(INTLTOOL_EXTRACT, [intltool-extract]) +if test -z "$INTLTOOL_UPDATE" -o -z "$INTLTOOL_MERGE" -o -z "$INTLTOOL_EXTRACT"; then + AC_MSG_ERROR([The intltool scripts were not found. Please install intltool.]) +fi + +if test -z "$AM_DEFAULT_VERBOSITY"; then + AM_DEFAULT_VERBOSITY=1 +fi +AC_SUBST([AM_DEFAULT_VERBOSITY]) + +INTLTOOL_V_MERGE='$(INTLTOOL__v_MERGE_$(V))' +INTLTOOL__v_MERGE_='$(INTLTOOL__v_MERGE_$(AM_DEFAULT_VERBOSITY))' +INTLTOOL__v_MERGE_0='@echo " ITMRG " [$]@;' +AC_SUBST(INTLTOOL_V_MERGE) +AC_SUBST(INTLTOOL__v_MERGE_) +AC_SUBST(INTLTOOL__v_MERGE_0) + +INTLTOOL_V_MERGE_OPTIONS='$(intltool__v_merge_options_$(V))' +intltool__v_merge_options_='$(intltool__v_merge_options_$(AM_DEFAULT_VERBOSITY))' +intltool__v_merge_options_0='-q' +AC_SUBST(INTLTOOL_V_MERGE_OPTIONS) +AC_SUBST(intltool__v_merge_options_) +AC_SUBST(intltool__v_merge_options_0) + + INTLTOOL_DESKTOP_RULE='%.desktop: %.desktop.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' +INTLTOOL_DIRECTORY_RULE='%.directory: %.directory.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' + INTLTOOL_KEYS_RULE='%.keys: %.keys.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -k -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' + INTLTOOL_PROP_RULE='%.prop: %.prop.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' + INTLTOOL_OAF_RULE='%.oaf: %.oaf.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -o -p $(top_srcdir)/po $< [$]@' + INTLTOOL_PONG_RULE='%.pong: %.pong.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' + INTLTOOL_SERVER_RULE='%.server: %.server.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -o -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' + INTLTOOL_SHEET_RULE='%.sheet: %.sheet.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' +INTLTOOL_SOUNDLIST_RULE='%.soundlist: %.soundlist.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' + INTLTOOL_UI_RULE='%.ui: %.ui.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' + INTLTOOL_XML_RULE='%.xml: %.xml.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' +if test "$INTLTOOL_APPLIED_VERSION_AS_INT" -ge 5000; then + INTLTOOL_XML_NOMERGE_RULE='%.xml: %.xml.in $(INTLTOOL_MERGE) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u --no-translations $< [$]@' +else + INTLTOOL_XML_NOMERGE_RULE='%.xml: %.xml.in $(INTLTOOL_MERGE) ; $(INTLTOOL_V_MERGE)_it_tmp_dir=tmp.intltool.[$][$]RANDOM && mkdir [$][$]_it_tmp_dir && LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u [$][$]_it_tmp_dir $< [$]@ && rmdir [$][$]_it_tmp_dir' +fi + INTLTOOL_XAM_RULE='%.xam: %.xml.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' + INTLTOOL_KBD_RULE='%.kbd: %.kbd.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u -m -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' + INTLTOOL_CAVES_RULE='%.caves: %.caves.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' + INTLTOOL_SCHEMAS_RULE='%.schemas: %.schemas.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -s -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' + INTLTOOL_THEME_RULE='%.theme: %.theme.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' + INTLTOOL_SERVICE_RULE='%.service: %.service.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' + INTLTOOL_POLICY_RULE='%.policy: %.policy.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' + +_IT_SUBST(INTLTOOL_DESKTOP_RULE) +_IT_SUBST(INTLTOOL_DIRECTORY_RULE) +_IT_SUBST(INTLTOOL_KEYS_RULE) +_IT_SUBST(INTLTOOL_PROP_RULE) +_IT_SUBST(INTLTOOL_OAF_RULE) +_IT_SUBST(INTLTOOL_PONG_RULE) +_IT_SUBST(INTLTOOL_SERVER_RULE) +_IT_SUBST(INTLTOOL_SHEET_RULE) +_IT_SUBST(INTLTOOL_SOUNDLIST_RULE) +_IT_SUBST(INTLTOOL_UI_RULE) +_IT_SUBST(INTLTOOL_XAM_RULE) +_IT_SUBST(INTLTOOL_KBD_RULE) +_IT_SUBST(INTLTOOL_XML_RULE) +_IT_SUBST(INTLTOOL_XML_NOMERGE_RULE) +_IT_SUBST(INTLTOOL_CAVES_RULE) +_IT_SUBST(INTLTOOL_SCHEMAS_RULE) +_IT_SUBST(INTLTOOL_THEME_RULE) +_IT_SUBST(INTLTOOL_SERVICE_RULE) +_IT_SUBST(INTLTOOL_POLICY_RULE) + +# Check the gettext tools to make sure they are GNU +AC_PATH_PROG(XGETTEXT, xgettext) +AC_PATH_PROG(MSGMERGE, msgmerge) +AC_PATH_PROG(MSGFMT, msgfmt) +AC_PATH_PROG(GMSGFMT, gmsgfmt, $MSGFMT) +if test -z "$XGETTEXT" -o -z "$MSGMERGE" -o -z "$MSGFMT"; then + AC_MSG_ERROR([GNU gettext tools not found; required for intltool]) +fi +xgversion="`$XGETTEXT --version|grep '(GNU ' 2> /dev/null`" +mmversion="`$MSGMERGE --version|grep '(GNU ' 2> /dev/null`" +mfversion="`$MSGFMT --version|grep '(GNU ' 2> /dev/null`" +if test -z "$xgversion" -o -z "$mmversion" -o -z "$mfversion"; then + AC_MSG_ERROR([GNU gettext tools not found; required for intltool]) +fi + +AC_PATH_PROG(INTLTOOL_PERL, perl) +if test -z "$INTLTOOL_PERL"; then + AC_MSG_ERROR([perl not found]) +fi +AC_MSG_CHECKING([for perl >= 5.8.1]) +$INTLTOOL_PERL -e "use 5.8.1;" > /dev/null 2>&1 +if test $? -ne 0; then + AC_MSG_ERROR([perl 5.8.1 is required for intltool]) +else + IT_PERL_VERSION=`$INTLTOOL_PERL -e "printf '%vd', $^V"` + AC_MSG_RESULT([$IT_PERL_VERSION]) +fi +if test "x$2" != "xno-xml"; then + AC_MSG_CHECKING([for XML::Parser]) + if `$INTLTOOL_PERL -e "require XML::Parser" 2>/dev/null`; then + AC_MSG_RESULT([ok]) + else + AC_MSG_ERROR([XML::Parser perl module is required for intltool]) + fi +fi + +# Substitute ALL_LINGUAS so we can use it in po/Makefile +AC_SUBST(ALL_LINGUAS) + +IT_PO_SUBDIR([po]) + +]) + + +# IT_PO_SUBDIR(DIRNAME) +# --------------------- +# All po subdirs have to be declared with this macro; the subdir "po" is +# declared by IT_PROG_INTLTOOL. +# +AC_DEFUN([IT_PO_SUBDIR], +[AC_PREREQ([2.53])dnl We use ac_top_srcdir inside AC_CONFIG_COMMANDS. +dnl +dnl The following CONFIG_COMMANDS should be executed at the very end +dnl of config.status. +AC_CONFIG_COMMANDS_PRE([ + AC_CONFIG_COMMANDS([$1/stamp-it], [ + if [ ! grep "^# INTLTOOL_MAKEFILE$" "$1/Makefile.in" > /dev/null ]; then + AC_MSG_ERROR([$1/Makefile.in.in was not created by intltoolize.]) + fi + rm -f "$1/stamp-it" "$1/stamp-it.tmp" "$1/POTFILES" "$1/Makefile.tmp" + >"$1/stamp-it.tmp" + [sed '/^#/d + s/^[[].*] *// + /^[ ]*$/d + '"s|^| $ac_top_srcdir/|" \ + "$srcdir/$1/POTFILES.in" | sed '$!s/$/ \\/' >"$1/POTFILES" + ] + [sed '/^POTFILES =/,/[^\\]$/ { + /^POTFILES =/!d + r $1/POTFILES + } + ' "$1/Makefile.in" >"$1/Makefile"] + rm -f "$1/Makefile.tmp" + mv "$1/stamp-it.tmp" "$1/stamp-it" + ]) +])dnl +]) + +# _IT_SUBST(VARIABLE) +# ------------------- +# Abstract macro to do either _AM_SUBST_NOTMAKE or AC_SUBST +# +AC_DEFUN([_IT_SUBST], +[ +AC_SUBST([$1]) +m4_ifdef([_AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE([$1])]) +] +) + +# deprecated macros +AU_ALIAS([AC_PROG_INTLTOOL], [IT_PROG_INTLTOOL]) +# A hint is needed for aclocal from Automake <= 1.9.4: +# AC_DEFUN([AC_PROG_INTLTOOL], ...) + diff --git a/m4/introspection.m4 b/m4/introspection.m4 new file mode 100644 index 0000000..589721c --- /dev/null +++ b/m4/introspection.m4 @@ -0,0 +1,94 @@ +dnl -*- mode: autoconf -*- +dnl Copyright 2009 Johan Dahlin +dnl +dnl This file is free software; the author(s) gives unlimited +dnl permission to copy and/or distribute it, with or without +dnl modifications, as long as this notice is preserved. +dnl + +# serial 1 + +m4_define([_GOBJECT_INTROSPECTION_CHECK_INTERNAL], +[ + AC_BEFORE([AC_PROG_LIBTOOL],[$0])dnl setup libtool first + AC_BEFORE([AM_PROG_LIBTOOL],[$0])dnl setup libtool first + AC_BEFORE([LT_INIT],[$0])dnl setup libtool first + + dnl enable/disable introspection + m4_if([$2], [require], + [dnl + enable_introspection=yes + ],[dnl + AC_ARG_ENABLE(introspection, + AS_HELP_STRING([--enable-introspection[=@<:@no/auto/yes@:>@]], + [Enable introspection for this build]),, + [enable_introspection=auto]) + ])dnl + + AC_MSG_CHECKING([for gobject-introspection]) + + dnl presence/version checking + AS_CASE([$enable_introspection], + [no], [dnl + found_introspection="no (disabled, use --enable-introspection to enable)" + ],dnl + [yes],[dnl + PKG_CHECK_EXISTS([gobject-introspection-1.0],, + AC_MSG_ERROR([gobject-introspection-1.0 is not installed])) + PKG_CHECK_EXISTS([gobject-introspection-1.0 >= $1], + found_introspection=yes, + AC_MSG_ERROR([You need to have gobject-introspection >= $1 installed to build AC_PACKAGE_NAME])) + ],dnl + [auto],[dnl + PKG_CHECK_EXISTS([gobject-introspection-1.0 >= $1], found_introspection=yes, found_introspection=no) + ],dnl + [dnl + AC_MSG_ERROR([invalid argument passed to --enable-introspection, should be one of @<:@no/auto/yes@:>@]) + ])dnl + + AC_MSG_RESULT([$found_introspection]) + + INTROSPECTION_SCANNER= + INTROSPECTION_COMPILER= + INTROSPECTION_GENERATE= + INTROSPECTION_GIRDIR= + INTROSPECTION_TYPELIBDIR= + if test "x$found_introspection" = "xyes"; then + INTROSPECTION_SCANNER=`$PKG_CONFIG --variable=g_ir_scanner gobject-introspection-1.0` + INTROSPECTION_COMPILER=`$PKG_CONFIG --variable=g_ir_compiler gobject-introspection-1.0` + INTROSPECTION_GENERATE=`$PKG_CONFIG --variable=g_ir_generate gobject-introspection-1.0` + INTROSPECTION_GIRDIR=`$PKG_CONFIG --variable=girdir gobject-introspection-1.0` + INTROSPECTION_TYPELIBDIR="$($PKG_CONFIG --variable=typelibdir gobject-introspection-1.0)" + INTROSPECTION_CFLAGS=`$PKG_CONFIG --cflags gobject-introspection-1.0` + INTROSPECTION_LIBS=`$PKG_CONFIG --libs gobject-introspection-1.0` + INTROSPECTION_MAKEFILE=`$PKG_CONFIG --variable=datadir gobject-introspection-1.0`/gobject-introspection-1.0/Makefile.introspection + fi + AC_SUBST(INTROSPECTION_SCANNER) + AC_SUBST(INTROSPECTION_COMPILER) + AC_SUBST(INTROSPECTION_GENERATE) + AC_SUBST(INTROSPECTION_GIRDIR) + AC_SUBST(INTROSPECTION_TYPELIBDIR) + AC_SUBST(INTROSPECTION_CFLAGS) + AC_SUBST(INTROSPECTION_LIBS) + AC_SUBST(INTROSPECTION_MAKEFILE) + + AM_CONDITIONAL(HAVE_INTROSPECTION, test "x$found_introspection" = "xyes") +]) + + +dnl Usage: +dnl GOBJECT_INTROSPECTION_CHECK([minimum-g-i-version]) + +AC_DEFUN([GOBJECT_INTROSPECTION_CHECK], +[ + _GOBJECT_INTROSPECTION_CHECK_INTERNAL([$1]) +]) + +dnl Usage: +dnl GOBJECT_INTROSPECTION_REQUIRE([minimum-g-i-version]) + + +AC_DEFUN([GOBJECT_INTROSPECTION_REQUIRE], +[ + _GOBJECT_INTROSPECTION_CHECK_INTERNAL([$1], [require]) +]) diff --git a/m4/libtool.m4 b/m4/libtool.m4 new file mode 100644 index 0000000..ee80844 --- /dev/null +++ b/m4/libtool.m4 @@ -0,0 +1,8387 @@ +# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- +# +# Copyright (C) 1996-2001, 2003-2015 Free Software Foundation, Inc. +# Written by Gordon Matzigkeit, 1996 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +m4_define([_LT_COPYING], [dnl +# Copyright (C) 2014 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. + +# GNU Libtool 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 of the License, or +# (at your option) any later version. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program or library that is built +# using GNU Libtool, you may include this file under the same +# distribution terms that you use for the rest of that program. +# +# GNU Libtool is distributed in the hope that 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 . +]) + +# serial 58 LT_INIT + + +# LT_PREREQ(VERSION) +# ------------------ +# Complain and exit if this libtool version is less that VERSION. +m4_defun([LT_PREREQ], +[m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1, + [m4_default([$3], + [m4_fatal([Libtool version $1 or higher is required], + 63)])], + [$2])]) + + +# _LT_CHECK_BUILDDIR +# ------------------ +# Complain if the absolute build directory name contains unusual characters +m4_defun([_LT_CHECK_BUILDDIR], +[case `pwd` in + *\ * | *\ *) + AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;; +esac +]) + + +# LT_INIT([OPTIONS]) +# ------------------ +AC_DEFUN([LT_INIT], +[AC_PREREQ([2.62])dnl We use AC_PATH_PROGS_FEATURE_CHECK +AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl +AC_BEFORE([$0], [LT_LANG])dnl +AC_BEFORE([$0], [LT_OUTPUT])dnl +AC_BEFORE([$0], [LTDL_INIT])dnl +m4_require([_LT_CHECK_BUILDDIR])dnl + +dnl Autoconf doesn't catch unexpanded LT_ macros by default: +m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl +m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl +dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4 +dnl unless we require an AC_DEFUNed macro: +AC_REQUIRE([LTOPTIONS_VERSION])dnl +AC_REQUIRE([LTSUGAR_VERSION])dnl +AC_REQUIRE([LTVERSION_VERSION])dnl +AC_REQUIRE([LTOBSOLETE_VERSION])dnl +m4_require([_LT_PROG_LTMAIN])dnl + +_LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}]) + +dnl Parse OPTIONS +_LT_SET_OPTIONS([$0], [$1]) + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS=$ltmain + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' +AC_SUBST(LIBTOOL)dnl + +_LT_SETUP + +# Only expand once: +m4_define([LT_INIT]) +])# LT_INIT + +# Old names: +AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT]) +AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_PROG_LIBTOOL], []) +dnl AC_DEFUN([AM_PROG_LIBTOOL], []) + + +# _LT_PREPARE_CC_BASENAME +# ----------------------- +m4_defun([_LT_PREPARE_CC_BASENAME], [ +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +func_cc_basename () +{ + for cc_temp in @S|@*""; do + case $cc_temp in + compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; + distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; + \-*) ;; + *) break;; + esac + done + func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` +} +])# _LT_PREPARE_CC_BASENAME + + +# _LT_CC_BASENAME(CC) +# ------------------- +# It would be clearer to call AC_REQUIREs from _LT_PREPARE_CC_BASENAME, +# but that macro is also expanded into generated libtool script, which +# arranges for $SED and $ECHO to be set by different means. +m4_defun([_LT_CC_BASENAME], +[m4_require([_LT_PREPARE_CC_BASENAME])dnl +AC_REQUIRE([_LT_DECL_SED])dnl +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl +func_cc_basename $1 +cc_basename=$func_cc_basename_result +]) + + +# _LT_FILEUTILS_DEFAULTS +# ---------------------- +# It is okay to use these file commands and assume they have been set +# sensibly after 'm4_require([_LT_FILEUTILS_DEFAULTS])'. +m4_defun([_LT_FILEUTILS_DEFAULTS], +[: ${CP="cp -f"} +: ${MV="mv -f"} +: ${RM="rm -f"} +])# _LT_FILEUTILS_DEFAULTS + + +# _LT_SETUP +# --------- +m4_defun([_LT_SETUP], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl + +_LT_DECL([], [PATH_SEPARATOR], [1], [The PATH separator for the build system])dnl +dnl +_LT_DECL([], [host_alias], [0], [The host system])dnl +_LT_DECL([], [host], [0])dnl +_LT_DECL([], [host_os], [0])dnl +dnl +_LT_DECL([], [build_alias], [0], [The build system])dnl +_LT_DECL([], [build], [0])dnl +_LT_DECL([], [build_os], [0])dnl +dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([LT_PATH_LD])dnl +AC_REQUIRE([LT_PATH_NM])dnl +dnl +AC_REQUIRE([AC_PROG_LN_S])dnl +test -z "$LN_S" && LN_S="ln -s" +_LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl +dnl +AC_REQUIRE([LT_CMD_MAX_LEN])dnl +_LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl +_LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl +dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_CHECK_SHELL_FEATURES])dnl +m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl +m4_require([_LT_CMD_RELOAD])dnl +m4_require([_LT_CHECK_MAGIC_METHOD])dnl +m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl +m4_require([_LT_CMD_OLD_ARCHIVE])dnl +m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl +m4_require([_LT_WITH_SYSROOT])dnl +m4_require([_LT_CMD_TRUNCATE])dnl + +_LT_CONFIG_LIBTOOL_INIT([ +# See if we are running on zsh, and set the options that allow our +# commands through without removal of \ escapes INIT. +if test -n "\${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST +fi +]) +if test -n "${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST +fi + +_LT_CHECK_OBJDIR + +m4_require([_LT_TAG_COMPILER])dnl + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test set != "${COLLECT_NAMES+set}"; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Global variables: +ofile=libtool +can_build_shared=yes + +# All known linkers require a '.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a + +with_gnu_ld=$lt_cv_prog_gnu_ld + +old_CC=$CC +old_CFLAGS=$CFLAGS + +# Set sane defaults for various variables +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS +test -z "$LD" && LD=ld +test -z "$ac_objext" && ac_objext=o + +_LT_CC_BASENAME([$compiler]) + +# Only perform the check for file, if the check method requires it +test -z "$MAGIC_CMD" && MAGIC_CMD=file +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + _LT_PATH_MAGIC + fi + ;; +esac + +# Use C for the default configuration in the libtool script +LT_SUPPORTED_TAG([CC]) +_LT_LANG_C_CONFIG +_LT_LANG_DEFAULT_CONFIG +_LT_CONFIG_COMMANDS +])# _LT_SETUP + + +# _LT_PREPARE_SED_QUOTE_VARS +# -------------------------- +# Define a few sed substitution that help us do robust quoting. +m4_defun([_LT_PREPARE_SED_QUOTE_VARS], +[# Backslashify metacharacters that are still active within +# double-quoted strings. +sed_quote_subst='s/\([["`$\\]]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\([["`\\]]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to delay expansion of an escaped single quote. +delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' +]) + +# _LT_PROG_LTMAIN +# --------------- +# Note that this code is called both from 'configure', and 'config.status' +# now that we use AC_CONFIG_COMMANDS to generate libtool. Notably, +# 'config.status' has no value for ac_aux_dir unless we are using Automake, +# so we pass a copy along to make sure it has a sensible value anyway. +m4_defun([_LT_PROG_LTMAIN], +[m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl +_LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir']) +ltmain=$ac_aux_dir/ltmain.sh +])# _LT_PROG_LTMAIN + + +## ------------------------------------- ## +## Accumulate code for creating libtool. ## +## ------------------------------------- ## + +# So that we can recreate a full libtool script including additional +# tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS +# in macros and then make a single call at the end using the 'libtool' +# label. + + +# _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS]) +# ---------------------------------------- +# Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later. +m4_define([_LT_CONFIG_LIBTOOL_INIT], +[m4_ifval([$1], + [m4_append([_LT_OUTPUT_LIBTOOL_INIT], + [$1 +])])]) + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_INIT]) + + +# _LT_CONFIG_LIBTOOL([COMMANDS]) +# ------------------------------ +# Register COMMANDS to be passed to AC_CONFIG_COMMANDS later. +m4_define([_LT_CONFIG_LIBTOOL], +[m4_ifval([$1], + [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS], + [$1 +])])]) + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS]) + + +# _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS]) +# ----------------------------------------------------- +m4_defun([_LT_CONFIG_SAVE_COMMANDS], +[_LT_CONFIG_LIBTOOL([$1]) +_LT_CONFIG_LIBTOOL_INIT([$2]) +]) + + +# _LT_FORMAT_COMMENT([COMMENT]) +# ----------------------------- +# Add leading comment marks to the start of each line, and a trailing +# full-stop to the whole comment if one is not present already. +m4_define([_LT_FORMAT_COMMENT], +[m4_ifval([$1], [ +m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])], + [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.]) +)]) + + + +## ------------------------ ## +## FIXME: Eliminate VARNAME ## +## ------------------------ ## + + +# _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?]) +# ------------------------------------------------------------------- +# CONFIGNAME is the name given to the value in the libtool script. +# VARNAME is the (base) name used in the configure script. +# VALUE may be 0, 1 or 2 for a computed quote escaped value based on +# VARNAME. Any other value will be used directly. +m4_define([_LT_DECL], +[lt_if_append_uniq([lt_decl_varnames], [$2], [, ], + [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name], + [m4_ifval([$1], [$1], [$2])]) + lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3]) + m4_ifval([$4], + [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])]) + lt_dict_add_subkey([lt_decl_dict], [$2], + [tagged?], [m4_ifval([$5], [yes], [no])])]) +]) + + +# _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION]) +# -------------------------------------------------------- +m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])]) + + +# lt_decl_tag_varnames([SEPARATOR], [VARNAME1...]) +# ------------------------------------------------ +m4_define([lt_decl_tag_varnames], +[_lt_decl_filter([tagged?], [yes], $@)]) + + +# _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..]) +# --------------------------------------------------------- +m4_define([_lt_decl_filter], +[m4_case([$#], + [0], [m4_fatal([$0: too few arguments: $#])], + [1], [m4_fatal([$0: too few arguments: $#: $1])], + [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)], + [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)], + [lt_dict_filter([lt_decl_dict], $@)])[]dnl +]) + + +# lt_decl_quote_varnames([SEPARATOR], [VARNAME1...]) +# -------------------------------------------------- +m4_define([lt_decl_quote_varnames], +[_lt_decl_filter([value], [1], $@)]) + + +# lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...]) +# --------------------------------------------------- +m4_define([lt_decl_dquote_varnames], +[_lt_decl_filter([value], [2], $@)]) + + +# lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...]) +# --------------------------------------------------- +m4_define([lt_decl_varnames_tagged], +[m4_assert([$# <= 2])dnl +_$0(m4_quote(m4_default([$1], [[, ]])), + m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]), + m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))]) +m4_define([_lt_decl_varnames_tagged], +[m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])]) + + +# lt_decl_all_varnames([SEPARATOR], [VARNAME1...]) +# ------------------------------------------------ +m4_define([lt_decl_all_varnames], +[_$0(m4_quote(m4_default([$1], [[, ]])), + m4_if([$2], [], + m4_quote(lt_decl_varnames), + m4_quote(m4_shift($@))))[]dnl +]) +m4_define([_lt_decl_all_varnames], +[lt_join($@, lt_decl_varnames_tagged([$1], + lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl +]) + + +# _LT_CONFIG_STATUS_DECLARE([VARNAME]) +# ------------------------------------ +# Quote a variable value, and forward it to 'config.status' so that its +# declaration there will have the same value as in 'configure'. VARNAME +# must have a single quote delimited value for this to work. +m4_define([_LT_CONFIG_STATUS_DECLARE], +[$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`']) + + +# _LT_CONFIG_STATUS_DECLARATIONS +# ------------------------------ +# We delimit libtool config variables with single quotes, so when +# we write them to config.status, we have to be sure to quote all +# embedded single quotes properly. In configure, this macro expands +# each variable declared with _LT_DECL (and _LT_TAGDECL) into: +# +# ='`$ECHO "$" | $SED "$delay_single_quote_subst"`' +m4_defun([_LT_CONFIG_STATUS_DECLARATIONS], +[m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames), + [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])]) + + +# _LT_LIBTOOL_TAGS +# ---------------- +# Output comment and list of tags supported by the script +m4_defun([_LT_LIBTOOL_TAGS], +[_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl +available_tags='_LT_TAGS'dnl +]) + + +# _LT_LIBTOOL_DECLARE(VARNAME, [TAG]) +# ----------------------------------- +# Extract the dictionary values for VARNAME (optionally with TAG) and +# expand to a commented shell variable setting: +# +# # Some comment about what VAR is for. +# visible_name=$lt_internal_name +m4_define([_LT_LIBTOOL_DECLARE], +[_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], + [description])))[]dnl +m4_pushdef([_libtool_name], + m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl +m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])), + [0], [_libtool_name=[$]$1], + [1], [_libtool_name=$lt_[]$1], + [2], [_libtool_name=$lt_[]$1], + [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl +m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl +]) + + +# _LT_LIBTOOL_CONFIG_VARS +# ----------------------- +# Produce commented declarations of non-tagged libtool config variables +# suitable for insertion in the LIBTOOL CONFIG section of the 'libtool' +# script. Tagged libtool config variables (even for the LIBTOOL CONFIG +# section) are produced by _LT_LIBTOOL_TAG_VARS. +m4_defun([_LT_LIBTOOL_CONFIG_VARS], +[m4_foreach([_lt_var], + m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)), + [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])]) + + +# _LT_LIBTOOL_TAG_VARS(TAG) +# ------------------------- +m4_define([_LT_LIBTOOL_TAG_VARS], +[m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames), + [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])]) + + +# _LT_TAGVAR(VARNAME, [TAGNAME]) +# ------------------------------ +m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])]) + + +# _LT_CONFIG_COMMANDS +# ------------------- +# Send accumulated output to $CONFIG_STATUS. Thanks to the lists of +# variables for single and double quote escaping we saved from calls +# to _LT_DECL, we can put quote escaped variables declarations +# into 'config.status', and then the shell code to quote escape them in +# for loops in 'config.status'. Finally, any additional code accumulated +# from calls to _LT_CONFIG_LIBTOOL_INIT is expanded. +m4_defun([_LT_CONFIG_COMMANDS], +[AC_PROVIDE_IFELSE([LT_OUTPUT], + dnl If the libtool generation code has been placed in $CONFIG_LT, + dnl instead of duplicating it all over again into config.status, + dnl then we will have config.status run $CONFIG_LT later, so it + dnl needs to know what name is stored there: + [AC_CONFIG_COMMANDS([libtool], + [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])], + dnl If the libtool generation code is destined for config.status, + dnl expand the accumulated commands and init code now: + [AC_CONFIG_COMMANDS([libtool], + [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])]) +])#_LT_CONFIG_COMMANDS + + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT], +[ + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +sed_quote_subst='$sed_quote_subst' +double_quote_subst='$double_quote_subst' +delay_variable_subst='$delay_variable_subst' +_LT_CONFIG_STATUS_DECLARATIONS +LTCC='$LTCC' +LTCFLAGS='$LTCFLAGS' +compiler='$compiler_DEFAULT' + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$[]1 +_LTECHO_EOF' +} + +# Quote evaled strings. +for var in lt_decl_all_varnames([[ \ +]], lt_decl_quote_varnames); do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[[\\\\\\\`\\"\\\$]]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +# Double-quote double-evaled strings. +for var in lt_decl_all_varnames([[ \ +]], lt_decl_dquote_varnames); do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[[\\\\\\\`\\"\\\$]]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +_LT_OUTPUT_LIBTOOL_INIT +]) + +# _LT_GENERATED_FILE_INIT(FILE, [COMMENT]) +# ------------------------------------ +# Generate a child script FILE with all initialization necessary to +# reuse the environment learned by the parent script, and make the +# file executable. If COMMENT is supplied, it is inserted after the +# '#!' sequence but before initialization text begins. After this +# macro, additional text can be appended to FILE to form the body of +# the child script. The macro ends with non-zero status if the +# file could not be fully written (such as if the disk is full). +m4_ifdef([AS_INIT_GENERATED], +[m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])], +[m4_defun([_LT_GENERATED_FILE_INIT], +[m4_require([AS_PREPARE])]dnl +[m4_pushdef([AS_MESSAGE_LOG_FD])]dnl +[lt_write_fail=0 +cat >$1 <<_ASEOF || lt_write_fail=1 +#! $SHELL +# Generated by $as_me. +$2 +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$1 <<\_ASEOF || lt_write_fail=1 +AS_SHELL_SANITIZE +_AS_PREPARE +exec AS_MESSAGE_FD>&1 +_ASEOF +test 0 = "$lt_write_fail" && chmod +x $1[]dnl +m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT + +# LT_OUTPUT +# --------- +# This macro allows early generation of the libtool script (before +# AC_OUTPUT is called), incase it is used in configure for compilation +# tests. +AC_DEFUN([LT_OUTPUT], +[: ${CONFIG_LT=./config.lt} +AC_MSG_NOTICE([creating $CONFIG_LT]) +_LT_GENERATED_FILE_INIT(["$CONFIG_LT"], +[# Run this file to recreate a libtool stub with the current configuration.]) + +cat >>"$CONFIG_LT" <<\_LTEOF +lt_cl_silent=false +exec AS_MESSAGE_LOG_FD>>config.log +{ + echo + AS_BOX([Running $as_me.]) +} >&AS_MESSAGE_LOG_FD + +lt_cl_help="\ +'$as_me' creates a local libtool stub from the current configuration, +for use in further configure time tests before the real libtool is +generated. + +Usage: $[0] [[OPTIONS]] + + -h, --help print this help, then exit + -V, --version print version number, then exit + -q, --quiet do not print progress messages + -d, --debug don't remove temporary files + +Report bugs to ." + +lt_cl_version="\ +m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl +m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION]) +configured by $[0], generated by m4_PACKAGE_STRING. + +Copyright (C) 2011 Free Software Foundation, Inc. +This config.lt script is free software; the Free Software Foundation +gives unlimited permision to copy, distribute and modify it." + +while test 0 != $[#] +do + case $[1] in + --version | --v* | -V ) + echo "$lt_cl_version"; exit 0 ;; + --help | --h* | -h ) + echo "$lt_cl_help"; exit 0 ;; + --debug | --d* | -d ) + debug=: ;; + --quiet | --q* | --silent | --s* | -q ) + lt_cl_silent=: ;; + + -*) AC_MSG_ERROR([unrecognized option: $[1] +Try '$[0] --help' for more information.]) ;; + + *) AC_MSG_ERROR([unrecognized argument: $[1] +Try '$[0] --help' for more information.]) ;; + esac + shift +done + +if $lt_cl_silent; then + exec AS_MESSAGE_FD>/dev/null +fi +_LTEOF + +cat >>"$CONFIG_LT" <<_LTEOF +_LT_OUTPUT_LIBTOOL_COMMANDS_INIT +_LTEOF + +cat >>"$CONFIG_LT" <<\_LTEOF +AC_MSG_NOTICE([creating $ofile]) +_LT_OUTPUT_LIBTOOL_COMMANDS +AS_EXIT(0) +_LTEOF +chmod +x "$CONFIG_LT" + +# configure is writing to config.log, but config.lt does its own redirection, +# appending to config.log, which fails on DOS, as config.log is still kept +# open by configure. Here we exec the FD to /dev/null, effectively closing +# config.log, so it can be properly (re)opened and appended to by config.lt. +lt_cl_success=: +test yes = "$silent" && + lt_config_lt_args="$lt_config_lt_args --quiet" +exec AS_MESSAGE_LOG_FD>/dev/null +$SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false +exec AS_MESSAGE_LOG_FD>>config.log +$lt_cl_success || AS_EXIT(1) +])# LT_OUTPUT + + +# _LT_CONFIG(TAG) +# --------------- +# If TAG is the built-in tag, create an initial libtool script with a +# default configuration from the untagged config vars. Otherwise add code +# to config.status for appending the configuration named by TAG from the +# matching tagged config vars. +m4_defun([_LT_CONFIG], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +_LT_CONFIG_SAVE_COMMANDS([ + m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl + m4_if(_LT_TAG, [C], [ + # See if we are running on zsh, and set the options that allow our + # commands through without removal of \ escapes. + if test -n "${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST + fi + + cfgfile=${ofile}T + trap "$RM \"$cfgfile\"; exit 1" 1 2 15 + $RM "$cfgfile" + + cat <<_LT_EOF >> "$cfgfile" +#! $SHELL +# Generated automatically by $as_me ($PACKAGE) $VERSION +# NOTE: Changes made to this file will be lost: look at ltmain.sh. + +# Provide generalized library-building support services. +# Written by Gordon Matzigkeit, 1996 + +_LT_COPYING +_LT_LIBTOOL_TAGS + +# Configured defaults for sys_lib_dlsearch_path munging. +: \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} + +# ### BEGIN LIBTOOL CONFIG +_LT_LIBTOOL_CONFIG_VARS +_LT_LIBTOOL_TAG_VARS +# ### END LIBTOOL CONFIG + +_LT_EOF + + cat <<'_LT_EOF' >> "$cfgfile" + +# ### BEGIN FUNCTIONS SHARED WITH CONFIGURE + +_LT_PREPARE_MUNGE_PATH_LIST +_LT_PREPARE_CC_BASENAME + +# ### END FUNCTIONS SHARED WITH CONFIGURE + +_LT_EOF + + case $host_os in + aix3*) + cat <<\_LT_EOF >> "$cfgfile" +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test set != "${COLLECT_NAMES+set}"; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +_LT_EOF + ;; + esac + + _LT_PROG_LTMAIN + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '$q' "$ltmain" >> "$cfgfile" \ + || (rm -f "$cfgfile"; exit 1) + + mv -f "$cfgfile" "$ofile" || + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" +], +[cat <<_LT_EOF >> "$ofile" + +dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded +dnl in a comment (ie after a #). +# ### BEGIN LIBTOOL TAG CONFIG: $1 +_LT_LIBTOOL_TAG_VARS(_LT_TAG) +# ### END LIBTOOL TAG CONFIG: $1 +_LT_EOF +])dnl /m4_if +], +[m4_if([$1], [], [ + PACKAGE='$PACKAGE' + VERSION='$VERSION' + RM='$RM' + ofile='$ofile'], []) +])dnl /_LT_CONFIG_SAVE_COMMANDS +])# _LT_CONFIG + + +# LT_SUPPORTED_TAG(TAG) +# --------------------- +# Trace this macro to discover what tags are supported by the libtool +# --tag option, using: +# autoconf --trace 'LT_SUPPORTED_TAG:$1' +AC_DEFUN([LT_SUPPORTED_TAG], []) + + +# C support is built-in for now +m4_define([_LT_LANG_C_enabled], []) +m4_define([_LT_TAGS], []) + + +# LT_LANG(LANG) +# ------------- +# Enable libtool support for the given language if not already enabled. +AC_DEFUN([LT_LANG], +[AC_BEFORE([$0], [LT_OUTPUT])dnl +m4_case([$1], + [C], [_LT_LANG(C)], + [C++], [_LT_LANG(CXX)], + [Go], [_LT_LANG(GO)], + [Java], [_LT_LANG(GCJ)], + [Fortran 77], [_LT_LANG(F77)], + [Fortran], [_LT_LANG(FC)], + [Windows Resource], [_LT_LANG(RC)], + [m4_ifdef([_LT_LANG_]$1[_CONFIG], + [_LT_LANG($1)], + [m4_fatal([$0: unsupported language: "$1"])])])dnl +])# LT_LANG + + +# _LT_LANG(LANGNAME) +# ------------------ +m4_defun([_LT_LANG], +[m4_ifdef([_LT_LANG_]$1[_enabled], [], + [LT_SUPPORTED_TAG([$1])dnl + m4_append([_LT_TAGS], [$1 ])dnl + m4_define([_LT_LANG_]$1[_enabled], [])dnl + _LT_LANG_$1_CONFIG($1)])dnl +])# _LT_LANG + + +m4_ifndef([AC_PROG_GO], [ +############################################################ +# NOTE: This macro has been submitted for inclusion into # +# GNU Autoconf as AC_PROG_GO. When it is available in # +# a released version of Autoconf we should remove this # +# macro and use it instead. # +############################################################ +m4_defun([AC_PROG_GO], +[AC_LANG_PUSH(Go)dnl +AC_ARG_VAR([GOC], [Go compiler command])dnl +AC_ARG_VAR([GOFLAGS], [Go compiler flags])dnl +_AC_ARG_VAR_LDFLAGS()dnl +AC_CHECK_TOOL(GOC, gccgo) +if test -z "$GOC"; then + if test -n "$ac_tool_prefix"; then + AC_CHECK_PROG(GOC, [${ac_tool_prefix}gccgo], [${ac_tool_prefix}gccgo]) + fi +fi +if test -z "$GOC"; then + AC_CHECK_PROG(GOC, gccgo, gccgo, false) +fi +])#m4_defun +])#m4_ifndef + + +# _LT_LANG_DEFAULT_CONFIG +# ----------------------- +m4_defun([_LT_LANG_DEFAULT_CONFIG], +[AC_PROVIDE_IFELSE([AC_PROG_CXX], + [LT_LANG(CXX)], + [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])]) + +AC_PROVIDE_IFELSE([AC_PROG_F77], + [LT_LANG(F77)], + [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])]) + +AC_PROVIDE_IFELSE([AC_PROG_FC], + [LT_LANG(FC)], + [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])]) + +dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal +dnl pulling things in needlessly. +AC_PROVIDE_IFELSE([AC_PROG_GCJ], + [LT_LANG(GCJ)], + [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], + [LT_LANG(GCJ)], + [AC_PROVIDE_IFELSE([LT_PROG_GCJ], + [LT_LANG(GCJ)], + [m4_ifdef([AC_PROG_GCJ], + [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])]) + m4_ifdef([A][M_PROG_GCJ], + [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])]) + m4_ifdef([LT_PROG_GCJ], + [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])]) + +AC_PROVIDE_IFELSE([AC_PROG_GO], + [LT_LANG(GO)], + [m4_define([AC_PROG_GO], defn([AC_PROG_GO])[LT_LANG(GO)])]) + +AC_PROVIDE_IFELSE([LT_PROG_RC], + [LT_LANG(RC)], + [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])]) +])# _LT_LANG_DEFAULT_CONFIG + +# Obsolete macros: +AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)]) +AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)]) +AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)]) +AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)]) +AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_CXX], []) +dnl AC_DEFUN([AC_LIBTOOL_F77], []) +dnl AC_DEFUN([AC_LIBTOOL_FC], []) +dnl AC_DEFUN([AC_LIBTOOL_GCJ], []) +dnl AC_DEFUN([AC_LIBTOOL_RC], []) + + +# _LT_TAG_COMPILER +# ---------------- +m4_defun([_LT_TAG_COMPILER], +[AC_REQUIRE([AC_PROG_CC])dnl + +_LT_DECL([LTCC], [CC], [1], [A C compiler])dnl +_LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl +_LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl +_LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC +])# _LT_TAG_COMPILER + + +# _LT_COMPILER_BOILERPLATE +# ------------------------ +# Check for compiler boilerplate output or warnings with +# the simple compiler test code. +m4_defun([_LT_COMPILER_BOILERPLATE], +[m4_require([_LT_DECL_SED])dnl +ac_outfile=conftest.$ac_objext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$RM conftest* +])# _LT_COMPILER_BOILERPLATE + + +# _LT_LINKER_BOILERPLATE +# ---------------------- +# Check for linker boilerplate output or warnings with +# the simple link test code. +m4_defun([_LT_LINKER_BOILERPLATE], +[m4_require([_LT_DECL_SED])dnl +ac_outfile=conftest.$ac_objext +echo "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$RM -r conftest* +])# _LT_LINKER_BOILERPLATE + +# _LT_REQUIRED_DARWIN_CHECKS +# ------------------------- +m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ + case $host_os in + rhapsody* | darwin*) + AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:]) + AC_CHECK_TOOL([NMEDIT], [nmedit], [:]) + AC_CHECK_TOOL([LIPO], [lipo], [:]) + AC_CHECK_TOOL([OTOOL], [otool], [:]) + AC_CHECK_TOOL([OTOOL64], [otool64], [:]) + _LT_DECL([], [DSYMUTIL], [1], + [Tool to manipulate archived DWARF debug symbol files on Mac OS X]) + _LT_DECL([], [NMEDIT], [1], + [Tool to change global to local symbols on Mac OS X]) + _LT_DECL([], [LIPO], [1], + [Tool to manipulate fat objects and archives on Mac OS X]) + _LT_DECL([], [OTOOL], [1], + [ldd/readelf like tool for Mach-O binaries on Mac OS X]) + _LT_DECL([], [OTOOL64], [1], + [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4]) + + AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod], + [lt_cv_apple_cc_single_mod=no + if test -z "$LT_MULTI_MODULE"; then + # By default we will add the -single_module flag. You can override + # by either setting the environment variable LT_MULTI_MODULE + # non-empty at configure time, or by adding -multi_module to the + # link flags. + rm -rf libconftest.dylib* + echo "int foo(void){return 1;}" > conftest.c + echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ +-dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ + -dynamiclib -Wl,-single_module conftest.c 2>conftest.err + _lt_result=$? + # If there is a non-empty error log, and "single_module" + # appears in it, assume the flag caused a linker warning + if test -s conftest.err && $GREP single_module conftest.err; then + cat conftest.err >&AS_MESSAGE_LOG_FD + # Otherwise, if the output was created with a 0 exit code from + # the compiler, it worked. + elif test -f libconftest.dylib && test 0 = "$_lt_result"; then + lt_cv_apple_cc_single_mod=yes + else + cat conftest.err >&AS_MESSAGE_LOG_FD + fi + rm -rf libconftest.dylib* + rm -f conftest.* + fi]) + + AC_CACHE_CHECK([for -exported_symbols_list linker flag], + [lt_cv_ld_exported_symbols_list], + [lt_cv_ld_exported_symbols_list=no + save_LDFLAGS=$LDFLAGS + echo "_main" > conftest.sym + LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" + AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], + [lt_cv_ld_exported_symbols_list=yes], + [lt_cv_ld_exported_symbols_list=no]) + LDFLAGS=$save_LDFLAGS + ]) + + AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load], + [lt_cv_ld_force_load=no + cat > conftest.c << _LT_EOF +int forced_loaded() { return 2;} +_LT_EOF + echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD + echo "$AR cru libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD + $AR cru libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD + echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD + $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD + cat > conftest.c << _LT_EOF +int main() { return 0;} +_LT_EOF + echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err + _lt_result=$? + if test -s conftest.err && $GREP force_load conftest.err; then + cat conftest.err >&AS_MESSAGE_LOG_FD + elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then + lt_cv_ld_force_load=yes + else + cat conftest.err >&AS_MESSAGE_LOG_FD + fi + rm -f conftest.err libconftest.a conftest conftest.c + rm -rf conftest.dSYM + ]) + case $host_os in + rhapsody* | darwin1.[[012]]) + _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;; + darwin1.*) + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; + darwin*) # darwin 5.x on + # if running on 10.5 or later, the deployment target defaults + # to the OS version, if on x86, and 10.4, the deployment + # target defaults to 10.4. Don't you love it? + case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in + 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*) + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; + 10.[[012]][[,.]]*) + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; + 10.*) + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; + esac + ;; + esac + if test yes = "$lt_cv_apple_cc_single_mod"; then + _lt_dar_single_mod='$single_module' + fi + if test yes = "$lt_cv_ld_exported_symbols_list"; then + _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym' + else + _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib' + fi + if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then + _lt_dsymutil='~$DSYMUTIL $lib || :' + else + _lt_dsymutil= + fi + ;; + esac +]) + + +# _LT_DARWIN_LINKER_FEATURES([TAG]) +# --------------------------------- +# Checks for linker and compiler features on darwin +m4_defun([_LT_DARWIN_LINKER_FEATURES], +[ + m4_require([_LT_REQUIRED_DARWIN_CHECKS]) + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_automatic, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + if test yes = "$lt_cv_ld_force_load"; then + _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + m4_case([$1], [F77], [_LT_TAGVAR(compiler_needs_object, $1)=yes], + [FC], [_LT_TAGVAR(compiler_needs_object, $1)=yes]) + else + _LT_TAGVAR(whole_archive_flag_spec, $1)='' + fi + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=$_lt_dar_allow_undefined + case $cc_basename in + ifort*|nagfor*) _lt_dar_can_shared=yes ;; + *) _lt_dar_can_shared=$GCC ;; + esac + if test yes = "$_lt_dar_can_shared"; then + output_verbose_link_cmd=func_echo_all + _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" + _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" + _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" + _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" + m4_if([$1], [CXX], +[ if test yes != "$lt_cv_apple_cc_single_mod"; then + _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dsymutil" + _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil" + fi +],[]) + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi +]) + +# _LT_SYS_MODULE_PATH_AIX([TAGNAME]) +# ---------------------------------- +# Links a minimal program and checks the executable +# for the system default hardcoded library path. In most cases, +# this is /usr/lib:/lib, but when the MPI compilers are used +# the location of the communication and MPI libs are included too. +# If we don't find anything, use the default library path according +# to the aix ld manual. +# Store the results from the different compilers for each TAGNAME. +# Allow to override them for all tags through lt_cv_aix_libpath. +m4_defun([_LT_SYS_MODULE_PATH_AIX], +[m4_require([_LT_DECL_SED])dnl +if test set = "${lt_cv_aix_libpath+set}"; then + aix_libpath=$lt_cv_aix_libpath +else + AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])], + [AC_LINK_IFELSE([AC_LANG_PROGRAM],[ + lt_aix_libpath_sed='[ + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }]' + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi],[]) + if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=/usr/lib:/lib + fi + ]) + aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1]) +fi +])# _LT_SYS_MODULE_PATH_AIX + + +# _LT_SHELL_INIT(ARG) +# ------------------- +m4_define([_LT_SHELL_INIT], +[m4_divert_text([M4SH-INIT], [$1 +])])# _LT_SHELL_INIT + + + +# _LT_PROG_ECHO_BACKSLASH +# ----------------------- +# Find how we can fake an echo command that does not interpret backslash. +# In particular, with Autoconf 2.60 or later we add some code to the start +# of the generated configure script that will find a shell with a builtin +# printf (that we can use as an echo command). +m4_defun([_LT_PROG_ECHO_BACKSLASH], +[ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + +AC_MSG_CHECKING([how to print strings]) +# Test print first, because it will be a builtin if present. +if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ + test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='print -r --' +elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='printf %s\n' +else + # Use this function as a fallback that always works. + func_fallback_echo () + { + eval 'cat <<_LTECHO_EOF +$[]1 +_LTECHO_EOF' + } + ECHO='func_fallback_echo' +fi + +# func_echo_all arg... +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "$*" +} + +case $ECHO in + printf*) AC_MSG_RESULT([printf]) ;; + print*) AC_MSG_RESULT([print -r]) ;; + *) AC_MSG_RESULT([cat]) ;; +esac + +m4_ifdef([_AS_DETECT_SUGGESTED], +[_AS_DETECT_SUGGESTED([ + test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || ( + ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' + ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO + ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + PATH=/empty FPATH=/empty; export PATH FPATH + test "X`printf %s $ECHO`" = "X$ECHO" \ + || test "X`print -r -- $ECHO`" = "X$ECHO" )])]) + +_LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts]) +_LT_DECL([], [ECHO], [1], [An echo program that protects backslashes]) +])# _LT_PROG_ECHO_BACKSLASH + + +# _LT_WITH_SYSROOT +# ---------------- +AC_DEFUN([_LT_WITH_SYSROOT], +[AC_MSG_CHECKING([for sysroot]) +AC_ARG_WITH([sysroot], +[AS_HELP_STRING([--with-sysroot@<:@=DIR@:>@], + [Search for dependent libraries within DIR (or the compiler's sysroot + if not specified).])], +[], [with_sysroot=no]) + +dnl lt_sysroot will always be passed unquoted. We quote it here +dnl in case the user passed a directory name. +lt_sysroot= +case $with_sysroot in #( + yes) + if test yes = "$GCC"; then + lt_sysroot=`$CC --print-sysroot 2>/dev/null` + fi + ;; #( + /*) + lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` + ;; #( + no|'') + ;; #( + *) + AC_MSG_RESULT([$with_sysroot]) + AC_MSG_ERROR([The sysroot must be an absolute path.]) + ;; +esac + + AC_MSG_RESULT([${lt_sysroot:-no}]) +_LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl +[dependent libraries, and where our libraries should be installed.])]) + +# _LT_ENABLE_LOCK +# --------------- +m4_defun([_LT_ENABLE_LOCK], +[AC_ARG_ENABLE([libtool-lock], + [AS_HELP_STRING([--disable-libtool-lock], + [avoid locking (might break parallel builds)])]) +test no = "$enable_libtool_lock" || enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out what ABI is being produced by ac_compile, and set mode + # options accordingly. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE=32 + ;; + *ELF-64*) + HPUX_IA64_MODE=64 + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + if test yes = "$lt_cv_prog_gnu_ld"; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +mips64*-*linux*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + emul=elf + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + emul="${emul}32" + ;; + *64-bit*) + emul="${emul}64" + ;; + esac + case `/usr/bin/file conftest.$ac_objext` in + *MSB*) + emul="${emul}btsmip" + ;; + *LSB*) + emul="${emul}ltsmip" + ;; + esac + case `/usr/bin/file conftest.$ac_objext` in + *N32*) + emul="${emul}n32" + ;; + esac + LD="${LD-ld} -m $emul" + fi + rm -rf conftest* + ;; + +x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ +s390*-*linux*|s390*-*tpf*|sparc*-*linux*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. Note that the listed cases only cover the + # situations where additional linker options are needed (such as when + # doing 32-bit compilation for a host where ld defaults to 64-bit, or + # vice versa); the common cases where no linker options are needed do + # not appear in the list. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_i386_fbsd" + ;; + x86_64-*linux*) + case `/usr/bin/file conftest.o` in + *x86-64*) + LD="${LD-ld} -m elf32_x86_64" + ;; + *) + LD="${LD-ld} -m elf_i386" + ;; + esac + ;; + powerpc64le-*linux*) + LD="${LD-ld} -m elf32lppclinux" + ;; + powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_x86_64_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + powerpcle-*linux*) + LD="${LD-ld} -m elf64lppc" + ;; + powerpc-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*|s390*-*tpf*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS=$CFLAGS + CFLAGS="$CFLAGS -belf" + AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, + [AC_LANG_PUSH(C) + AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) + AC_LANG_POP]) + if test yes != "$lt_cv_cc_needs_belf"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS=$SAVE_CFLAGS + fi + ;; +*-*solaris*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) + case $host in + i?86-*-solaris*|x86_64-*-solaris*) + LD="${LD-ld} -m elf_x86_64" + ;; + sparc*-*-solaris*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + # GNU ld 2.21 introduced _sol2 emulations. Use them if available. + if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then + LD=${LD-ld}_sol2 + fi + ;; + *) + if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then + LD="${LD-ld} -64" + fi + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; +esac + +need_locks=$enable_libtool_lock +])# _LT_ENABLE_LOCK + + +# _LT_PROG_AR +# ----------- +m4_defun([_LT_PROG_AR], +[AC_CHECK_TOOLS(AR, [ar], false) +: ${AR=ar} +: ${AR_FLAGS=cru} +_LT_DECL([], [AR], [1], [The archiver]) +_LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive]) + +AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file], + [lt_cv_ar_at_file=no + AC_COMPILE_IFELSE([AC_LANG_PROGRAM], + [echo conftest.$ac_objext > conftest.lst + lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD' + AC_TRY_EVAL([lt_ar_try]) + if test 0 -eq "$ac_status"; then + # Ensure the archiver fails upon bogus file names. + rm -f conftest.$ac_objext libconftest.a + AC_TRY_EVAL([lt_ar_try]) + if test 0 -ne "$ac_status"; then + lt_cv_ar_at_file=@ + fi + fi + rm -f conftest.* libconftest.a + ]) + ]) + +if test no = "$lt_cv_ar_at_file"; then + archiver_list_spec= +else + archiver_list_spec=$lt_cv_ar_at_file +fi +_LT_DECL([], [archiver_list_spec], [1], + [How to feed a file listing to the archiver]) +])# _LT_PROG_AR + + +# _LT_CMD_OLD_ARCHIVE +# ------------------- +m4_defun([_LT_CMD_OLD_ARCHIVE], +[_LT_PROG_AR + +AC_CHECK_TOOL(STRIP, strip, :) +test -z "$STRIP" && STRIP=: +_LT_DECL([], [STRIP], [1], [A symbol stripping program]) + +AC_CHECK_TOOL(RANLIB, ranlib, :) +test -z "$RANLIB" && RANLIB=: +_LT_DECL([], [RANLIB], [1], + [Commands used to install an old-style archive]) + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + bitrig* | openbsd*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" + ;; + *) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" +fi + +case $host_os in + darwin*) + lock_old_archive_extraction=yes ;; + *) + lock_old_archive_extraction=no ;; +esac +_LT_DECL([], [old_postinstall_cmds], [2]) +_LT_DECL([], [old_postuninstall_cmds], [2]) +_LT_TAGDECL([], [old_archive_cmds], [2], + [Commands used to build an old-style archive]) +_LT_DECL([], [lock_old_archive_extraction], [0], + [Whether to use a lock for old archive extraction]) +])# _LT_CMD_OLD_ARCHIVE + + +# _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) +# ---------------------------------------------------------------- +# Check whether the given compiler option works +AC_DEFUN([_LT_COMPILER_OPTION], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_SED])dnl +AC_CACHE_CHECK([$1], [$2], + [$2=no + m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$3" ## exclude from sc_useless_quotes_in_assignment + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + fi + $RM conftest* +]) + +if test yes = "[$]$2"; then + m4_if([$5], , :, [$5]) +else + m4_if([$6], , :, [$6]) +fi +])# _LT_COMPILER_OPTION + +# Old name: +AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], []) + + +# _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [ACTION-SUCCESS], [ACTION-FAILURE]) +# ---------------------------------------------------- +# Check whether the given linker option works +AC_DEFUN([_LT_LINKER_OPTION], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_SED])dnl +AC_CACHE_CHECK([$1], [$2], + [$2=no + save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS $3" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&AS_MESSAGE_LOG_FD + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + else + $2=yes + fi + fi + $RM -r conftest* + LDFLAGS=$save_LDFLAGS +]) + +if test yes = "[$]$2"; then + m4_if([$4], , :, [$4]) +else + m4_if([$5], , :, [$5]) +fi +])# _LT_LINKER_OPTION + +# Old name: +AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], []) + + +# LT_CMD_MAX_LEN +#--------------- +AC_DEFUN([LT_CMD_MAX_LEN], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +# find the maximum length of command line arguments +AC_MSG_CHECKING([the maximum length of command line arguments]) +AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl + i=0 + teststring=ABCD + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw* | cegcc*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + mint*) + # On MiNT this can take a long time and run out of memory. + lt_cv_sys_max_cmd_len=8192; + ;; + + amigaos*) + # On AmigaOS with pdksh, this test takes hours, literally. + # So we just punt and use a minimum line length of 8192. + lt_cv_sys_max_cmd_len=8192; + ;; + + bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*) + # This has been around since 386BSD, at least. Likely further. + if test -x /sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + ;; + + interix*) + # We know the value 262144 and hardcode it with a safety zone (like BSD) + lt_cv_sys_max_cmd_len=196608 + ;; + + os2*) + # The test takes a long time on OS/2. + lt_cv_sys_max_cmd_len=8192 + ;; + + osf*) + # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure + # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + sco3.2v5*) + lt_cv_sys_max_cmd_len=102400 + ;; + sysv5* | sco5v6* | sysv4.2uw2*) + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) + lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` + if test -n "$lt_cv_sys_max_cmd_len" && \ + test undefined != "$lt_cv_sys_max_cmd_len"; then + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + else + # Make teststring a little bigger before we do anything with it. + # a 1K string should be a reasonable start. + for i in 1 2 3 4 5 6 7 8; do + teststring=$teststring$teststring + done + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + # If test is not a shell built-in, we'll probably end up computing a + # maximum length that is only half of the actual maximum length, but + # we can't tell. + while { test X`env echo "$teststring$teststring" 2>/dev/null` \ + = "X$teststring$teststring"; } >/dev/null 2>&1 && + test 17 != "$i" # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + # Only check the string length outside the loop. + lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` + teststring= + # Add a significant safety factor because C++ compilers can tack on + # massive amounts of additional arguments before passing them to the + # linker. It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + fi + ;; + esac +]) +if test -n "$lt_cv_sys_max_cmd_len"; then + AC_MSG_RESULT($lt_cv_sys_max_cmd_len) +else + AC_MSG_RESULT(none) +fi +max_cmd_len=$lt_cv_sys_max_cmd_len +_LT_DECL([], [max_cmd_len], [0], + [What is the maximum length of a command?]) +])# LT_CMD_MAX_LEN + +# Old name: +AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], []) + + +# _LT_HEADER_DLFCN +# ---------------- +m4_defun([_LT_HEADER_DLFCN], +[AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl +])# _LT_HEADER_DLFCN + + +# _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, +# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) +# ---------------------------------------------------------------- +m4_defun([_LT_TRY_DLOPEN_SELF], +[m4_require([_LT_HEADER_DLFCN])dnl +if test yes = "$cross_compiling"; then : + [$4] +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +[#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisibility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +}] +_LT_EOF + if AC_TRY_EVAL(ac_link) && test -s "conftest$ac_exeext" 2>/dev/null; then + (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) $1 ;; + x$lt_dlneed_uscore) $2 ;; + x$lt_dlunknown|x*) $3 ;; + esac + else : + # compilation failed + $3 + fi +fi +rm -fr conftest* +])# _LT_TRY_DLOPEN_SELF + + +# LT_SYS_DLOPEN_SELF +# ------------------ +AC_DEFUN([LT_SYS_DLOPEN_SELF], +[m4_require([_LT_HEADER_DLFCN])dnl +if test yes != "$enable_dlopen"; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen=load_add_on + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32* | cegcc*) + lt_cv_dlopen=LoadLibrary + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen=dlopen + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl],[ + lt_cv_dlopen=dyld + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ]) + ;; + + tpf*) + # Don't try to run any link tests for TPF. We know it's impossible + # because TPF is a cross-compiler, and we know how we open DSOs. + lt_cv_dlopen=dlopen + lt_cv_dlopen_libs= + lt_cv_dlopen_self=no + ;; + + *) + AC_CHECK_FUNC([shl_load], + [lt_cv_dlopen=shl_load], + [AC_CHECK_LIB([dld], [shl_load], + [lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld], + [AC_CHECK_FUNC([dlopen], + [lt_cv_dlopen=dlopen], + [AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl], + [AC_CHECK_LIB([svld], [dlopen], + [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld], + [AC_CHECK_LIB([dld], [dld_link], + [lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld]) + ]) + ]) + ]) + ]) + ]) + ;; + esac + + if test no = "$lt_cv_dlopen"; then + enable_dlopen=no + else + enable_dlopen=yes + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS=$CPPFLAGS + test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS=$LDFLAGS + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS=$LIBS + LIBS="$lt_cv_dlopen_libs $LIBS" + + AC_CACHE_CHECK([whether a program can dlopen itself], + lt_cv_dlopen_self, [dnl + _LT_TRY_DLOPEN_SELF( + lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, + lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) + ]) + + if test yes = "$lt_cv_dlopen_self"; then + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" + AC_CACHE_CHECK([whether a statically linked program can dlopen itself], + lt_cv_dlopen_self_static, [dnl + _LT_TRY_DLOPEN_SELF( + lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, + lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) + ]) + fi + + CPPFLAGS=$save_CPPFLAGS + LDFLAGS=$save_LDFLAGS + LIBS=$save_LIBS + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi +_LT_DECL([dlopen_support], [enable_dlopen], [0], + [Whether dlopen is supported]) +_LT_DECL([dlopen_self], [enable_dlopen_self], [0], + [Whether dlopen of programs is supported]) +_LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0], + [Whether dlopen of statically linked programs is supported]) +])# LT_SYS_DLOPEN_SELF + +# Old name: +AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], []) + + +# _LT_COMPILER_C_O([TAGNAME]) +# --------------------------- +# Check to see if options -c and -o are simultaneously supported by compiler. +# This macro does not hard code the compiler like AC_PROG_CC_C_O. +m4_defun([_LT_COMPILER_C_O], +[m4_require([_LT_DECL_SED])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_TAG_COMPILER])dnl +AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], + [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)], + [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + fi + fi + chmod u+w . 2>&AS_MESSAGE_LOG_FD + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* +]) +_LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1], + [Does compiler simultaneously support -c and -o options?]) +])# _LT_COMPILER_C_O + + +# _LT_COMPILER_FILE_LOCKS([TAGNAME]) +# ---------------------------------- +# Check to see if we can do hard links to lock some files if needed +m4_defun([_LT_COMPILER_FILE_LOCKS], +[m4_require([_LT_ENABLE_LOCK])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +_LT_COMPILER_C_O([$1]) + +hard_links=nottested +if test no = "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" && test no != "$need_locks"; then + # do not overwrite the value of need_locks provided by the user + AC_MSG_CHECKING([if we can lock with hard links]) + hard_links=yes + $RM conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + AC_MSG_RESULT([$hard_links]) + if test no = "$hard_links"; then + AC_MSG_WARN(['$CC' does not support '-c -o', so 'make -j' may be unsafe]) + need_locks=warn + fi +else + need_locks=no +fi +_LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?]) +])# _LT_COMPILER_FILE_LOCKS + + +# _LT_CHECK_OBJDIR +# ---------------- +m4_defun([_LT_CHECK_OBJDIR], +[AC_CACHE_CHECK([for objdir], [lt_cv_objdir], +[rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null]) +objdir=$lt_cv_objdir +_LT_DECL([], [objdir], [0], + [The name of the directory that contains temporary libtool files])dnl +m4_pattern_allow([LT_OBJDIR])dnl +AC_DEFINE_UNQUOTED([LT_OBJDIR], "$lt_cv_objdir/", + [Define to the sub-directory where libtool stores uninstalled libraries.]) +])# _LT_CHECK_OBJDIR + + +# _LT_LINKER_HARDCODE_LIBPATH([TAGNAME]) +# -------------------------------------- +# Check hardcoding attributes. +m4_defun([_LT_LINKER_HARDCODE_LIBPATH], +[AC_MSG_CHECKING([how to hardcode library paths into programs]) +_LT_TAGVAR(hardcode_action, $1)= +if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" || + test -n "$_LT_TAGVAR(runpath_var, $1)" || + test yes = "$_LT_TAGVAR(hardcode_automatic, $1)"; then + + # We can hardcode non-existent directories. + if test no != "$_LT_TAGVAR(hardcode_direct, $1)" && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" && + test no != "$_LT_TAGVAR(hardcode_minus_L, $1)"; then + # Linking always hardcodes the temporary library directory. + _LT_TAGVAR(hardcode_action, $1)=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + _LT_TAGVAR(hardcode_action, $1)=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + _LT_TAGVAR(hardcode_action, $1)=unsupported +fi +AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)]) + +if test relink = "$_LT_TAGVAR(hardcode_action, $1)" || + test yes = "$_LT_TAGVAR(inherit_rpath, $1)"; then + # Fast installation is not supported + enable_fast_install=no +elif test yes = "$shlibpath_overrides_runpath" || + test no = "$enable_shared"; then + # Fast installation is not necessary + enable_fast_install=needless +fi +_LT_TAGDECL([], [hardcode_action], [0], + [How to hardcode a shared library path into an executable]) +])# _LT_LINKER_HARDCODE_LIBPATH + + +# _LT_CMD_STRIPLIB +# ---------------- +m4_defun([_LT_CMD_STRIPLIB], +[m4_require([_LT_DECL_EGREP]) +striplib= +old_striplib= +AC_MSG_CHECKING([whether stripping libraries is possible]) +if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + AC_MSG_RESULT([yes]) +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP"; then + striplib="$STRIP -x" + old_striplib="$STRIP -S" + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + fi + ;; + *) + AC_MSG_RESULT([no]) + ;; + esac +fi +_LT_DECL([], [old_striplib], [1], [Commands to strip libraries]) +_LT_DECL([], [striplib], [1]) +])# _LT_CMD_STRIPLIB + + +# _LT_PREPARE_MUNGE_PATH_LIST +# --------------------------- +# Make sure func_munge_path_list() is defined correctly. +m4_defun([_LT_PREPARE_MUNGE_PATH_LIST], +[[# func_munge_path_list VARIABLE PATH +# ----------------------------------- +# VARIABLE is name of variable containing _space_ separated list of +# directories to be munged by the contents of PATH, which is string +# having a format: +# "DIR[:DIR]:" +# string "DIR[ DIR]" will be prepended to VARIABLE +# ":DIR[:DIR]" +# string "DIR[ DIR]" will be appended to VARIABLE +# "DIRP[:DIRP]::[DIRA:]DIRA" +# string "DIRP[ DIRP]" will be prepended to VARIABLE and string +# "DIRA[ DIRA]" will be appended to VARIABLE +# "DIR[:DIR]" +# VARIABLE will be replaced by "DIR[ DIR]" +func_munge_path_list () +{ + case x@S|@2 in + x) + ;; + *:) + eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'` \@S|@@S|@1\" + ;; + x:*) + eval @S|@1=\"\@S|@@S|@1 `$ECHO @S|@2 | $SED 's/:/ /g'`\" + ;; + *::*) + eval @S|@1=\"\@S|@@S|@1\ `$ECHO @S|@2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" + eval @S|@1=\"`$ECHO @S|@2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \@S|@@S|@1\" + ;; + *) + eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'`\" + ;; + esac +} +]])# _LT_PREPARE_PATH_LIST + + +# _LT_SYS_DYNAMIC_LINKER([TAG]) +# ----------------------------- +# PORTME Fill in your ld.so characteristics +m4_defun([_LT_SYS_DYNAMIC_LINKER], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_OBJDUMP])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_CHECK_SHELL_FEATURES])dnl +m4_require([_LT_PREPARE_MUNGE_PATH_LIST])dnl +AC_MSG_CHECKING([dynamic linker characteristics]) +m4_if([$1], + [], [ +if test yes = "$GCC"; then + case $host_os in + darwin*) lt_awk_arg='/^libraries:/,/LR/' ;; + *) lt_awk_arg='/^libraries:/' ;; + esac + case $host_os in + mingw* | cegcc*) lt_sed_strip_eq='s|=\([[A-Za-z]]:\)|\1|g' ;; + *) lt_sed_strip_eq='s|=/|/|g' ;; + esac + lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` + case $lt_search_path_spec in + *\;*) + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` + ;; + *) + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` + ;; + esac + # Ok, now we have the path, separated by spaces, we can step through it + # and add multilib dir if necessary... + lt_tmp_lt_search_path_spec= + lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + # ...but if some path component already ends with the multilib dir we assume + # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer). + case "$lt_multi_os_dir; $lt_search_path_spec " in + "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*) + lt_multi_os_dir= + ;; + esac + for lt_sys_path in $lt_search_path_spec; do + if test -d "$lt_sys_path$lt_multi_os_dir"; then + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir" + elif test -n "$lt_multi_os_dir"; then + test -d "$lt_sys_path" && \ + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" + fi + done + lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' +BEGIN {RS = " "; FS = "/|\n";} { + lt_foo = ""; + lt_count = 0; + for (lt_i = NF; lt_i > 0; lt_i--) { + if ($lt_i != "" && $lt_i != ".") { + if ($lt_i == "..") { + lt_count++; + } else { + if (lt_count == 0) { + lt_foo = "/" $lt_i lt_foo; + } else { + lt_count--; + } + } + } + } + if (lt_foo != "") { lt_freq[[lt_foo]]++; } + if (lt_freq[[lt_foo]] == 1) { print lt_foo; } +}'` + # AWK program above erroneously prepends '/' to C:/dos/paths + # for these hosts. + case $host_os in + mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ + $SED 's|/\([[A-Za-z]]:\)|\1|g'` ;; + esac + sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi]) +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=.so +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +AC_ARG_VAR([LT_SYS_LIBRARY_PATH], +[User-defined run-time library search path.]) + +case $host_os in +aix3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='$libname$release$shared_ext$major' + ;; + +aix[[4-9]]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test ia64 = "$host_cpu"; then + # AIX 5 supports IA64 + library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line '#! .'. This would cause the generated library to + # depend on '.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[[01]] | aix4.[[01]].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # Using Import Files as archive members, it is possible to support + # filename-based versioning of shared library archives on AIX. While + # this would work for both with and without runtime linking, it will + # prevent static linking of such archives. So we do filename-based + # shared library versioning with .so extension only, which is used + # when both runtime linking and shared linking is enabled. + # Unfortunately, runtime linking may impact performance, so we do + # not want this to be the default eventually. Also, we use the + # versioned .so libs for executables only if there is the -brtl + # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. + # To allow for filename-based versioning support, we need to create + # libNAME.so.V as an archive file, containing: + # *) an Import File, referring to the versioned filename of the + # archive as well as the shared archive member, telling the + # bitwidth (32 or 64) of that shared object, and providing the + # list of exported symbols of that shared object, eventually + # decorated with the 'weak' keyword + # *) the shared object with the F_LOADONLY flag set, to really avoid + # it being seen by the linker. + # At run time we better use the real file rather than another symlink, + # but for link time we create the symlink libNAME.so -> libNAME.so.V + + case $with_aix_soname,$aix_use_runtimelinking in + # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + aix,yes) # traditional libtool + dynamic_linker='AIX unversionable lib.so' + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + aix,no) # traditional AIX only + dynamic_linker='AIX lib.a[(]lib.so.V[)]' + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + ;; + svr4,*) # full svr4 only + dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)]" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,yes) # both, prefer svr4 + dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)], lib.a[(]lib.so.V[)]" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # unpreferred sharedlib libNAME.a needs extra handling + postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' + postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,no) # both, prefer aix + dynamic_linker="AIX lib.a[(]lib.so.V[)], lib.so.V[(]$shared_archive_member_spec.o[)]" + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling + postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' + postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' + ;; + esac + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + case $host_cpu in + powerpc) + # Since July 2007 AmigaOS4 officially supports .so libraries. + # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + m68k) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + esac + ;; + +beos*) + library_names_spec='$libname$shared_ext' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[[45]]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32* | cegcc*) + version_type=windows + shrext_cmds=.dll + need_version=no + need_lib_prefix=no + + case $GCC,$cc_basename in + yes,*) + # gcc + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' +m4_if([$1], [],[ + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"]) + ;; + mingw* | cegcc*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' + ;; + esac + dynamic_linker='Win32 ld.exe' + ;; + + *,cl*) + # Native MSVC + libname_spec='$name' + soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' + library_names_spec='$libname.dll.lib' + + case $build_os in + mingw*) + sys_lib_search_path_spec= + lt_save_ifs=$IFS + IFS=';' + for lt_path in $LIB + do + IFS=$lt_save_ifs + # Let DOS variable expansion print the short 8.3 style file name. + lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` + sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" + done + IFS=$lt_save_ifs + # Convert to MSYS style. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'` + ;; + cygwin*) + # Convert to unix form, then to dos form, then back to unix form + # but this time dos style (no spaces!) so that the unix form looks + # like /cygdrive/c/PROGRA~1:/cygdr... + sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` + sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` + sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + ;; + *) + sys_lib_search_path_spec=$LIB + if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then + # It is most probably a Windows format PATH. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + # FIXME: find the short name or the path components, as spaces are + # common. (e.g. "Program Files" -> "PROGRA~1") + ;; + esac + + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + dynamic_linker='Win32 link.exe' + ;; + + *) + # Assume MSVC wrapper + library_names_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext $libname.lib' + dynamic_linker='Win32 ld.exe' + ;; + esac + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' + soname_spec='$libname$release$major$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' +m4_if([$1], [],[ + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"]) + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[[23]].*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2.*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[[01]]* | freebsdelf3.[[01]]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ + freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +haiku*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + dynamic_linker="$host_os runtime_loader" + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LIBRARY_PATH + shlibpath_overrides_runpath=no + sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + if test 32 = "$HPUX_IA64_MODE"; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + sys_lib_dlsearch_path_spec=/usr/lib/hpux32 + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + sys_lib_dlsearch_path_spec=/usr/lib/hpux64 + fi + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555, ... + postinstall_cmds='chmod 555 $lib' + # or fails outright, so override atomically: + install_override_mode=555 + ;; + +interix[[3-9]]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test yes = "$lt_cv_prog_gnu_ld"; then + version_type=linux # correct to gnu/linux during the next big refactor + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" + sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +linux*android*) + version_type=none # Android doesn't support versioned libraries. + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext' + soname_spec='$libname$release$shared_ext' + finish_cmds= + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + dynamic_linker='Android linker' + # Don't embed -rpath directories since the linker doesn't support them. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + + # Some binutils ld are patched to set DT_RUNPATH + AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath], + [lt_cv_shlibpath_overrides_runpath=no + save_LDFLAGS=$LDFLAGS + save_libdir=$libdir + eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \ + LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\"" + AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], + [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null], + [lt_cv_shlibpath_overrides_runpath=yes])]) + LDFLAGS=$save_LDFLAGS + libdir=$save_libdir + ]) + shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Ideally, we could use ldconfig to report *all* directores which are + # searched for libraries, however this is still not possible. Aside from not + # being certain /sbin/ldconfig is available, command + # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, + # even though it is searched at run-time. Try to do the best guess by + # appending ld.so.conf contents (and includes) to the search path. + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsdelf*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='NetBSD ld.elf_so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +*nto* | *qnx*) + version_type=qnx + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='ldqnx.so' + ;; + +openbsd* | bitrig*) + version_type=sunos + sys_lib_dlsearch_path_spec=/usr/lib + need_lib_prefix=no + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + need_version=no + else + need_version=yes + fi + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +os2*) + libname_spec='$name' + version_type=windows + shrext_cmds=.dll + need_version=no + need_lib_prefix=no + # OS/2 can only load a DLL with a base name of 8 characters or less. + soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; + v=$($ECHO $release$versuffix | tr -d .-); + n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); + $ECHO $n$v`$shared_ext' + library_names_spec='${libname}_dll.$libext' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=BEGINLIBPATH + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + +rdos*) + dynamic_linker=no + ;; + +solaris*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test yes = "$with_gnu_ld"; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec; then + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' + soname_spec='$libname$shared_ext.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=sco + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + if test yes = "$with_gnu_ld"; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +tpf*) + # TPF is a cross-target only. Preferred cross-host = GNU/Linux. + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +uts4*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +AC_MSG_RESULT([$dynamic_linker]) +test no = "$dynamic_linker" && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test yes = "$GCC"; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then + sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec +fi + +if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then + sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec +fi + +# remember unaugmented sys_lib_dlsearch_path content for libtool script decls... +configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec + +# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code +func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" + +# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool +configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH + +_LT_DECL([], [variables_saved_for_relink], [1], + [Variables whose values should be saved in libtool wrapper scripts and + restored at link time]) +_LT_DECL([], [need_lib_prefix], [0], + [Do we need the "lib" prefix for modules?]) +_LT_DECL([], [need_version], [0], [Do we need a version for libraries?]) +_LT_DECL([], [version_type], [0], [Library versioning type]) +_LT_DECL([], [runpath_var], [0], [Shared library runtime path variable]) +_LT_DECL([], [shlibpath_var], [0],[Shared library path variable]) +_LT_DECL([], [shlibpath_overrides_runpath], [0], + [Is shlibpath searched before the hard-coded library search path?]) +_LT_DECL([], [libname_spec], [1], [Format of library name prefix]) +_LT_DECL([], [library_names_spec], [1], + [[List of archive names. First name is the real one, the rest are links. + The last name is the one that the linker finds with -lNAME]]) +_LT_DECL([], [soname_spec], [1], + [[The coded name of the library, if different from the real name]]) +_LT_DECL([], [install_override_mode], [1], + [Permission mode override for installation of shared libraries]) +_LT_DECL([], [postinstall_cmds], [2], + [Command to use after installation of a shared archive]) +_LT_DECL([], [postuninstall_cmds], [2], + [Command to use after uninstallation of a shared archive]) +_LT_DECL([], [finish_cmds], [2], + [Commands used to finish a libtool library installation in a directory]) +_LT_DECL([], [finish_eval], [1], + [[As "finish_cmds", except a single script fragment to be evaled but + not shown]]) +_LT_DECL([], [hardcode_into_libs], [0], + [Whether we should hardcode library paths into libraries]) +_LT_DECL([], [sys_lib_search_path_spec], [2], + [Compile-time system search path for libraries]) +_LT_DECL([sys_lib_dlsearch_path_spec], [configure_time_dlsearch_path], [2], + [Detected run-time system search path for libraries]) +_LT_DECL([], [configure_time_lt_sys_library_path], [2], + [Explicit LT_SYS_LIBRARY_PATH set during ./configure time]) +])# _LT_SYS_DYNAMIC_LINKER + + +# _LT_PATH_TOOL_PREFIX(TOOL) +# -------------------------- +# find a file program that can recognize shared library +AC_DEFUN([_LT_PATH_TOOL_PREFIX], +[m4_require([_LT_DECL_EGREP])dnl +AC_MSG_CHECKING([for $1]) +AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, +[case $MAGIC_CMD in +[[\\/*] | ?:[\\/]*]) + lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD=$MAGIC_CMD + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR +dnl $ac_dummy forces splitting on constant user-supplied paths. +dnl POSIX.2 word splitting is done only on the output of word expansions, +dnl not every word. This closes a longstanding sh security hole. + ac_dummy="m4_if([$2], , $PATH, [$2])" + for ac_dir in $ac_dummy; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$1"; then + lt_cv_path_MAGIC_CMD=$ac_dir/"$1" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD=$lt_cv_path_MAGIC_CMD + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS=$lt_save_ifs + MAGIC_CMD=$lt_save_MAGIC_CMD + ;; +esac]) +MAGIC_CMD=$lt_cv_path_MAGIC_CMD +if test -n "$MAGIC_CMD"; then + AC_MSG_RESULT($MAGIC_CMD) +else + AC_MSG_RESULT(no) +fi +_LT_DECL([], [MAGIC_CMD], [0], + [Used to examine libraries when file_magic_cmd begins with "file"])dnl +])# _LT_PATH_TOOL_PREFIX + +# Old name: +AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], []) + + +# _LT_PATH_MAGIC +# -------------- +# find a file program that can recognize a shared library +m4_defun([_LT_PATH_MAGIC], +[_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) + else + MAGIC_CMD=: + fi +fi +])# _LT_PATH_MAGIC + + +# LT_PATH_LD +# ---------- +# find the pathname to the GNU or non-GNU linker +AC_DEFUN([LT_PATH_LD], +[AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_PROG_ECHO_BACKSLASH])dnl + +AC_ARG_WITH([gnu-ld], + [AS_HELP_STRING([--with-gnu-ld], + [assume the C compiler uses GNU ld @<:@default=no@:>@])], + [test no = "$withval" || with_gnu_ld=yes], + [with_gnu_ld=no])dnl + +ac_prog=ld +if test yes = "$GCC"; then + # Check if gcc -print-prog-name=ld gives a path. + AC_MSG_CHECKING([for ld used by $CC]) + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return, which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [[\\/]]* | ?:[[\\/]]*) + re_direlt='/[[^/]][[^/]]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` + while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do + ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD=$ac_prog + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test yes = "$with_gnu_ld"; then + AC_MSG_CHECKING([for GNU ld]) +else + AC_MSG_CHECKING([for non-GNU ld]) +fi +AC_CACHE_VAL(lt_cv_path_LD, +[if test -z "$LD"; then + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD=$ac_dir/$ac_prog + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &1 conftest.i +cat conftest.i conftest.i >conftest2.i +: ${lt_DD:=$DD} +AC_PATH_PROGS_FEATURE_CHECK([lt_DD], [dd], +[if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=: +fi]) +rm -f conftest.i conftest2.i conftest.out]) +])# _LT_PATH_DD + + +# _LT_CMD_TRUNCATE +# ---------------- +# find command to truncate a binary pipe +m4_defun([_LT_CMD_TRUNCATE], +[m4_require([_LT_PATH_DD]) +AC_CACHE_CHECK([how to truncate binary pipes], [lt_cv_truncate_bin], +[printf 0123456789abcdef0123456789abcdef >conftest.i +cat conftest.i conftest.i >conftest2.i +lt_cv_truncate_bin= +if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1" +fi +rm -f conftest.i conftest2.i conftest.out +test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q"]) +_LT_DECL([lt_truncate_bin], [lt_cv_truncate_bin], [1], + [Command to truncate a binary pipe]) +])# _LT_CMD_TRUNCATE + + +# _LT_CHECK_MAGIC_METHOD +# ---------------------- +# how to check for library dependencies +# -- PORTME fill in with the dynamic library characteristics +m4_defun([_LT_CHECK_MAGIC_METHOD], +[m4_require([_LT_DECL_EGREP]) +m4_require([_LT_DECL_OBJDUMP]) +AC_CACHE_CHECK([how to recognize dependent libraries], +lt_cv_deplibs_check_method, +[lt_cv_file_magic_cmd='$MAGIC_CMD' +lt_cv_file_magic_test_file= +lt_cv_deplibs_check_method='unknown' +# Need to set the preceding variable on all platforms that support +# interlibrary dependencies. +# 'none' -- dependencies not supported. +# 'unknown' -- same as none, but documents that we really don't know. +# 'pass_all' -- all dependencies passed with no checks. +# 'test_compile' -- check by making test program. +# 'file_magic [[regex]]' -- check by looking for files in library path +# that responds to the $file_magic_cmd with a given extended regex. +# If you have 'file' or equivalent on your system and you're not sure +# whether 'pass_all' will *always* work, you probably want this one. + +case $host_os in +aix[[4-9]]*) + lt_cv_deplibs_check_method=pass_all + ;; + +beos*) + lt_cv_deplibs_check_method=pass_all + ;; + +bsdi[[45]]*) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)' + lt_cv_file_magic_cmd='/usr/bin/file -L' + lt_cv_file_magic_test_file=/shlib/libc.so + ;; + +cygwin*) + # func_win32_libid is a shell function defined in ltmain.sh + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + ;; + +mingw* | pw32*) + # Base MSYS/MinGW do not provide the 'file' command needed by + # func_win32_libid shell function, so use a weaker test based on 'objdump', + # unless we find 'file', for example because we are cross-compiling. + if ( file / ) >/dev/null 2>&1; then + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + else + # Keep this pattern in sync with the one in func_win32_libid. + lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' + lt_cv_file_magic_cmd='$OBJDUMP -f' + fi + ;; + +cegcc*) + # use the weaker test based on 'objdump'. See mingw*. + lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + ;; + +darwin* | rhapsody*) + lt_cv_deplibs_check_method=pass_all + ;; + +freebsd* | dragonfly*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +haiku*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case $host_cpu in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]'] + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\.[[0-9]]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +interix[[3-9]]*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' + ;; + +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +*nto* | *qnx*) + lt_cv_deplibs_check_method=pass_all + ;; + +openbsd* | bitrig*) + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + fi + ;; + +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + +rdos*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.3*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + pc) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +tpf*) + lt_cv_deplibs_check_method=pass_all + ;; +os2*) + lt_cv_deplibs_check_method=pass_all + ;; +esac +]) + +file_magic_glob= +want_nocaseglob=no +if test "$build" = "$host"; then + case $host_os in + mingw* | pw32*) + if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then + want_nocaseglob=yes + else + file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"` + fi + ;; + esac +fi + +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown + +_LT_DECL([], [deplibs_check_method], [1], + [Method to check whether dependent libraries are shared objects]) +_LT_DECL([], [file_magic_cmd], [1], + [Command to use when deplibs_check_method = "file_magic"]) +_LT_DECL([], [file_magic_glob], [1], + [How to find potential files when deplibs_check_method = "file_magic"]) +_LT_DECL([], [want_nocaseglob], [1], + [Find potential files using nocaseglob when deplibs_check_method = "file_magic"]) +])# _LT_CHECK_MAGIC_METHOD + + +# LT_PATH_NM +# ---------- +# find the pathname to a BSD- or MS-compatible name lister +AC_DEFUN([LT_PATH_NM], +[AC_REQUIRE([AC_PROG_CC])dnl +AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM, +[if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM=$NM +else + lt_nm_to_check=${ac_tool_prefix}nm + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + tmp_nm=$ac_dir/$lt_tmp_nm + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the 'sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty + case $build_os in + mingw*) lt_bad_file=conftest.nm/nofile ;; + *) lt_bad_file=/dev/null ;; + esac + case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in + *$lt_bad_file* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break 2 + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break 2 + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + ;; + esac + fi + done + IFS=$lt_save_ifs + done + : ${lt_cv_path_NM=no} +fi]) +if test no != "$lt_cv_path_NM"; then + NM=$lt_cv_path_NM +else + # Didn't find any BSD compatible name lister, look for dumpbin. + if test -n "$DUMPBIN"; then : + # Let the user override the test. + else + AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :) + case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in + *COFF*) + DUMPBIN="$DUMPBIN -symbols -headers" + ;; + *) + DUMPBIN=: + ;; + esac + fi + AC_SUBST([DUMPBIN]) + if test : != "$DUMPBIN"; then + NM=$DUMPBIN + fi +fi +test -z "$NM" && NM=nm +AC_SUBST([NM]) +_LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl + +AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface], + [lt_cv_nm_interface="BSD nm" + echo "int some_variable = 0;" > conftest.$ac_ext + (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$ac_compile" 2>conftest.err) + cat conftest.err >&AS_MESSAGE_LOG_FD + (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD) + (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) + cat conftest.err >&AS_MESSAGE_LOG_FD + (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD) + cat conftest.out >&AS_MESSAGE_LOG_FD + if $GREP 'External.*some_variable' conftest.out > /dev/null; then + lt_cv_nm_interface="MS dumpbin" + fi + rm -f conftest*]) +])# LT_PATH_NM + +# Old names: +AU_ALIAS([AM_PROG_NM], [LT_PATH_NM]) +AU_ALIAS([AC_PROG_NM], [LT_PATH_NM]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_PROG_NM], []) +dnl AC_DEFUN([AC_PROG_NM], []) + +# _LT_CHECK_SHAREDLIB_FROM_LINKLIB +# -------------------------------- +# how to determine the name of the shared library +# associated with a specific link library. +# -- PORTME fill in with the dynamic library characteristics +m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB], +[m4_require([_LT_DECL_EGREP]) +m4_require([_LT_DECL_OBJDUMP]) +m4_require([_LT_DECL_DLLTOOL]) +AC_CACHE_CHECK([how to associate runtime and link libraries], +lt_cv_sharedlib_from_linklib_cmd, +[lt_cv_sharedlib_from_linklib_cmd='unknown' + +case $host_os in +cygwin* | mingw* | pw32* | cegcc*) + # two different shell functions defined in ltmain.sh; + # decide which one to use based on capabilities of $DLLTOOL + case `$DLLTOOL --help 2>&1` in + *--identify-strict*) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib + ;; + *) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback + ;; + esac + ;; +*) + # fallback: assume linklib IS sharedlib + lt_cv_sharedlib_from_linklib_cmd=$ECHO + ;; +esac +]) +sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd +test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO + +_LT_DECL([], [sharedlib_from_linklib_cmd], [1], + [Command to associate shared and link libraries]) +])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB + + +# _LT_PATH_MANIFEST_TOOL +# ---------------------- +# locate the manifest tool +m4_defun([_LT_PATH_MANIFEST_TOOL], +[AC_CHECK_TOOL(MANIFEST_TOOL, mt, :) +test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt +AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool], + [lt_cv_path_mainfest_tool=no + echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD + $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out + cat conftest.err >&AS_MESSAGE_LOG_FD + if $GREP 'Manifest Tool' conftest.out > /dev/null; then + lt_cv_path_mainfest_tool=yes + fi + rm -f conftest*]) +if test yes != "$lt_cv_path_mainfest_tool"; then + MANIFEST_TOOL=: +fi +_LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl +])# _LT_PATH_MANIFEST_TOOL + + +# _LT_DLL_DEF_P([FILE]) +# --------------------- +# True iff FILE is a Windows DLL '.def' file. +# Keep in sync with func_dll_def_p in the libtool script +AC_DEFUN([_LT_DLL_DEF_P], +[dnl + test DEF = "`$SED -n dnl + -e '\''s/^[[ ]]*//'\'' dnl Strip leading whitespace + -e '\''/^\(;.*\)*$/d'\'' dnl Delete empty lines and comments + -e '\''s/^\(EXPORTS\|LIBRARY\)\([[ ]].*\)*$/DEF/p'\'' dnl + -e q dnl Only consider the first "real" line + $1`" dnl +])# _LT_DLL_DEF_P + + +# LT_LIB_M +# -------- +# check for math library +AC_DEFUN([LT_LIB_M], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +LIBM= +case $host in +*-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*) + # These system don't have libm, or don't need it + ;; +*-ncr-sysv4.3*) + AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM=-lmw) + AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") + ;; +*) + AC_CHECK_LIB(m, cos, LIBM=-lm) + ;; +esac +AC_SUBST([LIBM]) +])# LT_LIB_M + +# Old name: +AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_CHECK_LIBM], []) + + +# _LT_COMPILER_NO_RTTI([TAGNAME]) +# ------------------------------- +m4_defun([_LT_COMPILER_NO_RTTI], +[m4_require([_LT_TAG_COMPILER])dnl + +_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= + +if test yes = "$GCC"; then + case $cc_basename in + nvcc*) + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;; + *) + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;; + esac + + _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], + lt_cv_prog_compiler_rtti_exceptions, + [-fno-rtti -fno-exceptions], [], + [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) +fi +_LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1], + [Compiler flag to turn off builtin functions]) +])# _LT_COMPILER_NO_RTTI + + +# _LT_CMD_GLOBAL_SYMBOLS +# ---------------------- +m4_defun([_LT_CMD_GLOBAL_SYMBOLS], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([LT_PATH_NM])dnl +AC_REQUIRE([LT_PATH_LD])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_TAG_COMPILER])dnl + +# Check for command to grab the raw symbol name followed by C symbol from nm. +AC_MSG_CHECKING([command to parse $NM output from $compiler object]) +AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], +[ +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[[BCDEGRST]]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[[BCDT]]' + ;; +cygwin* | mingw* | pw32* | cegcc*) + symcode='[[ABCDGISTW]]' + ;; +hpux*) + if test ia64 = "$host_cpu"; then + symcode='[[ABCDEGRST]]' + fi + ;; +irix* | nonstopux*) + symcode='[[BCDEGRST]]' + ;; +osf*) + symcode='[[BCDEGQRST]]' + ;; +solaris*) + symcode='[[BDRT]]' + ;; +sco3.2v5*) + symcode='[[DT]]' + ;; +sysv4.2uw2*) + symcode='[[DT]]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[[ABDT]]' + ;; +sysv4) + symcode='[[DFNSTU]]' + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[[ABCDGIRSTW]]' ;; +esac + +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Gets list of data symbols to import. + lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'" + # Adjust the below global symbol transforms to fixup imported variables. + lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" + lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" + lt_c_name_lib_hook="\ + -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\ + -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'" +else + # Disable hooks by default. + lt_cv_sys_global_symbol_to_import= + lt_cdecl_hook= + lt_c_name_hook= + lt_c_name_lib_hook= +fi + +# Transform an extracted symbol line into a proper C declaration. +# Some systems (esp. on ia64) link data and code symbols differently, +# so use this general approach. +lt_cv_sys_global_symbol_to_cdecl="sed -n"\ +$lt_cdecl_hook\ +" -e 's/^T .* \(.*\)$/extern int \1();/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n"\ +$lt_c_name_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" + +# Transform an extracted symbol line into symbol name with lib prefix and +# symbol address. +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\ +$lt_c_name_lib_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'" + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# Try without a prefix underscore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Fake it for dumpbin and say T for any non-static function, + # D for any global variable and I for any imported variable. + # Also find C++ and __fastcall symbols from MSVC++, + # which start with @ or ?. + lt_cv_sys_global_symbol_pipe="$AWK ['"\ +" {last_section=section; section=\$ 3};"\ +" /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ +" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ +" /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\ +" /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\ +" /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\ +" \$ 0!~/External *\|/{next};"\ +" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ +" {if(hide[section]) next};"\ +" {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\ +" {split(\$ 0,a,/\||\r/); split(a[2],s)};"\ +" s[1]~/^[@?]/{print f,s[1],s[1]; next};"\ +" s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\ +" ' prfx=^$ac_symprfx]" + else + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + fi + lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext <<_LT_EOF +#ifdef __cplusplus +extern "C" { +#endif +char nm_test_var; +void nm_test_func(void); +void nm_test_func(void){} +#ifdef __cplusplus +} +#endif +int main(){nm_test_var='a';nm_test_func();return(0);} +_LT_EOF + + if AC_TRY_EVAL(ac_compile); then + # Now try to grab the symbols. + nlist=conftest.nm + if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if $GREP ' nm_test_var$' "$nlist" >/dev/null; then + if $GREP ' nm_test_func$' "$nlist" >/dev/null; then + cat <<_LT_EOF > conftest.$ac_ext +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE +/* DATA imports from DLLs on WIN32 can't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT@&t@_DLSYM_CONST +#elif defined __osf__ +/* This system does not cope well with relocations in const data. */ +# define LT@&t@_DLSYM_CONST +#else +# define LT@&t@_DLSYM_CONST const +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +_LT_EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' + + cat <<_LT_EOF >> conftest.$ac_ext + +/* The mapping between symbol names and symbols. */ +LT@&t@_DLSYM_CONST struct { + const char *name; + void *address; +} +lt__PROGRAM__LTX_preloaded_symbols[[]] = +{ + { "@PROGRAM@", (void *) 0 }, +_LT_EOF + $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext + cat <<\_LT_EOF >> conftest.$ac_ext + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt__PROGRAM__LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif +_LT_EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_globsym_save_LIBS=$LIBS + lt_globsym_save_CFLAGS=$CFLAGS + LIBS=conftstm.$ac_objext + CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" + if AC_TRY_EVAL(ac_link) && test -s conftest$ac_exeext; then + pipe_works=yes + fi + LIBS=$lt_globsym_save_LIBS + CFLAGS=$lt_globsym_save_CFLAGS + else + echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD + fi + else + echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD + cat conftest.$ac_ext >&5 + fi + rm -rf conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test yes = "$pipe_works"; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done +]) +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + AC_MSG_RESULT(failed) +else + AC_MSG_RESULT(ok) +fi + +# Response file support. +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + nm_file_list_spec='@' +elif $NM --help 2>/dev/null | grep '[[@]]FILE' >/dev/null; then + nm_file_list_spec='@' +fi + +_LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1], + [Take the output of nm and produce a listing of raw symbols and C names]) +_LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1], + [Transform the output of nm in a proper C declaration]) +_LT_DECL([global_symbol_to_import], [lt_cv_sys_global_symbol_to_import], [1], + [Transform the output of nm into a list of symbols to manually relocate]) +_LT_DECL([global_symbol_to_c_name_address], + [lt_cv_sys_global_symbol_to_c_name_address], [1], + [Transform the output of nm in a C name address pair]) +_LT_DECL([global_symbol_to_c_name_address_lib_prefix], + [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1], + [Transform the output of nm in a C name address pair when lib prefix is needed]) +_LT_DECL([nm_interface], [lt_cv_nm_interface], [1], + [The name lister interface]) +_LT_DECL([], [nm_file_list_spec], [1], + [Specify filename containing input files for $NM]) +]) # _LT_CMD_GLOBAL_SYMBOLS + + +# _LT_COMPILER_PIC([TAGNAME]) +# --------------------------- +m4_defun([_LT_COMPILER_PIC], +[m4_require([_LT_TAG_COMPILER])dnl +_LT_TAGVAR(lt_prog_compiler_wl, $1)= +_LT_TAGVAR(lt_prog_compiler_pic, $1)= +_LT_TAGVAR(lt_prog_compiler_static, $1)= + +m4_if([$1], [CXX], [ + # C++ specific cases for pic, static, wl, etc. + if test yes = "$GXX"; then + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the '-m68020' flag to GCC prevents building anything better, + # like '-m68040'. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + mingw* | cygwin* | os2* | pw32* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + case $host_os in + os2*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' + ;; + esac + ;; + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + *djgpp*) + # DJGPP does not support shared libraries at all + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + _LT_TAGVAR(lt_prog_compiler_static, $1)= + ;; + interix[[3-9]]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + *qnx* | *nto*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + else + case $host_os in + aix[[4-9]]*) + # All AIX code is PIC. + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + chorus*) + case $cc_basename in + cxch68*) + # Green Hills C++ Compiler + # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" + ;; + esac + ;; + mingw* | cygwin* | os2* | pw32* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + ;; + dgux*) + case $cc_basename in + ec++*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + ghcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + freebsd* | dragonfly*) + # FreeBSD uses GNU C++ + ;; + hpux9* | hpux10* | hpux11*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' + if test ia64 != "$host_cpu"; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + fi + ;; + aCC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + ;; + *) + ;; + esac + ;; + interix*) + # This is c89, which is MS Visual C++ (no shared libs) + # Anyone wants to do a port? + ;; + irix5* | irix6* | nonstopux*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + # CC pic flag -KPIC is the default. + ;; + *) + ;; + esac + ;; + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + case $cc_basename in + KCC*) + # KAI C++ Compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + ecpc* ) + # old Intel C++ for x86_64, which still supported -KPIC. + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + icpc* ) + # Intel C++, used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + pgCC* | pgcpp*) + # Portland Group C++ compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + cxx*) + # Compaq C++ + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*) + # IBM XL 8.0, 9.0 on PPC and BlueGene + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + esac + ;; + esac + ;; + lynxos*) + ;; + m88k*) + ;; + mvs*) + case $cc_basename in + cxx*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' + ;; + *) + ;; + esac + ;; + netbsd* | netbsdelf*-gnu) + ;; + *qnx* | *nto*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + ;; + RCC*) + # Rational C++ 2.4.1 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + cxx*) + # Digital/Compaq C++ + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + *) + ;; + esac + ;; + psos*) + ;; + solaris*) + case $cc_basename in + CC* | sunCC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + ;; + *) + ;; + esac + ;; + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + lcc*) + # Lucid + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + *) + ;; + esac + ;; + vxworks*) + ;; + *) + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +], +[ + if test yes = "$GCC"; then + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the '-m68020' flag to GCC prevents building anything better, + # like '-m68040'. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + case $host_os in + os2*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' + ;; + esac + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + _LT_TAGVAR(lt_prog_compiler_static, $1)= + ;; + + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + + interix[[3-9]]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + enable_shared=no + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + + case $cc_basename in + nvcc*) # Cuda Compiler Driver 2.2 + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker ' + if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)="-Xcompiler $_LT_TAGVAR(lt_prog_compiler_pic, $1)" + fi + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + case $cc_basename in + nagfor*) + # NAG Fortran compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + case $host_os in + os2*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' + ;; + esac + ;; + + hpux9* | hpux10* | hpux11*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC (with -KPIC) is the default. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + case $cc_basename in + # old Intel for x86_64, which still supported -KPIC. + ecc*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + # icc used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + icc* | ifort*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + # Lahey Fortran 8.1. + lf95*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared' + _LT_TAGVAR(lt_prog_compiler_static, $1)='--static' + ;; + nagfor*) + # NAG Fortran compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + ccc*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All Alpha code is PIC. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + xl* | bgxl* | bgf* | mpixl*) + # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [[1-7]].* | *Sun*Fortran*\ 8.[[0-3]]*) + # Sun Fortran 8.3 passes all unrecognized flags to the linker + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='' + ;; + *Sun\ F* | *Sun*Fortran*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + *Sun\ C*) + # Sun C 5.9 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + ;; + *Intel*\ [[CF]]*Compiler*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + *Portland\ Group*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + esac + ;; + + newsos6) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + + osf3* | osf4* | osf5*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All OSF/1 code is PIC. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + rdos*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + solaris*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + case $cc_basename in + f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; + *) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; + esac + ;; + + sunos4*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + unicos*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + + uts4*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + *) + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +]) +case $host_os in + # For platforms that do not support PIC, -DPIC is meaningless: + *djgpp*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])" + ;; +esac + +AC_CACHE_CHECK([for $compiler option to produce PIC], + [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)], + [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)]) +_LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1) + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then + _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works], + [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)], + [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [], + [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in + "" | " "*) ;; + *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;; + esac], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) +fi +_LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1], + [Additional compiler flags for building library objects]) + +_LT_TAGDECL([wl], [lt_prog_compiler_wl], [1], + [How to pass a linker flag through the compiler]) +# +# Check to make sure the static flag actually works. +# +wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\" +_LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], + _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1), + $lt_tmp_static_flag, + [], + [_LT_TAGVAR(lt_prog_compiler_static, $1)=]) +_LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1], + [Compiler flag to prevent dynamic linking]) +])# _LT_COMPILER_PIC + + +# _LT_LINKER_SHLIBS([TAGNAME]) +# ---------------------------- +# See if the linker supports building shared libraries. +m4_defun([_LT_LINKER_SHLIBS], +[AC_REQUIRE([LT_PATH_LD])dnl +AC_REQUIRE([LT_PATH_NM])dnl +m4_require([_LT_PATH_MANIFEST_TOOL])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl +m4_require([_LT_TAG_COMPILER])dnl +AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) +m4_if([$1], [CXX], [ + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] + case $host_os in + aix[[4-9]]*) + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to GNU nm, but means don't demangle to AIX nm. + # Without the "-l" option, or with the "-B" option, AIX nm treats + # weak defined symbols like other global defined symbols, whereas + # GNU nm marks them as "W". + # While the 'weak' keyword is ignored in the Export File, we need + # it in the Import File for the 'aix-soname' feature, so we have + # to replace the "-B" option with "-P" for AIX nm. + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' + else + _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' + fi + ;; + pw32*) + _LT_TAGVAR(export_symbols_cmds, $1)=$ltdll_cmds + ;; + cygwin* | mingw* | cegcc*) + case $cc_basename in + cl*) + _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' + ;; + *) + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] + ;; + esac + ;; + linux* | k*bsd*-gnu | gnu*) + _LT_TAGVAR(link_all_deplibs, $1)=no + ;; + *) + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + ;; + esac +], [ + runpath_var= + _LT_TAGVAR(allow_undefined_flag, $1)= + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(archive_cmds, $1)= + _LT_TAGVAR(archive_expsym_cmds, $1)= + _LT_TAGVAR(compiler_needs_object, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + _LT_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(hardcode_automatic, $1)=no + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_TAGVAR(hardcode_libdir_separator, $1)= + _LT_TAGVAR(hardcode_minus_L, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_TAGVAR(inherit_rpath, $1)=no + _LT_TAGVAR(link_all_deplibs, $1)=unknown + _LT_TAGVAR(module_cmds, $1)= + _LT_TAGVAR(module_expsym_cmds, $1)= + _LT_TAGVAR(old_archive_from_new_cmds, $1)= + _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)= + _LT_TAGVAR(thread_safe_flag_spec, $1)= + _LT_TAGVAR(whole_archive_flag_spec, $1)= + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + _LT_TAGVAR(include_expsyms, $1)= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ' (' and ')$', so one must not match beginning or + # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc', + # as well as any symbol that contains 'd'. + _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + # Exclude shared library initialization/finalization symbols. +dnl Note also adjust exclude_expsyms for C++ above. + extract_expsyms_cmds= + + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test yes != "$GCC"; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd* | bitrig*) + with_gnu_ld=no + ;; + linux* | k*bsd*-gnu | gnu*) + _LT_TAGVAR(link_all_deplibs, $1)=no + ;; + esac + + _LT_TAGVAR(ld_shlibs, $1)=yes + + # On some targets, GNU ld is compatible enough with the native linker + # that we're better off using the native interface for both. + lt_use_gnu_ld_interface=no + if test yes = "$with_gnu_ld"; then + case $host_os in + aix*) + # The AIX port of GNU ld has always aspired to compatibility + # with the native linker. However, as the warning in the GNU ld + # block says, versions before 2.19.5* couldn't really create working + # shared libraries, regardless of the interface used. + case `$LD -v 2>&1` in + *\ \(GNU\ Binutils\)\ 2.19.5*) ;; + *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;; + *\ \(GNU\ Binutils\)\ [[3-9]]*) ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + fi + + if test yes = "$lt_use_gnu_ld_interface"; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='$wl' + + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + runpath_var=LD_RUN_PATH + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then + _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + supports_anon_versioning=no + case `$LD -v | $SED -e 's/([^)]\+)\s\+//' 2>&1` in + *GNU\ gold*) supports_anon_versioning=yes ;; + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix[[3-9]]*) + # On AIX/PPC, the GNU linker is very broken + if test ia64 != "$host_cpu"; then + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: the GNU linker, at least up to release 2.19, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to install binutils +*** 2.20 or above, or modify your PATH so that a non-GNU linker is found. +*** You will then need to restart the configuration process. + +_LT_EOF + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='' + ;; + m68k) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file, use it as + # is; otherwise, prepend EXPORTS... + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + haiku*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + os2*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + shrext_cmds=.dll + _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + + interix[[3-9]]*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) + tmp_diet=no + if test linux-dietlibc = "$host_os"; then + case $cc_basename in + diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) + esac + fi + if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ + && test no = "$tmp_diet" + then + tmp_addflag=' $pic_flag' + tmp_sharedflag='-shared' + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group f77 and f90 compilers + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + lf95*) # Lahey Fortran 8.1 + _LT_TAGVAR(whole_archive_flag_spec, $1)= + tmp_sharedflag='--shared' ;; + nagfor*) # NAGFOR 5.3 + tmp_sharedflag='-Wl,-shared' ;; + xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) + tmp_sharedflag='-qmkshrobj' + tmp_addflag= ;; + nvcc*) # Cuda Compiler Driver 2.2 + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + ;; + esac + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C 5.9 + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + tmp_sharedflag='-G' ;; + *Sun\ F*) # Sun Fortran 8.3 + tmp_sharedflag='-G' ;; + esac + _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + + if test yes = "$supports_anon_versioning"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' + fi + + case $cc_basename in + tcc*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='-rdynamic' + ;; + xlf* | bgf* | bgxlf* | mpixlf*) + # IBM XL Fortran 10.1 on PPC cannot create shared libs itself + _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' + if test yes = "$supports_anon_versioning"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' + fi + ;; + esac + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + # For security reasons, it is highly recommended that you always + # use absolute paths for naming shared libraries, and exclude the + # DT_RUNPATH tag from executables and libraries. But doing so + # requires that you compile everything twice, which is a pain. + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + sunos4*) + _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + + if test no = "$_LT_TAGVAR(ld_shlibs, $1)"; then + runpath_var= + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + _LT_TAGVAR(hardcode_direct, $1)=unsupported + fi + ;; + + aix[[4-9]]*) + if test ia64 = "$host_cpu"; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag= + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to GNU nm, but means don't demangle to AIX nm. + # Without the "-l" option, or with the "-B" option, AIX nm treats + # weak defined symbols like other global defined symbols, whereas + # GNU nm marks them as "W". + # While the 'weak' keyword is ignored in the Export File, we need + # it in the Import File for the 'aix-soname' feature, so we have + # to replace the "-B" option with "-P" for AIX nm. + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' + else + _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # have runtime linking enabled, and use it for executables. + # For shared libraries, we enable/disable runtime linking + # depending on the kind of the shared library created - + # when "with_aix_soname,aix_use_runtimelinking" is: + # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables + # "aix,yes" lib.so shared, rtl:yes, for executables + # lib.a static archive + # "both,no" lib.so.V(shr.o) shared, rtl:yes + # lib.a(lib.so.V) shared, rtl:no, for executables + # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a(lib.so.V) shared, rtl:no + # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a static archive + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) + for ld_flag in $LDFLAGS; do + if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then + aix_use_runtimelinking=yes + break + fi + done + if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then + # With aix-soname=svr4, we create the lib.so.V shared archives only, + # so we don't have lib.a shared libs to link our executables. + # We have to force runtime linking in this case. + aix_use_runtimelinking=yes + LDFLAGS="$LDFLAGS -Wl,-brtl" + fi + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_TAGVAR(archive_cmds, $1)='' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='$wl-f,' + case $with_aix_soname,$aix_use_runtimelinking in + aix,*) ;; # traditional, no import file + svr4,* | *,yes) # use import file + # The Import File defines what to hardcode. + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=no + ;; + esac + + if test yes = "$GCC"; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`$CC -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + _LT_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)= + fi + ;; + esac + shared_flag='-shared' + if test yes = "$aix_use_runtimelinking"; then + shared_flag="$shared_flag "'$wl-G' + fi + # Need to ensure runtime linking is disabled for the traditional + # shared library, or the linker may eventually find shared libraries + # /with/ Import File - we do not want to mix them. + shared_flag_aix='-shared' + shared_flag_svr4='-shared $wl-G' + else + # not using gcc + if test ia64 = "$host_cpu"; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test yes = "$aix_use_runtimelinking"; then + shared_flag='$wl-G' + else + shared_flag='$wl-bM:SRE' + fi + shared_flag_aix='$wl-bM:SRE' + shared_flag_svr4='$wl-G' + fi + fi + + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + _LT_TAGVAR(always_export_symbols, $1)=yes + if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(allow_undefined_flag, $1)='-berok' + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag + else + if test ia64 = "$host_cpu"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' + _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' + if test yes = "$with_gnu_ld"; then + # We only use this code for GNU lds that support --whole-archive. + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' + # -brtl affects multiple linker settings, -berok does not and is overridden later + compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' + if test svr4 != "$with_aix_soname"; then + # This is similar to how AIX traditionally builds its shared libraries. + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' + fi + if test aix != "$with_aix_soname"; then + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' + else + # used by -dlpreopen to get the symbols + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' + fi + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' + fi + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='' + ;; + m68k) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + ;; + + bsdi[[45]]*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + case $cc_basename in + cl*) + # Native MSVC + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp "$export_symbols" "$output_objdir/$soname.def"; + echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; + else + $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' + # Don't use ranlib + _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' + _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile=$lt_outputfile.exe + lt_tool_outputfile=$lt_tool_outputfile.exe + ;; + esac~ + if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # Assume MSVC wrapper + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + # FIXME: Should let the user specify the lib program. + _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + esac + ;; + + darwin* | rhapsody*) + _LT_DARWIN_LINKER_FEATURES($1) + ;; + + dgux*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2.*) + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | dragonfly*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + hpux9*) + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + else + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_direct, $1)=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + ;; + + hpux10*) + if test yes,no = "$GCC,$with_gnu_ld"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + fi + ;; + + hpux11*) + if test yes,no = "$GCC,$with_gnu_ld"; then + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + m4_if($1, [], [ + # Older versions of the 11.00 compiler do not understand -b yet + # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) + _LT_LINKER_OPTION([if $CC understands -b], + _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b], + [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'], + [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])], + [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags']) + ;; + esac + fi + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + # Try to use the -exported_symbol ld option, if it does not + # work, assume that -exports_file does not work either and + # implicitly export all symbols. + # This should be the same for all languages, so no per-tag cache variable. + AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol], + [lt_cv_irix_exported_symbol], + [save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null" + AC_LINK_IFELSE( + [AC_LANG_SOURCE( + [AC_LANG_CASE([C], [[int foo (void) { return 0; }]], + [C++], [[int foo (void) { return 0; }]], + [Fortran 77], [[ + subroutine foo + end]], + [Fortran], [[ + subroutine foo + end]])])], + [lt_cv_irix_exported_symbol=yes], + [lt_cv_irix_exported_symbol=no]) + LDFLAGS=$save_LDFLAGS]) + if test yes = "$lt_cv_irix_exported_symbol"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' + fi + _LT_TAGVAR(link_all_deplibs, $1)=no + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(inherit_rpath, $1)=yes + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + linux*) + case $cc_basename in + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + _LT_TAGVAR(ld_shlibs, $1)=yes + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + newsos6) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *nto* | *qnx*) + ;; + + openbsd* | bitrig*) + if test -f /usr/libexec/ld.so; then + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + fi + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + os2*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + shrext_cmds=.dll + _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + + osf3*) + if test yes = "$GCC"; then + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + else + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test yes = "$GCC"; then + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + else + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp' + + # Both c and cxx compiler support -rpath directly + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + solaris*) + _LT_TAGVAR(no_undefined_flag, $1)=' -z defs' + if test yes = "$GCC"; then + wlarc='$wl' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + else + case `$CC -V 2>&1` in + *"Compilers 5.0"*) + wlarc='' + _LT_TAGVAR(archive_cmds, $1)='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' + ;; + *) + wlarc='$wl' + _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + ;; + esac + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands '-z linker_flag'. GCC discards it without '$wl', + # but is careful enough not to reorder. + # Supported since Solaris 2.6 (maybe 2.5.1?) + if test yes = "$GCC"; then + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' + fi + ;; + esac + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + sunos4*) + if test sequent = "$host_vendor"; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4) + case $host_vendor in + sni) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' + _LT_TAGVAR(hardcode_direct, $1)=no + ;; + motorola) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4.3*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + _LT_TAGVAR(ld_shlibs, $1)=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We CANNOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' + runpath_var='LD_RUN_PATH' + + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + + if test sni = "$host_vendor"; then + case $host in + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Blargedynsym' + ;; + esac + fi + fi +]) +AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) +test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no + +_LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld + +_LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl +_LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl +_LT_DECL([], [extract_expsyms_cmds], [2], + [The commands to extract the exported symbol list from a shared archive]) + +# +# Do we need to explicitly link libc? +# +case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in +x|xyes) + # Assume -lc should be added + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + + if test yes,yes = "$GCC,$enable_shared"; then + case $_LT_TAGVAR(archive_cmds, $1) in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + AC_CACHE_CHECK([whether -lc should be explicitly linked in], + [lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1), + [$RM conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if AC_TRY_EVAL(ac_compile) 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) + pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1) + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1) + _LT_TAGVAR(allow_undefined_flag, $1)= + if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) + then + lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no + else + lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes + fi + _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $RM conftest* + ]) + _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1) + ;; + esac + fi + ;; +esac + +_LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0], + [Whether or not to add -lc for building shared libraries]) +_LT_TAGDECL([allow_libtool_libs_with_static_runtimes], + [enable_shared_with_static_runtimes], [0], + [Whether or not to disallow shared libs when runtime libs are static]) +_LT_TAGDECL([], [export_dynamic_flag_spec], [1], + [Compiler flag to allow reflexive dlopens]) +_LT_TAGDECL([], [whole_archive_flag_spec], [1], + [Compiler flag to generate shared objects directly from archives]) +_LT_TAGDECL([], [compiler_needs_object], [1], + [Whether the compiler copes with passing no objects directly]) +_LT_TAGDECL([], [old_archive_from_new_cmds], [2], + [Create an old-style archive from a shared archive]) +_LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2], + [Create a temporary old-style archive to link instead of a shared archive]) +_LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive]) +_LT_TAGDECL([], [archive_expsym_cmds], [2]) +_LT_TAGDECL([], [module_cmds], [2], + [Commands used to build a loadable module if different from building + a shared archive.]) +_LT_TAGDECL([], [module_expsym_cmds], [2]) +_LT_TAGDECL([], [with_gnu_ld], [1], + [Whether we are building with GNU ld or not]) +_LT_TAGDECL([], [allow_undefined_flag], [1], + [Flag that allows shared libraries with undefined symbols to be built]) +_LT_TAGDECL([], [no_undefined_flag], [1], + [Flag that enforces no undefined symbols]) +_LT_TAGDECL([], [hardcode_libdir_flag_spec], [1], + [Flag to hardcode $libdir into a binary during linking. + This must work even if $libdir does not exist]) +_LT_TAGDECL([], [hardcode_libdir_separator], [1], + [Whether we need a single "-rpath" flag with a separated argument]) +_LT_TAGDECL([], [hardcode_direct], [0], + [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes + DIR into the resulting binary]) +_LT_TAGDECL([], [hardcode_direct_absolute], [0], + [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes + DIR into the resulting binary and the resulting library dependency is + "absolute", i.e impossible to change by setting $shlibpath_var if the + library is relocated]) +_LT_TAGDECL([], [hardcode_minus_L], [0], + [Set to "yes" if using the -LDIR flag during linking hardcodes DIR + into the resulting binary]) +_LT_TAGDECL([], [hardcode_shlibpath_var], [0], + [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR + into the resulting binary]) +_LT_TAGDECL([], [hardcode_automatic], [0], + [Set to "yes" if building a shared library automatically hardcodes DIR + into the library and all subsequent libraries and executables linked + against it]) +_LT_TAGDECL([], [inherit_rpath], [0], + [Set to yes if linker adds runtime paths of dependent libraries + to runtime path list]) +_LT_TAGDECL([], [link_all_deplibs], [0], + [Whether libtool must link a program against all its dependency libraries]) +_LT_TAGDECL([], [always_export_symbols], [0], + [Set to "yes" if exported symbols are required]) +_LT_TAGDECL([], [export_symbols_cmds], [2], + [The commands to list exported symbols]) +_LT_TAGDECL([], [exclude_expsyms], [1], + [Symbols that should not be listed in the preloaded symbols]) +_LT_TAGDECL([], [include_expsyms], [1], + [Symbols that must always be exported]) +_LT_TAGDECL([], [prelink_cmds], [2], + [Commands necessary for linking programs (against libraries) with templates]) +_LT_TAGDECL([], [postlink_cmds], [2], + [Commands necessary for finishing linking programs]) +_LT_TAGDECL([], [file_list_spec], [1], + [Specify filename containing input files]) +dnl FIXME: Not yet implemented +dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1], +dnl [Compiler flag to generate thread safe objects]) +])# _LT_LINKER_SHLIBS + + +# _LT_LANG_C_CONFIG([TAG]) +# ------------------------ +# Ensure that the configuration variables for a C compiler are suitably +# defined. These variables are subsequently used by _LT_CONFIG to write +# the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_C_CONFIG], +[m4_require([_LT_DECL_EGREP])dnl +lt_save_CC=$CC +AC_LANG_PUSH(C) + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}' + +_LT_TAG_COMPILER +# Save the default compiler, since it gets overwritten when the other +# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. +compiler_DEFAULT=$CC + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + LT_SYS_DLOPEN_SELF + _LT_CMD_STRIPLIB + + # Report what library types will actually be built + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test no = "$can_build_shared" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test yes = "$enable_shared" && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + + aix[[4-9]]*) + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test yes = "$enable_shared" || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_CONFIG($1) +fi +AC_LANG_POP +CC=$lt_save_CC +])# _LT_LANG_C_CONFIG + + +# _LT_LANG_CXX_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for a C++ compiler are suitably +# defined. These variables are subsequently used by _LT_CONFIG to write +# the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_CXX_CONFIG], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_PATH_MANIFEST_TOOL])dnl +if test -n "$CXX" && ( test no != "$CXX" && + ( (test g++ = "$CXX" && `g++ -v >/dev/null 2>&1` ) || + (test g++ != "$CXX"))); then + AC_PROG_CXXCPP +else + _lt_caught_CXX_error=yes +fi + +AC_LANG_PUSH(C++) +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(compiler_needs_object, $1)=no +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for C++ test sources. +ac_ext=cpp + +# Object file extension for compiled C++ test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the CXX compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test yes != "$_lt_caught_CXX_error"; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="int some_variable = 0;" + + # Code to be used in simple link tests + lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }' + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC=$CC + lt_save_CFLAGS=$CFLAGS + lt_save_LD=$LD + lt_save_GCC=$GCC + GCC=$GXX + lt_save_with_gnu_ld=$with_gnu_ld + lt_save_path_LD=$lt_cv_path_LD + if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then + lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx + else + $as_unset lt_cv_prog_gnu_ld + fi + if test -n "${lt_cv_path_LDCXX+set}"; then + lt_cv_path_LD=$lt_cv_path_LDCXX + else + $as_unset lt_cv_path_LD + fi + test -z "${LDCXX+set}" || LD=$LDCXX + CC=${CXX-"c++"} + CFLAGS=$CXXFLAGS + compiler=$CC + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + + if test -n "$compiler"; then + # We don't want -fno-exception when compiling C++ code, so set the + # no_builtin_flag separately + if test yes = "$GXX"; then + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' + else + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= + fi + + if test yes = "$GXX"; then + # Set up default GNU C++ configuration + + LT_PATH_LD + + # Check if GNU C++ uses GNU ld as the underlying linker, since the + # archiving commands below assume that GNU ld is being used. + if test yes = "$with_gnu_ld"; then + _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + + # If archive_cmds runs LD, not CC, wlarc should be empty + # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to + # investigate it a little bit more. (MM) + wlarc='$wl' + + # ancient GNU ld didn't support --whole-archive et. al. + if eval "`$CC -print-prog-name=ld` --help 2>&1" | + $GREP 'no-whole-archive' > /dev/null; then + _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + with_gnu_ld=no + wlarc= + + # A generic and very simple default shared library creation + # command for GNU C++ for the case where it uses the native + # linker, instead of GNU ld. If possible, this setting should + # overridden to take advantage of the native linker features on + # the platform it is being used on. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + fi + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + + else + GXX=no + with_gnu_ld=no + wlarc= + fi + + # PORTME: fill in a description of your system's C++ link characteristics + AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) + _LT_TAGVAR(ld_shlibs, $1)=yes + case $host_os in + aix3*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aix[[4-9]]*) + if test ia64 = "$host_cpu"; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag= + else + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # have runtime linking enabled, and use it for executables. + # For shared libraries, we enable/disable runtime linking + # depending on the kind of the shared library created - + # when "with_aix_soname,aix_use_runtimelinking" is: + # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables + # "aix,yes" lib.so shared, rtl:yes, for executables + # lib.a static archive + # "both,no" lib.so.V(shr.o) shared, rtl:yes + # lib.a(lib.so.V) shared, rtl:no, for executables + # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a(lib.so.V) shared, rtl:no + # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a static archive + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) + for ld_flag in $LDFLAGS; do + case $ld_flag in + *-brtl*) + aix_use_runtimelinking=yes + break + ;; + esac + done + if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then + # With aix-soname=svr4, we create the lib.so.V shared archives only, + # so we don't have lib.a shared libs to link our executables. + # We have to force runtime linking in this case. + aix_use_runtimelinking=yes + LDFLAGS="$LDFLAGS -Wl,-brtl" + fi + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_TAGVAR(archive_cmds, $1)='' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='$wl-f,' + case $with_aix_soname,$aix_use_runtimelinking in + aix,*) ;; # no import file + svr4,* | *,yes) # use import file + # The Import File defines what to hardcode. + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=no + ;; + esac + + if test yes = "$GXX"; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`$CC -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + _LT_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)= + fi + esac + shared_flag='-shared' + if test yes = "$aix_use_runtimelinking"; then + shared_flag=$shared_flag' $wl-G' + fi + # Need to ensure runtime linking is disabled for the traditional + # shared library, or the linker may eventually find shared libraries + # /with/ Import File - we do not want to mix them. + shared_flag_aix='-shared' + shared_flag_svr4='-shared $wl-G' + else + # not using gcc + if test ia64 = "$host_cpu"; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test yes = "$aix_use_runtimelinking"; then + shared_flag='$wl-G' + else + shared_flag='$wl-bM:SRE' + fi + shared_flag_aix='$wl-bM:SRE' + shared_flag_svr4='$wl-G' + fi + fi + + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to + # export. + _LT_TAGVAR(always_export_symbols, $1)=yes + if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + # The "-G" linker flag allows undefined symbols. + _LT_TAGVAR(no_undefined_flag, $1)='-bernotok' + # Determine the default libpath from the value encoded in an empty + # executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" + + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag + else + if test ia64 = "$host_cpu"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' + _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' + if test yes = "$with_gnu_ld"; then + # We only use this code for GNU lds that support --whole-archive. + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' + # -brtl affects multiple linker settings, -berok does not and is overridden later + compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' + if test svr4 != "$with_aix_soname"; then + # This is similar to how AIX traditionally builds its shared + # libraries. Need -bnortl late, we may have -brtl in LDFLAGS. + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' + fi + if test aix != "$with_aix_soname"; then + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' + else + # used by -dlpreopen to get the symbols + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' + fi + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' + fi + fi + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + chorus*) + case $cc_basename in + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + cygwin* | mingw* | pw32* | cegcc*) + case $GXX,$cc_basename in + ,cl* | no,cl*) + # Native MSVC + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp "$export_symbols" "$output_objdir/$soname.def"; + echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; + else + $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + # Don't use ranlib + _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' + _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile=$lt_outputfile.exe + lt_tool_outputfile=$lt_tool_outputfile.exe + ;; + esac~ + func_to_tool_file "$lt_outputfile"~ + if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # g++ + # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file, use it as + # is; otherwise, prepend EXPORTS... + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + darwin* | rhapsody*) + _LT_DARWIN_LINKER_FEATURES($1) + ;; + + os2*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + shrext_cmds=.dll + _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + + dgux*) + case $cc_basename in + ec++*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + ghcx*) + # Green Hills C++ Compiler + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + freebsd2.*) + # C++ shared libraries reported to be fairly broken before + # switch to ELF + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + freebsd-elf*) + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + ;; + + freebsd* | dragonfly*) + # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF + # conventions + _LT_TAGVAR(ld_shlibs, $1)=yes + ;; + + haiku*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + hpux9*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test yes = "$GXX"; then + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + hpux10*|hpux11*) + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + ;; + *) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + ;; + esac + fi + case $host_cpu in + hppa*64*|ia64*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + ;; + esac + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test yes = "$GXX"; then + if test no = "$with_gnu_ld"; then + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + fi + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + interix[[3-9]]*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + irix5* | irix6*) + case $cc_basename in + CC*) + # SGI C++ + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + + # Archives containing C++ object files must be created using + # "CC -ar", where "CC" is the IRIX C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' + ;; + *) + if test yes = "$GXX"; then + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` -o $lib' + fi + fi + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + esac + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(inherit_rpath, $1)=yes + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib $wl-retain-symbols-file,$export_symbols; mv \$templib $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' + ;; + icpc* | ecpc* ) + # Intel C++ + with_gnu_ld=yes + # version 8.0 and above of icpc choke on multiply defined symbols + # if we add $predep_objects and $postdep_objects, however 7.1 and + # earlier do not add the objects themselves. + case `$CC -V 2>&1` in + *"Version 7."*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 8.0 or newer + tmp_idyn= + case $host_cpu in + ia64*) tmp_idyn=' -i_dynamic';; + esac + _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' + ;; + pgCC* | pgcpp*) + # Portland Group C++ compiler + case `$CC -V` in + *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*) + _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ + compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' + _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ + $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ + $RANLIB $oldlib' + _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 6 and above use weak symbols + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl--rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + ;; + cxx*) + # Compaq C++ + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib $wl-retain-symbols-file $wl$export_symbols' + + runpath_var=LD_RUN_PATH + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' + ;; + xl* | mpixl* | bgxl*) + # IBM XL 8.0 on PPC, with GNU ld + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + if test yes = "$supports_anon_versioning"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' + fi + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file $wl$export_symbols' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + + # Not sure whether something based on + # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 + # would be better. + output_verbose_link_cmd='func_echo_all' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + esac + ;; + esac + ;; + + lynxos*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + m88k*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + mvs*) + case $cc_basename in + cxx*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' + wlarc= + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + fi + # Workaround some broken pre-1.5 toolchains + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' + ;; + + *nto* | *qnx*) + _LT_TAGVAR(ld_shlibs, $1)=yes + ;; + + openbsd* | bitrig*) + if test -f /usr/libexec/ld.so; then + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file,$export_symbols -o $lib' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + fi + output_verbose_link_cmd=func_echo_all + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Archives containing C++ object files must be created using + # the KAI C++ compiler. + case $host in + osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; + *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;; + esac + ;; + RCC*) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + cxx*) + case $host in + osf3*) + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $soname `test -n "$verstring" && func_echo_all "$wl-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + ;; + *) + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ + echo "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname $wl-input $wl$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~ + $RM $lib.exp' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test yes,no = "$GXX,$with_gnu_ld"; then + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + case $host in + osf3*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + psos*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + lcc*) + # Lucid + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + solaris*) + case $cc_basename in + CC* | sunCC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_TAGVAR(archive_cmds_need_lc,$1)=yes + _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G$allow_undefined_flag $wl-M $wl$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands '-z linker_flag'. + # Supported since Solaris 2.6 (maybe 2.5.1?) + _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' + ;; + esac + _LT_TAGVAR(link_all_deplibs, $1)=yes + + output_verbose_link_cmd='func_echo_all' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' + + # The C++ compiler must be used to create the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' + ;; + *) + # GNU C++ compiler with Solaris linker + if test yes,no = "$GXX,$with_gnu_ld"; then + _LT_TAGVAR(no_undefined_flag, $1)=' $wl-z ${wl}defs' + if $CC --version | $GREP -v '^2\.7' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + else + # g++ 2.7 appears to require '-G' NOT '-shared' on this + # platform. + _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + fi + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $wl$libdir' + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' + ;; + esac + fi + ;; + esac + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We CANNOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~ + '"$_LT_TAGVAR(old_archive_cmds, $1)" + _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~ + '"$_LT_TAGVAR(reload_cmds, $1)" + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + vxworks*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + + AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) + test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no + + _LT_TAGVAR(GCC, $1)=$GXX + _LT_TAGVAR(LD, $1)=$LD + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_SYS_HIDDEN_LIBDEPS($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS + LDCXX=$LD + LD=$lt_save_LD + GCC=$lt_save_GCC + with_gnu_ld=$lt_save_with_gnu_ld + lt_cv_path_LDCXX=$lt_cv_path_LD + lt_cv_path_LD=$lt_save_path_LD + lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld + lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld +fi # test yes != "$_lt_caught_CXX_error" + +AC_LANG_POP +])# _LT_LANG_CXX_CONFIG + + +# _LT_FUNC_STRIPNAME_CNF +# ---------------------- +# func_stripname_cnf prefix suffix name +# strip PREFIX and SUFFIX off of NAME. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +# +# This function is identical to the (non-XSI) version of func_stripname, +# except this one can be used by m4 code that may be executed by configure, +# rather than the libtool script. +m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl +AC_REQUIRE([_LT_DECL_SED]) +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH]) +func_stripname_cnf () +{ + case @S|@2 in + .*) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%\\\\@S|@2\$%%"`;; + *) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%@S|@2\$%%"`;; + esac +} # func_stripname_cnf +])# _LT_FUNC_STRIPNAME_CNF + + +# _LT_SYS_HIDDEN_LIBDEPS([TAGNAME]) +# --------------------------------- +# Figure out "hidden" library dependencies from verbose +# compiler output when linking a shared library. +# Parse the compiler output and extract the necessary +# objects, libraries and library flags. +m4_defun([_LT_SYS_HIDDEN_LIBDEPS], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl +# Dependencies to place before and after the object being linked: +_LT_TAGVAR(predep_objects, $1)= +_LT_TAGVAR(postdep_objects, $1)= +_LT_TAGVAR(predeps, $1)= +_LT_TAGVAR(postdeps, $1)= +_LT_TAGVAR(compiler_lib_search_path, $1)= + +dnl we can't use the lt_simple_compile_test_code here, +dnl because it contains code intended for an executable, +dnl not a library. It's possible we should let each +dnl tag define a new lt_????_link_test_code variable, +dnl but it's only used here... +m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF +int a; +void foo (void) { a = 0; } +_LT_EOF +], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF +class Foo +{ +public: + Foo (void) { a = 0; } +private: + int a; +}; +_LT_EOF +], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF + subroutine foo + implicit none + integer*4 a + a=0 + return + end +_LT_EOF +], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF + subroutine foo + implicit none + integer a + a=0 + return + end +_LT_EOF +], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF +public class foo { + private int a; + public void bar (void) { + a = 0; + } +}; +_LT_EOF +], [$1], [GO], [cat > conftest.$ac_ext <<_LT_EOF +package foo +func foo() { +} +_LT_EOF +]) + +_lt_libdeps_save_CFLAGS=$CFLAGS +case "$CC $CFLAGS " in #( +*\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; +*\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; +*\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;; +esac + +dnl Parse the compiler output and extract the necessary +dnl objects, libraries and library flags. +if AC_TRY_EVAL(ac_compile); then + # Parse the compiler output and extract the necessary + # objects, libraries and library flags. + + # Sentinel used to keep track of whether or not we are before + # the conftest object file. + pre_test_object_deps_done=no + + for p in `eval "$output_verbose_link_cmd"`; do + case $prev$p in + + -L* | -R* | -l*) + # Some compilers place space between "-{L,R}" and the path. + # Remove the space. + if test x-L = "$p" || + test x-R = "$p"; then + prev=$p + continue + fi + + # Expand the sysroot to ease extracting the directories later. + if test -z "$prev"; then + case $p in + -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; + -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; + -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; + esac + fi + case $p in + =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; + esac + if test no = "$pre_test_object_deps_done"; then + case $prev in + -L | -R) + # Internal compiler library paths should come after those + # provided the user. The postdeps already come after the + # user supplied libs so there is no need to process them. + if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then + _LT_TAGVAR(compiler_lib_search_path, $1)=$prev$p + else + _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} $prev$p" + fi + ;; + # The "-l" case would never come before the object being + # linked, so don't bother handling this case. + esac + else + if test -z "$_LT_TAGVAR(postdeps, $1)"; then + _LT_TAGVAR(postdeps, $1)=$prev$p + else + _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} $prev$p" + fi + fi + prev= + ;; + + *.lto.$objext) ;; # Ignore GCC LTO objects + *.$objext) + # This assumes that the test object file only shows up + # once in the compiler output. + if test "$p" = "conftest.$objext"; then + pre_test_object_deps_done=yes + continue + fi + + if test no = "$pre_test_object_deps_done"; then + if test -z "$_LT_TAGVAR(predep_objects, $1)"; then + _LT_TAGVAR(predep_objects, $1)=$p + else + _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p" + fi + else + if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then + _LT_TAGVAR(postdep_objects, $1)=$p + else + _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p" + fi + fi + ;; + + *) ;; # Ignore the rest. + + esac + done + + # Clean up. + rm -f a.out a.exe +else + echo "libtool.m4: error: problem compiling $1 test program" +fi + +$RM -f confest.$objext +CFLAGS=$_lt_libdeps_save_CFLAGS + +# PORTME: override above test on systems where it is broken +m4_if([$1], [CXX], +[case $host_os in +interix[[3-9]]*) + # Interix 3.5 installs completely hosed .la files for C++, so rather than + # hack all around it, let's just trust "g++" to DTRT. + _LT_TAGVAR(predep_objects,$1)= + _LT_TAGVAR(postdep_objects,$1)= + _LT_TAGVAR(postdeps,$1)= + ;; +esac +]) + +case " $_LT_TAGVAR(postdeps, $1) " in +*" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; +esac + _LT_TAGVAR(compiler_lib_search_dirs, $1)= +if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then + _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | $SED -e 's! -L! !g' -e 's!^ !!'` +fi +_LT_TAGDECL([], [compiler_lib_search_dirs], [1], + [The directories searched by this compiler when creating a shared library]) +_LT_TAGDECL([], [predep_objects], [1], + [Dependencies to place before and after the objects being linked to + create a shared library]) +_LT_TAGDECL([], [postdep_objects], [1]) +_LT_TAGDECL([], [predeps], [1]) +_LT_TAGDECL([], [postdeps], [1]) +_LT_TAGDECL([], [compiler_lib_search_path], [1], + [The library search path used internally by the compiler when linking + a shared library]) +])# _LT_SYS_HIDDEN_LIBDEPS + + +# _LT_LANG_F77_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for a Fortran 77 compiler are +# suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_F77_CONFIG], +[AC_LANG_PUSH(Fortran 77) +if test -z "$F77" || test no = "$F77"; then + _lt_disable_F77=yes +fi + +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for f77 test sources. +ac_ext=f + +# Object file extension for compiled f77 test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the F77 compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test yes != "$_lt_disable_F77"; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="\ + subroutine t + return + end +" + + # Code to be used in simple link tests + lt_simple_link_test_code="\ + program t + end +" + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC=$CC + lt_save_GCC=$GCC + lt_save_CFLAGS=$CFLAGS + CC=${F77-"f77"} + CFLAGS=$FFLAGS + compiler=$CC + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + GCC=$G77 + if test -n "$compiler"; then + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test no = "$can_build_shared" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test yes = "$enable_shared" && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + aix[[4-9]]*) + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test yes = "$enable_shared" || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_TAGVAR(GCC, $1)=$G77 + _LT_TAGVAR(LD, $1)=$LD + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + GCC=$lt_save_GCC + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS +fi # test yes != "$_lt_disable_F77" + +AC_LANG_POP +])# _LT_LANG_F77_CONFIG + + +# _LT_LANG_FC_CONFIG([TAG]) +# ------------------------- +# Ensure that the configuration variables for a Fortran compiler are +# suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_FC_CONFIG], +[AC_LANG_PUSH(Fortran) + +if test -z "$FC" || test no = "$FC"; then + _lt_disable_FC=yes +fi + +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for fc test sources. +ac_ext=${ac_fc_srcext-f} + +# Object file extension for compiled fc test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the FC compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test yes != "$_lt_disable_FC"; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="\ + subroutine t + return + end +" + + # Code to be used in simple link tests + lt_simple_link_test_code="\ + program t + end +" + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC=$CC + lt_save_GCC=$GCC + lt_save_CFLAGS=$CFLAGS + CC=${FC-"f95"} + CFLAGS=$FCFLAGS + compiler=$CC + GCC=$ac_cv_fc_compiler_gnu + + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + + if test -n "$compiler"; then + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test no = "$can_build_shared" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test yes = "$enable_shared" && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + aix[[4-9]]*) + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test yes = "$enable_shared" || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_TAGVAR(GCC, $1)=$ac_cv_fc_compiler_gnu + _LT_TAGVAR(LD, $1)=$LD + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_SYS_HIDDEN_LIBDEPS($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + GCC=$lt_save_GCC + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS +fi # test yes != "$_lt_disable_FC" + +AC_LANG_POP +])# _LT_LANG_FC_CONFIG + + +# _LT_LANG_GCJ_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for the GNU Java Compiler compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_GCJ_CONFIG], +[AC_REQUIRE([LT_PROG_GCJ])dnl +AC_LANG_SAVE + +# Source file extension for Java test sources. +ac_ext=java + +# Object file extension for compiled Java test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="class foo {}" + +# Code to be used in simple link tests +lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC=yes +CC=${GCJ-"gcj"} +CFLAGS=$GCJFLAGS +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_TAGVAR(LD, $1)=$LD +_LT_CC_BASENAME([$compiler]) + +# GCJ did not exist at the time GCC didn't implicitly link libc in. +_LT_TAGVAR(archive_cmds_need_lc, $1)=no + +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) +fi + +AC_LANG_RESTORE + +GCC=$lt_save_GCC +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_GCJ_CONFIG + + +# _LT_LANG_GO_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for the GNU Go compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_GO_CONFIG], +[AC_REQUIRE([LT_PROG_GO])dnl +AC_LANG_SAVE + +# Source file extension for Go test sources. +ac_ext=go + +# Object file extension for compiled Go test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="package main; func main() { }" + +# Code to be used in simple link tests +lt_simple_link_test_code='package main; func main() { }' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC=yes +CC=${GOC-"gccgo"} +CFLAGS=$GOFLAGS +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_TAGVAR(LD, $1)=$LD +_LT_CC_BASENAME([$compiler]) + +# Go did not exist at the time GCC didn't implicitly link libc in. +_LT_TAGVAR(archive_cmds_need_lc, $1)=no + +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) +fi + +AC_LANG_RESTORE + +GCC=$lt_save_GCC +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_GO_CONFIG + + +# _LT_LANG_RC_CONFIG([TAG]) +# ------------------------- +# Ensure that the configuration variables for the Windows resource compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_RC_CONFIG], +[AC_REQUIRE([LT_PROG_RC])dnl +AC_LANG_SAVE + +# Source file extension for RC test sources. +ac_ext=rc + +# Object file extension for compiled RC test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' + +# Code to be used in simple link tests +lt_simple_link_test_code=$lt_simple_compile_test_code + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC= +CC=${RC-"windres"} +CFLAGS= +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_CC_BASENAME([$compiler]) +_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + +if test -n "$compiler"; then + : + _LT_CONFIG($1) +fi + +GCC=$lt_save_GCC +AC_LANG_RESTORE +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_RC_CONFIG + + +# LT_PROG_GCJ +# ----------- +AC_DEFUN([LT_PROG_GCJ], +[m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ], + [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ], + [AC_CHECK_TOOL(GCJ, gcj,) + test set = "${GCJFLAGS+set}" || GCJFLAGS="-g -O2" + AC_SUBST(GCJFLAGS)])])[]dnl +]) + +# Old name: +AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_GCJ], []) + + +# LT_PROG_GO +# ---------- +AC_DEFUN([LT_PROG_GO], +[AC_CHECK_TOOL(GOC, gccgo,) +]) + + +# LT_PROG_RC +# ---------- +AC_DEFUN([LT_PROG_RC], +[AC_CHECK_TOOL(RC, windres,) +]) + +# Old name: +AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_RC], []) + + +# _LT_DECL_EGREP +# -------------- +# If we don't have a new enough Autoconf to choose the best grep +# available, choose the one first in the user's PATH. +m4_defun([_LT_DECL_EGREP], +[AC_REQUIRE([AC_PROG_EGREP])dnl +AC_REQUIRE([AC_PROG_FGREP])dnl +test -z "$GREP" && GREP=grep +_LT_DECL([], [GREP], [1], [A grep program that handles long lines]) +_LT_DECL([], [EGREP], [1], [An ERE matcher]) +_LT_DECL([], [FGREP], [1], [A literal string matcher]) +dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too +AC_SUBST([GREP]) +]) + + +# _LT_DECL_OBJDUMP +# -------------- +# If we don't have a new enough Autoconf to choose the best objdump +# available, choose the one first in the user's PATH. +m4_defun([_LT_DECL_OBJDUMP], +[AC_CHECK_TOOL(OBJDUMP, objdump, false) +test -z "$OBJDUMP" && OBJDUMP=objdump +_LT_DECL([], [OBJDUMP], [1], [An object symbol dumper]) +AC_SUBST([OBJDUMP]) +]) + +# _LT_DECL_DLLTOOL +# ---------------- +# Ensure DLLTOOL variable is set. +m4_defun([_LT_DECL_DLLTOOL], +[AC_CHECK_TOOL(DLLTOOL, dlltool, false) +test -z "$DLLTOOL" && DLLTOOL=dlltool +_LT_DECL([], [DLLTOOL], [1], [DLL creation program]) +AC_SUBST([DLLTOOL]) +]) + +# _LT_DECL_SED +# ------------ +# Check for a fully-functional sed program, that truncates +# as few characters as possible. Prefer GNU sed if found. +m4_defun([_LT_DECL_SED], +[AC_PROG_SED +test -z "$SED" && SED=sed +Xsed="$SED -e 1s/^X//" +_LT_DECL([], [SED], [1], [A sed program that does not truncate output]) +_LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"], + [Sed that helps us avoid accidentally triggering echo(1) options like -n]) +])# _LT_DECL_SED + +m4_ifndef([AC_PROG_SED], [ +############################################################ +# NOTE: This macro has been submitted for inclusion into # +# GNU Autoconf as AC_PROG_SED. When it is available in # +# a released version of Autoconf we should remove this # +# macro and use it instead. # +############################################################ + +m4_defun([AC_PROG_SED], +[AC_MSG_CHECKING([for a sed that does not truncate output]) +AC_CACHE_VAL(lt_cv_path_SED, +[# Loop through the user's path and test for sed and gsed. +# Then use that list of sed's as ones to test for truncation. +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for lt_ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then + lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" + fi + done + done +done +IFS=$as_save_IFS +lt_ac_max=0 +lt_ac_count=0 +# Add /usr/xpg4/bin/sed as it is typically found on Solaris +# along with /bin/sed that truncates output. +for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do + test ! -f "$lt_ac_sed" && continue + cat /dev/null > conftest.in + lt_ac_count=0 + echo $ECHO_N "0123456789$ECHO_C" >conftest.in + # Check for GNU sed and select it if it is found. + if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then + lt_cv_path_SED=$lt_ac_sed + break + fi + while true; do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo >>conftest.nl + $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break + cmp -s conftest.out conftest.nl || break + # 10000 chars as input seems more than enough + test 10 -lt "$lt_ac_count" && break + lt_ac_count=`expr $lt_ac_count + 1` + if test "$lt_ac_count" -gt "$lt_ac_max"; then + lt_ac_max=$lt_ac_count + lt_cv_path_SED=$lt_ac_sed + fi + done +done +]) +SED=$lt_cv_path_SED +AC_SUBST([SED]) +AC_MSG_RESULT([$SED]) +])#AC_PROG_SED +])#m4_ifndef + +# Old name: +AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_SED], []) + + +# _LT_CHECK_SHELL_FEATURES +# ------------------------ +# Find out whether the shell is Bourne or XSI compatible, +# or has some other useful features. +m4_defun([_LT_CHECK_SHELL_FEATURES], +[if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + lt_unset=unset +else + lt_unset=false +fi +_LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl + +# test EBCDIC or ASCII +case `echo X|tr X '\101'` in + A) # ASCII based system + # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr + lt_SP2NL='tr \040 \012' + lt_NL2SP='tr \015\012 \040\040' + ;; + *) # EBCDIC based system + lt_SP2NL='tr \100 \n' + lt_NL2SP='tr \r\n \100\100' + ;; +esac +_LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl +_LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl +])# _LT_CHECK_SHELL_FEATURES + + +# _LT_PATH_CONVERSION_FUNCTIONS +# ----------------------------- +# Determine what file name conversion functions should be used by +# func_to_host_file (and, implicitly, by func_to_host_path). These are needed +# for certain cross-compile configurations and native mingw. +m4_defun([_LT_PATH_CONVERSION_FUNCTIONS], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_MSG_CHECKING([how to convert $build file names to $host format]) +AC_CACHE_VAL(lt_cv_to_host_file_cmd, +[case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 + ;; + esac + ;; + *-*-cygwin* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin + ;; + esac + ;; + * ) # unhandled hosts (and "normal" native builds) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; +esac +]) +to_host_file_cmd=$lt_cv_to_host_file_cmd +AC_MSG_RESULT([$lt_cv_to_host_file_cmd]) +_LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd], + [0], [convert $build file names to $host format])dnl + +AC_MSG_CHECKING([how to convert $build file names to toolchain format]) +AC_CACHE_VAL(lt_cv_to_tool_file_cmd, +[#assume ordinary cross tools, or native build. +lt_cv_to_tool_file_cmd=func_convert_file_noop +case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 + ;; + esac + ;; +esac +]) +to_tool_file_cmd=$lt_cv_to_tool_file_cmd +AC_MSG_RESULT([$lt_cv_to_tool_file_cmd]) +_LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd], + [0], [convert $build files to toolchain format])dnl +])# _LT_PATH_CONVERSION_FUNCTIONS diff --git a/m4/ltoptions.m4 b/m4/ltoptions.m4 new file mode 100644 index 0000000..94b0829 --- /dev/null +++ b/m4/ltoptions.m4 @@ -0,0 +1,437 @@ +# Helper functions for option handling. -*- Autoconf -*- +# +# Copyright (C) 2004-2005, 2007-2009, 2011-2015 Free Software +# Foundation, Inc. +# Written by Gary V. Vaughan, 2004 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 8 ltoptions.m4 + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) + + +# _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME) +# ------------------------------------------ +m4_define([_LT_MANGLE_OPTION], +[[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])]) + + +# _LT_SET_OPTION(MACRO-NAME, OPTION-NAME) +# --------------------------------------- +# Set option OPTION-NAME for macro MACRO-NAME, and if there is a +# matching handler defined, dispatch to it. Other OPTION-NAMEs are +# saved as a flag. +m4_define([_LT_SET_OPTION], +[m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl +m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), + _LT_MANGLE_DEFUN([$1], [$2]), + [m4_warning([Unknown $1 option '$2'])])[]dnl +]) + + +# _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET]) +# ------------------------------------------------------------ +# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. +m4_define([_LT_IF_OPTION], +[m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])]) + + +# _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET) +# ------------------------------------------------------- +# Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME +# are set. +m4_define([_LT_UNLESS_OPTIONS], +[m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), + [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option), + [m4_define([$0_found])])])[]dnl +m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3 +])[]dnl +]) + + +# _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST) +# ---------------------------------------- +# OPTION-LIST is a space-separated list of Libtool options associated +# with MACRO-NAME. If any OPTION has a matching handler declared with +# LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about +# the unknown option and exit. +m4_defun([_LT_SET_OPTIONS], +[# Set options +m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), + [_LT_SET_OPTION([$1], _LT_Option)]) + +m4_if([$1],[LT_INIT],[ + dnl + dnl Simply set some default values (i.e off) if boolean options were not + dnl specified: + _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no + ]) + _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no + ]) + dnl + dnl If no reference was made to various pairs of opposing options, then + dnl we run the default mode handler for the pair. For example, if neither + dnl 'shared' nor 'disable-shared' was passed, we enable building of shared + dnl archives by default: + _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) + _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) + _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) + _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], + [_LT_ENABLE_FAST_INSTALL]) + _LT_UNLESS_OPTIONS([LT_INIT], [aix-soname=aix aix-soname=both aix-soname=svr4], + [_LT_WITH_AIX_SONAME([aix])]) + ]) +])# _LT_SET_OPTIONS + + +## --------------------------------- ## +## Macros to handle LT_INIT options. ## +## --------------------------------- ## + +# _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME) +# ----------------------------------------- +m4_define([_LT_MANGLE_DEFUN], +[[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])]) + + +# LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE) +# ----------------------------------------------- +m4_define([LT_OPTION_DEFINE], +[m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl +])# LT_OPTION_DEFINE + + +# dlopen +# ------ +LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes +]) + +AU_DEFUN([AC_LIBTOOL_DLOPEN], +[_LT_SET_OPTION([LT_INIT], [dlopen]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the 'dlopen' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], []) + + +# win32-dll +# --------- +# Declare package support for building win32 dll's. +LT_OPTION_DEFINE([LT_INIT], [win32-dll], +[enable_win32_dll=yes + +case $host in +*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) + AC_CHECK_TOOL(AS, as, false) + AC_CHECK_TOOL(DLLTOOL, dlltool, false) + AC_CHECK_TOOL(OBJDUMP, objdump, false) + ;; +esac + +test -z "$AS" && AS=as +_LT_DECL([], [AS], [1], [Assembler program])dnl + +test -z "$DLLTOOL" && DLLTOOL=dlltool +_LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl + +test -z "$OBJDUMP" && OBJDUMP=objdump +_LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl +])# win32-dll + +AU_DEFUN([AC_LIBTOOL_WIN32_DLL], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +_LT_SET_OPTION([LT_INIT], [win32-dll]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the 'win32-dll' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) + + +# _LT_ENABLE_SHARED([DEFAULT]) +# ---------------------------- +# implement the --enable-shared flag, and supports the 'shared' and +# 'disable-shared' LT_INIT options. +# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. +m4_define([_LT_ENABLE_SHARED], +[m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([shared], + [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@], + [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS=$lt_save_ifs + ;; + esac], + [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) + + _LT_DECL([build_libtool_libs], [enable_shared], [0], + [Whether or not to build shared libraries]) +])# _LT_ENABLE_SHARED + +LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])]) + +# Old names: +AC_DEFUN([AC_ENABLE_SHARED], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared]) +]) + +AC_DEFUN([AC_DISABLE_SHARED], +[_LT_SET_OPTION([LT_INIT], [disable-shared]) +]) + +AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) +AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_ENABLE_SHARED], []) +dnl AC_DEFUN([AM_DISABLE_SHARED], []) + + + +# _LT_ENABLE_STATIC([DEFAULT]) +# ---------------------------- +# implement the --enable-static flag, and support the 'static' and +# 'disable-static' LT_INIT options. +# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. +m4_define([_LT_ENABLE_STATIC], +[m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([static], + [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@], + [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS=$lt_save_ifs + ;; + esac], + [enable_static=]_LT_ENABLE_STATIC_DEFAULT) + + _LT_DECL([build_old_libs], [enable_static], [0], + [Whether or not to build static libraries]) +])# _LT_ENABLE_STATIC + +LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])]) + +# Old names: +AC_DEFUN([AC_ENABLE_STATIC], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static]) +]) + +AC_DEFUN([AC_DISABLE_STATIC], +[_LT_SET_OPTION([LT_INIT], [disable-static]) +]) + +AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) +AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_ENABLE_STATIC], []) +dnl AC_DEFUN([AM_DISABLE_STATIC], []) + + + +# _LT_ENABLE_FAST_INSTALL([DEFAULT]) +# ---------------------------------- +# implement the --enable-fast-install flag, and support the 'fast-install' +# and 'disable-fast-install' LT_INIT options. +# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. +m4_define([_LT_ENABLE_FAST_INSTALL], +[m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([fast-install], + [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], + [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS=$lt_save_ifs + ;; + esac], + [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) + +_LT_DECL([fast_install], [enable_fast_install], [0], + [Whether or not to optimize for fast installation])dnl +])# _LT_ENABLE_FAST_INSTALL + +LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])]) + +# Old names: +AU_DEFUN([AC_ENABLE_FAST_INSTALL], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you put +the 'fast-install' option into LT_INIT's first parameter.]) +]) + +AU_DEFUN([AC_DISABLE_FAST_INSTALL], +[_LT_SET_OPTION([LT_INIT], [disable-fast-install]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you put +the 'disable-fast-install' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) +dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) + + +# _LT_WITH_AIX_SONAME([DEFAULT]) +# ---------------------------------- +# implement the --with-aix-soname flag, and support the `aix-soname=aix' +# and `aix-soname=both' and `aix-soname=svr4' LT_INIT options. DEFAULT +# is either `aix', `both' or `svr4'. If omitted, it defaults to `aix'. +m4_define([_LT_WITH_AIX_SONAME], +[m4_define([_LT_WITH_AIX_SONAME_DEFAULT], [m4_if($1, svr4, svr4, m4_if($1, both, both, aix))])dnl +shared_archive_member_spec= +case $host,$enable_shared in +power*-*-aix[[5-9]]*,yes) + AC_MSG_CHECKING([which variant of shared library versioning to provide]) + AC_ARG_WITH([aix-soname], + [AS_HELP_STRING([--with-aix-soname=aix|svr4|both], + [shared library versioning (aka "SONAME") variant to provide on AIX, @<:@default=]_LT_WITH_AIX_SONAME_DEFAULT[@:>@.])], + [case $withval in + aix|svr4|both) + ;; + *) + AC_MSG_ERROR([Unknown argument to --with-aix-soname]) + ;; + esac + lt_cv_with_aix_soname=$with_aix_soname], + [AC_CACHE_VAL([lt_cv_with_aix_soname], + [lt_cv_with_aix_soname=]_LT_WITH_AIX_SONAME_DEFAULT) + with_aix_soname=$lt_cv_with_aix_soname]) + AC_MSG_RESULT([$with_aix_soname]) + if test aix != "$with_aix_soname"; then + # For the AIX way of multilib, we name the shared archive member + # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o', + # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File. + # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag, + # the AIX toolchain works better with OBJECT_MODE set (default 32). + if test 64 = "${OBJECT_MODE-32}"; then + shared_archive_member_spec=shr_64 + else + shared_archive_member_spec=shr + fi + fi + ;; +*) + with_aix_soname=aix + ;; +esac + +_LT_DECL([], [shared_archive_member_spec], [0], + [Shared archive member basename, for filename based shared library versioning on AIX])dnl +])# _LT_WITH_AIX_SONAME + +LT_OPTION_DEFINE([LT_INIT], [aix-soname=aix], [_LT_WITH_AIX_SONAME([aix])]) +LT_OPTION_DEFINE([LT_INIT], [aix-soname=both], [_LT_WITH_AIX_SONAME([both])]) +LT_OPTION_DEFINE([LT_INIT], [aix-soname=svr4], [_LT_WITH_AIX_SONAME([svr4])]) + + +# _LT_WITH_PIC([MODE]) +# -------------------- +# implement the --with-pic flag, and support the 'pic-only' and 'no-pic' +# LT_INIT options. +# MODE is either 'yes' or 'no'. If omitted, it defaults to 'both'. +m4_define([_LT_WITH_PIC], +[AC_ARG_WITH([pic], + [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@], + [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], + [lt_p=${PACKAGE-default} + case $withval in + yes|no) pic_mode=$withval ;; + *) + pic_mode=default + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for lt_pkg in $withval; do + IFS=$lt_save_ifs + if test "X$lt_pkg" = "X$lt_p"; then + pic_mode=yes + fi + done + IFS=$lt_save_ifs + ;; + esac], + [pic_mode=m4_default([$1], [default])]) + +_LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl +])# _LT_WITH_PIC + +LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])]) +LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])]) + +# Old name: +AU_DEFUN([AC_LIBTOOL_PICMODE], +[_LT_SET_OPTION([LT_INIT], [pic-only]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the 'pic-only' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_PICMODE], []) + +## ----------------- ## +## LTDL_INIT Options ## +## ----------------- ## + +m4_define([_LTDL_MODE], []) +LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive], + [m4_define([_LTDL_MODE], [nonrecursive])]) +LT_OPTION_DEFINE([LTDL_INIT], [recursive], + [m4_define([_LTDL_MODE], [recursive])]) +LT_OPTION_DEFINE([LTDL_INIT], [subproject], + [m4_define([_LTDL_MODE], [subproject])]) + +m4_define([_LTDL_TYPE], []) +LT_OPTION_DEFINE([LTDL_INIT], [installable], + [m4_define([_LTDL_TYPE], [installable])]) +LT_OPTION_DEFINE([LTDL_INIT], [convenience], + [m4_define([_LTDL_TYPE], [convenience])]) diff --git a/m4/ltsugar.m4 b/m4/ltsugar.m4 new file mode 100644 index 0000000..48bc934 --- /dev/null +++ b/m4/ltsugar.m4 @@ -0,0 +1,124 @@ +# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- +# +# Copyright (C) 2004-2005, 2007-2008, 2011-2015 Free Software +# Foundation, Inc. +# Written by Gary V. Vaughan, 2004 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 6 ltsugar.m4 + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) + + +# lt_join(SEP, ARG1, [ARG2...]) +# ----------------------------- +# Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their +# associated separator. +# Needed until we can rely on m4_join from Autoconf 2.62, since all earlier +# versions in m4sugar had bugs. +m4_define([lt_join], +[m4_if([$#], [1], [], + [$#], [2], [[$2]], + [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) +m4_define([_lt_join], +[m4_if([$#$2], [2], [], + [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) + + +# lt_car(LIST) +# lt_cdr(LIST) +# ------------ +# Manipulate m4 lists. +# These macros are necessary as long as will still need to support +# Autoconf-2.59, which quotes differently. +m4_define([lt_car], [[$1]]) +m4_define([lt_cdr], +[m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], + [$#], 1, [], + [m4_dquote(m4_shift($@))])]) +m4_define([lt_unquote], $1) + + +# lt_append(MACRO-NAME, STRING, [SEPARATOR]) +# ------------------------------------------ +# Redefine MACRO-NAME to hold its former content plus 'SEPARATOR''STRING'. +# Note that neither SEPARATOR nor STRING are expanded; they are appended +# to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). +# No SEPARATOR is output if MACRO-NAME was previously undefined (different +# than defined and empty). +# +# This macro is needed until we can rely on Autoconf 2.62, since earlier +# versions of m4sugar mistakenly expanded SEPARATOR but not STRING. +m4_define([lt_append], +[m4_define([$1], + m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) + + + +# lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) +# ---------------------------------------------------------- +# Produce a SEP delimited list of all paired combinations of elements of +# PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list +# has the form PREFIXmINFIXSUFFIXn. +# Needed until we can rely on m4_combine added in Autoconf 2.62. +m4_define([lt_combine], +[m4_if(m4_eval([$# > 3]), [1], + [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl +[[m4_foreach([_Lt_prefix], [$2], + [m4_foreach([_Lt_suffix], + ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, + [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) + + +# lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) +# ----------------------------------------------------------------------- +# Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited +# by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. +m4_define([lt_if_append_uniq], +[m4_ifdef([$1], + [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], + [lt_append([$1], [$2], [$3])$4], + [$5])], + [lt_append([$1], [$2], [$3])$4])]) + + +# lt_dict_add(DICT, KEY, VALUE) +# ----------------------------- +m4_define([lt_dict_add], +[m4_define([$1($2)], [$3])]) + + +# lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) +# -------------------------------------------- +m4_define([lt_dict_add_subkey], +[m4_define([$1($2:$3)], [$4])]) + + +# lt_dict_fetch(DICT, KEY, [SUBKEY]) +# ---------------------------------- +m4_define([lt_dict_fetch], +[m4_ifval([$3], + m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), + m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) + + +# lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) +# ----------------------------------------------------------------- +m4_define([lt_if_dict_fetch], +[m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], + [$5], + [$6])]) + + +# lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) +# -------------------------------------------------------------- +m4_define([lt_dict_filter], +[m4_if([$5], [], [], + [lt_join(m4_quote(m4_default([$4], [[, ]])), + lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), + [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl +]) diff --git a/m4/ltversion.m4 b/m4/ltversion.m4 new file mode 100644 index 0000000..fa04b52 --- /dev/null +++ b/m4/ltversion.m4 @@ -0,0 +1,23 @@ +# ltversion.m4 -- version numbers -*- Autoconf -*- +# +# Copyright (C) 2004, 2011-2015 Free Software Foundation, Inc. +# Written by Scott James Remnant, 2004 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# @configure_input@ + +# serial 4179 ltversion.m4 +# This file is part of GNU Libtool + +m4_define([LT_PACKAGE_VERSION], [2.4.6]) +m4_define([LT_PACKAGE_REVISION], [2.4.6]) + +AC_DEFUN([LTVERSION_VERSION], +[macro_version='2.4.6' +macro_revision='2.4.6' +_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) +_LT_DECL(, macro_revision, 0) +]) diff --git a/m4/lt~obsolete.m4 b/m4/lt~obsolete.m4 new file mode 100644 index 0000000..c6b26f8 --- /dev/null +++ b/m4/lt~obsolete.m4 @@ -0,0 +1,99 @@ +# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- +# +# Copyright (C) 2004-2005, 2007, 2009, 2011-2015 Free Software +# Foundation, Inc. +# Written by Scott James Remnant, 2004. +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 5 lt~obsolete.m4 + +# These exist entirely to fool aclocal when bootstrapping libtool. +# +# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN), +# which have later been changed to m4_define as they aren't part of the +# exported API, or moved to Autoconf or Automake where they belong. +# +# The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN +# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us +# using a macro with the same name in our local m4/libtool.m4 it'll +# pull the old libtool.m4 in (it doesn't see our shiny new m4_define +# and doesn't know about Autoconf macros at all.) +# +# So we provide this file, which has a silly filename so it's always +# included after everything else. This provides aclocal with the +# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything +# because those macros already exist, or will be overwritten later. +# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. +# +# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. +# Yes, that means every name once taken will need to remain here until +# we give up compatibility with versions before 1.7, at which point +# we need to keep only those names which we still refer to. + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) + +m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) +m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) +m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) +m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) +m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) +m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) +m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) +m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) +m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) +m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) +m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) +m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) +m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) +m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) +m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) +m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) +m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) +m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) +m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) +m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) +m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) +m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) +m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) +m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) +m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) +m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) +m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) +m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) +m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) +m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) +m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) +m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) +m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) +m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) +m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) +m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) +m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) +m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) +m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) +m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) +m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) +m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) +m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) +m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) +m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) +m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) +m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) +m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) +m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) +m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) +m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])]) +m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])]) +m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])]) +m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])]) +m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])]) +m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])]) +m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])]) diff --git a/m4/vapigen.m4 b/m4/vapigen.m4 new file mode 100644 index 0000000..99e5493 --- /dev/null +++ b/m4/vapigen.m4 @@ -0,0 +1,177 @@ +dnl vapigen.m4 +dnl +dnl Copyright 2012 Evan Nemerson, Daniel Espinosa +dnl +dnl This library is free software; you can redistribute it and/or +dnl modify it under the terms of the GNU Lesser General Public +dnl License as published by the Free Software Foundation; either +dnl version 2.1 of the License, or (at your option) any later version. +dnl +dnl This library is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +dnl Lesser General Public License for more details. +dnl +dnl You should have received a copy of the GNU Lesser General Public +dnl License along with this library; if not, write to the Free Software +dnl Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# VAPIGEN_CHECK([VERSION], [API_VERSION], [FOUND-INTROSPECTION], [DEFAULT]) +# -------------------------------------- +# Check vapigen existence and version. GObject Introspection is required, then +# set FOUND-INTROSPECTION to [yes] or use call GOBJECT_INTROSPECTION_CHECK or +# GOBJECT_INTROSPECTION_REQUIRE. This is an internal macro, use VAPIGEN_CHECK, +# VAPIGEN_GI_CHECK or VAPIGEN_GI_REQUIRE. +# +# See http://live.gnome.org/Vala/UpstreamGuide for detailed documentation +m4_define([_VAPIGEN_CHECK_INTERNAL], +[ + AC_REQUIRE([PKG_PROG_PKG_CONFIG]) + AC_REQUIRE([AM_PROG_VALAC]) + AC_ARG_ENABLE([vala], + [AS_HELP_STRING([--enable-vala[=@<:@no/auto/yes@:>@]],[build Vala bindings @<:@default=]ifelse($4,,auto,$4)[@:>@])],,[ + AS_IF([ test "x$4" = "x"], [ + enable_vala=auto + ], [ + enable_vala=$4 + ]) + ]) + AS_IF([ test "x$enable_vala" = "xyes" -o "x$enable_vala" = "xauto"], + [ + AS_IF([ test "x$3" != "xyes" -a "x$found_introspection" != "xyes"], [ + AC_MSG_ERROR([Vala bindings require GObject Introspection]) + ]) + ], [ + AS_IF([ test "x$enable_vala" != "no"],[ + vapigen_pkg_found=no + ],[ + AC_MSG_ERROR([Invalid argument passed to --enable-vala, should be one of @<:@no/auto/yes@:>@]) + ]) + ]) + AS_IF([ test "x$2" = "x"], [ + vapigen_pkg_name=vapigen + ], [ + vapigen_pkg_name=vapigen-$2 + ]) + AS_IF([ test "x$1" = "x"], [ + vapigen_pkg="$vapigen_pkg_name" + ], [ + vapigen_pkg="$vapigen_pkg_name >= $1" + ]) + AS_IF([ test "x$enable_vala" = "xyes" -o "x$enable_vala" = "xauto"], [ + AC_MSG_CHECKING([for vapigen $vapigen_pkg_name]) + PKG_CHECK_EXISTS([ $vapigen_pkg ], [ + vapigen_pkg_found=yes + ], [ + vapigen_pkg_found=no + AC_MSG_RESULT([no]) + AC_MSG_NOTICE([Searching for $vapigen_pkg_name program...]) + AC_PATH_PROG(VAPIGEN, [$vapigen_pkg_name], [no]) + if test "x$VAPIGEN" = "xno" + then + check_prog=no + else + check_prog=yes + fi + ]) + + AS_CASE([$vapigen_pkg_found], + [yes], [ + VAPIGEN=`$PKG_CONFIG --variable=vapigen vapigen` + VAPIGEN_MAKEFILE=`$PKG_CONFIG --variable=datadir vapigen`/vala/Makefile.vapigen + VAPIDIR=`$PKG_CONFIG --variable=vapidir vapigen` + AS_IF([ test "x$2" = "x"], [ + VAPIGEN_VAPIDIR=`$PKG_CONFIG --variable=vapidir vapigen` + ], [ + VAPIGEN_VAPIDIR=`$PKG_CONFIG --variable=vapidir_versioned vapigen` + ]) + ], + [no], [ + AS_CASE([$check_prog],[no],[ + AC_MSG_ERROR([Can't locate $vapigen_pkg program]) + ], [yes], [ + AS_IF([ test "x$2" = "x"], [ + vala_pkg_name=libvala + ], [ + vala_pkg_name=libvala-$2 + ]) + AS_IF([ test "x$1" = "x"], [ + vala_pkg="$vala_pkg_name" + ], [ + vala_pkg="$vala_pkg_name >= $1" + ]) + AC_MSG_CHECKING([for $vala_pkg]) + PKG_CHECK_EXISTS([$vala_pkg], [ + VALA_DATADIR=`pkg-config $vala_pkg --variable=datadir` + VAPIDIR="$VALA_DATADIR/vala/vapi" + VAPIGEN_MAKEFILE="$VALA_DATADIR/vala/Makefile.vapigen" + AS_IF([ test "x$2" = "x"], [ + VAPIGEN_VAPIDIR=`$PKG_CONFIG --variable=vapidir vapigen` + ], [ + VAPIGEN_VAPIDIR=`$PKG_CONFIG --variable=vapidir_versioned vapigen` + ]) + vapigen_pkg_found=yes + ], [ + AS_CASE([$enable_vala], [yes], [ + AC_MSG_ERROR([$vala_pkg not found]) + ], [auto], [ + vapigen_pkg_found=no + ]) + ]) + ]) + ]) + + AC_MSG_RESULT([$vapigen_pkg_found]) + + + ]) + AC_SUBST([VAPIGEN]) + AC_SUBST([VAPIGEN_VAPIDIR]) + AC_SUBST([VAPIDIR]) + AC_SUBST([VAPIGEN_MAKEFILE]) + + AM_CONDITIONAL(ENABLE_VAPIGEN, test "x$vapigen_pkg_found" = "xyes") +]) + +dnl Check VAPIGEN +# VAPIGEN_CHECK([VERSION], [API_VERSION], [FOUND-INTROSPECTION], [DEFAULT]) +# -------------------------------------- +# Check vapigen existence and version. Set FOUND-INTROSPECTION to [yes] +# if you have detected GObject Introspection without GOBJECT_INTROSPECTION_CHECK +# or GOBJECT_INTROSPECTION_REQUIRE macros. +# +# See http://live.gnome.org/Vala/UpstreamGuide for detailed documentation +AC_DEFUN([VAPIGEN_CHECK], +[ + _VAPIGEN_CHECK_INTERNAL($1,$2,$3,$4) +] +) + +dnl usage: +# VAPIGEN_GI_CHECK([VERSION], [API_VERSION], [DEFAULT]) +# -------------------------------------- +# Check vapigen existence and version. You must call GOBJECT_INTROSPECTION_CHECK +# first in order to call this macro. +# +# See http://live.gnome.org/Vala/UpstreamGuide for detailed documentation +AC_DEFUN([VAPIGEN_GI_CHECK], +[ + AC_REQUIRE([GOBJECT_INTROSPECTION_CHECK]) + _VAPIGEN_CHECK_INTERNAL([$1],[$2],[$found_introspection],[$3]) +] +) + +dnl usage: +# VAPIGEN_GI_REQUIRE([VERSION], [API_VERSION], [DEFAULT]) +# -------------------------------------- +# Check vapigen existence and version. You must call GOBJECT_INTROSPECTION_REQUIRE +# first in order to call this macro. +# +# See http://live.gnome.org/Vala/UpstreamGuide for detailed documentation +AC_DEFUN([VAPIGEN_GI_REQUIRE], +[ + AC_REQUIRE([GOBJECT_INTROSPECTION_REQUIRE]) + _VAPIGEN_CHECK_INTERNAL([$1],[$2],[$found_introspection],[$3]) +] +) + diff --git a/missing b/missing new file mode 100755 index 0000000..f62bbae --- /dev/null +++ b/missing @@ -0,0 +1,215 @@ +#! /bin/sh +# Common wrapper for a few potentially missing GNU programs. + +scriptversion=2013-10-28.13; # UTC + +# Copyright (C) 1996-2014 Free Software Foundation, Inc. +# Originally written by Fran,cois Pinard , 1996. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, 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. + +if test $# -eq 0; then + echo 1>&2 "Try '$0 --help' for more information" + exit 1 +fi + +case $1 in + + --is-lightweight) + # Used by our autoconf macros to check whether the available missing + # script is modern enough. + exit 0 + ;; + + --run) + # Back-compat with the calling convention used by older automake. + shift + ;; + + -h|--h|--he|--hel|--help) + echo "\ +$0 [OPTION]... PROGRAM [ARGUMENT]... + +Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due +to PROGRAM being missing or too old. + +Options: + -h, --help display this help and exit + -v, --version output version information and exit + +Supported PROGRAM values: + aclocal autoconf autoheader autom4te automake makeinfo + bison yacc flex lex help2man + +Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and +'g' are ignored when checking the name. + +Send bug reports to ." + exit $? + ;; + + -v|--v|--ve|--ver|--vers|--versi|--versio|--version) + echo "missing $scriptversion (GNU Automake)" + exit $? + ;; + + -*) + echo 1>&2 "$0: unknown '$1' option" + echo 1>&2 "Try '$0 --help' for more information" + exit 1 + ;; + +esac + +# Run the given program, remember its exit status. +"$@"; st=$? + +# If it succeeded, we are done. +test $st -eq 0 && exit 0 + +# Also exit now if we it failed (or wasn't found), and '--version' was +# passed; such an option is passed most likely to detect whether the +# program is present and works. +case $2 in --version|--help) exit $st;; esac + +# Exit code 63 means version mismatch. This often happens when the user +# tries to use an ancient version of a tool on a file that requires a +# minimum version. +if test $st -eq 63; then + msg="probably too old" +elif test $st -eq 127; then + # Program was missing. + msg="missing on your system" +else + # Program was found and executed, but failed. Give up. + exit $st +fi + +perl_URL=http://www.perl.org/ +flex_URL=http://flex.sourceforge.net/ +gnu_software_URL=http://www.gnu.org/software + +program_details () +{ + case $1 in + aclocal|automake) + echo "The '$1' program is part of the GNU Automake package:" + echo "<$gnu_software_URL/automake>" + echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" + echo "<$gnu_software_URL/autoconf>" + echo "<$gnu_software_URL/m4/>" + echo "<$perl_URL>" + ;; + autoconf|autom4te|autoheader) + echo "The '$1' program is part of the GNU Autoconf package:" + echo "<$gnu_software_URL/autoconf/>" + echo "It also requires GNU m4 and Perl in order to run:" + echo "<$gnu_software_URL/m4/>" + echo "<$perl_URL>" + ;; + esac +} + +give_advice () +{ + # Normalize program name to check for. + normalized_program=`echo "$1" | sed ' + s/^gnu-//; t + s/^gnu//; t + s/^g//; t'` + + printf '%s\n' "'$1' is $msg." + + configure_deps="'configure.ac' or m4 files included by 'configure.ac'" + case $normalized_program in + autoconf*) + echo "You should only need it if you modified 'configure.ac'," + echo "or m4 files included by it." + program_details 'autoconf' + ;; + autoheader*) + echo "You should only need it if you modified 'acconfig.h' or" + echo "$configure_deps." + program_details 'autoheader' + ;; + automake*) + echo "You should only need it if you modified 'Makefile.am' or" + echo "$configure_deps." + program_details 'automake' + ;; + aclocal*) + echo "You should only need it if you modified 'acinclude.m4' or" + echo "$configure_deps." + program_details 'aclocal' + ;; + autom4te*) + echo "You might have modified some maintainer files that require" + echo "the 'autom4te' program to be rebuilt." + program_details 'autom4te' + ;; + bison*|yacc*) + echo "You should only need it if you modified a '.y' file." + echo "You may want to install the GNU Bison package:" + echo "<$gnu_software_URL/bison/>" + ;; + lex*|flex*) + echo "You should only need it if you modified a '.l' file." + echo "You may want to install the Fast Lexical Analyzer package:" + echo "<$flex_URL>" + ;; + help2man*) + echo "You should only need it if you modified a dependency" \ + "of a man page." + echo "You may want to install the GNU Help2man package:" + echo "<$gnu_software_URL/help2man/>" + ;; + makeinfo*) + echo "You should only need it if you modified a '.texi' file, or" + echo "any other file indirectly affecting the aspect of the manual." + echo "You might want to install the Texinfo package:" + echo "<$gnu_software_URL/texinfo/>" + echo "The spurious makeinfo call might also be the consequence of" + echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" + echo "want to install GNU make:" + echo "<$gnu_software_URL/make/>" + ;; + *) + echo "You might have modified some files without having the proper" + echo "tools for further handling them. Check the 'README' file, it" + echo "often tells you about the needed prerequisites for installing" + echo "this package. You may also peek at any GNU archive site, in" + echo "case some other package contains this missing '$1' program." + ;; + esac +} + +give_advice "$1" | sed -e '1s/^/WARNING: /' \ + -e '2,$s/^/ /' >&2 + +# Propagate the correct exit status (expected to be 127 for a program +# not found, 63 for a program that failed due to version mismatch). +exit $st + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/po/LINGUAS b/po/LINGUAS new file mode 100644 index 0000000..0eaf8a7 --- /dev/null +++ b/po/LINGUAS @@ -0,0 +1,64 @@ +an +as +be +bg +bn_IN +bs +ca +ca@valencia +cs +da +de +el +en_GB +eo +es +et +eu +fa +fr +fur +gd +gl +gu +he +hi +hr +hu +id +it +ja +kn +ko +lt +lv +ml +mr +nb +ne +nl +oc +or +pa +pl +pt +pt_BR +ro +ru +sk +sl +sr +sr@latin +sv +ta +te +tg +th +tr +ug +uk +uz@cyrillic +vi +zh_CN +zh_HK +zh_TW diff --git a/po/Makefile.in.in b/po/Makefile.in.in new file mode 100644 index 0000000..fcd2c3b --- /dev/null +++ b/po/Makefile.in.in @@ -0,0 +1,221 @@ +# Makefile for program source directory in GNU NLS utilities package. +# Copyright (C) 1995, 1996, 1997 by Ulrich Drepper +# Copyright (C) 2004-2008 Rodney Dawes +# +# This file may be copied and used freely without restrictions. It may +# be used in projects which are not available under a GNU Public License, +# but which still want to provide support for the GNU gettext functionality. +# +# - Modified by Owen Taylor to use GETTEXT_PACKAGE +# instead of PACKAGE and to look for po2tbl in ./ not in intl/ +# +# - Modified by jacob berkman to install +# Makefile.in.in and po2tbl.sed.in for use with glib-gettextize +# +# - Modified by Rodney Dawes for use with intltool +# +# We have the following line for use by intltoolize: +# INTLTOOL_MAKEFILE + +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +PACKAGE = @PACKAGE@ +VERSION = @VERSION@ + +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +top_builddir = @top_builddir@ +VPATH = @srcdir@ + +prefix = @prefix@ +exec_prefix = @exec_prefix@ +datadir = @datadir@ +datarootdir = @datarootdir@ +libdir = @libdir@ +localedir = @localedir@ +subdir = po +install_sh = @install_sh@ +# Automake >= 1.8 provides @mkdir_p@. +# Until it can be supposed, use the safe fallback: +mkdir_p = $(install_sh) -d + +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ + +GMSGFMT = @GMSGFMT@ +MSGFMT = @MSGFMT@ +XGETTEXT = @XGETTEXT@ +INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ +INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ +MSGMERGE = INTLTOOL_EXTRACT="$(INTLTOOL_EXTRACT)" XGETTEXT="$(XGETTEXT)" srcdir=$(srcdir) $(INTLTOOL_UPDATE) --gettext-package $(GETTEXT_PACKAGE) --dist +GENPOT = INTLTOOL_EXTRACT="$(INTLTOOL_EXTRACT)" XGETTEXT="$(XGETTEXT)" srcdir=$(srcdir) $(INTLTOOL_UPDATE) --gettext-package $(GETTEXT_PACKAGE) --pot + +ALL_LINGUAS = @ALL_LINGUAS@ + +PO_LINGUAS=$(shell if test -r $(srcdir)/LINGUAS; then grep -v "^\#" $(srcdir)/LINGUAS; else echo "$(ALL_LINGUAS)"; fi) + +USER_LINGUAS=$(shell if test -n "$(LINGUAS)"; then LLINGUAS="$(LINGUAS)"; ALINGUAS="$(ALL_LINGUAS)"; for lang in $$LLINGUAS; do if test -n "`grep \^$$lang$$ $(srcdir)/LINGUAS 2>/dev/null`" -o -n "`echo $$ALINGUAS|tr ' ' '\n'|grep \^$$lang$$`"; then printf "$$lang "; fi; done; fi) + +USE_LINGUAS=$(shell if test -n "$(USER_LINGUAS)" -o -n "$(LINGUAS)"; then LLINGUAS="$(USER_LINGUAS)"; else if test -n "$(PO_LINGUAS)"; then LLINGUAS="$(PO_LINGUAS)"; else LLINGUAS="$(ALL_LINGUAS)"; fi; fi; for lang in $$LLINGUAS; do printf "$$lang "; done) + +POFILES=$(shell LINGUAS="$(PO_LINGUAS)"; for lang in $$LINGUAS; do printf "$$lang.po "; done) + +DISTFILES = Makefile.in.in POTFILES.in $(POFILES) +EXTRA_DISTFILES = ChangeLog POTFILES.skip Makevars LINGUAS + +POTFILES = \ +# This comment gets stripped out + +CATALOGS=$(shell LINGUAS="$(USE_LINGUAS)"; for lang in $$LINGUAS; do printf "$$lang.gmo "; done) + +.SUFFIXES: +.SUFFIXES: .po .pox .gmo .mo .msg .cat + +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +INTLTOOL_V_MSGFMT = $(INTLTOOL__v_MSGFMT_$(V)) +INTLTOOL__v_MSGFMT_= $(INTLTOOL__v_MSGFMT_$(AM_DEFAULT_VERBOSITY)) +INTLTOOL__v_MSGFMT_0 = @echo " MSGFMT" $@; + +.po.pox: + $(MAKE) $(GETTEXT_PACKAGE).pot + $(MSGMERGE) $* $(GETTEXT_PACKAGE).pot -o $*.pox + +.po.mo: + $(INTLTOOL_V_MSGFMT)$(MSGFMT) -o $@ $< + +.po.gmo: + $(INTLTOOL_V_MSGFMT)file=`echo $* | sed 's,.*/,,'`.gmo \ + && rm -f $$file && $(GMSGFMT) -o $$file $< + +.po.cat: + sed -f ../intl/po2msg.sed < $< > $*.msg \ + && rm -f $@ && gencat $@ $*.msg + + +all: all-@USE_NLS@ + +all-yes: $(CATALOGS) +all-no: + +$(GETTEXT_PACKAGE).pot: $(POTFILES) + $(GENPOT) + +install: install-data +install-data: install-data-@USE_NLS@ +install-data-no: all +install-data-yes: all + linguas="$(USE_LINGUAS)"; \ + for lang in $$linguas; do \ + dir=$(DESTDIR)$(localedir)/$$lang/LC_MESSAGES; \ + $(mkdir_p) $$dir; \ + if test -r $$lang.gmo; then \ + $(INSTALL_DATA) $$lang.gmo $$dir/$(GETTEXT_PACKAGE).mo; \ + echo "installing $$lang.gmo as $$dir/$(GETTEXT_PACKAGE).mo"; \ + else \ + $(INSTALL_DATA) $(srcdir)/$$lang.gmo $$dir/$(GETTEXT_PACKAGE).mo; \ + echo "installing $(srcdir)/$$lang.gmo as" \ + "$$dir/$(GETTEXT_PACKAGE).mo"; \ + fi; \ + if test -r $$lang.gmo.m; then \ + $(INSTALL_DATA) $$lang.gmo.m $$dir/$(GETTEXT_PACKAGE).mo.m; \ + echo "installing $$lang.gmo.m as $$dir/$(GETTEXT_PACKAGE).mo.m"; \ + else \ + if test -r $(srcdir)/$$lang.gmo.m ; then \ + $(INSTALL_DATA) $(srcdir)/$$lang.gmo.m \ + $$dir/$(GETTEXT_PACKAGE).mo.m; \ + echo "installing $(srcdir)/$$lang.gmo.m as" \ + "$$dir/$(GETTEXT_PACKAGE).mo.m"; \ + else \ + true; \ + fi; \ + fi; \ + done + +# Empty stubs to satisfy archaic automake needs +dvi info ctags tags CTAGS TAGS ID: + +# Define this as empty until I found a useful application. +install-exec installcheck: + +uninstall: + linguas="$(USE_LINGUAS)"; \ + for lang in $$linguas; do \ + rm -f $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(GETTEXT_PACKAGE).mo; \ + rm -f $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(GETTEXT_PACKAGE).mo.m; \ + done + +check: all $(GETTEXT_PACKAGE).pot + rm -f missing notexist + srcdir=$(srcdir) $(INTLTOOL_UPDATE) -m + if [ -r missing -o -r notexist ]; then \ + exit 1; \ + fi + +mostlyclean: + rm -f *.pox $(GETTEXT_PACKAGE).pot *.old.po cat-id-tbl.tmp + rm -f .intltool-merge-cache + +clean: mostlyclean + +distclean: clean + rm -f Makefile Makefile.in POTFILES stamp-it + rm -f *.mo *.msg *.cat *.cat.m *.gmo + +maintainer-clean: distclean + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + rm -f Makefile.in.in + +distdir = ../$(PACKAGE)-$(VERSION)/$(subdir) +dist distdir: $(DISTFILES) + dists="$(DISTFILES)"; \ + extra_dists="$(EXTRA_DISTFILES)"; \ + for file in $$extra_dists; do \ + test -f $(srcdir)/$$file && dists="$$dists $(srcdir)/$$file"; \ + done; \ + for file in $$dists; do \ + test -f $$file || file="$(srcdir)/$$file"; \ + ln $$file $(distdir) 2> /dev/null \ + || cp -p $$file $(distdir); \ + done + +update-po: Makefile + $(MAKE) $(GETTEXT_PACKAGE).pot + tmpdir=`pwd`; \ + linguas="$(USE_LINGUAS)"; \ + for lang in $$linguas; do \ + echo "$$lang:"; \ + result="`$(MSGMERGE) -o $$tmpdir/$$lang.new.po $$lang`"; \ + if $$result; then \ + if cmp $(srcdir)/$$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \ + rm -f $$tmpdir/$$lang.new.po; \ + else \ + if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \ + :; \ + else \ + echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \ + rm -f $$tmpdir/$$lang.new.po; \ + exit 1; \ + fi; \ + fi; \ + else \ + echo "msgmerge for $$lang.gmo failed!"; \ + rm -f $$tmpdir/$$lang.new.po; \ + fi; \ + done + +Makefile POTFILES: stamp-it + @if test ! -f $@; then \ + rm -f stamp-it; \ + $(MAKE) stamp-it; \ + fi + +stamp-it: Makefile.in.in $(top_builddir)/config.status POTFILES.in + cd $(top_builddir) \ + && CONFIG_FILES=$(subdir)/Makefile.in CONFIG_HEADERS= CONFIG_LINKS= \ + $(SHELL) ./config.status + +# Tell versions [3.59,3.63) of GNU make not to export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/po/POTFILES.in b/po/POTFILES.in new file mode 100644 index 0000000..3cd20bf --- /dev/null +++ b/po/POTFILES.in @@ -0,0 +1,12 @@ +libsoup/soup-body-input-stream.c +libsoup/soup-cache-input-stream.c +libsoup/soup-converter-wrapper.c +libsoup/soup-message-client-io.c +libsoup/soup-message-io.c +libsoup/soup-message-server-io.c +libsoup/soup-request.c +libsoup/soup-server.c +libsoup/soup-session.c +libsoup/soup-socket.c +libsoup/soup-websocket.c +libsoup/soup-tld.c diff --git a/po/an.po b/po/an.po new file mode 100644 index 0000000..c846069 --- /dev/null +++ b/po/an.po @@ -0,0 +1,176 @@ +# Aragonese translation for libsoup. +# Copyright (C) 2013 libsoup's COPYRIGHT HOLDER +# This file is distributed under the same license as the libsoup package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: libsoup master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=libsoup" +"&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2015-05-06 22:23+0000\n" +"PO-Revision-Date: 2015-05-07 23:03+0200\n" +"Last-Translator: Daniel \n" +"Language-Team: Aragonese \n" +"Language: an\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Pootle 2.5.1.1\n" +"X-POOTLE-MTIME: 1431036239.000000\n" + +#: ../libsoup/soup-body-input-stream.c:140 +#: ../libsoup/soup-body-input-stream.c:171 +#: ../libsoup/soup-body-input-stream.c:204 ../libsoup/soup-message-io.c:235 +msgid "Connection terminated unexpectedly" +msgstr "A connexión remató inasperadament" + +#: ../libsoup/soup-body-input-stream.c:462 +msgid "Invalid seek request" +msgstr "Petición de búsqueda no válida" + +#: ../libsoup/soup-body-input-stream.c:490 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "No se puede truncar SoupBodyInputStream" + +#: ../libsoup/soup-cache-input-stream.c:74 +msgid "Network stream unexpectedly closed" +msgstr "O fluxo de ret se zarró inasperadament" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "Falló en cachear completament o recurso" + +#: ../libsoup/soup-converter-wrapper.c:192 +#, c-format +msgid "Output buffer is too small" +msgstr "O búfer de salida ye masiau chicot" + +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "No se podió analisar a respuesta HTTP" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "Codificación d'a respuesta HTTP no reconoixida" + +#: ../libsoup/soup-message-io.c:392 ../libsoup/soup-message-io.c:1020 +msgid "Operation would block" +msgstr "A operación se blocará" + +#: ../libsoup/soup-message-io.c:972 ../libsoup/soup-message-io.c:1005 +msgid "Operation was cancelled" +msgstr "Se canceló a operación" + +#: ../libsoup/soup-message-server-io.c:64 +msgid "Could not parse HTTP request" +msgstr "No se podió analisar a solicitut HTTP" + +#: ../libsoup/soup-request.c:140 +#, c-format +msgid "No URI provided" +msgstr "No s'ha proporcionau un URI" + +#: ../libsoup/soup-request.c:150 +#, c-format +msgid "Invalid '%s' URI: %s" +msgstr "URI '%s' no válida: %s" + +#: ../libsoup/soup-server.c:1711 +msgid "Can't create a TLS server without a TLS certificate" +msgstr "No se puede creyar un servidor TLS sin un certificau TLS" + +#: ../libsoup/soup-server.c:1730 +#, c-format +msgid "Could not listen on address %s, port %d: " +msgstr "No se puede escuitar en l'adreza %s, puerto %d: " + +#: ../libsoup/soup-session.c:4554 +#, c-format +msgid "Could not parse URI '%s'" +msgstr "No se podió analisar l'URI '%s'" + +#: ../libsoup/soup-session.c:4591 +#, c-format +msgid "Unsupported URI scheme '%s'" +msgstr "Esquema '%s' d'URI no suportau" + +#: ../libsoup/soup-session.c:4613 +#, c-format +msgid "Not an HTTP URI" +msgstr "No ye un URI HTTP" + +#: ../libsoup/soup-session.c:4797 +msgid "The server did not accept the WebSocket handshake." +msgstr "O servidor no ha acceptau a negociación WebSocket." + +#: ../libsoup/soup-socket.c:148 +msgid "Can't import non-socket as SoupSocket" +msgstr "No se puede importar bella cosa que no ye un socket como SoupSocket" + +#: ../libsoup/soup-socket.c:166 +msgid "Could not import existing socket: " +msgstr "No se podió importar o socket existent: " + +#: ../libsoup/soup-socket.c:175 +msgid "Can't import unconnected socket" +msgstr "No se puede importar un socket no connectau" + +#: ../libsoup/soup-websocket.c:336 ../libsoup/soup-websocket.c:345 +msgid "WebSocket handshake expected" +msgstr "S'asperaba a negociación WebSocket" + +#: ../libsoup/soup-websocket.c:353 +msgid "Unsupported WebSocket version" +msgstr "Versión de Websocket no suportada" + +#: ../libsoup/soup-websocket.c:362 +msgid "Invalid WebSocket key" +msgstr "Clau de WebSocket no valida" + +#: ../libsoup/soup-websocket.c:372 +#, c-format +msgid "Incorrect WebSocket \"%s\" header" +msgstr "Capitero \"%s\" de WebSocket no valida" + +#: ../libsoup/soup-websocket.c:381 +msgid "Unsupported WebSocket subprotocol" +msgstr "Subprotocolo de WebSocket no suportau" + +#: ../libsoup/soup-websocket.c:508 +msgid "Server rejected WebSocket handshake" +msgstr "O servidor ha refusau a negociación de WebSocket" + +#: ../libsoup/soup-websocket.c:516 ../libsoup/soup-websocket.c:525 +msgid "Server ignored WebSocket handshake" +msgstr "O servidor ha ignorau a negociación de WebSocket" + +#: ../libsoup/soup-websocket.c:537 +msgid "Server requested unsupported protocol" +msgstr "O servidor ha solicitau un protocolo no suportau" + +#: ../libsoup/soup-websocket.c:547 +msgid "Server requested unsupported extension" +msgstr "O servidor ha solicitau una extensión no suportada" + +#: ../libsoup/soup-websocket.c:560 +#, c-format +msgid "Server returned incorrect \"%s\" key" +msgstr "O servidor ha tornau una clau \"%s\" incorrecta" + +#: ../libsoup/soup-tld.c:188 +msgid "Hostname is an IP address" +msgstr "O nombre de l'equipo ye una adreza IP" + +#: ../libsoup/soup-tld.c:198 ../libsoup/soup-tld.c:220 +msgid "Invalid hostname" +msgstr "O nombre de l'equipo no ye válido" + +#: ../libsoup/soup-tld.c:250 +msgid "Hostname has no base domain" +msgstr "O nombre de l'equipo no tiene un dominio base" + +#: ../libsoup/soup-tld.c:304 +msgid "Not enough domains" +msgstr "No i hai suficients dominios" diff --git a/po/as.po b/po/as.po new file mode 100644 index 0000000..4c83912 --- /dev/null +++ b/po/as.po @@ -0,0 +1,130 @@ +# Assamese translation for libsoup. +# Copyright (C) 2012 libsoup's COPYRIGHT HOLDER +# This file is distributed under the same license as the libsoup package. +# +# Nilamdyuti Goswami , 2012, 2013, 2014. +msgid "" +msgstr "" +"Project-Id-Version: libsoup master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2014-08-18 09:39+0000\n" +"PO-Revision-Date: 2014-08-18 21:29+0530\n" +"Last-Translator: Nilamdyuti Goswami \n" +"Language-Team: Assamese \n" +"Language: as\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Lokalize 1.5\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +#: ../libsoup/soup-body-input-stream.c:140 +#: ../libsoup/soup-body-input-stream.c:171 +#: ../libsoup/soup-body-input-stream.c:204 ../libsoup/soup-message-io.c:196 +msgid "Connection terminated unexpectedly" +msgstr "সংযোগ অপ্ৰত্যাশিতভাৱে অন্ত হল" + +#: ../libsoup/soup-body-input-stream.c:462 +msgid "Invalid seek request" +msgstr "অবৈধ সন্ধান অনুৰোধ" + +#: ../libsoup/soup-body-input-stream.c:490 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "SoupBodyInputStream চুটি কৰিব নোৱাৰি" + +#: ../libsoup/soup-cache-input-stream.c:73 +msgid "Network stream unexpectedly closed" +msgstr "নেটৱৰ্ক স্ট্ৰিম অপ্ৰত্যাশিতভাৱে বন্ধ হল" + +#: ../libsoup/soup-cache-input-stream.c:290 +msgid "Failed to completely cache the resource" +msgstr "সম্পদক সম্পূৰ্ণভাৱে ক্যাশ কৰিবলে ব্যৰ্থ" + +#: ../libsoup/soup-converter-wrapper.c:192 +#, c-format +msgid "Output buffer is too small" +msgstr "আউটপুট বাফাৰ অতি সৰু" + +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "HTTP প্ৰতিক্ৰিয়া বিশ্লেষণ কৰিব পৰা নগল" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "অপৰিচিত HTTP প্ৰতিক্ৰিয়া এনক'ডিং" + +#: ../libsoup/soup-message-io.c:854 ../libsoup/soup-message-io.c:890 +msgid "Operation was cancelled" +msgstr "কাৰ্য্য বাতিল কৰা হৈছিল" + +#: ../libsoup/soup-message-io.c:901 +msgid "Operation would block" +msgstr "কাৰ্য্য প্ৰতিৰোধ কৰিব" + +#: ../libsoup/soup-message-server-io.c:41 +msgid "Could not parse HTTP request" +msgstr "HTTP অনুৰোধ বিশ্লেষণ কৰিব পৰা নগল" + +#: ../libsoup/soup-request.c:140 +#, c-format +msgid "No URI provided" +msgstr "কোনো URl প্ৰদান কৰা হোৱা নাই" + +#: ../libsoup/soup-request.c:150 +#, c-format +msgid "Invalid '%s' URI: %s" +msgstr "অবৈধ '%s' URI: %s" + +#: ../libsoup/soup-server.c:1528 +msgid "Can't create a TLS server without a TLS certificate" +msgstr "এটা TLS প্ৰমাণপত্ৰ নহোৱাকৈ এটা TLS চাৰ্ভাৰ সৃষ্টি কৰিব নোৱাৰি" + +#: ../libsoup/soup-server.c:1547 +#, c-format +msgid "Could not listen on address %s, port %d: " +msgstr "ঠিকনা %s, পৰ্ট %d ত শুনিব নোৱাৰি: " + +#: ../libsoup/soup-session.c:4466 +#, c-format +msgid "Could not parse URI '%s'" +msgstr "URI '%s' বিশ্লেষণ কৰিব পৰা নগল" + +#: ../libsoup/soup-session.c:4503 +#, c-format +msgid "Unsupported URI scheme '%s'" +msgstr "অসমৰ্থিত URl আঁচনি '%s'" + +#: ../libsoup/soup-session.c:4525 +#, c-format +msgid "Not an HTTP URI" +msgstr "এটা HTTP URI নহয়" + +#: ../libsoup/soup-socket.c:142 +msgid "Can't import non-socket as SoupSocket" +msgstr "SoupSocket ৰূপে নন-চকেটক ইমপৰ্ট কৰিব নোৱাৰি" + +#: ../libsoup/soup-socket.c:160 +msgid "Could not import existing socket: " +msgstr "স্থায়ী চকেটক ইমপৰ্ট কৰিব নোৱাৰি" + +#: ../libsoup/soup-socket.c:169 +msgid "Can't import unconnected socket" +msgstr "অসংযুক্ত চকেটক ইমপৰ্ট কৰিব নোৱাৰি" + +#: ../libsoup/soup-tld.c:188 +msgid "Hostname is an IP address" +msgstr "হস্টনাম এটা IP ঠিকনা" + +#: ../libsoup/soup-tld.c:198 ../libsoup/soup-tld.c:220 +msgid "Invalid hostname" +msgstr "অবৈধ হস্টনাম" + +#: ../libsoup/soup-tld.c:250 +msgid "Hostname has no base domain" +msgstr "হস্টনামৰ কোনো ভিত্তি ডমেইন নাই" + +#: ../libsoup/soup-tld.c:304 +msgid "Not enough domains" +msgstr "পৰ্যাপ্ত ডমেইন নাই" + diff --git a/po/be.po b/po/be.po new file mode 100644 index 0000000..841678b --- /dev/null +++ b/po/be.po @@ -0,0 +1,172 @@ +# Ihar Hrachyshka , 2012. +# Yuras Shumovich , 2017. +# +msgid "" +msgstr "" +"Project-Id-Version: libsoup master\n" +"Report-Msgid-Bugs-To: https://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=Misc\n" +"POT-Creation-Date: 2017-02-23 10:17+0000\n" +"PO-Revision-Date: 2017-03-27 11:48+0300\n" +"Last-Translator: Yuras Shumovich \n" +"Language-Team: Belarusian \n" +"Language: be\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 1.8.11\n" + +#: ../libsoup/soup-body-input-stream.c:139 +#: ../libsoup/soup-body-input-stream.c:170 +#: ../libsoup/soup-body-input-stream.c:203 ../libsoup/soup-message-io.c:235 +msgid "Connection terminated unexpectedly" +msgstr "Злучэнне нечакана перарвана" + +#: ../libsoup/soup-body-input-stream.c:459 +msgid "Invalid seek request" +msgstr "Хібны запыт пракручвання змесціва" + +#: ../libsoup/soup-body-input-stream.c:487 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "Немагчыма абрэзаць SoupBodyInputStream" + +#: ../libsoup/soup-cache-input-stream.c:76 +msgid "Network stream unexpectedly closed" +msgstr "Сеткавы струмень нечакана закрыўся" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "Не ўдалося цалкам змясціць рэсурс у кэш-памяці" + +#: ../libsoup/soup-converter-wrapper.c:189 +#, c-format +msgid "Output buffer is too small" +msgstr "Выхадны буфер надта малы" + +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "Не ўдалося разабраць HTTP-адказ" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "Невядомае кадаванне HTTP-адказу" + +#: ../libsoup/soup-message-io.c:392 ../libsoup/soup-message-io.c:1020 +msgid "Operation would block" +msgstr "Аперацыя заблакіруе працэс" + +#: ../libsoup/soup-message-io.c:972 ../libsoup/soup-message-io.c:1005 +msgid "Operation was cancelled" +msgstr "Аперацыя была скасавана" + +#: ../libsoup/soup-message-server-io.c:64 +msgid "Could not parse HTTP request" +msgstr "Не ўдалося разабраць HTTP-запыт" + +#: ../libsoup/soup-request.c:141 +#, c-format +msgid "No URI provided" +msgstr "URI-адрас не пададзены" + +#: ../libsoup/soup-request.c:151 +#, c-format +msgid "Invalid “%s” URI: %s" +msgstr "Хібны URI-адрас \"%s\": %s" + +#: ../libsoup/soup-server.c:1725 +msgid "Can’t create a TLS server without a TLS certificate" +msgstr "Нельга стварыць TLS сервер без сертыфіката TLS" + +#: ../libsoup/soup-server.c:1742 +#, c-format +msgid "Could not listen on address %s, port %d: " +msgstr "Не ўдалося праслухаць адрас %s, порт %d: " + +#: ../libsoup/soup-session.c:4518 +#, c-format +msgid "Could not parse URI “%s”" +msgstr "Не ўдалося разабраць URI-адрас \"%s\"" + +#: ../libsoup/soup-session.c:4555 +#, c-format +msgid "Unsupported URI scheme “%s”" +msgstr "URI-схема \"%s\" не падтрымліваецца" + +#: ../libsoup/soup-session.c:4577 +#, c-format +msgid "Not an HTTP URI" +msgstr "Гэта не HTTP URI-адрас" + +#: ../libsoup/soup-session.c:4763 +msgid "The server did not accept the WebSocket handshake." +msgstr "Сервер не прыняў поціск WebSocket." + +#: ../libsoup/soup-socket.c:148 +msgid "Can’t import non-socket as SoupSocket" +msgstr "Толькі сокет можна імпартаваць як SoupSocket" + +#: ../libsoup/soup-socket.c:166 +msgid "Could not import existing socket: " +msgstr "Не ўдалося імпартаваць існуючы сокет: " + +#: ../libsoup/soup-socket.c:175 +msgid "Can’t import unconnected socket" +msgstr "Нельга імпартаваць нязвязаны сокет" + +#: ../libsoup/soup-websocket.c:338 ../libsoup/soup-websocket.c:347 +msgid "WebSocket handshake expected" +msgstr "Чакаўся поціск WebSocket" + +#: ../libsoup/soup-websocket.c:355 +msgid "Unsupported WebSocket version" +msgstr "Версія WebSocket не падтрымліваецца" + +#: ../libsoup/soup-websocket.c:364 +msgid "Invalid WebSocket key" +msgstr "Хібны ключ WebSocket" + +#: ../libsoup/soup-websocket.c:374 +#, c-format +msgid "Incorrect WebSocket “%s” header" +msgstr "Хібны загаловак WebSocket %s" + +#: ../libsoup/soup-websocket.c:383 +msgid "Unsupported WebSocket subprotocol" +msgstr "Падпратакол WebSocket не падтрымліваецца" + +#: ../libsoup/soup-websocket.c:510 +msgid "Server rejected WebSocket handshake" +msgstr "Сервер адхіліў поціск WebSocket" + +#: ../libsoup/soup-websocket.c:518 ../libsoup/soup-websocket.c:527 +msgid "Server ignored WebSocket handshake" +msgstr "Сервер ігнараваў поціск WebSocket" + +#: ../libsoup/soup-websocket.c:539 +msgid "Server requested unsupported protocol" +msgstr "Сервер запрасіў непадтрымліваемы пратакол" + +#: ../libsoup/soup-websocket.c:549 +msgid "Server requested unsupported extension" +msgstr "Сервер запрасіў непадтрымліваемае пашырэнне" + +#: ../libsoup/soup-websocket.c:562 +#, c-format +msgid "Server returned incorrect “%s” key" +msgstr "Сервер вярнуў хібны ключ \"%s\"" + +#: ../libsoup/soup-tld.c:188 +msgid "Hostname is an IP address" +msgstr "Назва хоста з'яўляецца IP-адрасам" + +#: ../libsoup/soup-tld.c:198 ../libsoup/soup-tld.c:220 +msgid "Invalid hostname" +msgstr "Хібная назва хоста" + +#: ../libsoup/soup-tld.c:250 +msgid "Hostname has no base domain" +msgstr "Назва хоста не мае базавага дамена" + +#: ../libsoup/soup-tld.c:304 +msgid "Not enough domains" +msgstr "Не хапае даменаў" diff --git a/po/bg.po b/po/bg.po new file mode 100644 index 0000000..6bac87b --- /dev/null +++ b/po/bg.po @@ -0,0 +1,173 @@ +# Bulgarian translation of libsoup po-file. +# Copyright (C) 2012, 2013, 2016 Free Software Foundation, Inc. +# This file is distributed under the same license as the libsoup package. +# Alexander Shopov , 2012, 2013, 2016. +# +msgid "" +msgstr "" +"Project-Id-Version: libsoup master\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-02-01 06:26+0200\n" +"PO-Revision-Date: 2016-02-01 06:26+0200\n" +"Last-Translator: Alexander Shopov \n" +"Language-Team: Bulgarian \n" +"Language: bg\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: ../libsoup/soup-body-input-stream.c:140 +#: ../libsoup/soup-body-input-stream.c:171 +#: ../libsoup/soup-body-input-stream.c:204 ../libsoup/soup-message-io.c:235 +msgid "Connection terminated unexpectedly" +msgstr "Връзката прекъсна неочаквано" + +#: ../libsoup/soup-body-input-stream.c:462 +msgid "Invalid seek request" +msgstr "Неправилна заявка за търсене" + +#: ../libsoup/soup-body-input-stream.c:490 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "Потокът SoupBodyInputStream не може да бъде прекъснат" + +#: ../libsoup/soup-cache-input-stream.c:74 +msgid "Network stream unexpectedly closed" +msgstr "Потокът от мрежата неочаквано прекъсна" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "Ресурсът не може да бъде напълно кеширан" + +#: ../libsoup/soup-converter-wrapper.c:192 +#, c-format +msgid "Output buffer is too small" +msgstr "Прекалено малък изходен буфер" + +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "Отговорът от HTTP не може да бъде анализиран" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "Непознато кодиране на отговора от HTTP" + +#: ../libsoup/soup-message-io.c:392 ../libsoup/soup-message-io.c:1020 +msgid "Operation would block" +msgstr "Операцията ще блокира" + +#: ../libsoup/soup-message-io.c:972 ../libsoup/soup-message-io.c:1005 +msgid "Operation was cancelled" +msgstr "Операцията е отменена" + +#: ../libsoup/soup-message-server-io.c:64 +msgid "Could not parse HTTP request" +msgstr "Заявката към HTTP не може да бъде анализирана" + +#: ../libsoup/soup-request.c:140 +#, c-format +msgid "No URI provided" +msgstr "Не е даден адрес" + +#: ../libsoup/soup-request.c:150 +#, c-format +msgid "Invalid '%s' URI: %s" +msgstr "Неправилен адрес на „%s“: %s" + +#: ../libsoup/soup-server.c:1720 +msgid "Can't create a TLS server without a TLS certificate" +msgstr "Не може да се създаде сървър с TLS без съответния сертификат" + +#: ../libsoup/soup-server.c:1739 +#, c-format +msgid "Could not listen on address %s, port %d: " +msgstr "Не може да се слуша на адрес „%s“, порт %d: " + +#: ../libsoup/soup-session.c:4543 +#, c-format +msgid "Could not parse URI '%s'" +msgstr "Адресът „%s“ е неправилен" + +#: ../libsoup/soup-session.c:4580 +#, c-format +msgid "Unsupported URI scheme '%s'" +msgstr "Схемата на адреса не се поддържа „%s“" + +#: ../libsoup/soup-session.c:4602 +#, c-format +msgid "Not an HTTP URI" +msgstr "Не е адрес за HTTP" + +#: ../libsoup/soup-session.c:4788 +msgid "The server did not accept the WebSocket handshake." +msgstr "Сървърът не прие ръкостискането за WebSocket." + +#: ../libsoup/soup-socket.c:148 +msgid "Can't import non-socket as SoupSocket" +msgstr "Не може да се внесе като гнездо за soup нещо, което не е гнездо" + +#: ../libsoup/soup-socket.c:166 +msgid "Could not import existing socket: " +msgstr "Съществуващото гнездо не може да бъде внесено: " + +#: ../libsoup/soup-socket.c:175 +msgid "Can't import unconnected socket" +msgstr "Гнездо, което не е свързано, не може да се внесе" + +#: ../libsoup/soup-websocket.c:338 ../libsoup/soup-websocket.c:347 +msgid "WebSocket handshake expected" +msgstr "Очаква се ръкостискане за WebSocket" + +#: ../libsoup/soup-websocket.c:355 +msgid "Unsupported WebSocket version" +msgstr "Неподдържана версия на WebSocket" + +#: ../libsoup/soup-websocket.c:364 +msgid "Invalid WebSocket key" +msgstr "Неправилен ключ за WebSocket" + +#: ../libsoup/soup-websocket.c:374 +#, c-format +msgid "Incorrect WebSocket \"%s\" header" +msgstr "Неправилна заглавна част „%s“ за WebSocket" + +#: ../libsoup/soup-websocket.c:383 +msgid "Unsupported WebSocket subprotocol" +msgstr "Неподдържан подпротокол за WebSocket" + +#: ../libsoup/soup-websocket.c:510 +msgid "Server rejected WebSocket handshake" +msgstr "Сървърът отхвърли ръкостискането по WebSocket" + +#: ../libsoup/soup-websocket.c:518 ../libsoup/soup-websocket.c:527 +msgid "Server ignored WebSocket handshake" +msgstr "Сървърът пренебрегна ръкостискането по WebSocket" + +#: ../libsoup/soup-websocket.c:539 +msgid "Server requested unsupported protocol" +msgstr "Сървърът изиска неподдържан протокол" + +#: ../libsoup/soup-websocket.c:549 +msgid "Server requested unsupported extension" +msgstr "Сървърът изиска неподдържано разширение" + +#: ../libsoup/soup-websocket.c:562 +#, c-format +msgid "Server returned incorrect \"%s\" key" +msgstr "Сървърът върна неправилен ключ „%s“" + +#: ../libsoup/soup-tld.c:188 +msgid "Hostname is an IP address" +msgstr "Името на машината е адрес по IP" + +#: ../libsoup/soup-tld.c:198 ../libsoup/soup-tld.c:220 +msgid "Invalid hostname" +msgstr "Неправилно име на машина" + +#: ../libsoup/soup-tld.c:250 +msgid "Hostname has no base domain" +msgstr "Името на машината не съдържа домейн" + +#: ../libsoup/soup-tld.c:304 +msgid "Not enough domains" +msgstr "Няма достатъчно домейни" diff --git a/po/bn_IN.po b/po/bn_IN.po new file mode 100644 index 0000000..7d9c8fd --- /dev/null +++ b/po/bn_IN.po @@ -0,0 +1,131 @@ +# Bengali (India) translation for libsoup. +# Copyright (C) 2012 libsoup's COPYRIGHT HOLDER +# This file is distributed under the same license as the libsoup package. +# +# Sayak Sarkar , 2012. +# sray , 2013, 2014. #zanata. +msgid "" +msgstr "" +"Project-Id-Version: libsoup master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2014-10-06 21:59+0000\n" +"PO-Revision-Date: 2014-10-07 13:28+0000\n" +"Last-Translator: \n" +"Language-Team: Bengali (India) \n" +"Language: bn_IN\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Lokalize 1.5\n" + +#: ../libsoup/soup-body-input-stream.c:140 +#: ../libsoup/soup-body-input-stream.c:171 +#: ../libsoup/soup-body-input-stream.c:204 ../libsoup/soup-message-io.c:196 +msgid "Connection terminated unexpectedly" +msgstr "সংযোগ অপ্রত্যাশিতভাবে পর্যবসিত" + +#: ../libsoup/soup-body-input-stream.c:462 +msgid "Invalid seek request" +msgstr "অবৈধ সিক্ অনুরোধ" + +#: ../libsoup/soup-body-input-stream.c:490 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "SoupBodyInputStream ছাঁটা যাচ্ছে না।" + +#: ../libsoup/soup-cache-input-stream.c:73 +msgid "Network stream unexpectedly closed" +msgstr "নেটওয়ার্ক স্ট্রীম অপ্রত্যাশিত ভাবে বন্ধ হয়েছে" + +#: ../libsoup/soup-cache-input-stream.c:290 +msgid "Failed to completely cache the resource" +msgstr "রিসোর্স সম্পূর্ণ ভাবে ক্যাশ করতে ব্যর্থ" + +#: ../libsoup/soup-converter-wrapper.c:192 +#, c-format +msgid "Output buffer is too small" +msgstr "আউটপুট বাফার অত্যন্ত ছোট" + +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "HTTP প্রত্যুত্তর পার্জ করা গেল না" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "অস্বীকৃত HTTP প্রত্যুত্তর এনকোডিং" + +#: ../libsoup/soup-message-io.c:854 ../libsoup/soup-message-io.c:890 +msgid "Operation was cancelled" +msgstr "অপারেশন বাতিল হয়েছে" + +#: ../libsoup/soup-message-io.c:901 +msgid "Operation would block" +msgstr "অপারেশন ব্লক করবে" + +#: ../libsoup/soup-message-server-io.c:41 +msgid "Could not parse HTTP request" +msgstr "HTTP অনুরোধ পার্জ করা গেল না" + +#: ../libsoup/soup-request.c:140 +#, c-format +msgid "No URI provided" +msgstr "কোন URI দেওয়া হয়নি" + +#: ../libsoup/soup-request.c:150 +#, c-format +msgid "Invalid '%s' URI: %s" +msgstr "অবৈধ '%s' URI: %s" + +#: ../libsoup/soup-server.c:1528 +msgid "Can't create a TLS server without a TLS certificate" +msgstr "একটি TLS সার্টিফিকেট ছাড়া একটি TLS সার্ভার তৈরি করা সম্ভব নয়" + +#: ../libsoup/soup-server.c:1547 +#, c-format +msgid "Could not listen on address %s, port %d: " +msgstr "ঠিকানা %s, পোর্ট %d এ শোনা যায়নি: " + +#: ../libsoup/soup-session.c:4466 +#, c-format +msgid "Could not parse URI '%s'" +msgstr "URI '%s' পার্স করা যায়নি" + +#: ../libsoup/soup-session.c:4503 +#, c-format +msgid "Unsupported URI scheme '%s'" +msgstr "অসমর্থিত URI স্কিম '%s'" + +#: ../libsoup/soup-session.c:4525 +#, c-format +msgid "Not an HTTP URI" +msgstr "একটি HTTP URI নয়" + +#: ../libsoup/soup-socket.c:142 +msgid "Can't import non-socket as SoupSocket" +msgstr "নন-সকেট SoupSocket হিসাবে অামদানি করা সম্ভব নয়" + +#: ../libsoup/soup-socket.c:160 +msgid "Could not import existing socket: " +msgstr "বিদ্যমান সকেট অামদানি করা যায়নি: " + +#: ../libsoup/soup-socket.c:169 +msgid "Can't import unconnected socket" +msgstr "অসংযুক্ত সকেট অামদানি করা সম্ভব নয়" + +#: ../libsoup/soup-tld.c:188 +msgid "Hostname is an IP address" +msgstr "হোস্টনেমটি একটি IP অ্যাড্রেস" + +#: ../libsoup/soup-tld.c:198 ../libsoup/soup-tld.c:220 +msgid "Invalid hostname" +msgstr "অবৈধ হোস্টনেম" + +#: ../libsoup/soup-tld.c:250 +msgid "Hostname has no base domain" +msgstr "হোস্টনেমটির কোনো বেস ডোমেইন নেই" + +#: ../libsoup/soup-tld.c:304 +msgid "Not enough domains" +msgstr "ডোমেইনগুলি পর্যাপ্ত নয়" + diff --git a/po/bs.po b/po/bs.po new file mode 100644 index 0000000..3b0f911 --- /dev/null +++ b/po/bs.po @@ -0,0 +1,124 @@ +msgid "" +msgstr "" +"Project-Id-Version: libsoup2.4\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2015-02-26 23:06+0000\n" +"PO-Revision-Date: 2015-02-04 15:38+0000\n" +"Last-Translator: Samir Ribić \n" +"Language-Team: Bosnian \n" +"Language: bs\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2015-02-05 06:47+0000\n" +"X-Generator: Launchpad (build 17331)\n" + +#: ../libsoup/soup-body-input-stream.c:140 +#: ../libsoup/soup-body-input-stream.c:171 +#: ../libsoup/soup-body-input-stream.c:204 ../libsoup/soup-message-io.c:200 +msgid "Connection terminated unexpectedly" +msgstr "Konekcija je neočekivano završena" + +#: ../libsoup/soup-body-input-stream.c:462 +msgid "Invalid seek request" +msgstr "Zatražena je neispravna pretraga" + +#: ../libsoup/soup-body-input-stream.c:490 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "Ne mogu odsjećie SoupBodyInputStream" + +#: ../libsoup/soup-cache-input-stream.c:73 +msgid "Network stream unexpectedly closed" +msgstr "Mrežni protok neočekivano zatvoren" + +#: ../libsoup/soup-cache-input-stream.c:290 +msgid "Failed to completely cache the resource" +msgstr "Nije uspjelo u potpunosti keširanje resursa" + +#: ../libsoup/soup-converter-wrapper.c:192 +#, c-format +msgid "Output buffer is too small" +msgstr "Izlazni bafer je premali" + +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "Nije moguće analizirati HTTP odgovor" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "Neprepoznato HTTP kodiranje odgovora" + +#: ../libsoup/soup-message-io.c:357 ../libsoup/soup-message-io.c:960 +msgid "Operation would block" +msgstr "Operacija bi se blokirala" + +#: ../libsoup/soup-message-io.c:912 ../libsoup/soup-message-io.c:949 +msgid "Operation was cancelled" +msgstr "Operacija je prekinuta" + +#: ../libsoup/soup-message-server-io.c:41 +msgid "Could not parse HTTP request" +msgstr "Nije moguće analizirati HTTP zahtjeve" + +#: ../libsoup/soup-request.c:140 +#, c-format +msgid "No URI provided" +msgstr "URI nije naveden" + +#: ../libsoup/soup-request.c:150 +#, c-format +msgid "Invalid '%s' URI: %s" +msgstr "Nevažeći '%s' URI: %s" + +#: ../libsoup/soup-server.c:1585 +msgid "Can't create a TLS server without a TLS certificate" +msgstr "Ne mogu stvoriti TLS poslužitelja bez TLS certifikat" + +#: ../libsoup/soup-server.c:1604 +#, c-format +msgid "Could not listen on address %s, port %d: " +msgstr "Ne mogu slušati na adresi %s,%d port: " + +#: ../libsoup/soup-session.c:4485 +#, c-format +msgid "Could not parse URI '%s'" +msgstr "Ne mogu analizirati URI '%s'" + +#: ../libsoup/soup-session.c:4522 +#, c-format +msgid "Unsupported URI scheme '%s'" +msgstr "Nepodržana URI šema '%s'" + +#: ../libsoup/soup-session.c:4544 +#, c-format +msgid "Not an HTTP URI" +msgstr "Nije HTTP URI" + +#: ../libsoup/soup-socket.c:150 +msgid "Can't import non-socket as SoupSocket" +msgstr "Ne možete uvesti ne-utičnice kao SoupSocket" + +#: ../libsoup/soup-socket.c:168 +msgid "Could not import existing socket: " +msgstr "Ne mogu se uvesti postojeće utičnice: " + +#: ../libsoup/soup-socket.c:177 +msgid "Can't import unconnected socket" +msgstr "Ne mogu uvesti nepovezane utičnice" + +#: ../libsoup/soup-tld.c:188 +msgid "Hostname is an IP address" +msgstr "Ime domaćina je IP adresa" + +#: ../libsoup/soup-tld.c:198 ../libsoup/soup-tld.c:220 +msgid "Invalid hostname" +msgstr "Loše ime domaćina" + +#: ../libsoup/soup-tld.c:250 +msgid "Hostname has no base domain" +msgstr "Ime domaćina nema baznu domenu" + +#: ../libsoup/soup-tld.c:304 +msgid "Not enough domains" +msgstr "Nema dovoljno domena" diff --git a/po/ca.po b/po/ca.po new file mode 100644 index 0000000..5941c4d --- /dev/null +++ b/po/ca.po @@ -0,0 +1,178 @@ +# Catalan translation for libsoup. +# Copyright (C) 2012 Free Software Foundation, Inc. +# This file is distributed under the same license as the libsoup package. +# Gil Forcada , 2012, 2013, 2014. +# Xavi Ivars , 2015. +# Jordi Serratosa , 2017. +msgid "" +msgstr "" +"Project-Id-Version: libsoup master\n" +"Report-Msgid-Bugs-To: https://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=Misc\n" +"POT-Creation-Date: 2017-08-28 17:31+0000\n" +"PO-Revision-Date: 2017-08-21 23:33+0200\n" +"Last-Translator: Xavi Ivars \n" +"Language-Team: Catalan \n" +"Language: ca\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Poedit 1.8.11\n" +"X-Project-Style: gnome\n" + +#: ../libsoup/soup-body-input-stream.c:139 +#: ../libsoup/soup-body-input-stream.c:170 +#: ../libsoup/soup-body-input-stream.c:203 ../libsoup/soup-message-io.c:237 +msgid "Connection terminated unexpectedly" +msgstr "S'ha finalitzat la connexió inesperadament" + +#: ../libsoup/soup-body-input-stream.c:459 +msgid "Invalid seek request" +msgstr "La petició de cerca no és vàlida" + +#: ../libsoup/soup-body-input-stream.c:487 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "No es pot truncar el SoupBodyInputStream" + +#: ../libsoup/soup-cache-input-stream.c:76 +msgid "Network stream unexpectedly closed" +msgstr "S'ha tancat inesperadament el flux de xarxa" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "No s'ha pogut carregar completament el recurs a la memòria cau" + +#: ../libsoup/soup-converter-wrapper.c:189 +#, c-format +msgid "Output buffer is too small" +msgstr "La memòria intermèdia de sortida és massa petita" + +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "No s'ha pogut analitzar la resposta HTTP" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "No es reconeix la codificació de la resposta HTTP" + +#: ../libsoup/soup-message-io.c:387 ../libsoup/soup-message-io.c:1015 +msgid "Operation would block" +msgstr "L'operació bloquejaria" + +#: ../libsoup/soup-message-io.c:967 ../libsoup/soup-message-io.c:1000 +msgid "Operation was cancelled" +msgstr "S'ha cancel·lat l'operació" + +#: ../libsoup/soup-message-server-io.c:64 +msgid "Could not parse HTTP request" +msgstr "No s'ha pogut analitzar la petició HTTP" + +#: ../libsoup/soup-request.c:141 +#, c-format +msgid "No URI provided" +msgstr "No s'ha proporcionat cap URI" + +#: ../libsoup/soup-request.c:151 +#, c-format +msgid "Invalid “%s” URI: %s" +msgstr "L'URI «%s» no és vàlid: %s" + +#: ../libsoup/soup-server.c:1725 +msgid "Can’t create a TLS server without a TLS certificate" +msgstr "No es pot crear un servidor de TLS sense un certificat TLS" + +#: ../libsoup/soup-server.c:1742 +#, c-format +msgid "Could not listen on address %s, port %d: " +msgstr "No es pot escoltar a l'adreça %s, port %d: " + +#: ../libsoup/soup-session.c:4517 +#, c-format +msgid "Could not parse URI “%s”" +msgstr "No s'ha pogut analitzar l'URI «%s»" + +#: ../libsoup/soup-session.c:4554 +#, c-format +msgid "Unsupported URI scheme “%s”" +msgstr "L'esquema d'URI «%s» és incompatible" + +#: ../libsoup/soup-session.c:4576 +#, c-format +msgid "Not an HTTP URI" +msgstr "No és un URI HTTP" + +#: ../libsoup/soup-session.c:4762 +msgid "The server did not accept the WebSocket handshake." +msgstr "" +"El servidor no ha acceptat la conformitat de la connexió del WebSocket." + +#: ../libsoup/soup-socket.c:148 +msgid "Can’t import non-socket as SoupSocket" +msgstr "No es pot importar un objecte que no sigui un sòcol com a SoupSocket" + +#: ../libsoup/soup-socket.c:166 +msgid "Could not import existing socket: " +msgstr "No s'ha pogut importar un sòcol existent: " + +#: ../libsoup/soup-socket.c:175 +msgid "Can’t import unconnected socket" +msgstr "No es pot importar un sòcol desconnectat" + +#: ../libsoup/soup-websocket.c:338 ../libsoup/soup-websocket.c:347 +msgid "WebSocket handshake expected" +msgstr "S'esperava una conformitat de la connexió del WebSocket" + +#: ../libsoup/soup-websocket.c:355 +msgid "Unsupported WebSocket version" +msgstr "Versió del WebSocket no implementada" + +#: ../libsoup/soup-websocket.c:364 +msgid "Invalid WebSocket key" +msgstr "Clau del WebSocket invàlida" + +#: ../libsoup/soup-websocket.c:374 +#, c-format +msgid "Incorrect WebSocket “%s” header" +msgstr "La capçalera «%s» del WebSocket és incorrecta" + +#: ../libsoup/soup-websocket.c:383 +msgid "Unsupported WebSocket subprotocol" +msgstr "Subprotocol del WebSocket no implementat" + +#: ../libsoup/soup-websocket.c:510 +msgid "Server rejected WebSocket handshake" +msgstr "El servidor ha rebutjat la conformitat de la connexió del WebSocket" + +#: ../libsoup/soup-websocket.c:518 ../libsoup/soup-websocket.c:527 +msgid "Server ignored WebSocket handshake" +msgstr "El servidor ha ignorat la conformitat de la connexió del WebSocket" + +#: ../libsoup/soup-websocket.c:539 +msgid "Server requested unsupported protocol" +msgstr "El servidor ha demanat un protocol no implementat" + +#: ../libsoup/soup-websocket.c:549 +msgid "Server requested unsupported extension" +msgstr "El servidor ha demanat una extensió no implementada" + +#: ../libsoup/soup-websocket.c:562 +#, c-format +msgid "Server returned incorrect “%s” key" +msgstr "El servidor ha enviat una clau «%s» incorrecta" + +#: ../libsoup/soup-tld.c:188 +msgid "Hostname is an IP address" +msgstr "El nom d'ordinador és una adreça IP" + +#: ../libsoup/soup-tld.c:198 ../libsoup/soup-tld.c:220 +msgid "Invalid hostname" +msgstr "El nom d'ordinador no és vàlid" + +#: ../libsoup/soup-tld.c:250 +msgid "Hostname has no base domain" +msgstr "El nom d'ordinador no té cap domini base" + +#: ../libsoup/soup-tld.c:304 +msgid "Not enough domains" +msgstr "No hi ha prou dominis" diff --git a/po/ca@valencia.po b/po/ca@valencia.po new file mode 100644 index 0000000..a8e8240 --- /dev/null +++ b/po/ca@valencia.po @@ -0,0 +1,178 @@ +# Catalan translation for libsoup. +# Copyright (C) 2012 Free Software Foundation, Inc. +# This file is distributed under the same license as the libsoup package. +# Gil Forcada , 2012, 2013, 2014. +# Xavi Ivars , 2015. +# Jordi Serratosa , 2017. +msgid "" +msgstr "" +"Project-Id-Version: libsoup master\n" +"Report-Msgid-Bugs-To: https://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=Misc\n" +"POT-Creation-Date: 2017-10-02 12:16+0000\n" +"PO-Revision-Date: 2017-08-21 23:33+0200\n" +"Last-Translator: Xavi Ivars \n" +"Language-Team: Catalan \n" +"Language: ca-valencia\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Poedit 1.8.11\n" +"X-Project-Style: gnome\n" + +#: ../libsoup/soup-body-input-stream.c:139 +#: ../libsoup/soup-body-input-stream.c:170 +#: ../libsoup/soup-body-input-stream.c:203 ../libsoup/soup-message-io.c:237 +msgid "Connection terminated unexpectedly" +msgstr "S'ha finalitzat la connexió inesperadament" + +#: ../libsoup/soup-body-input-stream.c:459 +msgid "Invalid seek request" +msgstr "La petició de busca no és vàlida" + +#: ../libsoup/soup-body-input-stream.c:487 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "No es pot truncar el SoupBodyInputStream" + +#: ../libsoup/soup-cache-input-stream.c:76 +msgid "Network stream unexpectedly closed" +msgstr "S'ha tancat inesperadament el flux de xarxa" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "No s'ha pogut carregar completament el recurs a la memòria cau" + +#: ../libsoup/soup-converter-wrapper.c:189 +#, c-format +msgid "Output buffer is too small" +msgstr "La memòria intermèdia d'eixida és massa petita" + +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "No s'ha pogut analitzar la resposta HTTP" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "No es reconeix la codificació de la resposta HTTP" + +#: ../libsoup/soup-message-io.c:387 ../libsoup/soup-message-io.c:1015 +msgid "Operation would block" +msgstr "L'operació bloquejaria" + +#: ../libsoup/soup-message-io.c:967 ../libsoup/soup-message-io.c:1000 +msgid "Operation was cancelled" +msgstr "S'ha cancel·lat l'operació" + +#: ../libsoup/soup-message-server-io.c:64 +msgid "Could not parse HTTP request" +msgstr "No s'ha pogut analitzar la petició HTTP" + +#: ../libsoup/soup-request.c:141 +#, c-format +msgid "No URI provided" +msgstr "No s'ha proporcionat cap URI" + +#: ../libsoup/soup-request.c:151 +#, c-format +msgid "Invalid “%s” URI: %s" +msgstr "L'URI «%s» no és vàlid: %s" + +#: ../libsoup/soup-server.c:1725 +msgid "Can’t create a TLS server without a TLS certificate" +msgstr "No es pot crear un servidor de TLS sense un certificat TLS" + +#: ../libsoup/soup-server.c:1742 +#, c-format +msgid "Could not listen on address %s, port %d: " +msgstr "No es pot escoltar a l'adreça %s, port %d: " + +#: ../libsoup/soup-session.c:4517 +#, c-format +msgid "Could not parse URI “%s”" +msgstr "No s'ha pogut analitzar l'URI «%s»" + +#: ../libsoup/soup-session.c:4554 +#, c-format +msgid "Unsupported URI scheme “%s”" +msgstr "L'esquema d'URI «%s» és incompatible" + +#: ../libsoup/soup-session.c:4576 +#, c-format +msgid "Not an HTTP URI" +msgstr "No és un URI HTTP" + +#: ../libsoup/soup-session.c:4762 +msgid "The server did not accept the WebSocket handshake." +msgstr "" +"El servidor no ha acceptat la conformitat de la connexió del WebSocket." + +#: ../libsoup/soup-socket.c:148 +msgid "Can’t import non-socket as SoupSocket" +msgstr "No es pot importar un objecte que no siga un sòcol com a SoupSocket" + +#: ../libsoup/soup-socket.c:166 +msgid "Could not import existing socket: " +msgstr "No s'ha pogut importar un sòcol existent: " + +#: ../libsoup/soup-socket.c:175 +msgid "Can’t import unconnected socket" +msgstr "No es pot importar un sòcol desconnectat" + +#: ../libsoup/soup-websocket.c:338 ../libsoup/soup-websocket.c:347 +msgid "WebSocket handshake expected" +msgstr "S'esperava una conformitat de la connexió del WebSocket" + +#: ../libsoup/soup-websocket.c:355 +msgid "Unsupported WebSocket version" +msgstr "Versió del WebSocket no implementada" + +#: ../libsoup/soup-websocket.c:364 +msgid "Invalid WebSocket key" +msgstr "Clau del WebSocket invàlida" + +#: ../libsoup/soup-websocket.c:374 +#, c-format +msgid "Incorrect WebSocket “%s” header" +msgstr "La capçalera «%s» del WebSocket és incorrecta" + +#: ../libsoup/soup-websocket.c:383 +msgid "Unsupported WebSocket subprotocol" +msgstr "Subprotocol del WebSocket no implementat" + +#: ../libsoup/soup-websocket.c:510 +msgid "Server rejected WebSocket handshake" +msgstr "El servidor ha rebutjat la conformitat de la connexió del WebSocket" + +#: ../libsoup/soup-websocket.c:518 ../libsoup/soup-websocket.c:527 +msgid "Server ignored WebSocket handshake" +msgstr "El servidor ha ignorat la conformitat de la connexió del WebSocket" + +#: ../libsoup/soup-websocket.c:539 +msgid "Server requested unsupported protocol" +msgstr "El servidor ha demanat un protocol no implementat" + +#: ../libsoup/soup-websocket.c:549 +msgid "Server requested unsupported extension" +msgstr "El servidor ha demanat una extensió no implementada" + +#: ../libsoup/soup-websocket.c:562 +#, c-format +msgid "Server returned incorrect “%s” key" +msgstr "El servidor ha enviat una clau «%s» incorrecta" + +#: ../libsoup/soup-tld.c:188 +msgid "Hostname is an IP address" +msgstr "El nom d'ordinador és una adreça IP" + +#: ../libsoup/soup-tld.c:198 ../libsoup/soup-tld.c:220 +msgid "Invalid hostname" +msgstr "El nom d'ordinador no és vàlid" + +#: ../libsoup/soup-tld.c:250 +msgid "Hostname has no base domain" +msgstr "El nom d'ordinador no té cap domini base" + +#: ../libsoup/soup-tld.c:304 +msgid "Not enough domains" +msgstr "No hi ha prou dominis" diff --git a/po/cs.po b/po/cs.po new file mode 100644 index 0000000..e066de4 --- /dev/null +++ b/po/cs.po @@ -0,0 +1,179 @@ +# Czech translation for libsoup. +# Copyright (C) 2012 libsoup's COPYRIGHT HOLDER +# This file is distributed under the same license as the libsoup package. +# Marek Černocký , 2012, 2013, 2014, 2015, 2016, 2018. +# +msgid "" +msgstr "" +"Project-Id-Version: libsoup master\n" +"Report-Msgid-Bugs-To: https://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=Misc\n" +"POT-Creation-Date: 2018-02-09 14:43+0000\n" +"PO-Revision-Date: 2018-02-22 10:25+0100\n" +"Last-Translator: Marek Černocký \n" +"Language-Team: čeština \n" +"Language: cs\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" +"X-Generator: Gtranslator 2.91.7\n" + +#: ../libsoup/soup-body-input-stream.c:139 +#: ../libsoup/soup-body-input-stream.c:170 +#: ../libsoup/soup-body-input-stream.c:203 ../libsoup/soup-message-io.c:238 +msgid "Connection terminated unexpectedly" +msgstr "Připojení bylo neočekávaně ukončeno" + +#: ../libsoup/soup-body-input-stream.c:459 +msgid "Invalid seek request" +msgstr "Neplatný požadavek na posun" + +#: ../libsoup/soup-body-input-stream.c:487 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "Nelze zkrátit SoupBodyInputStream" + +#: ../libsoup/soup-cache-input-stream.c:76 +msgid "Network stream unexpectedly closed" +msgstr "Síťový proud byl neočekávaně uzavřen" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "Selhalo úplné uložení prostředku do mezipaměti" + +#: ../libsoup/soup-converter-wrapper.c:189 +#, c-format +msgid "Output buffer is too small" +msgstr "Výstupní vyrovnávací paměť je příliš malá" + +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "Nelze zpracovat odpověď HTTP" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "Nerozpoznáno kódování odpovědi HTTP" + +#: ../libsoup/soup-message-io.c:263 +msgid "Header too big" +msgstr "Hlavička je příliš velká" + +#: ../libsoup/soup-message-io.c:396 ../libsoup/soup-message-io.c:1024 +msgid "Operation would block" +msgstr "Operace by blokovala" + +#: ../libsoup/soup-message-io.c:976 ../libsoup/soup-message-io.c:1009 +msgid "Operation was cancelled" +msgstr "Operace byla zrušena" + +#: ../libsoup/soup-message-server-io.c:64 +msgid "Could not parse HTTP request" +msgstr "Nelze zpracovat požadavek HTTP" + +#: ../libsoup/soup-request.c:141 +#, c-format +msgid "No URI provided" +msgstr "Není poskytnuta žádná adresa URI" + +#: ../libsoup/soup-request.c:151 +#, c-format +msgid "Invalid “%s” URI: %s" +msgstr "Neplatná adresa URI „%s“: %s" + +#: ../libsoup/soup-server.c:1725 +msgid "Can’t create a TLS server without a TLS certificate" +msgstr "Nelze vytvořit server TLS bez certifikátu TLS" + +#: ../libsoup/soup-server.c:1742 +#, c-format +msgid "Could not listen on address %s, port %d: " +msgstr "Nelze naslouchat na adrese %s, portu %d: " + +#: ../libsoup/soup-session.c:4524 +#, c-format +msgid "Could not parse URI “%s”" +msgstr "Nelze zpracovat adresu URI „%s“" + +#: ../libsoup/soup-session.c:4561 +#, c-format +msgid "Unsupported URI scheme “%s”" +msgstr "Nepodporované schéma URI „%s“" + +#: ../libsoup/soup-session.c:4583 +#, c-format +msgid "Not an HTTP URI" +msgstr "Nejedná se o adresu HTTP URI" + +#: ../libsoup/soup-session.c:4781 +msgid "The server did not accept the WebSocket handshake." +msgstr "Server nepřijímá vyjednávání WebSocket." + +#: ../libsoup/soup-socket.c:148 +msgid "Can’t import non-socket as SoupSocket" +msgstr "Nelze naimportovat ne-soket jako SoupSocket" + +#: ../libsoup/soup-socket.c:166 +msgid "Could not import existing socket: " +msgstr "Nelze naimportovat stávající soket: " + +#: ../libsoup/soup-socket.c:175 +msgid "Can’t import unconnected socket" +msgstr "Nelze naimportovat nepřipojený soket" + +#: ../libsoup/soup-websocket.c:338 ../libsoup/soup-websocket.c:347 +msgid "WebSocket handshake expected" +msgstr "Očekáváno vyjednávání WebSocket" + +#: ../libsoup/soup-websocket.c:355 +msgid "Unsupported WebSocket version" +msgstr "Nepodporovaná verze protokolu WebSocket" + +#: ../libsoup/soup-websocket.c:364 +msgid "Invalid WebSocket key" +msgstr "Neplatný klíč WebSocket" + +#: ../libsoup/soup-websocket.c:374 +#, c-format +msgid "Incorrect WebSocket “%s” header" +msgstr "Nesprávná hlavička „%s“ protokolu WebSocket" + +#: ../libsoup/soup-websocket.c:383 +msgid "Unsupported WebSocket subprotocol" +msgstr "Nepodporovaný podprotokol protokolu WebSocket" + +#: ../libsoup/soup-websocket.c:510 +msgid "Server rejected WebSocket handshake" +msgstr "Server odmítl vyjednávání WebSocket" + +#: ../libsoup/soup-websocket.c:518 ../libsoup/soup-websocket.c:527 +msgid "Server ignored WebSocket handshake" +msgstr "Server ignoruje vyjednávání WebSocket" + +#: ../libsoup/soup-websocket.c:539 +msgid "Server requested unsupported protocol" +msgstr "Server požaduje nepodporovaný protokol" + +#: ../libsoup/soup-websocket.c:549 +msgid "Server requested unsupported extension" +msgstr "Server požaduje nepodporované rozšíření" + +#: ../libsoup/soup-websocket.c:562 +#, c-format +msgid "Server returned incorrect “%s” key" +msgstr "Server vrátil nesprávný klíč „%s“" + +#: ../libsoup/soup-tld.c:188 +msgid "Hostname is an IP address" +msgstr "Název počítače je adresa IP" + +#: ../libsoup/soup-tld.c:198 ../libsoup/soup-tld.c:220 +msgid "Invalid hostname" +msgstr "Neplatný název počítače" + +#: ../libsoup/soup-tld.c:250 +msgid "Hostname has no base domain" +msgstr "Název počítače nemá základní doménu" + +#: ../libsoup/soup-tld.c:304 +msgid "Not enough domains" +msgstr "Nedostatek domén" diff --git a/po/da.po b/po/da.po new file mode 100644 index 0000000..68f28e3 --- /dev/null +++ b/po/da.po @@ -0,0 +1,180 @@ +# Danish translation for libsoup. +# Copyright (C) 2013-15, 2018 libsoup's COPYRIGHT HOLDER +# This file is distributed under the same license as the libsoup package. +# Ask Hjorth Larsen , 2012, 2014-15, 2018. +# Joe Hansen (joedalton2@yahoo.dk), 2013. +# +msgid "" +msgstr "" +"Project-Id-Version: libsoup master\n" +"Report-Msgid-Bugs-To: https://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=Misc\n" +"POT-Creation-Date: 2018-02-09 14:43+0000\n" +"PO-Revision-Date: 2018-03-06 23:20+0100\n" +"Last-Translator: Ask Hjorth Larsen \n" +"Language-Team: Danish \n" +"Language: da\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: ../libsoup/soup-body-input-stream.c:139 +#: ../libsoup/soup-body-input-stream.c:170 +#: ../libsoup/soup-body-input-stream.c:203 ../libsoup/soup-message-io.c:238 +msgid "Connection terminated unexpectedly" +msgstr "Forbindelsen blev uventet afbrudt" + +#: ../libsoup/soup-body-input-stream.c:459 +msgid "Invalid seek request" +msgstr "Ugyldig søgeforespørgsel" + +#: ../libsoup/soup-body-input-stream.c:487 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "Kan ikke afkorte SoupBodyInputStream" + +# evt. Netværksstrømmen +#: ../libsoup/soup-cache-input-stream.c:76 +msgid "Network stream unexpectedly closed" +msgstr "Netværksudsendelsen blev uventet lukket ned" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "Kunne ikke lave fuldt mellemlager for ressourcen" + +#: ../libsoup/soup-converter-wrapper.c:189 +#, c-format +msgid "Output buffer is too small" +msgstr "Outputbuffer er for lille" + +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "Kunne ikke fortolke HTTP-svar" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "Ej genkendt HTTP-svarkodning" + +#: ../libsoup/soup-message-io.c:263 +msgid "Header too big" +msgstr "Teksthovedet er for stort" + +#: ../libsoup/soup-message-io.c:396 ../libsoup/soup-message-io.c:1024 +msgid "Operation would block" +msgstr "Operationen ville blokere" + +#: ../libsoup/soup-message-io.c:976 ../libsoup/soup-message-io.c:1009 +msgid "Operation was cancelled" +msgstr "Operationen blev annulleret" + +#: ../libsoup/soup-message-server-io.c:64 +msgid "Could not parse HTTP request" +msgstr "Kunne ikke fortolke HTTP-forespørgsel" + +#: ../libsoup/soup-request.c:141 +#, c-format +msgid "No URI provided" +msgstr "Ingen URI givet" + +#: ../libsoup/soup-request.c:151 +#, c-format +msgid "Invalid “%s” URI: %s" +msgstr "Ugyldig “%s”-URI: %s" + +#: ../libsoup/soup-server.c:1725 +msgid "Can’t create a TLS server without a TLS certificate" +msgstr "Kan ikke oprette en TLS-server uden et TLS-certifikat" + +#: ../libsoup/soup-server.c:1742 +#, c-format +msgid "Could not listen on address %s, port %d: " +msgstr "Kunne ikke lytte på adresse %s, port %d: " + +#: ../libsoup/soup-session.c:4524 +#, c-format +msgid "Could not parse URI “%s”" +msgstr "Kunne ikke fortolke URI “%s”" + +#: ../libsoup/soup-session.c:4561 +#, c-format +msgid "Unsupported URI scheme “%s”" +msgstr "Uunderstøttet URI-skema “%s”" + +#: ../libsoup/soup-session.c:4583 +#, c-format +msgid "Not an HTTP URI" +msgstr "Ikke en HTTP URI" + +#: ../libsoup/soup-session.c:4781 +msgid "The server did not accept the WebSocket handshake." +msgstr "Serveren accepterede ikke WebSocket-håndtrykket." + +#: ../libsoup/soup-socket.c:148 +msgid "Can’t import non-socket as SoupSocket" +msgstr "Kan ikke importere ikke-sokkel som SoupSocket" + +#: ../libsoup/soup-socket.c:166 +msgid "Could not import existing socket: " +msgstr "Kunne ikke importere eksisterende sokkel: " + +#: ../libsoup/soup-socket.c:175 +msgid "Can’t import unconnected socket" +msgstr "Kan ikke importere uforbundet sokkel" + +#: ../libsoup/soup-websocket.c:338 ../libsoup/soup-websocket.c:347 +msgid "WebSocket handshake expected" +msgstr "WebSocket-håndtryk forventet" + +#: ../libsoup/soup-websocket.c:355 +msgid "Unsupported WebSocket version" +msgstr "Version af WebSocket understøttes ikke" + +#: ../libsoup/soup-websocket.c:364 +msgid "Invalid WebSocket key" +msgstr "Igyldig WebSocket-nøgle" + +#: ../libsoup/soup-websocket.c:374 +#, c-format +msgid "Incorrect WebSocket “%s” header" +msgstr "Forkert “%s”-header for WebSocket" + +#: ../libsoup/soup-websocket.c:383 +msgid "Unsupported WebSocket subprotocol" +msgstr "Underprotokol for WebSocket understøttes ikke" + +#: ../libsoup/soup-websocket.c:510 +msgid "Server rejected WebSocket handshake" +msgstr "Serveren afviste WebSocket-håndtryk" + +#: ../libsoup/soup-websocket.c:518 ../libsoup/soup-websocket.c:527 +msgid "Server ignored WebSocket handshake" +msgstr "Serveren ignorerede WebSocket-håndtryk" + +#: ../libsoup/soup-websocket.c:539 +msgid "Server requested unsupported protocol" +msgstr "Serveren forespurgte om en protokol som ikke understøttes" + +#: ../libsoup/soup-websocket.c:549 +msgid "Server requested unsupported extension" +msgstr "Serveren forespurgte om en udvidelse som ikke understøttes" + +#: ../libsoup/soup-websocket.c:562 +#, c-format +msgid "Server returned incorrect “%s” key" +msgstr "Serveren returnerede forkert “%s”-nøgle" + +#: ../libsoup/soup-tld.c:188 +msgid "Hostname is an IP address" +msgstr "Værtsnavn er en IP-adresse" + +#: ../libsoup/soup-tld.c:198 ../libsoup/soup-tld.c:220 +msgid "Invalid hostname" +msgstr "Ugyldigt værtsnavn" + +#: ../libsoup/soup-tld.c:250 +msgid "Hostname has no base domain" +msgstr "Værtsnavnet har intet basisdomæne" + +#: ../libsoup/soup-tld.c:304 +msgid "Not enough domains" +msgstr "Ikke nok domæner" diff --git a/po/de.po b/po/de.po new file mode 100644 index 0000000..ecc3c10 --- /dev/null +++ b/po/de.po @@ -0,0 +1,182 @@ +# German translation for libsoup. +# Copyright (C) 2012 libsoup's COPYRIGHT HOLDER +# This file is distributed under the same license as the libsoup package. +# Tobias Endrigkeit , 2012. +# Mario Blättermann , 2012-2013, 2016, 2018. +# Andre Jonas , 2013. +# Bernd Homuth , 2015. +# +msgid "" +msgstr "" +"Project-Id-Version: libsoup master\n" +"Report-Msgid-Bugs-To: https://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=Misc\n" +"POT-Creation-Date: 2018-02-09 14:43+0000\n" +"PO-Revision-Date: 2018-02-18 14:09+0100\n" +"Last-Translator: Mario Blättermann \n" +"Language-Team: Deutsch \n" +"Language: de\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Poedit 2.0.6\n" + +#: ../libsoup/soup-body-input-stream.c:139 +#: ../libsoup/soup-body-input-stream.c:170 +#: ../libsoup/soup-body-input-stream.c:203 ../libsoup/soup-message-io.c:238 +msgid "Connection terminated unexpectedly" +msgstr "Die Verbindung wurde unerwartet beendet" + +#: ../libsoup/soup-body-input-stream.c:459 +msgid "Invalid seek request" +msgstr "Ungültige Suchanfrage" + +#: ../libsoup/soup-body-input-stream.c:487 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "SoupBodyInputStream konnte nicht abgeschnitten werden" + +#: ../libsoup/soup-cache-input-stream.c:76 +msgid "Network stream unexpectedly closed" +msgstr "Netzwerk-Stream wurde unerwartet geschlossen" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "Das vollständige Zwischenspeichern der Ressource ist fehlgeschlagen" + +#: ../libsoup/soup-converter-wrapper.c:189 +#, c-format +msgid "Output buffer is too small" +msgstr "Der Ausgabe-Zwischenspeicher ist zu klein" + +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "HTTP-Antwort konnte nicht verarbeitet werden" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "Unbekannte Kodierung der HTTP-Antwort" + +#: ../libsoup/soup-message-io.c:263 +msgid "Header too big" +msgstr "Kopf ist zu groß" + +#: ../libsoup/soup-message-io.c:396 ../libsoup/soup-message-io.c:1024 +msgid "Operation would block" +msgstr "Der Vorgang würde gestoppt werden" + +#: ../libsoup/soup-message-io.c:976 ../libsoup/soup-message-io.c:1009 +msgid "Operation was cancelled" +msgstr "Der Vorgang wurde abgebrochen" + +#: ../libsoup/soup-message-server-io.c:64 +msgid "Could not parse HTTP request" +msgstr "HTTP-Anfrage konnte nicht verarbeitet werden" + +#: ../libsoup/soup-request.c:141 +#, c-format +msgid "No URI provided" +msgstr "Es wurde keine Adresse bereitgestellt" + +#: ../libsoup/soup-request.c:151 +#, c-format +msgid "Invalid “%s” URI: %s" +msgstr "Ungültige »%s«-Adresse: %s" + +#: ../libsoup/soup-server.c:1725 +msgid "Can’t create a TLS server without a TLS certificate" +msgstr "TLS-Server kann nicht ohne TLS-Zertifikat erstellt werden" + +#: ../libsoup/soup-server.c:1742 +#, c-format +msgid "Could not listen on address %s, port %d: " +msgstr "Auf Adresse %s, Port %d kann nicht gehört werden: " + +#: ../libsoup/soup-session.c:4524 +#, c-format +msgid "Could not parse URI “%s”" +msgstr "Die Adresse »%s« konnte nicht verarbeitet werden" + +#: ../libsoup/soup-session.c:4561 +#, c-format +msgid "Unsupported URI scheme “%s”" +msgstr "Nicht unterstütztes Adressenschema »%s«" + +#: ../libsoup/soup-session.c:4583 +#, c-format +msgid "Not an HTTP URI" +msgstr "Keine HTTP-Adresse" + +#: ../libsoup/soup-session.c:4781 +msgid "The server did not accept the WebSocket handshake." +msgstr "Der Server hat den WebSocket-Handshake nicht angenommen." + +#: ../libsoup/soup-socket.c:148 +msgid "Can’t import non-socket as SoupSocket" +msgstr "Nicht-Socket kann nicht als SoupSocket importiert werden" + +#: ../libsoup/soup-socket.c:166 +msgid "Could not import existing socket: " +msgstr "Bestehendes Socket konnte nicht importieren werden: " + +#: ../libsoup/soup-socket.c:175 +msgid "Can’t import unconnected socket" +msgstr "Unverbundenes Socket kann nicht importiert werden" + +#: ../libsoup/soup-websocket.c:338 ../libsoup/soup-websocket.c:347 +msgid "WebSocket handshake expected" +msgstr "WebSocket-Handshale erwartet" + +#: ../libsoup/soup-websocket.c:355 +msgid "Unsupported WebSocket version" +msgstr "Nicht unterstütze WebSocket-Version" + +#: ../libsoup/soup-websocket.c:364 +msgid "Invalid WebSocket key" +msgstr "Ungültiger WebSocket-Schlüssel" + +#: ../libsoup/soup-websocket.c:374 +#, c-format +msgid "Incorrect WebSocket “%s” header" +msgstr "Falscher WebSocket »%s«-Kopf" + +#: ../libsoup/soup-websocket.c:383 +msgid "Unsupported WebSocket subprotocol" +msgstr "Nicht unterstütztes WebSocket-Subprotokoll" + +#: ../libsoup/soup-websocket.c:510 +msgid "Server rejected WebSocket handshake" +msgstr "Server lehnte WebSocket-Handshake ab" + +#: ../libsoup/soup-websocket.c:518 ../libsoup/soup-websocket.c:527 +msgid "Server ignored WebSocket handshake" +msgstr "Server ignorierte WebSocket-Handshake" + +#: ../libsoup/soup-websocket.c:539 +msgid "Server requested unsupported protocol" +msgstr "Server forderte nicht unterstütztes Protokoll an" + +#: ../libsoup/soup-websocket.c:549 +msgid "Server requested unsupported extension" +msgstr "Server forderte nicht unterstützte Erweiterung an" + +#: ../libsoup/soup-websocket.c:562 +#, c-format +msgid "Server returned incorrect “%s” key" +msgstr "Server gab falschen »%s«-Schlüssel zurück" + +#: ../libsoup/soup-tld.c:188 +msgid "Hostname is an IP address" +msgstr "Der Rechnername ist eine IP-Adresse" + +#: ../libsoup/soup-tld.c:198 ../libsoup/soup-tld.c:220 +msgid "Invalid hostname" +msgstr "Ungültiger Rechnername" + +#: ../libsoup/soup-tld.c:250 +msgid "Hostname has no base domain" +msgstr "Der Rechnername hat keine Hauptdomäne" + +#: ../libsoup/soup-tld.c:304 +msgid "Not enough domains" +msgstr "Nicht genug Domänen" diff --git a/po/el.po b/po/el.po new file mode 100644 index 0000000..d72673d --- /dev/null +++ b/po/el.po @@ -0,0 +1,182 @@ +# Greek translation for libsoup. +# Copyright (C) 2012 libsoup's COPYRIGHT HOLDER +# This file is distributed under the same license as the libsoup package. +# Tom Tryfonidis , 2012. +# Dimitris Spingos (Δημήτρης Σπίγγος) , 2013. +# Efstathios Iosifidis , 2018. +# +msgid "" +msgstr "" +"Project-Id-Version: libsoup master\n" +"Report-Msgid-Bugs-To: https://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=Misc\n" +"POT-Creation-Date: 2018-02-09 14:43+0000\n" +"PO-Revision-Date: 2018-02-20 22:19+0200\n" +"Last-Translator: Efstathios Iosifidis \n" +"Language-Team: Ελληνικά <>\n" +"Language: el\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Gtranslator 2.91.7\n" +"X-Project-Style: gnome\n" + +#: ../libsoup/soup-body-input-stream.c:139 +#: ../libsoup/soup-body-input-stream.c:170 +#: ../libsoup/soup-body-input-stream.c:203 ../libsoup/soup-message-io.c:238 +msgid "Connection terminated unexpectedly" +msgstr "Η σύνδεση τερματίστηκε απρόσμενα" + +#: ../libsoup/soup-body-input-stream.c:459 +msgid "Invalid seek request" +msgstr "Άκυρη αίτηση αναζήτησης" + +#: ../libsoup/soup-body-input-stream.c:487 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "Αδυναμία περικοπής του SoupBodyInputStream" + +#: ../libsoup/soup-cache-input-stream.c:76 +msgid "Network stream unexpectedly closed" +msgstr "Η ροή του δικτύου έκλεισε απρόσμενα" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "Αποτυχία πλήρους απόκρυψης του πόρου" + +#: ../libsoup/soup-converter-wrapper.c:189 +#, c-format +msgid "Output buffer is too small" +msgstr "Η ενδιάμεση μνήμη εξόδου είναι πολύ μικρή" + +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "Αδυναμία ανάλυσης της απάντησης HTTP" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "Μη αναγνωρίσιμη κωδικοποίηση απάντησης HTTP" + +#: ../libsoup/soup-message-io.c:263 +msgid "Header too big" +msgstr "Η επικεφαλίδα είναι πολύ μεγάλη" + +#: ../libsoup/soup-message-io.c:396 ../libsoup/soup-message-io.c:1024 +msgid "Operation would block" +msgstr "Η λειτουργία θα μπλοκαριστεί" + +#: ../libsoup/soup-message-io.c:976 ../libsoup/soup-message-io.c:1009 +msgid "Operation was cancelled" +msgstr "Η λειτουργία ακυρώθηκε" + +#: ../libsoup/soup-message-server-io.c:64 +msgid "Could not parse HTTP request" +msgstr "Αδυναμία ανάλυσης αιτήματος HTTP" + +#: ../libsoup/soup-request.c:141 +#, c-format +msgid "No URI provided" +msgstr "Δεν έχει δοθεί URI" + +#: ../libsoup/soup-request.c:151 +#, c-format +msgid "Invalid “%s” URI: %s" +msgstr "Μη έγκυρο «%s» URI: %s" + +#: ../libsoup/soup-server.c:1725 +msgid "Can’t create a TLS server without a TLS certificate" +msgstr "Αδύνατη η δημιουργία ενός διακομιστή TLS χωρίς πιστοποιητικό TLS" + +#: ../libsoup/soup-server.c:1742 +#, c-format +msgid "Could not listen on address %s, port %d: " +msgstr "Αδυναμία ακρόασης στη διεύθυνση %s, θύρα %d: " + +#: ../libsoup/soup-session.c:4524 +#, c-format +msgid "Could not parse URI “%s”" +msgstr "Αδυναμία ανάλυσης URI «%s»" + +#: ../libsoup/soup-session.c:4561 +#, c-format +msgid "Unsupported URI scheme “%s”" +msgstr "Μη υποστηριζόμενο σχήμα URI «%s»" + +#: ../libsoup/soup-session.c:4583 +#, c-format +msgid "Not an HTTP URI" +msgstr "Δεν είναι HTTP URI" + +#: ../libsoup/soup-session.c:4781 +msgid "The server did not accept the WebSocket handshake." +msgstr "Ο διακομιστής δεν αποδέχεται τη χειραψία WebSocket" + +#: ../libsoup/soup-socket.c:148 +msgid "Can’t import non-socket as SoupSocket" +msgstr "Αδύνατη η εισαγωγή μιας μη υποδοχής ως SoupSocket" + +#: ../libsoup/soup-socket.c:166 +msgid "Could not import existing socket: " +msgstr "Αδυναμία εισαγωγής υπάρχουσας υποδοχής" + +#: ../libsoup/soup-socket.c:175 +msgid "Can’t import unconnected socket" +msgstr "Αδύνατη η εισαγωγή μιας μη συνδεμένης υποδοχής" + +#: ../libsoup/soup-websocket.c:338 ../libsoup/soup-websocket.c:347 +msgid "WebSocket handshake expected" +msgstr "Αναμένεται χειραψία WebSocket" + +#: ../libsoup/soup-websocket.c:355 +msgid "Unsupported WebSocket version" +msgstr "Η έκδοση WebSocket δεν υποστηρίζεται" + +#: ../libsoup/soup-websocket.c:364 +msgid "Invalid WebSocket key" +msgstr "Μη έγκυρο κλειδί κρυπτογράφησης WebSocket" + +#: ../libsoup/soup-websocket.c:374 +#, c-format +msgid "Incorrect WebSocket “%s” header" +msgstr "Εσφαλμένη κεφαλίδα WebSocket «%s»" + +#: ../libsoup/soup-websocket.c:383 +msgid "Unsupported WebSocket subprotocol" +msgstr "Το υποπρωτόκολλο WebSocket δεν υποστηρίζεται" + +#: ../libsoup/soup-websocket.c:510 +msgid "Server rejected WebSocket handshake" +msgstr "Ο διακομιστής απέρριψε την χειραψία WebSocket" + +#: ../libsoup/soup-websocket.c:518 ../libsoup/soup-websocket.c:527 +msgid "Server ignored WebSocket handshake" +msgstr "Ο διακομιστής αγνόησε την χειραψία WebSocket" + +#: ../libsoup/soup-websocket.c:539 +msgid "Server requested unsupported protocol" +msgstr "Ο διακομιστής αιτήθηκε ένα μη υποστηριζόμενο πρωτόκολλο" + +#: ../libsoup/soup-websocket.c:549 +msgid "Server requested unsupported extension" +msgstr "Ο διακομιστής αιτήθηκε μια μη υποστηριζόμενη επέκταση" + +#: ../libsoup/soup-websocket.c:562 +#, c-format +msgid "Server returned incorrect “%s” key" +msgstr "Ο διακομιστής επέστρεψε ένα εσφαλμένο κλειδί «%s»" + +#: ../libsoup/soup-tld.c:188 +msgid "Hostname is an IP address" +msgstr "Το όνομα κεντρικού υπολογιστή είναι μια διεύθυνση IP" + +#: ../libsoup/soup-tld.c:198 ../libsoup/soup-tld.c:220 +msgid "Invalid hostname" +msgstr "Μη έγκυρο όνομα κεντρικού υπολογιστή" + +#: ../libsoup/soup-tld.c:250 +msgid "Hostname has no base domain" +msgstr "Το όνομα κεντρικού υπολογιστή δεν έχει βασικό τομέα" + +#: ../libsoup/soup-tld.c:304 +msgid "Not enough domains" +msgstr "Δεν υπάρχουν αρκετοί τομείς" diff --git a/po/en_GB.po b/po/en_GB.po new file mode 100644 index 0000000..ac6df72 --- /dev/null +++ b/po/en_GB.po @@ -0,0 +1,176 @@ +# British English translation for libsoup. +# Copyright (C) 2012 libsoup's COPYRIGHT HOLDER +# This file is distributed under the same license as the libsoup package. +# Bruce Cowan , 2012. +# Chris Leonard , 2012. +msgid "" +msgstr "" +"Project-Id-Version: libsoup master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2016-04-25 20:57+0000\n" +"PO-Revision-Date: 2016-09-18 12:16+0200\n" +"Last-Translator: David King \n" +"Language-Team: Sugar Labs\n" +"Language: en_GB\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Virtaal 0.7.0\n" +"X-Project-Style: gnome\n" + +#: ../libsoup/soup-body-input-stream.c:140 +#: ../libsoup/soup-body-input-stream.c:171 +#: ../libsoup/soup-body-input-stream.c:204 ../libsoup/soup-message-io.c:235 +msgid "Connection terminated unexpectedly" +msgstr "Connection terminated unexpectedly" + +#: ../libsoup/soup-body-input-stream.c:462 +msgid "Invalid seek request" +msgstr "Invalid seek request" + +#: ../libsoup/soup-body-input-stream.c:490 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "Cannot truncate SoupBodyInputStream" + +#: ../libsoup/soup-cache-input-stream.c:74 +msgid "Network stream unexpectedly closed" +msgstr "Network stream unexpectedly closed" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "Failed to completely cache the resource" + +#: ../libsoup/soup-converter-wrapper.c:192 +#, c-format +msgid "Output buffer is too small" +msgstr "Output buffer is too small" + +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "Could not parse HTTP response" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "Unrecognised HTTP response encoding" + +#: ../libsoup/soup-message-io.c:392 ../libsoup/soup-message-io.c:1020 +msgid "Operation would block" +msgstr "Operation would block" + +#: ../libsoup/soup-message-io.c:972 ../libsoup/soup-message-io.c:1005 +msgid "Operation was cancelled" +msgstr "Operation was cancelled" + +#: ../libsoup/soup-message-server-io.c:64 +msgid "Could not parse HTTP request" +msgstr "Could not parse HTTP request" + +#: ../libsoup/soup-request.c:140 +#, c-format +msgid "No URI provided" +msgstr "No URI provided" + +#: ../libsoup/soup-request.c:150 +#, c-format +msgid "Invalid '%s' URI: %s" +msgstr "Invalid '%s' URI: %s" + +#: ../libsoup/soup-server.c:1720 +msgid "Can't create a TLS server without a TLS certificate" +msgstr "Can't create a TLS server without a TLS certificate" + +#: ../libsoup/soup-server.c:1737 +#, c-format +msgid "Could not listen on address %s, port %d: " +msgstr "Could not listen on address %s, port %d: " + +#: ../libsoup/soup-session.c:4543 +#, c-format +msgid "Could not parse URI '%s'" +msgstr "Could not parse URI '%s'" + +#: ../libsoup/soup-session.c:4580 +#, c-format +msgid "Unsupported URI scheme '%s'" +msgstr "Unsupported URI scheme '%s'" + +#: ../libsoup/soup-session.c:4602 +#, c-format +msgid "Not an HTTP URI" +msgstr "Not an HTTP URI" + +#: ../libsoup/soup-session.c:4788 +msgid "The server did not accept the WebSocket handshake." +msgstr "The server did not accept the WebSocket handshake." + +#: ../libsoup/soup-socket.c:148 +msgid "Can't import non-socket as SoupSocket" +msgstr "Can't import non-socket as SoupSocket" + +#: ../libsoup/soup-socket.c:166 +msgid "Could not import existing socket: " +msgstr "Could not import existing socket: " + +#: ../libsoup/soup-socket.c:175 +msgid "Can't import unconnected socket" +msgstr "Can't import unconnected socket" + +#: ../libsoup/soup-websocket.c:338 ../libsoup/soup-websocket.c:347 +msgid "WebSocket handshake expected" +msgstr "WebSocket handshake expected" + +#: ../libsoup/soup-websocket.c:355 +msgid "Unsupported WebSocket version" +msgstr "Unsupported WebSocket version" + +#: ../libsoup/soup-websocket.c:364 +msgid "Invalid WebSocket key" +msgstr "Invalid WebSocket key" + +#: ../libsoup/soup-websocket.c:374 +#, c-format +msgid "Incorrect WebSocket \"%s\" header" +msgstr "Incorrect WebSocket \"%s\" header" + +#: ../libsoup/soup-websocket.c:383 +msgid "Unsupported WebSocket subprotocol" +msgstr "Unsupported WebSocket subprotocol" + +#: ../libsoup/soup-websocket.c:510 +msgid "Server rejected WebSocket handshake" +msgstr "Server rejected WebSocket handshake" + +#: ../libsoup/soup-websocket.c:518 ../libsoup/soup-websocket.c:527 +msgid "Server ignored WebSocket handshake" +msgstr "Server ignored WebSocket handshake" + +#: ../libsoup/soup-websocket.c:539 +msgid "Server requested unsupported protocol" +msgstr "Server requested unsupported protocol" + +#: ../libsoup/soup-websocket.c:549 +msgid "Server requested unsupported extension" +msgstr "Server requested unsupported extension" + +#: ../libsoup/soup-websocket.c:562 +#, c-format +msgid "Server returned incorrect \"%s\" key" +msgstr "Server returned incorrect \"%s\" key" + +#: ../libsoup/soup-tld.c:188 +msgid "Hostname is an IP address" +msgstr "Hostname is an IP address" + +#: ../libsoup/soup-tld.c:198 ../libsoup/soup-tld.c:220 +msgid "Invalid hostname" +msgstr "Invalid hostname" + +#: ../libsoup/soup-tld.c:250 +msgid "Hostname has no base domain" +msgstr "Hostname has no base domain" + +#: ../libsoup/soup-tld.c:304 +msgid "Not enough domains" +msgstr "Not enough domains" diff --git a/po/eo.po b/po/eo.po new file mode 100644 index 0000000..678e12f --- /dev/null +++ b/po/eo.po @@ -0,0 +1,180 @@ +# Esperanto translation for libsoup. +# Copyright (C) 2012 Free Software Foundation, Inc. +# This file is distributed under the same license as the libsoup package. +# Kristjan SCHMIDT , 2012, 2017. +msgid "" +msgstr "" +"Project-Id-Version: libsoup master\n" +"Report-Msgid-Bugs-To: https://bugzilla.gnome.org/enter_bug.cgi?product=libsou" +"p&keywords=I18N+L10N&component=Misc\n" +"POT-Creation-Date: 2017-02-23 10:17+0000\n" +"PO-Revision-Date: 2017-06-11 12:37+0200\n" +"Last-Translator: Kristjan SCHMIDT \n" +"Language-Team: Esperanto \n" +"Language: eo\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Virtaal 0.7.1\n" +"X-Project-Style: gnome\n" + +#: ../libsoup/soup-body-input-stream.c:139 +#: ../libsoup/soup-body-input-stream.c:170 +#: ../libsoup/soup-body-input-stream.c:203 ../libsoup/soup-message-io.c:235 +msgid "Connection terminated unexpectedly" +msgstr "La konekto estas neatendite fermita" + +#: ../libsoup/soup-body-input-stream.c:459 +msgid "Invalid seek request" +msgstr "Nevalida serĉ-peto" + +#: ../libsoup/soup-body-input-stream.c:487 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "Ne eblas trunki SoupBodyInputStream-on" + +#: ../libsoup/soup-cache-input-stream.c:76 +msgid "Network stream unexpectedly closed" +msgstr "Reta fluo neatatendite fermiĝis" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "" + +#: ../libsoup/soup-converter-wrapper.c:189 +#, c-format +msgid "Output buffer is too small" +msgstr "La elig-bufro estas tro malgranda" + +#: ../libsoup/soup-message-client-io.c:41 +#| msgid "Could not parse URI '%s'" +msgid "Could not parse HTTP response" +msgstr "Ne eblis analizi HTTP-respondon" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "" + +#: ../libsoup/soup-message-io.c:392 ../libsoup/soup-message-io.c:1020 +msgid "Operation would block" +msgstr "La operacio estus haltigota" + +#: ../libsoup/soup-message-io.c:972 ../libsoup/soup-message-io.c:1005 +msgid "Operation was cancelled" +msgstr "La operacio estas ĉesigita" + +#: ../libsoup/soup-message-server-io.c:64 +#| msgid "Could not parse URI '%s'" +msgid "Could not parse HTTP request" +msgstr "Ne eblis analizi HTTP-peton" + +#: ../libsoup/soup-request.c:141 +#, c-format +msgid "No URI provided" +msgstr "Neniu URI estas diponigita" + +#: ../libsoup/soup-request.c:151 +#, c-format +#| msgid "Invalid '%s' URI: %s" +msgid "Invalid “%s” URI: %s" +msgstr "Nevalida “%s” URI: %s" + +#: ../libsoup/soup-server.c:1725 +msgid "Can’t create a TLS server without a TLS certificate" +msgstr "" + +#: ../libsoup/soup-server.c:1742 +#, c-format +msgid "Could not listen on address %s, port %d: " +msgstr "" + +#: ../libsoup/soup-session.c:4518 +#, c-format +#| msgid "Could not parse URI '%s'" +msgid "Could not parse URI “%s”" +msgstr "Ne eblis analizi na URI “%s”" + +#: ../libsoup/soup-session.c:4555 +#, c-format +#| msgid "Unsupported URI scheme '%s'" +msgid "Unsupported URI scheme “%s”" +msgstr "Nesubtenata URI-skemo “%s”" + +#: ../libsoup/soup-session.c:4577 +#, c-format +msgid "Not an HTTP URI" +msgstr "" + +#: ../libsoup/soup-session.c:4763 +msgid "The server did not accept the WebSocket handshake." +msgstr "" + +#: ../libsoup/soup-socket.c:148 +msgid "Can’t import non-socket as SoupSocket" +msgstr "" + +#: ../libsoup/soup-socket.c:166 +msgid "Could not import existing socket: " +msgstr "" + +#: ../libsoup/soup-socket.c:175 +msgid "Can’t import unconnected socket" +msgstr "" + +#: ../libsoup/soup-websocket.c:338 ../libsoup/soup-websocket.c:347 +msgid "WebSocket handshake expected" +msgstr "" + +#: ../libsoup/soup-websocket.c:355 +msgid "Unsupported WebSocket version" +msgstr "Nesubtenata WebSocket-versio" + +#: ../libsoup/soup-websocket.c:364 +msgid "Invalid WebSocket key" +msgstr "Nevalida WebSocket-ŝlosilo" + +#: ../libsoup/soup-websocket.c:374 +#, c-format +msgid "Incorrect WebSocket “%s” header" +msgstr "" + +#: ../libsoup/soup-websocket.c:383 +msgid "Unsupported WebSocket subprotocol" +msgstr "" + +#: ../libsoup/soup-websocket.c:510 +msgid "Server rejected WebSocket handshake" +msgstr "" + +#: ../libsoup/soup-websocket.c:518 ../libsoup/soup-websocket.c:527 +msgid "Server ignored WebSocket handshake" +msgstr "" + +#: ../libsoup/soup-websocket.c:539 +msgid "Server requested unsupported protocol" +msgstr "Servilo petis nesubtenatan protokolon" + +#: ../libsoup/soup-websocket.c:549 +msgid "Server requested unsupported extension" +msgstr "" + +#: ../libsoup/soup-websocket.c:562 +#, c-format +msgid "Server returned incorrect “%s” key" +msgstr "Servilo redonis malĝustan ŝlosilon “%s”" + +#: ../libsoup/soup-tld.c:188 +msgid "Hostname is an IP address" +msgstr "La komputilnomo estas IP-adreso" + +#: ../libsoup/soup-tld.c:198 ../libsoup/soup-tld.c:220 +msgid "Invalid hostname" +msgstr "Nevalida komputilnomo" + +#: ../libsoup/soup-tld.c:250 +msgid "Hostname has no base domain" +msgstr "La komputilnomo ne havas ĉefan retregionon" + +#: ../libsoup/soup-tld.c:304 +msgid "Not enough domains" +msgstr "Ne sufiĉe da retregionoj" diff --git a/po/es.po b/po/es.po new file mode 100644 index 0000000..a9158d7 --- /dev/null +++ b/po/es.po @@ -0,0 +1,180 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# Daniel Mustieles , 2012, 2013, 2014, 2015, 2016, 2018. +# +msgid "" +msgstr "" +"Project-Id-Version: libsoup\n" +"Report-Msgid-Bugs-To: https://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=Misc\n" +"POT-Creation-Date: 2018-02-09 14:43+0000\n" +"PO-Revision-Date: 2018-02-21 17:30+0100\n" +"Last-Translator: Daniel Mustieles \n" +"Language-Team: es \n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Gtranslator 2.91.6\n" + +#: ../libsoup/soup-body-input-stream.c:139 +#: ../libsoup/soup-body-input-stream.c:170 +#: ../libsoup/soup-body-input-stream.c:203 ../libsoup/soup-message-io.c:238 +msgid "Connection terminated unexpectedly" +msgstr "La conexión terminó inesperadamente" + +#: ../libsoup/soup-body-input-stream.c:459 +msgid "Invalid seek request" +msgstr "Petición de búsqueda no válida" + +#: ../libsoup/soup-body-input-stream.c:487 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "No se puede truncar SoupBodyInputStream" + +#: ../libsoup/soup-cache-input-stream.c:76 +msgid "Network stream unexpectedly closed" +msgstr "El flujo de red se cerró inesperadamente" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "Falló al cachear completamente el recurso" + +#: ../libsoup/soup-converter-wrapper.c:189 +#, c-format +msgid "Output buffer is too small" +msgstr "El búfer de salida es demasiado pequeño" + +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "No se pudo analizar la respuesta HTTP" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "Codificación de la respuesta HTTP no reconocida" + +#: ../libsoup/soup-message-io.c:263 +msgid "Header too big" +msgstr "La cabecera es demasiado grande" + +#: ../libsoup/soup-message-io.c:396 ../libsoup/soup-message-io.c:1024 +msgid "Operation would block" +msgstr "La operación se bloqueará" + +#: ../libsoup/soup-message-io.c:976 ../libsoup/soup-message-io.c:1009 +msgid "Operation was cancelled" +msgstr "Se canceló la operación" + +#: ../libsoup/soup-message-server-io.c:64 +msgid "Could not parse HTTP request" +msgstr "No se pudo analizar la solicitud HTTP" + +#: ../libsoup/soup-request.c:141 +#, c-format +msgid "No URI provided" +msgstr "No se ha proporcionado un URI" + +#: ../libsoup/soup-request.c:151 +#, c-format +msgid "Invalid “%s” URI: %s" +msgstr "URI «%s» no válida: %s" + +#: ../libsoup/soup-server.c:1725 +msgid "Can’t create a TLS server without a TLS certificate" +msgstr "No se puede crear un servidor TLS sin un certificado TLS" + +#: ../libsoup/soup-server.c:1742 +#, c-format +msgid "Could not listen on address %s, port %d: " +msgstr "No se puede escuchar en la dirección %s, puerto %d: " + +#: ../libsoup/soup-session.c:4524 +#, c-format +msgid "Could not parse URI “%s”" +msgstr "No se pudo analizar el URI «%s»" + +#: ../libsoup/soup-session.c:4561 +#, c-format +msgid "Unsupported URI scheme “%s”" +msgstr "Esquema «%s» de URI no soportado" + +#: ../libsoup/soup-session.c:4583 +#, c-format +msgid "Not an HTTP URI" +msgstr "No es un URI HTTP" + +#: ../libsoup/soup-session.c:4781 +msgid "The server did not accept the WebSocket handshake." +msgstr "El servidor no ha aceptado la negociación WebSocket." + +#: ../libsoup/soup-socket.c:148 +msgid "Can’t import non-socket as SoupSocket" +msgstr "No se puede importar algo que no es un socket como SoupSocket" + +#: ../libsoup/soup-socket.c:166 +msgid "Could not import existing socket: " +msgstr "No se pudo importar el socket existente: " + +#: ../libsoup/soup-socket.c:175 +msgid "Can’t import unconnected socket" +msgstr "No se puede importar un socket no conectado" + +#: ../libsoup/soup-websocket.c:338 ../libsoup/soup-websocket.c:347 +msgid "WebSocket handshake expected" +msgstr "Se esperaba la negociación WebSocket" + +#: ../libsoup/soup-websocket.c:355 +msgid "Unsupported WebSocket version" +msgstr "Versión de Websocket no soportada" + +#: ../libsoup/soup-websocket.c:364 +msgid "Invalid WebSocket key" +msgstr "Clave de WebSocket no válida" + +#: ../libsoup/soup-websocket.c:374 +#, c-format +msgid "Incorrect WebSocket “%s” header" +msgstr "Cabecera «%s» de WebSocket no válida" + +#: ../libsoup/soup-websocket.c:383 +msgid "Unsupported WebSocket subprotocol" +msgstr "Subprotocolo de WebSocket no válido" + +#: ../libsoup/soup-websocket.c:510 +msgid "Server rejected WebSocket handshake" +msgstr "El servidor ha rechazado la negociación de WebSocket" + +#: ../libsoup/soup-websocket.c:518 ../libsoup/soup-websocket.c:527 +msgid "Server ignored WebSocket handshake" +msgstr "El servidor ha ignorado la negociación de WebSocket" + +#: ../libsoup/soup-websocket.c:539 +msgid "Server requested unsupported protocol" +msgstr "El servidor ha solicitado un protocolo no soportado" + +#: ../libsoup/soup-websocket.c:549 +msgid "Server requested unsupported extension" +msgstr "El servidor ha solicitado una extensión no soportada" + +#: ../libsoup/soup-websocket.c:562 +#, c-format +msgid "Server returned incorrect “%s” key" +msgstr "El servidor ha devuelto una clave «%s» incorrecta" + +#: ../libsoup/soup-tld.c:188 +msgid "Hostname is an IP address" +msgstr "El nombre del equipo es una dirección IP" + +#: ../libsoup/soup-tld.c:198 ../libsoup/soup-tld.c:220 +msgid "Invalid hostname" +msgstr "El nombre del equipo no es válido" + +#: ../libsoup/soup-tld.c:250 +msgid "Hostname has no base domain" +msgstr "El nombre del equipo no tiene un dominio base" + +#: ../libsoup/soup-tld.c:304 +msgid "Not enough domains" +msgstr "No hay suficientes dominios" diff --git a/po/et.po b/po/et.po new file mode 100644 index 0000000..8a3ac39 --- /dev/null +++ b/po/et.po @@ -0,0 +1,180 @@ +# Estonian translation for libsoup. +# Copyright (C) 2012 libsoup's COPYRIGHT HOLDER +# This file is distributed under the same license as the libsoup package. +# Mattias Põldaru , 2012, 2013. +# Mart Raudsepp , 2018. +# +msgid "" +msgstr "" +"Project-Id-Version: libsoup master\n" +"Report-Msgid-Bugs-To: https://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=Misc\n" +"POT-Creation-Date: 2018-02-09 14:43+0000\n" +"PO-Revision-Date: 2018-02-14 03:02+0200\n" +"Last-Translator: Mart Raudsepp \n" +"Language-Team: Estonian \n" +"Language: et\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Poedit 2.0.6\n" + +#: ../libsoup/soup-body-input-stream.c:139 +#: ../libsoup/soup-body-input-stream.c:170 +#: ../libsoup/soup-body-input-stream.c:203 ../libsoup/soup-message-io.c:238 +msgid "Connection terminated unexpectedly" +msgstr "Ühendus katkes ootamatult" + +#: ../libsoup/soup-body-input-stream.c:459 +msgid "Invalid seek request" +msgstr "Sobimatu kerimispäring" + +#: ../libsoup/soup-body-input-stream.c:487 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "SoupBodyInputStream-i pole võimalik lühendada" + +#: ../libsoup/soup-cache-input-stream.c:76 +msgid "Network stream unexpectedly closed" +msgstr "Võrguvoog sulgus ootamatult" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "Ressursi täielik puhverdamine nurjus" + +#: ../libsoup/soup-converter-wrapper.c:189 +#, c-format +msgid "Output buffer is too small" +msgstr "Väljundpuhver on liiga väike" + +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "HTTP vastust polnud võimalik parsida" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "Tundmatu HTTP vastuse kodeering" + +#: ../libsoup/soup-message-io.c:263 +msgid "Header too big" +msgstr "Päis on liiga suur" + +#: ../libsoup/soup-message-io.c:396 ../libsoup/soup-message-io.c:1024 +msgid "Operation would block" +msgstr "Operatsioon blokeeruks" + +#: ../libsoup/soup-message-io.c:976 ../libsoup/soup-message-io.c:1009 +msgid "Operation was cancelled" +msgstr "Operatsioon katkestati" + +#: ../libsoup/soup-message-server-io.c:64 +msgid "Could not parse HTTP request" +msgstr "HTTP päringut polnud võimalik parsida" + +#: ../libsoup/soup-request.c:141 +#, c-format +msgid "No URI provided" +msgstr "URI-d ei antud" + +#: ../libsoup/soup-request.c:151 +#, c-format +msgid "Invalid “%s” URI: %s" +msgstr "Sobimatu „%s“ URI: %s" + +#: ../libsoup/soup-server.c:1725 +msgid "Can’t create a TLS server without a TLS certificate" +msgstr "TLS serverit pole võimalik luua ilma TLS sertifikaadita" + +#: ../libsoup/soup-server.c:1742 +#, c-format +msgid "Could not listen on address %s, port %d: " +msgstr "Aadressi %s pordil %d polnud võimalik kuulata: " + +#: ../libsoup/soup-session.c:4524 +#, c-format +msgid "Could not parse URI “%s”" +msgstr "URI-d „%s“ polnud võimalik parsida" + +#: ../libsoup/soup-session.c:4561 +#, c-format +msgid "Unsupported URI scheme “%s”" +msgstr "URI skeem „%s“ pole toetatud" + +#: ../libsoup/soup-session.c:4583 +#, c-format +msgid "Not an HTTP URI" +msgstr "Pole HTTP URI" + +#: ../libsoup/soup-session.c:4781 +msgid "The server did not accept the WebSocket handshake." +msgstr "Server ei nõustunud WebSocket kätlusega." + +#: ../libsoup/soup-socket.c:148 +msgid "Can’t import non-socket as SoupSocket" +msgstr "Mitte-soklit pole võimalik importida SoupSocket'ina" + +#: ../libsoup/soup-socket.c:166 +msgid "Could not import existing socket: " +msgstr "Olemasoleva sokli import ebaõnnestus: " + +#: ../libsoup/soup-socket.c:175 +msgid "Can’t import unconnected socket" +msgstr "Ühendamata soklit pole võimalik importida" + +#: ../libsoup/soup-websocket.c:338 ../libsoup/soup-websocket.c:347 +msgid "WebSocket handshake expected" +msgstr "WebSocket kätlus on eeldatud" + +#: ../libsoup/soup-websocket.c:355 +msgid "Unsupported WebSocket version" +msgstr "Toetamata WebSocket versioon" + +#: ../libsoup/soup-websocket.c:364 +msgid "Invalid WebSocket key" +msgstr "Sobimatu WebSocket võti" + +#: ../libsoup/soup-websocket.c:374 +#, c-format +msgid "Incorrect WebSocket “%s” header" +msgstr "Vigane WebSocket „%s“ päis" + +#: ../libsoup/soup-websocket.c:383 +msgid "Unsupported WebSocket subprotocol" +msgstr "Toetamata WebSocket alamprotokoll" + +#: ../libsoup/soup-websocket.c:510 +msgid "Server rejected WebSocket handshake" +msgstr "Server keeldus WebSocket kätlusest" + +#: ../libsoup/soup-websocket.c:518 ../libsoup/soup-websocket.c:527 +msgid "Server ignored WebSocket handshake" +msgstr "Server eiras WebSocket kätlust" + +#: ../libsoup/soup-websocket.c:539 +msgid "Server requested unsupported protocol" +msgstr "Server küsis toetamata protokolli" + +#: ../libsoup/soup-websocket.c:549 +msgid "Server requested unsupported extension" +msgstr "Server küsis toetamata laiendust" + +#: ../libsoup/soup-websocket.c:562 +#, c-format +msgid "Server returned incorrect “%s” key" +msgstr "Server tagastas vigase „%s“ võtme" + +#: ../libsoup/soup-tld.c:188 +msgid "Hostname is an IP address" +msgstr "Hostinimi on IP-aadress" + +#: ../libsoup/soup-tld.c:198 ../libsoup/soup-tld.c:220 +msgid "Invalid hostname" +msgstr "Sobimatu hostinimi" + +#: ../libsoup/soup-tld.c:250 +msgid "Hostname has no base domain" +msgstr "Hostinimel puudub baasdomeen" + +#: ../libsoup/soup-tld.c:304 +msgid "Not enough domains" +msgstr "Pole piisavalt domeene" diff --git a/po/eu.po b/po/eu.po new file mode 100644 index 0000000..81ae38e --- /dev/null +++ b/po/eu.po @@ -0,0 +1,185 @@ +# Basque translation for libsoup. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# +# Iñaki Larrañaga Murgoitio , 2013, 2014, 2015, 2017. +msgid "" +msgstr "" +"Project-Id-Version: libsoup master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=Misc\n" +"POT-Creation-Date: 2016-10-27 12:38+0000\n" +"PO-Revision-Date: 2017-02-16 22:10+0100\n" +"Last-Translator: Iñaki Larrañaga Murgoitio \n" +"Language-Team: Basque \n" +"Language: eu\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Lokalize 1.5\n" + +#: ../libsoup/soup-body-input-stream.c:140 +#: ../libsoup/soup-body-input-stream.c:171 +#: ../libsoup/soup-body-input-stream.c:204 ../libsoup/soup-message-io.c:235 +msgid "Connection terminated unexpectedly" +msgstr "Konexioa ustekabean amaitu da" + +#: ../libsoup/soup-body-input-stream.c:462 +msgid "Invalid seek request" +msgstr "Bilaketa-eskaera baliogabea" + +#: ../libsoup/soup-body-input-stream.c:490 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "Ezin da SoupBodyInputStream trunkatu" + +#: ../libsoup/soup-cache-input-stream.c:74 +msgid "Network stream unexpectedly closed" +msgstr "Sarearen korrontea ustekabean itxi da" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "Huts egin du baliabidea erabat cachean gordetzean" + +#: ../libsoup/soup-converter-wrapper.c:192 +#, c-format +msgid "Output buffer is too small" +msgstr "Irteeraren bufferra txikiegia da" + +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "Ezin izan da HTTP erantzuna analizatu" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "HTTP erantzunaren kodeketa ezezaguna" + +#: ../libsoup/soup-message-io.c:392 ../libsoup/soup-message-io.c:1020 +msgid "Operation would block" +msgstr "Eragiketak blokea dezake" + +#: ../libsoup/soup-message-io.c:972 ../libsoup/soup-message-io.c:1005 +msgid "Operation was cancelled" +msgstr "Eragiketa bertan behera utzi da" + +#: ../libsoup/soup-message-server-io.c:64 +msgid "Could not parse HTTP request" +msgstr "Ezin izan da HTTP eskaera analizatu" + +#: ../libsoup/soup-request.c:140 +#, c-format +msgid "No URI provided" +msgstr "Ez da URIrik eman" + +#: ../libsoup/soup-request.c:150 +#, c-format +#| msgid "Invalid '%s' URI: %s" +msgid "Invalid “%s” URI: %s" +msgstr "Baliogabeko “%s“ URIa: %s" + +#: ../libsoup/soup-server.c:1727 +#| msgid "Can't create a TLS server without a TLS certificate" +msgid "Can’t create a TLS server without a TLS certificate" +msgstr "Ezin da TLS zerbitzaria sortu TLS ziurtagirik gabe" + +#: ../libsoup/soup-server.c:1744 +#, c-format +msgid "Could not listen on address %s, port %d: " +msgstr "Ezin izan da '%s:%d' helbidean entzun: " + +#: ../libsoup/soup-session.c:4525 +#, c-format +#| msgid "Could not parse URI '%s'" +msgid "Could not parse URI “%s”" +msgstr "Ezin izan da “%s“ URIa analizatu" + +#: ../libsoup/soup-session.c:4562 +#, c-format +#| msgid "Unsupported URI scheme '%s'" +msgid "Unsupported URI scheme “%s”" +msgstr "Onartu gabeko “%s“ URI eskema" + +#: ../libsoup/soup-session.c:4584 +#, c-format +msgid "Not an HTTP URI" +msgstr "Ez da HTTP URIa" + +#: ../libsoup/soup-session.c:4770 +msgid "The server did not accept the WebSocket handshake." +msgstr "Zerbitzariak ez du WebSocket diosala onartu" + +#: ../libsoup/soup-socket.c:148 +#| msgid "Can't import non-socket as SoupSocket" +msgid "Can’t import non-socket as SoupSocket" +msgstr "Ezin da SoupSocket bezalako ez-socketa inportatu" + +#: ../libsoup/soup-socket.c:166 +msgid "Could not import existing socket: " +msgstr "Ezin izan da dagoen socket-a inportatu: " + +#: ../libsoup/soup-socket.c:175 +#| msgid "Can't import unconnected socket" +msgid "Can’t import unconnected socket" +msgstr "Ezin da deskonektatutako socket-a inportatu" + +#: ../libsoup/soup-websocket.c:338 ../libsoup/soup-websocket.c:347 +msgid "WebSocket handshake expected" +msgstr "WebSocket diosala espero zen" + +#: ../libsoup/soup-websocket.c:355 +msgid "Unsupported WebSocket version" +msgstr "Onartu gabeko WebSocket bertsioa" + +#: ../libsoup/soup-websocket.c:364 +msgid "Invalid WebSocket key" +msgstr "Baliogabeko WebSocket gakoa" + +#: ../libsoup/soup-websocket.c:374 +#, c-format +#| msgid "Incorrect WebSocket \"%s\" header" +msgid "Incorrect WebSocket “%s” header" +msgstr "Okerreko “%s“ WebSocket-aren goiburua" + +#: ../libsoup/soup-websocket.c:383 +msgid "Unsupported WebSocket subprotocol" +msgstr "Onartu gabeko WebSocket azpi-protokoloa" + +#: ../libsoup/soup-websocket.c:510 +msgid "Server rejected WebSocket handshake" +msgstr "Zerbitzariak ukatu egin du WebSocket diosala" + +#: ../libsoup/soup-websocket.c:518 ../libsoup/soup-websocket.c:527 +msgid "Server ignored WebSocket handshake" +msgstr "Zerbitzariak ez ikusi egin dio WebSocket diosalari" + +#: ../libsoup/soup-websocket.c:539 +msgid "Server requested unsupported protocol" +msgstr "Zerbitzariak onartu gabeko protokoloa eskatu du" + +#: ../libsoup/soup-websocket.c:549 +msgid "Server requested unsupported extension" +msgstr "Zerbitzariak onartu gabeko hedapena eskatu du" + +#: ../libsoup/soup-websocket.c:562 +#, c-format +#| msgid "Server returned incorrect \"%s\" key" +msgid "Server returned incorrect “%s” key" +msgstr "Zerbitzariak okerreko “%s“ gakoa itzuli du" + +#: ../libsoup/soup-tld.c:188 +msgid "Hostname is an IP address" +msgstr "Ostalari-izena IP helbide bat da" + +#: ../libsoup/soup-tld.c:198 ../libsoup/soup-tld.c:220 +msgid "Invalid hostname" +msgstr "Baliogabeko ostalari-izena" + +#: ../libsoup/soup-tld.c:250 +msgid "Hostname has no base domain" +msgstr "Ostalari-izenak ez dauka oinarrizko domeinurik" + +#: ../libsoup/soup-tld.c:304 +msgid "Not enough domains" +msgstr "Ez dago nahikoa domeinurik" + diff --git a/po/fa.po b/po/fa.po new file mode 100644 index 0000000..74ee1e7 --- /dev/null +++ b/po/fa.po @@ -0,0 +1,109 @@ +# Persian translation for libsoup. +# Copyright (C) 2012 libsoup's COPYRIGHT HOLDER +# This file is distributed under the same license as the libsoup package. +# Arash Mousavi , 2012, 2013. +# +msgid "" +msgstr "" +"Project-Id-Version: libsoup master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2013-02-18 10:20+0000\n" +"PO-Revision-Date: 2013-03-23 18:07+0330\n" +"Last-Translator: Arash Mousavi \n" +"Language-Team: Persian\n" +"Language: fa\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 1.5.4\n" + +#: ../libsoup/soup-body-input-stream.c:141 +#: ../libsoup/soup-body-input-stream.c:172 +#: ../libsoup/soup-body-input-stream.c:205 ../libsoup/soup-message-io.c:191 +msgid "Connection terminated unexpectedly" +msgstr "اتصال به شکل غیرمنتظره‌ای بسته شد" + +#: ../libsoup/soup-body-input-stream.c:463 +msgid "Invalid seek request" +msgstr "درخواست جستجو نامعتبر" + +#: ../libsoup/soup-body-input-stream.c:491 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "نمی‌توان SoupBodyInputStream را کوتاه کرد" + +#: ../libsoup/soup-cache-input-stream.c:74 +msgid "Network stream unexpectedly closed" +msgstr "جریان شبکه به‌طور غیرمنتظره‌ای بسته شد" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "به‌طور کامل حافظه‌ی نهان کردن منبع شکست خورد" + +#: ../libsoup/soup-converter-wrapper.c:192 +#, c-format +msgid "Output buffer is too small" +msgstr "میانگیر خروجی خیلی کوتاه است" + +#: ../libsoup/soup-message-client-io.c:41 +#| msgid "Could not parse URI '%s'" +msgid "Could not parse HTTP response" +msgstr "نمی‌توان پاسخ HTTP را تجزیه کرد" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "کدگذاری پاسخ HTTP شناخته نشد" + +#: ../libsoup/soup-message-io.c:846 ../libsoup/soup-message-io.c:882 +msgid "Operation was cancelled" +msgstr "عملیات لغو شده بود" + +#: ../libsoup/soup-message-io.c:893 +msgid "Operation would block" +msgstr "عملیات می‌توانست بسته شود" + +#: ../libsoup/soup-message-server-io.c:40 +#| msgid "Could not parse URI '%s'" +msgid "Could not parse HTTP request" +msgstr "نمی‌توان درخواست HTTP را تجزیه کرد" + +#: ../libsoup/soup-request.c:140 +#, c-format +msgid "No URI provided" +msgstr "هیچ URIای داده نشده است" + +#: ../libsoup/soup-request.c:150 +#, c-format +msgid "Invalid '%s' URI: %s" +msgstr "«%s» نامعتبر URI: %s" + +#: ../libsoup/soup-session.c:4209 +#, c-format +msgid "Could not parse URI '%s'" +msgstr "نمی‌توان URI را تجزیه کرد «%s»" + +#: ../libsoup/soup-session.c:4246 +#, c-format +msgid "Unsupported URI scheme '%s'" +msgstr "شِما URI پشتیبانی نشده «%s»" + +#: ../libsoup/soup-session.c:4268 +#, c-format +msgid "Not an HTTP URI" +msgstr "آدرس HTTP نیست" + +#: ../libsoup/soup-tld.c:185 +msgid "Hostname is an IP address" +msgstr "نام میزبان یک آدرس آی‌پی است" + +#: ../libsoup/soup-tld.c:206 +msgid "Invalid hostname" +msgstr "نام‌میزبان نامعتبر" + +#: ../libsoup/soup-tld.c:235 +msgid "Hostname has no base domain" +msgstr "نام‌میزبان دامنه‌ی پایه ندارد" + +#: ../libsoup/soup-tld.c:257 +msgid "Not enough domains" +msgstr "دامنه‌های کافی موجود نیست" diff --git a/po/fr.po b/po/fr.po new file mode 100644 index 0000000..82b1b21 --- /dev/null +++ b/po/fr.po @@ -0,0 +1,183 @@ +# French translation for libsoup. +# Copyright (C) 2012-2017 libsoup's COPYRIGHT HOLDER +# This file is distributed under the same license as the libsoup package. +# +# Pierre Henry , 2012. +# Alain Lojewski , 2012. +# Mickael Albertus , 2012. +# Charles Monzat , 2018. +# +msgid "" +msgstr "" +"Project-Id-Version: libsoup master\n" +"Report-Msgid-Bugs-To: https://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=Misc\n" +"POT-Creation-Date: 2018-02-09 14:43+0000\n" +"PO-Revision-Date: 2018-03-01 11:53+0100\n" +"Last-Translator: Charles Monzat \n" +"Language-Team: français \n" +"Language: fr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" +"X-Generator: Gtranslator 2.91.7\n" + +#: ../libsoup/soup-body-input-stream.c:139 +#: ../libsoup/soup-body-input-stream.c:170 +#: ../libsoup/soup-body-input-stream.c:203 ../libsoup/soup-message-io.c:238 +msgid "Connection terminated unexpectedly" +msgstr "La connexion a été interrompue de manière inattendue" + +#: ../libsoup/soup-body-input-stream.c:459 +msgid "Invalid seek request" +msgstr "Requête de recherche invalide" + +#: ../libsoup/soup-body-input-stream.c:487 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "Impossible de tronquer le SoupBodyInputStream" + +#: ../libsoup/soup-cache-input-stream.c:76 +msgid "Network stream unexpectedly closed" +msgstr "Le flux réseau s’est arrêté inopinément" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "Impossible de mettre la ressource totalement en cache" + +#: ../libsoup/soup-converter-wrapper.c:189 +#, c-format +msgid "Output buffer is too small" +msgstr "La mémoire tampon de sortie est trop petite" + +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "Impossible d’analyser la réponse HTTP" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "Codage de réponse HTTP inconnu" + +#: ../libsoup/soup-message-io.c:263 +msgid "Header too big" +msgstr "En-tête trop grand" + +#: ../libsoup/soup-message-io.c:396 ../libsoup/soup-message-io.c:1024 +msgid "Operation would block" +msgstr "L’opération aurait bloqué" + +#: ../libsoup/soup-message-io.c:976 ../libsoup/soup-message-io.c:1009 +msgid "Operation was cancelled" +msgstr "L’opération a été annulée" + +#: ../libsoup/soup-message-server-io.c:64 +msgid "Could not parse HTTP request" +msgstr "Impossible d’analyser la requête HTTP" + +#: ../libsoup/soup-request.c:141 +#, c-format +msgid "No URI provided" +msgstr "Aucun URI fourni" + +#: ../libsoup/soup-request.c:151 +#, c-format +msgid "Invalid “%s” URI: %s" +msgstr "URI « %s » non valide : %s" + +#: ../libsoup/soup-server.c:1725 +msgid "Can’t create a TLS server without a TLS certificate" +msgstr "Impossible de créer un serveur TLS sans un certificat TLS" + +#: ../libsoup/soup-server.c:1742 +#, c-format +msgid "Could not listen on address %s, port %d: " +msgstr "Impossible d’écouter l’adresse %s sur le port %d: " + +#: ../libsoup/soup-session.c:4524 +#, c-format +msgid "Could not parse URI “%s”" +msgstr "Impossible d’analyser l’URI « %s »" + +#: ../libsoup/soup-session.c:4561 +#, c-format +msgid "Unsupported URI scheme “%s”" +msgstr "Le schéma d’URI « %s » n’est pas pris en charge" + +#: ../libsoup/soup-session.c:4583 +#, c-format +msgid "Not an HTTP URI" +msgstr "Ce n’est pas un URI HTTP" + +#: ../libsoup/soup-session.c:4781 +msgid "The server did not accept the WebSocket handshake." +msgstr "Le serveur n’a pas accepté la négociation WebSocket." + +#: ../libsoup/soup-socket.c:148 +msgid "Can’t import non-socket as SoupSocket" +msgstr "Impossible d’importer du contenu non-socket comme SoupSocket" + +#: ../libsoup/soup-socket.c:166 +msgid "Could not import existing socket: " +msgstr "Impossible d’importer le connecteur réseau existant : " + +#: ../libsoup/soup-socket.c:175 +msgid "Can’t import unconnected socket" +msgstr "Impossible d’importer le connecteur réseau non connecté" + +#: ../libsoup/soup-websocket.c:338 ../libsoup/soup-websocket.c:347 +msgid "WebSocket handshake expected" +msgstr "Négociation WebSocket attendue" + +#: ../libsoup/soup-websocket.c:355 +msgid "Unsupported WebSocket version" +msgstr "Version de WebSocket non prise en charge" + +#: ../libsoup/soup-websocket.c:364 +msgid "Invalid WebSocket key" +msgstr "Clé WebSocket non valable" + +#: ../libsoup/soup-websocket.c:374 +#, c-format +msgid "Incorrect WebSocket “%s” header" +msgstr "En-tête WebSocket « %s » incorrect" + +#: ../libsoup/soup-websocket.c:383 +msgid "Unsupported WebSocket subprotocol" +msgstr "Sous-protocole de WebSocket non pris en charge" + +#: ../libsoup/soup-websocket.c:510 +msgid "Server rejected WebSocket handshake" +msgstr "Le serveur a rejeté la négociation WebSocket" + +#: ../libsoup/soup-websocket.c:518 ../libsoup/soup-websocket.c:527 +msgid "Server ignored WebSocket handshake" +msgstr "Le serveur a ignoré la négociation WebSocket" + +#: ../libsoup/soup-websocket.c:539 +msgid "Server requested unsupported protocol" +msgstr "Le serveur a demandé un protocole non pris en charge" + +#: ../libsoup/soup-websocket.c:549 +msgid "Server requested unsupported extension" +msgstr "Le serveur a demandé une extension non prise en charge" + +#: ../libsoup/soup-websocket.c:562 +#, c-format +msgid "Server returned incorrect “%s” key" +msgstr "Le serveur a renvoyé une clé « %s » incorrecte" + +#: ../libsoup/soup-tld.c:188 +msgid "Hostname is an IP address" +msgstr "Le nom d’hôte est une adresse IP" + +#: ../libsoup/soup-tld.c:198 ../libsoup/soup-tld.c:220 +msgid "Invalid hostname" +msgstr "Nom d’hôte non valide" + +#: ../libsoup/soup-tld.c:250 +msgid "Hostname has no base domain" +msgstr "Le nom d’hôte n’a pas de domaine de base" + +#: ../libsoup/soup-tld.c:304 +msgid "Not enough domains" +msgstr "Pas assez de domaines" diff --git a/po/fur.po b/po/fur.po new file mode 100644 index 0000000..437edde --- /dev/null +++ b/po/fur.po @@ -0,0 +1,178 @@ +# Friulian translation for libsoup. +# Copyright (C) 2012 libsoup's COPYRIGHT HOLDER +# This file is distributed under the same license as the libsoup package. +# TmTFx , 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: libsoup gnome-3-6\n" +"Report-Msgid-Bugs-To: https://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=Misc\n" +"POT-Creation-Date: 2018-02-09 14:43+0000\n" +"PO-Revision-Date: 2018-02-10 00:41+0100\n" +"Last-Translator: Fabio Tomat \n" +"Language-Team: Friulian \n" +"Language: fur\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 2.0.3\n" + +#: ../libsoup/soup-body-input-stream.c:139 +#: ../libsoup/soup-body-input-stream.c:170 +#: ../libsoup/soup-body-input-stream.c:203 ../libsoup/soup-message-io.c:238 +msgid "Connection terminated unexpectedly" +msgstr "No si spietave il termin de conession" + +#: ../libsoup/soup-body-input-stream.c:459 +msgid "Invalid seek request" +msgstr "Domande di ricerche no valide" + +#: ../libsoup/soup-body-input-stream.c:487 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "No puès cjonçâ SoupBodyInputStream" + +#: ../libsoup/soup-cache-input-stream.c:76 +msgid "Network stream unexpectedly closed" +msgstr "Flus di rêt sierât a colp" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "Salvament in memorie de risorse falît" + +#: ../libsoup/soup-converter-wrapper.c:189 +#, c-format +msgid "Output buffer is too small" +msgstr "Il buffer di jessude al è masse piçul" + +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "Impussibil analizâ la rispueste HTTP" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "Codifiche rispueste HTTP no cognossude" + +#: ../libsoup/soup-message-io.c:263 +msgid "Header too big" +msgstr "Intestazion masse grande" + +#: ../libsoup/soup-message-io.c:396 ../libsoup/soup-message-io.c:1024 +msgid "Operation would block" +msgstr "L'operazion e sarà blocade" + +#: ../libsoup/soup-message-io.c:976 ../libsoup/soup-message-io.c:1009 +msgid "Operation was cancelled" +msgstr "L'operazion e je stade scancelade" + +#: ../libsoup/soup-message-server-io.c:64 +msgid "Could not parse HTTP request" +msgstr "Impussibil analizâ la richieste HTTP" + +#: ../libsoup/soup-request.c:141 +#, c-format +msgid "No URI provided" +msgstr "No'l è stât furnît un URI" + +#: ../libsoup/soup-request.c:151 +#, c-format +msgid "Invalid “%s” URI: %s" +msgstr "URI “%s”no valit: %s" + +#: ../libsoup/soup-server.c:1725 +msgid "Can’t create a TLS server without a TLS certificate" +msgstr "Impussibil creâ un servidôr TLS cence un certificât TLS" + +#: ../libsoup/soup-server.c:1742 +#, c-format +msgid "Could not listen on address %s, port %d: " +msgstr "Impussibil scoltâ te direzion %s, puarte %d: " + +#: ../libsoup/soup-session.c:4524 +#, c-format +msgid "Could not parse URI “%s”" +msgstr "No puès analizâ il URI “%s”" + +#: ../libsoup/soup-session.c:4561 +#, c-format +msgid "Unsupported URI scheme “%s”" +msgstr "Scheme URI “%s” no supuartât" + +#: ../libsoup/soup-session.c:4583 +#, c-format +msgid "Not an HTTP URI" +msgstr "No un URI HTTP" + +#: ../libsoup/soup-session.c:4781 +msgid "The server did not accept the WebSocket handshake." +msgstr "Il servidôr nol acete il handshake WebSocket" + +#: ../libsoup/soup-socket.c:148 +msgid "Can’t import non-socket as SoupSocket" +msgstr "Impussibil impuartâ non-socket come SoupSocket" + +#: ../libsoup/soup-socket.c:166 +msgid "Could not import existing socket: " +msgstr "Impussibil impuartâ socket esistent: " + +#: ../libsoup/soup-socket.c:175 +msgid "Can’t import unconnected socket" +msgstr "Impussibil impuartâ socket no conetût" + +#: ../libsoup/soup-websocket.c:338 ../libsoup/soup-websocket.c:347 +msgid "WebSocket handshake expected" +msgstr "Si spietave handshake WebSocket" + +#: ../libsoup/soup-websocket.c:355 +msgid "Unsupported WebSocket version" +msgstr "Version WebSocket no supuartade" + +#: ../libsoup/soup-websocket.c:364 +msgid "Invalid WebSocket key" +msgstr "Clâf WebSocket no valide" + +#: ../libsoup/soup-websocket.c:374 +#, c-format +msgid "Incorrect WebSocket “%s” header" +msgstr "Intestazion WebSocket “%s” no valide" + +#: ../libsoup/soup-websocket.c:383 +msgid "Unsupported WebSocket subprotocol" +msgstr "Sot-protocol WebSocket no supuartât" + +#: ../libsoup/soup-websocket.c:510 +msgid "Server rejected WebSocket handshake" +msgstr "Il servidôr al à refudât l'handshake WebSocket" + +#: ../libsoup/soup-websocket.c:518 ../libsoup/soup-websocket.c:527 +msgid "Server ignored WebSocket handshake" +msgstr "Il servidôr al à ignorât l'handshake WebSocket" + +#: ../libsoup/soup-websocket.c:539 +msgid "Server requested unsupported protocol" +msgstr "Il servidôr al à domandât un protocol no supuartât" + +#: ../libsoup/soup-websocket.c:549 +msgid "Server requested unsupported extension" +msgstr "Il servidôr al à domandât une estension no supuartade" + +#: ../libsoup/soup-websocket.c:562 +#, c-format +msgid "Server returned incorrect “%s” key" +msgstr "Il servidôr al à tornât la clâf “%s” sbaliade" + +#: ../libsoup/soup-tld.c:188 +msgid "Hostname is an IP address" +msgstr "Il non host al è un indiriz IP" + +#: ../libsoup/soup-tld.c:198 ../libsoup/soup-tld.c:220 +msgid "Invalid hostname" +msgstr "Il non host nol è valit" + +#: ../libsoup/soup-tld.c:250 +msgid "Hostname has no base domain" +msgstr "Il non host nol à un domini di base" + +#: ../libsoup/soup-tld.c:304 +msgid "Not enough domains" +msgstr "No vonde dominis" diff --git a/po/gd.po b/po/gd.po new file mode 100644 index 0000000..7007ec3 --- /dev/null +++ b/po/gd.po @@ -0,0 +1,186 @@ +# Scottish Gaelic translation for libsoup. +# Copyright (C) 2016 libsoup's COPYRIGHT HOLDER +# This file is distributed under the same license as the libsoup package. +# GunChleoc , 2016, 2018. +msgid "" +msgstr "" +"Project-Id-Version: libsoup master\n" +"Report-Msgid-Bugs-To: https://bugzilla.gnome.org/enter_bug.cgi?product=libso" +"up&keywords=I18N+L10N&component=Misc\n" +"POT-Creation-Date: 2017-10-27 08:22+0000\n" +"PO-Revision-Date: 2018-03-01 10:41+0100\n" +"Last-Translator: GunChleoc \n" +"Language-Team: Fòram na Gàidhlig\n" +"Language: gd\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=4; plural=(n==1 || n==11) ? 0 : (n==2 || n==12) ? 1 : " +"(n > 2 && n < 20) ? 2 : 3;\n" +"X-Generator: Virtaal 0.7.1\n" +"X-Project-Style: gnome\n" + +#: ../libsoup/soup-body-input-stream.c:139 +#: ../libsoup/soup-body-input-stream.c:170 +#: ../libsoup/soup-body-input-stream.c:203 ../libsoup/soup-message-io.c:237 +msgid "Connection terminated unexpectedly" +msgstr "Chaidh crìoch a chur air a’ cheangal gun dùil" + +#: ../libsoup/soup-body-input-stream.c:459 +msgid "Invalid seek request" +msgstr "Iarrtas siridh mì-dhligheach" + +#: ../libsoup/soup-body-input-stream.c:487 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "Chan urrainn dhuinn buntach a dhèanamh air SoupBodyInputStream" + +#: ../libsoup/soup-cache-input-stream.c:76 +msgid "Network stream unexpectedly closed" +msgstr "Chaidh an sreath lìonraidh a dhùnadh gun dùil" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "Cha deach leinn an goireas slàn a chur dhan tasgadan" + +#: ../libsoup/soup-converter-wrapper.c:189 +#, c-format +msgid "Output buffer is too small" +msgstr "Tha bufair an às-chuir ro bheag" + +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "Cha b’ urrainn dhuinn an fhreagairt HTTP a pharsadh" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "Cha do dh’aithnich sinn còdachadh an fhreagairt HTTP" + +#: ../libsoup/soup-message-io.c:387 ../libsoup/soup-message-io.c:1015 +msgid "Operation would block" +msgstr "Dhèanadh an t-obrachadh bacadh" + +#: ../libsoup/soup-message-io.c:967 ../libsoup/soup-message-io.c:1000 +msgid "Operation was cancelled" +msgstr "Chaidh sgur dhen obrachadh" + +#: ../libsoup/soup-message-server-io.c:64 +msgid "Could not parse HTTP request" +msgstr "Cha b’ urrainn dhuinn an t-iarrtas HTTP a pharsadh" + +#: ../libsoup/soup-request.c:141 +#, c-format +msgid "No URI provided" +msgstr "Cha deach URI a sholar" + +#: ../libsoup/soup-request.c:151 +#, c-format +#| msgid "Invalid '%s' URI: %s" +msgid "Invalid “%s” URI: %s" +msgstr "URI “%s” mì-dhligheach: %s" + +#: ../libsoup/soup-server.c:1725 +#| msgid "Can't create a TLS server without a TLS certificate" +msgid "Can’t create a TLS server without a TLS certificate" +msgstr "" +"Chan urrainn dhuinn frithealaiche TLS a chruthachadh às aonais teisteanais " +"TLS" + +#: ../libsoup/soup-server.c:1742 +#, c-format +msgid "Could not listen on address %s, port %d: " +msgstr "Chan urrainn dhuinn èisteachd ris an t-seòladh %s, port %d: " + +#: ../libsoup/soup-session.c:4517 +#, c-format +#| msgid "Could not parse URI '%s'" +msgid "Could not parse URI “%s”" +msgstr "Cha b’ urrainn dhuinn an URI “%s” a pharsadh" + +#: ../libsoup/soup-session.c:4554 +#, c-format +#| msgid "Unsupported URI scheme '%s'" +msgid "Unsupported URI scheme “%s”" +msgstr "Chan eil taic ri sgeama “%s” an URI" + +#: ../libsoup/soup-session.c:4576 +#, c-format +msgid "Not an HTTP URI" +msgstr "Chan e URI HTTP a th’ ann" + +#: ../libsoup/soup-session.c:4762 +msgid "The server did not accept the WebSocket handshake." +msgstr "Cha do ghabh am frithealaiche ris a’ chrathadh-làimhe WebSocket." + +#: ../libsoup/soup-socket.c:148 +#| msgid "Can't import non-socket as SoupSocket" +msgid "Can’t import non-socket as SoupSocket" +msgstr "Chan urrainn dhuinn nì nach eil ’na shocaid ion-phortadh mar SoupSocket" + +#: ../libsoup/soup-socket.c:166 +msgid "Could not import existing socket: " +msgstr "Cha b’ urrainn dhuinn socaid a tha ann ion-phortadh: " + +#: ../libsoup/soup-socket.c:175 +#| msgid "Can't import unconnected socket" +msgid "Can’t import unconnected socket" +msgstr "Chan urrainn dhuinn socaid gun cheangal ion-phortadh" + +#: ../libsoup/soup-websocket.c:338 ../libsoup/soup-websocket.c:347 +msgid "WebSocket handshake expected" +msgstr "An dùil air crathadh-làimhe WebSocket" + +#: ../libsoup/soup-websocket.c:355 +msgid "Unsupported WebSocket version" +msgstr "Tionndadh dhe WebSocket ris nach cuirear taic" + +#: ../libsoup/soup-websocket.c:364 +msgid "Invalid WebSocket key" +msgstr "Iuchair WebSocket mì-dhligheach" + +#: ../libsoup/soup-websocket.c:374 +#, c-format +#| msgid "Incorrect WebSocket \"%s\" header" +msgid "Incorrect WebSocket “%s” header" +msgstr "Bann-cinn WebSocket “%s” nach eil mar bu chòir" + +#: ../libsoup/soup-websocket.c:383 +msgid "Unsupported WebSocket subprotocol" +msgstr "Fo-phròtacal aig WebSocket ris nach cuirear taic" + +#: ../libsoup/soup-websocket.c:510 +msgid "Server rejected WebSocket handshake" +msgstr "Dhiùlt am frithealaiche an crathadh-làimhe WebSocket" + +#: ../libsoup/soup-websocket.c:518 ../libsoup/soup-websocket.c:527 +msgid "Server ignored WebSocket handshake" +msgstr "Leig am frithealaiche an crathadh-làimhe WebSocket seachad" + +#: ../libsoup/soup-websocket.c:539 +msgid "Server requested unsupported protocol" +msgstr "Dh’iarr am frithealaiche pròtacal ris nach cuirear taic" + +#: ../libsoup/soup-websocket.c:549 +msgid "Server requested unsupported extension" +msgstr "Dh’iarr am frithealaiche leudachan ris nach cuirear taic" + +#: ../libsoup/soup-websocket.c:562 +#, c-format +#| msgid "Server returned incorrect \"%s\" key" +msgid "Server returned incorrect “%s” key" +msgstr "Thill am frithealaiche iuchair “%s” nach eil mar bu chòir" + +#: ../libsoup/soup-tld.c:188 +msgid "Hostname is an IP address" +msgstr "’S e seòladh IP a tha san ainm-òstair" + +#: ../libsoup/soup-tld.c:198 ../libsoup/soup-tld.c:220 +msgid "Invalid hostname" +msgstr "Ainm-òstair mì-dhligheach" + +#: ../libsoup/soup-tld.c:250 +msgid "Hostname has no base domain" +msgstr "Chan eil bun-àrainn aig an ainm-òstair" + +#: ../libsoup/soup-tld.c:304 +msgid "Not enough domains" +msgstr "Chan eil àrainnean gu leòr ann" diff --git a/po/gl.po b/po/gl.po new file mode 100644 index 0000000..261f168 --- /dev/null +++ b/po/gl.po @@ -0,0 +1,179 @@ +# Galician translation for libsoup. +# Copyright (C) 2012 libsoup's COPYRIGHT HOLDER +# This file is distributed under the same license as the libsoup package. +# Fran Dieguez , 2012, 2013, 2014, 2015, 2017, 2018. +msgid "" +msgstr "" +"Project-Id-Version: libsoup master\n" +"Report-Msgid-Bugs-To: https://bugzilla.gnome.org/enter_bug.cgi?product=libsou" +"p&keywords=I18N+L10N&component=Misc\n" +"POT-Creation-Date: 2018-02-09 14:43+0000\n" +"PO-Revision-Date: 2018-02-10 19:58+0200\n" +"Last-Translator: Fran Dieguez \n" +"Language-Team: Galician\n" +"Language: gl\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Virtaal 0.7.1\n" +"X-Project-Style: gnome\n" + +#: ../libsoup/soup-body-input-stream.c:139 +#: ../libsoup/soup-body-input-stream.c:170 +#: ../libsoup/soup-body-input-stream.c:203 ../libsoup/soup-message-io.c:238 +msgid "Connection terminated unexpectedly" +msgstr "A conexión rematou de forma non esperada" + +#: ../libsoup/soup-body-input-stream.c:459 +msgid "Invalid seek request" +msgstr "Petición de busca non válida" + +#: ../libsoup/soup-body-input-stream.c:487 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "Non é posíbel truncar SoupbodyInputStream" + +#: ../libsoup/soup-cache-input-stream.c:76 +msgid "Network stream unexpectedly closed" +msgstr "Fluxo de rede pechado de forma non esperada" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "Produciuse un fallo ao cachear completamente o recurso" + +#: ../libsoup/soup-converter-wrapper.c:189 +#, c-format +msgid "Output buffer is too small" +msgstr "O búfer de saída é demasiado pequeno" + +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "Non é posíbel analizar a resposta HTTP" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "Codificación da resposta HTTP non recoñecida" + +#: ../libsoup/soup-message-io.c:263 +msgid "Header too big" +msgstr "Cabeceira demasiado grande" + +#: ../libsoup/soup-message-io.c:396 ../libsoup/soup-message-io.c:1024 +msgid "Operation would block" +msgstr "A operación bloquearase" + +#: ../libsoup/soup-message-io.c:976 ../libsoup/soup-message-io.c:1009 +msgid "Operation was cancelled" +msgstr "A operación foi cancelada" + +#: ../libsoup/soup-message-server-io.c:64 +msgid "Could not parse HTTP request" +msgstr "Non é posíbel analizar a consulta HTTP" + +#: ../libsoup/soup-request.c:141 +#, c-format +msgid "No URI provided" +msgstr "Non se forneceu un URI" + +#: ../libsoup/soup-request.c:151 +#, c-format +msgid "Invalid “%s” URI: %s" +msgstr "URI «%s» non válida: %s" + +#: ../libsoup/soup-server.c:1725 +msgid "Can’t create a TLS server without a TLS certificate" +msgstr "Non é posíbel crear un servidor TLS sen un certificado TLS" + +#: ../libsoup/soup-server.c:1742 +#, c-format +msgid "Could not listen on address %s, port %d: " +msgstr "Non é posíbel escoitar no enderezo %s, porto %d: " + +#: ../libsoup/soup-session.c:4524 +#, c-format +msgid "Could not parse URI “%s”" +msgstr "Non é posíbel analizar o URI «%s»" + +#: ../libsoup/soup-session.c:4561 +#, c-format +msgid "Unsupported URI scheme “%s”" +msgstr "Esquema de URI «%s» non admitido" + +#: ../libsoup/soup-session.c:4583 +#, c-format +msgid "Not an HTTP URI" +msgstr "Non é unha URI de HTTP" + +#: ../libsoup/soup-session.c:4781 +msgid "The server did not accept the WebSocket handshake." +msgstr "O servidor non acepta un saúdo WebSocket." + +#: ../libsoup/soup-socket.c:148 +msgid "Can’t import non-socket as SoupSocket" +msgstr "Non é posíbel importar un non socket como SoupSocket" + +#: ../libsoup/soup-socket.c:166 +msgid "Could not import existing socket: " +msgstr "Non é posíbel importar un socket existente: " + +#: ../libsoup/soup-socket.c:175 +msgid "Can’t import unconnected socket" +msgstr "Non é posíbel importar un socket non conectado" + +#: ../libsoup/soup-websocket.c:338 ../libsoup/soup-websocket.c:347 +msgid "WebSocket handshake expected" +msgstr "Agardábase un saúdo WebSocket" + +#: ../libsoup/soup-websocket.c:355 +msgid "Unsupported WebSocket version" +msgstr "Versión de WebSocket non admitida" + +#: ../libsoup/soup-websocket.c:364 +msgid "Invalid WebSocket key" +msgstr "Chave de WebSocket non válida" + +#: ../libsoup/soup-websocket.c:374 +#, c-format +msgid "Incorrect WebSocket “%s” header" +msgstr "Cabeceira «%s» WebSocket incorrecta" + +#: ../libsoup/soup-websocket.c:383 +msgid "Unsupported WebSocket subprotocol" +msgstr "Subprotocolo WebSocket non compatíbel" + +#: ../libsoup/soup-websocket.c:510 +msgid "Server rejected WebSocket handshake" +msgstr "Saúdo WebSocket rexeitado polo servidor" + +#: ../libsoup/soup-websocket.c:518 ../libsoup/soup-websocket.c:527 +msgid "Server ignored WebSocket handshake" +msgstr "Saúdo WebSocket ignorado polo servidor" + +#: ../libsoup/soup-websocket.c:539 +msgid "Server requested unsupported protocol" +msgstr "Protocolo solicitado polo servidor non compatíbel" + +#: ../libsoup/soup-websocket.c:549 +msgid "Server requested unsupported extension" +msgstr "Extensión solicitado polo servidor non compatíbel" + +#: ../libsoup/soup-websocket.c:562 +#, c-format +msgid "Server returned incorrect “%s” key" +msgstr "Chave «%s» devolta polo servidor incorrecta" + +#: ../libsoup/soup-tld.c:188 +msgid "Hostname is an IP address" +msgstr "O nome do computador é un enderezo IP" + +#: ../libsoup/soup-tld.c:198 ../libsoup/soup-tld.c:220 +msgid "Invalid hostname" +msgstr "O nome do computador non é válido" + +#: ../libsoup/soup-tld.c:250 +msgid "Hostname has no base domain" +msgstr "O nome do computador non ten un dominio base" + +#: ../libsoup/soup-tld.c:304 +msgid "Not enough domains" +msgstr "Non hai dominios dabondo" diff --git a/po/gu.po b/po/gu.po new file mode 100644 index 0000000..a62920a --- /dev/null +++ b/po/gu.po @@ -0,0 +1,130 @@ +# Gujarati translation for libsoup. +# Copyright (C) 2012 libsoup's COPYRIGHT HOLDER +# This file is distributed under the same license as the libsoup package. +# +# , 2014. +msgid "" +msgstr "" +"Project-Id-Version: libsoup master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug." +"cgi?product=libsoup&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2014-09-11 21:40+0000\n" +"PO-Revision-Date: 2014-09-12 12:08+0530\n" +"Last-Translator: \n" +"Language-Team: American English \n" +"Language: gu\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Lokalize 1.0\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +#: ../libsoup/soup-body-input-stream.c:140 +#: ../libsoup/soup-body-input-stream.c:171 +#: ../libsoup/soup-body-input-stream.c:204 ../libsoup/soup-message-io.c:196 +msgid "Connection terminated unexpectedly" +msgstr "જોડાણ અનિચ્છનીય રીતે તૂટી ગયુ" + +#: ../libsoup/soup-body-input-stream.c:462 +msgid "Invalid seek request" +msgstr "અયોગ્ય સીક માંગણી" + +#: ../libsoup/soup-body-input-stream.c:490 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "SoupBodyInputStream કાઢી શકાતુ નથી" + +#: ../libsoup/soup-cache-input-stream.c:73 +msgid "Network stream unexpectedly closed" +msgstr "નેટવર્ક સ્ટ્રીમ અનિચ્છનીય રીતે બંધ થઇ ગઇ" + +#: ../libsoup/soup-cache-input-stream.c:290 +msgid "Failed to completely cache the resource" +msgstr "સ્ત્રોતને સંપૂર્ણપણે કેશ કરવામાં નિષ્ફળતા" + +#: ../libsoup/soup-converter-wrapper.c:192 +#, c-format +msgid "Output buffer is too small" +msgstr "આઉટપુટ બફર ઘણુ નાનું છે" + +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "HTTP જવાબનું પદચ્છેદન કરી શક્યા નહિં" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "બિનઓળખાયેલ HTTP જવાબ એનકોડીંગ" + +#: ../libsoup/soup-message-io.c:854 ../libsoup/soup-message-io.c:890 +msgid "Operation was cancelled" +msgstr "ક્રિયા રદ થયેલ હતી" + +#: ../libsoup/soup-message-io.c:901 +msgid "Operation would block" +msgstr "ક્રિયા રોકી રખાશે" + +#: ../libsoup/soup-message-server-io.c:41 +msgid "Could not parse HTTP request" +msgstr "HTTP માંગણીનુ પદચ્છેદન કરી શક્યા નહિં" + +#: ../libsoup/soup-request.c:140 +#, c-format +msgid "No URI provided" +msgstr "URI પૂરુ પાડેલ નથી" + +#: ../libsoup/soup-request.c:150 +#, c-format +msgid "Invalid '%s' URI: %s" +msgstr "અમાન્ય '%s' URI: %s" + +#: ../libsoup/soup-server.c:1528 +msgid "Can't create a TLS server without a TLS certificate" +msgstr "TLS પ્રમાણપત્ર વગર TLS સર્વરને બનાવી શકાતુ નથી" + +#: ../libsoup/soup-server.c:1547 +#, c-format +msgid "Could not listen on address %s, port %d: " +msgstr "સરનામાં %s પર સાંભળી શક્યા નહિં, પોર્ટ %d: " + +#: ../libsoup/soup-session.c:4466 +#, c-format +msgid "Could not parse URI '%s'" +msgstr "URI '%s' ને પદચ્છેદન કરી શક્યા નહિં" + +#: ../libsoup/soup-session.c:4503 +#, c-format +msgid "Unsupported URI scheme '%s'" +msgstr "બિનઆધારભૂત URI યોજના '%s'" + +#: ../libsoup/soup-session.c:4525 +#, c-format +msgid "Not an HTTP URI" +msgstr "HTTP URI નથી" + +#: ../libsoup/soup-socket.c:142 +msgid "Can't import non-socket as SoupSocket" +msgstr "SoupSocket તરીકે બિન-સોકેટને આયાત કરી શકાતુ નથી" + +#: ../libsoup/soup-socket.c:160 +msgid "Could not import existing socket: " +msgstr "હાલનાં સોકેટને આયાત કરી શક્યા નહિં: " + +#: ../libsoup/soup-socket.c:169 +msgid "Can't import unconnected socket" +msgstr "બિનજોડાયેલ સોકેટને આયાત કરી શકાતુ નથી" + +#: ../libsoup/soup-tld.c:188 +msgid "Hostname is an IP address" +msgstr "યજમાનનામ એ IP સરનામું છે" + +#: ../libsoup/soup-tld.c:198 ../libsoup/soup-tld.c:220 +msgid "Invalid hostname" +msgstr "અમાન્ય યજમાનનામ" + +#: ../libsoup/soup-tld.c:250 +msgid "Hostname has no base domain" +msgstr "યજમાન પાસે મૂળ ડોમેઇન નથી" + +#: ../libsoup/soup-tld.c:304 +msgid "Not enough domains" +msgstr "પૂરતુ ડોમેઇન નથી" + diff --git a/po/he.po b/po/he.po new file mode 100644 index 0000000..6bfc594 --- /dev/null +++ b/po/he.po @@ -0,0 +1,178 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# Yosef Or Boczko , 2014. +# +msgid "" +msgstr "" +"Project-Id-Version: libsoup gnome\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-11-17 22:36+0200\n" +"PO-Revision-Date: 2016-11-17 22:38+0200\n" +"Last-Translator: Yosef Or Boczko \n" +"Language-Team: עברית <>\n" +"Language: he\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Poedit-Language: Hebrew\n" +"X-Poedit-Country: ISRAEL\n" +"X-Poedit-SourceCharset: utf-8\n" +"X-Generator: Gtranslator 2.91.6\n" + +#: ../libsoup/soup-body-input-stream.c:139 +#: ../libsoup/soup-body-input-stream.c:170 +#: ../libsoup/soup-body-input-stream.c:203 ../libsoup/soup-message-io.c:235 +msgid "Connection terminated unexpectedly" +msgstr "החיבור הופסק באופן בלתי צפוי" + +#: ../libsoup/soup-body-input-stream.c:459 +msgid "Invalid seek request" +msgstr "בקשת חיפוש שגויה" + +#: ../libsoup/soup-body-input-stream.c:487 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "לא ניתן לקצץ את SoupBodyInputStream" + +#: ../libsoup/soup-cache-input-stream.c:76 +msgid "Network stream unexpectedly closed" +msgstr "תזרים הרשת נסגר בפתאומיות" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "שמירת המשאב במלואו במטמון נכשלה" + +#: ../libsoup/soup-converter-wrapper.c:189 +#, c-format +msgid "Output buffer is too small" +msgstr "אוגר הפלט קטן מדי" + +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "לא ניתן לנתח את תגובת ה־HTTP" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "קידוד תגובת ה־HTTP אינו מוכר" + +#: ../libsoup/soup-message-io.c:392 ../libsoup/soup-message-io.c:1020 +msgid "Operation would block" +msgstr "הפעולה תיחסם" + +#: ../libsoup/soup-message-io.c:972 ../libsoup/soup-message-io.c:1005 +msgid "Operation was cancelled" +msgstr "הפעולה בוטלה" + +#: ../libsoup/soup-message-server-io.c:64 +msgid "Could not parse HTTP request" +msgstr "לא ניתן לנתח את תגובת ה־HTTP" + +#: ../libsoup/soup-request.c:140 +#, c-format +msgid "No URI provided" +msgstr "לא סופקה כתובת" + +#: ../libsoup/soup-request.c:150 +#, c-format +msgid "Invalid “%s” URI: %s" +msgstr "כתובת „%s” שגויה: %s" + +#: ../libsoup/soup-server.c:1727 +msgid "Can’t create a TLS server without a TLS certificate" +msgstr "לא ניתן ליצור שרות TLS ללא תעודת TLS" + +#: ../libsoup/soup-server.c:1744 +#, c-format +msgid "Could not listen on address %s, port %d: " +msgstr "לא ניתן להאזין לכתובת %s, פתחה %d:" + +#: ../libsoup/soup-session.c:4525 +#, c-format +msgid "Could not parse URI “%s”" +msgstr "לא ניתן לנתח את הכתובת „%s”" + +#: ../libsoup/soup-session.c:4562 +#, c-format +msgid "Unsupported URI scheme “%s”" +msgstr "תבנית הכתובת אינה נתמכת „%s”" + +#: ../libsoup/soup-session.c:4584 +#, c-format +msgid "Not an HTTP URI" +msgstr "כתובת שאינה HTTP" + +#: ../libsoup/soup-session.c:4770 +msgid "The server did not accept the WebSocket handshake." +msgstr "השרת לא קיבל את לחיצת היד של ה־WebSocket" + +#: ../libsoup/soup-socket.c:148 +msgid "Can’t import non-socket as SoupSocket" +msgstr "לא ניתן לייבא לא-שקע כ־SoupSocket" + +#: ../libsoup/soup-socket.c:166 +msgid "Could not import existing socket: " +msgstr "לא ניתן לייבא שקע קיים:" + +#: ../libsoup/soup-socket.c:175 +msgid "Can’t import unconnected socket" +msgstr "לא ניתן לייבא שקע לא מחובר" + +#: ../libsoup/soup-websocket.c:338 ../libsoup/soup-websocket.c:347 +msgid "WebSocket handshake expected" +msgstr "צפויה לחיצת יד מה־WebSocket" + +#: ../libsoup/soup-websocket.c:355 +msgid "Unsupported WebSocket version" +msgstr "גרסת WebSocket לא נתמכת" + +#: ../libsoup/soup-websocket.c:364 +msgid "Invalid WebSocket key" +msgstr "מפתח WebSocket לא חוקי" + +#: ../libsoup/soup-websocket.c:374 +#, c-format +msgid "Incorrect WebSocket “%s” header" +msgstr "כותר WebSocket ‏„%s” שגוי" + +#: ../libsoup/soup-websocket.c:383 +msgid "Unsupported WebSocket subprotocol" +msgstr "פרוטוקול WebSocket לא נתמך" + +#: ../libsoup/soup-websocket.c:510 +msgid "Server rejected WebSocket handshake" +msgstr "השרת דחה את לחיצת היד של ה־WebSocket" + +#: ../libsoup/soup-websocket.c:518 ../libsoup/soup-websocket.c:527 +msgid "Server ignored WebSocket handshake" +msgstr "השרת התעלם מלחיצת היד של ה־WebSocket" + +#: ../libsoup/soup-websocket.c:539 +msgid "Server requested unsupported protocol" +msgstr "השרת דורש פרוטוקול לא נתמך" + +#: ../libsoup/soup-websocket.c:549 +msgid "Server requested unsupported extension" +msgstr "השרת דורש הרחבה לא נתמכת" + +#: ../libsoup/soup-websocket.c:562 +#, c-format +msgid "Server returned incorrect “%s” key" +msgstr "השרת מחזיר מפתח „%s” שגוי" + +#: ../libsoup/soup-tld.c:188 +msgid "Hostname is an IP address" +msgstr "שם המארח הוא כתובת IP" + +#: ../libsoup/soup-tld.c:198 ../libsoup/soup-tld.c:220 +msgid "Invalid hostname" +msgstr "שם מארח שגוי" + +#: ../libsoup/soup-tld.c:250 +msgid "Hostname has no base domain" +msgstr "לשם המארח אין שם מתחם בסיסי" + +#: ../libsoup/soup-tld.c:304 +msgid "Not enough domains" +msgstr "אין מספיק שמות מתחם" diff --git a/po/hi.po b/po/hi.po new file mode 100644 index 0000000..cff07c6 --- /dev/null +++ b/po/hi.po @@ -0,0 +1,133 @@ +# Hindi translation for libsoup. +# Copyright (C) 2012 libsoup's COPYRIGHT HOLDER +# This file is distributed under the same license as the libsoup package. +# 1 <1>, 2012. +# 1 Pratibha kumari <1pratibharoshan1526@gmail.com>, 2012. +# raj , 2013. +# rajesh , 2014. +msgid "" +msgstr "" +"Project-Id-Version: libsoup master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2014-09-19 21:50+0000\n" +"PO-Revision-Date: 2014-09-22 15:47+0630\n" +"Last-Translator: rajesh \n" +"Language-Team: Hindi \n" +"Language: hi\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Lokalize 1.5\n" +"X-Project-Style: gnome\n" + +#: ../libsoup/soup-body-input-stream.c:140 +#: ../libsoup/soup-body-input-stream.c:171 +#: ../libsoup/soup-body-input-stream.c:204 ../libsoup/soup-message-io.c:196 +msgid "Connection terminated unexpectedly" +msgstr "मिलाप अनपेक्षित रुप से खतम हो गया " + +#: ../libsoup/soup-body-input-stream.c:462 +msgid "Invalid seek request" +msgstr "अमान्य खोज अनुरोध" + +#: ../libsoup/soup-body-input-stream.c:490 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "SoupBodyInputStream का नहीं कर सकता" + +#: ../libsoup/soup-cache-input-stream.c:73 +msgid "Network stream unexpectedly closed" +msgstr "संजाल स्ट्रीम अप्रत्याशित रूप से बंद हो गया" + +#: ../libsoup/soup-cache-input-stream.c:290 +msgid "Failed to completely cache the resource" +msgstr "संसाधन को पूरी तरह कैश करने में विफल" + +#: ../libsoup/soup-converter-wrapper.c:192 +#, c-format +msgid "Output buffer is too small" +msgstr "निर्गम बफर बहुत छोटा है" + +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "HTTP अनुक्रिया विश्लेषित नहीं कर सका" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "अपरिचित HTTP अनुक्रिया एन्कोडिंग" + +#: ../libsoup/soup-message-io.c:854 ../libsoup/soup-message-io.c:890 +msgid "Operation was cancelled" +msgstr "आपरेशन रद्द कर दिया गया" + +#: ../libsoup/soup-message-io.c:901 +msgid "Operation would block" +msgstr "आपरेशन बंद हो जाएगा" + +#: ../libsoup/soup-message-server-io.c:41 +msgid "Could not parse HTTP request" +msgstr "HTTP आग्रह विश्लेषित नहीं कर सका" + +#: ../libsoup/soup-request.c:140 +#, c-format +msgid "No URI provided" +msgstr "यूआरआई नहीं प्रदान किया गया" + +#: ../libsoup/soup-request.c:150 +#, c-format +msgid "Invalid '%s' URI: %s" +msgstr "यूआरआई '%s' अमान्य: %s" + +#: ../libsoup/soup-server.c:1528 +msgid "Can't create a TLS server without a TLS certificate" +msgstr "TLS सर्वर को बिना TLS प्रमाणपत्र के बना नहीं सकता है" + +#: ../libsoup/soup-server.c:1547 +#, c-format +msgid "Could not listen on address %s, port %d: " +msgstr "पता %s, पोर्ट %d पर सुन नहीं सकता है: " + +#: ../libsoup/soup-session.c:4466 +#, c-format +msgid "Could not parse URI '%s'" +msgstr "URI '%s' पद व्याख्या नहीं हो सका" + +#: ../libsoup/soup-session.c:4503 +#, c-format +msgid "Unsupported URI scheme '%s'" +msgstr "URI योजना '%s' को सहारा नहीं" + +#: ../libsoup/soup-session.c:4525 +#, c-format +msgid "Not an HTTP URI" +msgstr "कोई HTTP URI नहीं" + +#: ../libsoup/soup-socket.c:142 +msgid "Can't import non-socket as SoupSocket" +msgstr "सूपसॉकेट के रूप में आयात नहीं कर सकता है" + +#: ../libsoup/soup-socket.c:160 +msgid "Could not import existing socket: " +msgstr "मौजूदा सॉकेट आयात नहीं कर सकता है: " + +#: ../libsoup/soup-socket.c:169 +msgid "Can't import unconnected socket" +msgstr "बिना कनेक्टेड सॉकेट आयात नहीं कर सकता है" + +#: ../libsoup/soup-tld.c:188 +msgid "Hostname is an IP address" +msgstr "मेजबाननाम एक आईपी पता है" + +#: ../libsoup/soup-tld.c:198 ../libsoup/soup-tld.c:220 +msgid "Invalid hostname" +msgstr "मेजबाननाम मान्य नहीं" + +#: ../libsoup/soup-tld.c:250 +msgid "Hostname has no base domain" +msgstr "मेजबाननाम को आधार डोमेन नहीं है" + +#: ../libsoup/soup-tld.c:304 +msgid "Not enough domains" +msgstr "डोमेन पर्याप्त नहीं" + diff --git a/po/hr.po b/po/hr.po new file mode 100644 index 0000000..57112e0 --- /dev/null +++ b/po/hr.po @@ -0,0 +1,178 @@ +# Croatian translation for libsoup2.4 +# Copyright (c) 2018 Rosetta Contributors and Canonical Ltd 2018 +# This file is distributed under the same license as the libsoup2.4 package. +# FIRST AUTHOR , 2018. +# +msgid "" +msgstr "" +"Project-Id-Version: libsoup2.4\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2018-03-12 23:01+0000\n" +"PO-Revision-Date: 2018-03-17 19:30+0100\n" +"Last-Translator: gogo \n" +"Language-Team: Croatian \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2018-03-17 18:28+0000\n" +"X-Generator: Poedit 2.0.6\n" +"Language: hr\n" + +#: ../libsoup/soup-body-input-stream.c:139 +#: ../libsoup/soup-body-input-stream.c:170 +#: ../libsoup/soup-body-input-stream.c:203 ../libsoup/soup-message-io.c:238 +msgid "Connection terminated unexpectedly" +msgstr "Povezivanje je neočekivano prekinuto" + +#: ../libsoup/soup-body-input-stream.c:459 +msgid "Invalid seek request" +msgstr "Neispravan zahtjev pretraživanja" + +#: ../libsoup/soup-body-input-stream.c:487 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "Nemoguće skaratiti SoupBodyInputStream" + +#: ../libsoup/soup-cache-input-stream.c:76 +msgid "Network stream unexpectedly closed" +msgstr "Mrežno strujanje je neočekivano zatvoreno" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "Neuspjelo potpuno međuspremanje resursa" + +#: ../libsoup/soup-converter-wrapper.c:189 +#, c-format +msgid "Output buffer is too small" +msgstr "Izlazni međuspremnik je premali" + +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "Nemoguća obrada HTTP odgovora" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "Nepoznato kôdiranje HTTP odgovora" + +#: ../libsoup/soup-message-io.c:263 +msgid "Header too big" +msgstr "Zaglavlje je preveliko" + +#: ../libsoup/soup-message-io.c:396 ../libsoup/soup-message-io.c:1024 +msgid "Operation would block" +msgstr "Radnja će blokirati" + +#: ../libsoup/soup-message-io.c:976 ../libsoup/soup-message-io.c:1009 +msgid "Operation was cancelled" +msgstr "Radnja je prekinuta" + +#: ../libsoup/soup-message-server-io.c:64 +msgid "Could not parse HTTP request" +msgstr "Nemoguća obrada HTTP zahtjeva" + +#: ../libsoup/soup-request.c:141 +#, c-format +msgid "No URI provided" +msgstr "Nema pruženog URI-ja" + +#: ../libsoup/soup-request.c:151 +#, c-format +msgid "Invalid “%s” URI: %s" +msgstr "Neispravno “%s” URI: %s" + +#: ../libsoup/soup-server.c:1725 +msgid "Can’t create a TLS server without a TLS certificate" +msgstr "Nemoguće stvaranje TLS poslužitelja bez TLS vjerodajnice" + +#: ../libsoup/soup-server.c:1742 +#, c-format +msgid "Could not listen on address %s, port %d: " +msgstr "Nemoguće osluškivanje adrese %s, ulaz %d: " + +#: ../libsoup/soup-session.c:4524 +#, c-format +msgid "Could not parse URI “%s”" +msgstr "Nemoguća obrada URI-ja “%s”" + +#: ../libsoup/soup-session.c:4561 +#, c-format +msgid "Unsupported URI scheme “%s”" +msgstr "Nepodržana URI shema “%s”" + +#: ../libsoup/soup-session.c:4583 +#, c-format +msgid "Not an HTTP URI" +msgstr "Nije HTTP URI" + +#: ../libsoup/soup-session.c:4781 +msgid "The server did not accept the WebSocket handshake." +msgstr "Poslužitelj ne prihvaća WebSocket rukovanje." + +#: ../libsoup/soup-socket.c:148 +msgid "Can’t import non-socket as SoupSocket" +msgstr "Nemoguće prihvaćanje nepriključnice bez SoupSocketa" + +#: ../libsoup/soup-socket.c:166 +msgid "Could not import existing socket: " +msgstr "Nemoguć uvoz postojeće priključnice: " + +#: ../libsoup/soup-socket.c:175 +msgid "Can’t import unconnected socket" +msgstr "Nemoguć uvoz nepovezane priključnice" + +#: ../libsoup/soup-websocket.c:338 ../libsoup/soup-websocket.c:347 +msgid "WebSocket handshake expected" +msgstr "WebSocket rukovanje je očekivano" + +#: ../libsoup/soup-websocket.c:355 +msgid "Unsupported WebSocket version" +msgstr "Nepodržana WebSocket inačica" + +#: ../libsoup/soup-websocket.c:364 +msgid "Invalid WebSocket key" +msgstr "Neispravan WebSocket ključ" + +#: ../libsoup/soup-websocket.c:374 +#, c-format +msgid "Incorrect WebSocket “%s” header" +msgstr "Neispravno WebSocket “%s” zaglavlje" + +#: ../libsoup/soup-websocket.c:383 +msgid "Unsupported WebSocket subprotocol" +msgstr "Nepodržan WebSocket podprotokol" + +#: ../libsoup/soup-websocket.c:510 +msgid "Server rejected WebSocket handshake" +msgstr "Posljužitelj je odbio WebSocket rukovanje" + +#: ../libsoup/soup-websocket.c:518 ../libsoup/soup-websocket.c:527 +msgid "Server ignored WebSocket handshake" +msgstr "Posljužitelj je zanemario WebSocket rukovanje" + +#: ../libsoup/soup-websocket.c:539 +msgid "Server requested unsupported protocol" +msgstr "Poslužitelj je zahtijevao nepodržani protokol" + +#: ../libsoup/soup-websocket.c:549 +msgid "Server requested unsupported extension" +msgstr "Poslužitelj je zahtijevao nepodržano proširenje" + +#: ../libsoup/soup-websocket.c:562 +#, c-format +msgid "Server returned incorrect “%s” key" +msgstr "Poslužitelj je vratio neispravni “%s” ključ" + +#: ../libsoup/soup-tld.c:187 +msgid "Hostname is an IP address" +msgstr "Naziv poslužitelja je IP adresa" + +#: ../libsoup/soup-tld.c:197 ../libsoup/soup-tld.c:219 +msgid "Invalid hostname" +msgstr "Neispravan naziv poslužitelja" + +#: ../libsoup/soup-tld.c:249 +msgid "Hostname has no base domain" +msgstr "Naziv poslužitelja nema osnovnu domenu" + +#: ../libsoup/soup-tld.c:303 +msgid "Not enough domains" +msgstr "Nedovoljno domena" diff --git a/po/hu.po b/po/hu.po new file mode 100644 index 0000000..bd9561f --- /dev/null +++ b/po/hu.po @@ -0,0 +1,181 @@ +# Hungarian translation for libsoup. +# Copyright (C) 2012, 2013, 2014, 2015, 2016, 2018 Free Software Foundation, Inc. +# This file is distributed under the same license as the libsoup package. +# +# Gabor Kelemen , 2012, 2016. +# Balázs Úr , 2013, 2014, 2015, 2018. +msgid "" +msgstr "" +"Project-Id-Version: libsoup master\n" +"Report-Msgid-Bugs-To: https://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=Misc\n" +"POT-Creation-Date: 2018-02-09 14:43+0000\n" +"PO-Revision-Date: 2018-02-23 23:51+0100\n" +"Last-Translator: Balázs Úr \n" +"Language-Team: Hungarian \n" +"Language: hu\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Lokalize 1.2\n" + +#: ../libsoup/soup-body-input-stream.c:139 +#: ../libsoup/soup-body-input-stream.c:170 +#: ../libsoup/soup-body-input-stream.c:203 ../libsoup/soup-message-io.c:238 +msgid "Connection terminated unexpectedly" +msgstr "Kapcsolat váratlanul megszakítva" + +#: ../libsoup/soup-body-input-stream.c:459 +msgid "Invalid seek request" +msgstr "Érvénytelen pozicionálási kérés" + +#: ../libsoup/soup-body-input-stream.c:487 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "A SoupBodyInputStream nem csonkítható" + +#: ../libsoup/soup-cache-input-stream.c:76 +msgid "Network stream unexpectedly closed" +msgstr "Az hálózati adatfolyam váratlanul lezárult" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "Nem sikerült teljesen gyorsítótárazni az erőforrást" + +#: ../libsoup/soup-converter-wrapper.c:189 +#, c-format +msgid "Output buffer is too small" +msgstr "A kimeneti puffer túl kicsi" + +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "Nem dolgozható fel a HTTP válasz" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "Ismeretlen HTTP válasz kódolás" + +#: ../libsoup/soup-message-io.c:263 +msgid "Header too big" +msgstr "A fejléc túl nagy" + +#: ../libsoup/soup-message-io.c:396 ../libsoup/soup-message-io.c:1024 +msgid "Operation would block" +msgstr "A művelet blokkoló lenne" + +#: ../libsoup/soup-message-io.c:976 ../libsoup/soup-message-io.c:1009 +msgid "Operation was cancelled" +msgstr "A művelet megszakítva" + +#: ../libsoup/soup-message-server-io.c:64 +msgid "Could not parse HTTP request" +msgstr "Nem dolgozható fel a HTTP kérés" + +#: ../libsoup/soup-request.c:141 +#, c-format +msgid "No URI provided" +msgstr "Nincs megadva URI" + +#: ../libsoup/soup-request.c:151 +#, c-format +msgid "Invalid “%s” URI: %s" +msgstr "Érvénytelen „%s” URI: „%s”" + +#: ../libsoup/soup-server.c:1725 +msgid "Can’t create a TLS server without a TLS certificate" +msgstr "Nem lehet TLS kiszolgálót létrehozni TLS tanúsítvány nélkül" + +#: ../libsoup/soup-server.c:1742 +#, c-format +msgid "Could not listen on address %s, port %d: " +msgstr "Nem sikerült figyelni a(z) %s címen a(z) %d. porton: " + +#: ../libsoup/soup-session.c:4524 +#, c-format +msgid "Could not parse URI “%s”" +msgstr "Nem dolgozható fel a(z) „%s” URI" + +#: ../libsoup/soup-session.c:4561 +#, c-format +msgid "Unsupported URI scheme “%s”" +msgstr "Nem támogatott URI séma: „%s”" + +#: ../libsoup/soup-session.c:4583 +#, c-format +msgid "Not an HTTP URI" +msgstr "Ez nem HTTP URI" + +#: ../libsoup/soup-session.c:4781 +msgid "The server did not accept the WebSocket handshake." +msgstr "A kiszolgáló nem fogadta el a WebSocket kézfogást." + +#: ../libsoup/soup-socket.c:148 +msgid "Can’t import non-socket as SoupSocket" +msgstr "Nem lehet egy foglalattól eltérőt SoupSocket-ként importálni" + +#: ../libsoup/soup-socket.c:166 +msgid "Could not import existing socket: " +msgstr "Nem sikerült a meglévő foglalat importálása: " + +#: ../libsoup/soup-socket.c:175 +msgid "Can’t import unconnected socket" +msgstr "Nem lehet importálni a nem csatlakoztatott foglalatot" + +#: ../libsoup/soup-websocket.c:338 ../libsoup/soup-websocket.c:347 +msgid "WebSocket handshake expected" +msgstr "WebSocket kézfogást várt" + +#: ../libsoup/soup-websocket.c:355 +msgid "Unsupported WebSocket version" +msgstr "Nem támogatott WebSocket verzió" + +#: ../libsoup/soup-websocket.c:364 +msgid "Invalid WebSocket key" +msgstr "Érvénytelen WebSocket kulcs" + +#: ../libsoup/soup-websocket.c:374 +#, c-format +msgid "Incorrect WebSocket “%s” header" +msgstr "Helytelen „%s” WebSocket fejléc" + +#: ../libsoup/soup-websocket.c:383 +msgid "Unsupported WebSocket subprotocol" +msgstr "Nem támogatott WebSocket alprotokoll" + +#: ../libsoup/soup-websocket.c:510 +msgid "Server rejected WebSocket handshake" +msgstr "A kiszolgáló visszautasította a WebSocket kézfogást" + +#: ../libsoup/soup-websocket.c:518 ../libsoup/soup-websocket.c:527 +msgid "Server ignored WebSocket handshake" +msgstr "A kiszolgáló mellőzte a WebSocket kézfogást" + +#: ../libsoup/soup-websocket.c:539 +msgid "Server requested unsupported protocol" +msgstr "A kiszolgáló nem támogatott protokollt kért" + +#: ../libsoup/soup-websocket.c:549 +msgid "Server requested unsupported extension" +msgstr "A kiszolgáló nem támogatott kiterjesztést kért" + +#: ../libsoup/soup-websocket.c:562 +#, c-format +msgid "Server returned incorrect “%s” key" +msgstr "A kiszolgáló helytelen „%s” kulccsal tért vissza" + +#: ../libsoup/soup-tld.c:188 +msgid "Hostname is an IP address" +msgstr "A gépnév egy IP-cím" + +#: ../libsoup/soup-tld.c:198 ../libsoup/soup-tld.c:220 +msgid "Invalid hostname" +msgstr "Érvénytelen gépnév" + +#: ../libsoup/soup-tld.c:250 +msgid "Hostname has no base domain" +msgstr "A gépnévnek nincs alap tartománya" + +#: ../libsoup/soup-tld.c:304 +msgid "Not enough domains" +msgstr "Nincs elég tartomány" + diff --git a/po/id.po b/po/id.po new file mode 100644 index 0000000..3707411 --- /dev/null +++ b/po/id.po @@ -0,0 +1,180 @@ +# Indonesian translation for libsoup. +# Copyright (C) 2012 libsoup's COPYRIGHT HOLDER +# This file is distributed under the same license as the libsoup package. +# +# Andika Triwidada , 2012, 2015. +# Dirgita , 2012, 2013. +msgid "" +msgstr "" +"Project-Id-Version: libsoup master\n" +"Report-Msgid-Bugs-To: https://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=Misc\n" +"POT-Creation-Date: 2018-02-09 14:43+0000\n" +"PO-Revision-Date: 2018-02-11 20:48+0700\n" +"Last-Translator: Andika Triwidada \n" +"Language-Team: Indonesian \n" +"Language: id\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 1.8.11\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#: ../libsoup/soup-body-input-stream.c:139 +#: ../libsoup/soup-body-input-stream.c:170 +#: ../libsoup/soup-body-input-stream.c:203 ../libsoup/soup-message-io.c:238 +msgid "Connection terminated unexpectedly" +msgstr "Sambungan terputus secara tak diharapkan" + +#: ../libsoup/soup-body-input-stream.c:459 +msgid "Invalid seek request" +msgstr "Permintaan seek yang tak valid" + +#: ../libsoup/soup-body-input-stream.c:487 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "Tak bisa memenggal SoupBodyInputStream" + +#: ../libsoup/soup-cache-input-stream.c:76 +msgid "Network stream unexpectedly closed" +msgstr "Lalu lintas jaringan putus tak terduga" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "Gagal melengkapi tembolok sumber" + +#: ../libsoup/soup-converter-wrapper.c:189 +#, c-format +msgid "Output buffer is too small" +msgstr "Penyangga keluaran terlalu kecil" + +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "Tak dapat mengurai tanggapan HTTP" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "Enkode tanggapan HTTP tak dikenal" + +#: ../libsoup/soup-message-io.c:263 +msgid "Header too big" +msgstr "Header terlalu besar" + +#: ../libsoup/soup-message-io.c:396 ../libsoup/soup-message-io.c:1024 +msgid "Operation would block" +msgstr "Operasi akan memblokir" + +#: ../libsoup/soup-message-io.c:976 ../libsoup/soup-message-io.c:1009 +msgid "Operation was cancelled" +msgstr "Operasi dibatalkan" + +#: ../libsoup/soup-message-server-io.c:64 +msgid "Could not parse HTTP request" +msgstr "Tak dapat mengurai permintaan HTTP" + +#: ../libsoup/soup-request.c:141 +#, c-format +msgid "No URI provided" +msgstr "URI tak diberikan" + +#: ../libsoup/soup-request.c:151 +#, c-format +msgid "Invalid “%s” URI: %s" +msgstr "URI \"%s\" tak valid: %s" + +#: ../libsoup/soup-server.c:1725 +msgid "Can’t create a TLS server without a TLS certificate" +msgstr "Tak bisa membuat sebuah server TLS tanpa suatu sertifikat TLS" + +#: ../libsoup/soup-server.c:1742 +#, c-format +msgid "Could not listen on address %s, port %d: " +msgstr "Tak bisa mendengar pada alamat %s, port %d: " + +#: ../libsoup/soup-session.c:4524 +#, c-format +msgid "Could not parse URI “%s”" +msgstr "Tak bisa mengurai URI \"%s\"" + +#: ../libsoup/soup-session.c:4561 +#, c-format +msgid "Unsupported URI scheme “%s”" +msgstr "Skema URI \"%s\" tak didukung" + +#: ../libsoup/soup-session.c:4583 +#, c-format +msgid "Not an HTTP URI" +msgstr "Bukan URI HTTP" + +#: ../libsoup/soup-session.c:4781 +msgid "The server did not accept the WebSocket handshake." +msgstr "Server tak menerima jabat tangan WebSocket." + +#: ../libsoup/soup-socket.c:148 +msgid "Can’t import non-socket as SoupSocket" +msgstr "Tak bisa mengimpor non-soket sebagai SoupSocket" + +#: ../libsoup/soup-socket.c:166 +msgid "Could not import existing socket: " +msgstr "Tak dapat mengimpor soket yang telah ada: " + +#: ../libsoup/soup-socket.c:175 +msgid "Can’t import unconnected socket" +msgstr "Tak bisa mengimpor soket yang tak tersambung" + +#: ../libsoup/soup-websocket.c:338 ../libsoup/soup-websocket.c:347 +msgid "WebSocket handshake expected" +msgstr "Jabat tangan WebSocket diharapkan" + +#: ../libsoup/soup-websocket.c:355 +msgid "Unsupported WebSocket version" +msgstr "Versi WebSocket tak didukung" + +#: ../libsoup/soup-websocket.c:364 +msgid "Invalid WebSocket key" +msgstr "Kunci WebSocket tak valid" + +#: ../libsoup/soup-websocket.c:374 +#, c-format +msgid "Incorrect WebSocket “%s” header" +msgstr "Kepala WebSocket \"%s\" salah" + +#: ../libsoup/soup-websocket.c:383 +msgid "Unsupported WebSocket subprotocol" +msgstr "Subprotokol WebSocket tak didukung" + +#: ../libsoup/soup-websocket.c:510 +msgid "Server rejected WebSocket handshake" +msgstr "Server menolak jabat tangan WebSocket" + +#: ../libsoup/soup-websocket.c:518 ../libsoup/soup-websocket.c:527 +msgid "Server ignored WebSocket handshake" +msgstr "Server mengabaikan jabat tangan WebSocket" + +#: ../libsoup/soup-websocket.c:539 +msgid "Server requested unsupported protocol" +msgstr "Server meminta protokol yang tak didukung" + +#: ../libsoup/soup-websocket.c:549 +msgid "Server requested unsupported extension" +msgstr "Server meminta ekstensi yang tak didukung" + +#: ../libsoup/soup-websocket.c:562 +#, c-format +msgid "Server returned incorrect “%s” key" +msgstr "Server mengembalikan kunci \"%s\" yang salah" + +#: ../libsoup/soup-tld.c:188 +msgid "Hostname is an IP address" +msgstr "Nama host adalah suatu alamat IP" + +#: ../libsoup/soup-tld.c:198 ../libsoup/soup-tld.c:220 +msgid "Invalid hostname" +msgstr "Nama host tak valid" + +#: ../libsoup/soup-tld.c:250 +msgid "Hostname has no base domain" +msgstr "Nama host tidak memiliki domain dasar" + +#: ../libsoup/soup-tld.c:304 +msgid "Not enough domains" +msgstr "Tak cukup domain" diff --git a/po/it.po b/po/it.po new file mode 100644 index 0000000..8481f1f --- /dev/null +++ b/po/it.po @@ -0,0 +1,179 @@ +# Italian translations for libsoup package +# Copyright (C) 2012, 2013, 2014, 2015, 2017, 2018 the Free Software Foundation, Inc. +# This file is distributed under the same license as the libsoup package. +# Milo Casagrande , 2012, 2013, 2014, 2015, 2017, 2018. +# +msgid "" +msgstr "" +"Project-Id-Version: libsoup\n" +"Report-Msgid-Bugs-To: https://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=Misc\n" +"POT-Creation-Date: 2018-02-09 14:43+0000\n" +"PO-Revision-Date: 2018-02-09 16:37+0100\n" +"Last-Translator: Milo Casagrande \n" +"Language-Team: Italian \n" +"Language: it\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n!=1);\n" +"X-Generator: Poedit 2.0.4\n" + +#: ../libsoup/soup-body-input-stream.c:139 +#: ../libsoup/soup-body-input-stream.c:170 +#: ../libsoup/soup-body-input-stream.c:203 ../libsoup/soup-message-io.c:238 +msgid "Connection terminated unexpectedly" +msgstr "Connessione terminata inaspettatamente" + +#: ../libsoup/soup-body-input-stream.c:459 +msgid "Invalid seek request" +msgstr "Richiesta di posizionamento non valida" + +#: ../libsoup/soup-body-input-stream.c:487 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "Impossibile troncare SoupBodyInputStream" + +#: ../libsoup/soup-cache-input-stream.c:76 +msgid "Network stream unexpectedly closed" +msgstr "Flusso di rete chiuso inaspettatamente" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "Salvataggio in memoria della risorsa non riuscito" + +#: ../libsoup/soup-converter-wrapper.c:189 +#, c-format +msgid "Output buffer is too small" +msgstr "Il buffer di uscita è troppo piccolo" + +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "Impossibile analizzare la risposta HTTP" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "Codifica risposta HTTP non riconosciuta" + +#: ../libsoup/soup-message-io.c:263 +msgid "Header too big" +msgstr "Intestazione troppo grande" + +#: ../libsoup/soup-message-io.c:396 ../libsoup/soup-message-io.c:1024 +msgid "Operation would block" +msgstr "L'operazione potrebbe bloccarsi" + +#: ../libsoup/soup-message-io.c:976 ../libsoup/soup-message-io.c:1009 +msgid "Operation was cancelled" +msgstr "L'operazione è stata annullata" + +#: ../libsoup/soup-message-server-io.c:64 +msgid "Could not parse HTTP request" +msgstr "Impossibile analizzare la richiesta HTTP" + +#: ../libsoup/soup-request.c:141 +#, c-format +msgid "No URI provided" +msgstr "Nessun URI fornito" + +#: ../libsoup/soup-request.c:151 +#, c-format +msgid "Invalid “%s” URI: %s" +msgstr "URI «%s» non valido: %s" + +#: ../libsoup/soup-server.c:1725 +msgid "Can’t create a TLS server without a TLS certificate" +msgstr "Impossibile creare un server TLS senza un certificato TLS" + +#: ../libsoup/soup-server.c:1742 +#, c-format +msgid "Could not listen on address %s, port %d: " +msgstr "Impossibile restare in ascolto sull'indirizzo %s, porta %d: " + +#: ../libsoup/soup-session.c:4524 +#, c-format +msgid "Could not parse URI “%s”" +msgstr "Impossibile analizzare l'URI «%s»" + +#: ../libsoup/soup-session.c:4561 +#, c-format +msgid "Unsupported URI scheme “%s”" +msgstr "Schema URI «%s» non supportato" + +#: ../libsoup/soup-session.c:4583 +#, c-format +msgid "Not an HTTP URI" +msgstr "Non è uno URI HTTP" + +#: ../libsoup/soup-session.c:4781 +msgid "The server did not accept the WebSocket handshake." +msgstr "Il server non ha accettato l'handshake WebSocket." + +#: ../libsoup/soup-socket.c:148 +msgid "Can’t import non-socket as SoupSocket" +msgstr "Impossibile importare un non-socket come SoupSocket" + +#: ../libsoup/soup-socket.c:166 +msgid "Could not import existing socket: " +msgstr "Impossibile importare il socket esistente: " + +#: ../libsoup/soup-socket.c:175 +msgid "Can’t import unconnected socket" +msgstr "Impossibile importare un socket non connesso" + +#: ../libsoup/soup-websocket.c:338 ../libsoup/soup-websocket.c:347 +msgid "WebSocket handshake expected" +msgstr "Atteso handshake WebSocket" + +#: ../libsoup/soup-websocket.c:355 +msgid "Unsupported WebSocket version" +msgstr "Version WebSocket non supportata" + +#: ../libsoup/soup-websocket.c:364 +msgid "Invalid WebSocket key" +msgstr "Chiave WebSocket non valida" + +#: ../libsoup/soup-websocket.c:374 +#, c-format +msgid "Incorrect WebSocket “%s” header" +msgstr "Intestazione WebSocket «%s» non valida" + +#: ../libsoup/soup-websocket.c:383 +msgid "Unsupported WebSocket subprotocol" +msgstr "Sotto-protocollo WebSocket non supportato" + +#: ../libsoup/soup-websocket.c:510 +msgid "Server rejected WebSocket handshake" +msgstr "Il server ha rifiutato l'handshake WebSocket" + +#: ../libsoup/soup-websocket.c:518 ../libsoup/soup-websocket.c:527 +msgid "Server ignored WebSocket handshake" +msgstr "Il server ha ignorato l'handshake WebSocket" + +#: ../libsoup/soup-websocket.c:539 +msgid "Server requested unsupported protocol" +msgstr "Il server ha richiesto un protocollo non supportato" + +#: ../libsoup/soup-websocket.c:549 +msgid "Server requested unsupported extension" +msgstr "Il server ha richiesto un'estensione non supportata" + +#: ../libsoup/soup-websocket.c:562 +#, c-format +msgid "Server returned incorrect “%s” key" +msgstr "Il server ha restituito una chiave «%s» non corretta" + +#: ../libsoup/soup-tld.c:188 +msgid "Hostname is an IP address" +msgstr "Il nome host è un indirizzo IP" + +#: ../libsoup/soup-tld.c:198 ../libsoup/soup-tld.c:220 +msgid "Invalid hostname" +msgstr "Nome host non valido" + +#: ../libsoup/soup-tld.c:250 +msgid "Hostname has no base domain" +msgstr "Il nome host non ha un dominio di base" + +#: ../libsoup/soup-tld.c:304 +msgid "Not enough domains" +msgstr "Domini insufficienti" diff --git a/po/ja.po b/po/ja.po new file mode 100644 index 0000000..795fa84 --- /dev/null +++ b/po/ja.po @@ -0,0 +1,81 @@ +# libsoup ja.po +# Copyright (C) 2012 libsoup's COPYRIGHT HOLDER +# This file is distributed under the same license as the libsoup package. +# Takayuki KUSANO , 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: libsoup master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=libsoup&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2012-11-02 19:31+0000\n" +"PO-Revision-Date: 2012-10-12 13:30+0900\n" +"Last-Translator: Takayuki KUSANO \n" +"Language-Team: Japanese \n" +"Language: ja\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: ../libsoup/soup-body-input-stream.c:141 +#: ../libsoup/soup-body-input-stream.c:172 +#: ../libsoup/soup-body-input-stream.c:205 ../libsoup/soup-message-io.c:191 +msgid "Connection terminated unexpectedly" +msgstr "接続が突然切断されました" + +#: ../libsoup/soup-body-input-stream.c:461 +msgid "Invalid seek request" +msgstr "無効な seek 要求" + +#: ../libsoup/soup-body-input-stream.c:489 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "SoupBodyInputStream は truncate できません" + +#: ../libsoup/soup-converter-wrapper.c:192 +#, c-format +msgid "Output buffer is too small" +msgstr "出力バッファーが小さすぎます" + +#: ../libsoup/soup-message-io.c:846 ../libsoup/soup-message-io.c:882 +msgid "Operation was cancelled" +msgstr "動作が中止されました" + +#: ../libsoup/soup-message-io.c:893 +msgid "Operation would block" +msgstr "動作はブロックします" + +#: ../libsoup/soup-request.c:142 +#, c-format +msgid "No URI provided" +msgstr "URI が与えられていません" + +#: ../libsoup/soup-request.c:152 +#, c-format +msgid "Invalid '%s' URI: %s" +msgstr "不正なスキーム '%s' の URI: %s" + +#: ../libsoup/soup-requester.c:219 +#, c-format +msgid "Could not parse URI '%s'" +msgstr "URI '%s' をパースできませんでした" + +#: ../libsoup/soup-requester.c:253 +#, c-format +msgid "Unsupported URI scheme '%s'" +msgstr "サポートされていない URI のスキーム '%s'" + +#: ../libsoup/soup-tld.c:154 +msgid "Hostname is an IP address" +msgstr "ホスト名が IP アドレスです" + +#: ../libsoup/soup-tld.c:175 +msgid "Invalid hostname" +msgstr "不正なホスト名です" + +#: ../libsoup/soup-tld.c:204 +msgid "Hostname has no base domain" +msgstr "ホスト名にトップレベルドメインがありません" + +# ソースコードと http://www.nic.ad.jp/ja/dom/system.html 参照 +#: ../libsoup/soup-tld.c:226 +msgid "Not enough domains" +msgstr "ドメイン名が十分な数のラベルがありません" diff --git a/po/kn.po b/po/kn.po new file mode 100644 index 0000000..e53ba24 --- /dev/null +++ b/po/kn.po @@ -0,0 +1,129 @@ +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Shankar Prasad , 2012, 2013, 2014. +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2014-09-02 09:47+0000\n" +"PO-Revision-Date: 2014-09-22 09:37+0530\n" +"Last-Translator: Shankar Prasad \n" +"Language-Team: Kannada \n" +"Language: kn\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Lokalize 1.5\n" + +#: ../libsoup/soup-body-input-stream.c:140 +#: ../libsoup/soup-body-input-stream.c:171 +#: ../libsoup/soup-body-input-stream.c:204 ../libsoup/soup-message-io.c:196 +msgid "Connection terminated unexpectedly" +msgstr "ಸಂಪರ್ಕವು ಅನಿರೀಕ್ಷಿತವಾಗಿ ಕೊನೆಗೊಂಡಿದೆ" + +#: ../libsoup/soup-body-input-stream.c:462 +msgid "Invalid seek request" +msgstr "ಅಮಾನ್ಯವಾದ ಕೋರಿಕೆಯ ಮನವಿ" + +#: ../libsoup/soup-body-input-stream.c:490 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "SoupBodyInputStream ಅನ್ನು ತುಂಡರಿಸಲಾಗಿಲ್ಲ" + +#: ../libsoup/soup-cache-input-stream.c:73 +msgid "Network stream unexpectedly closed" +msgstr "ಜಾಲಬಂಧ ಸ್ಟ್ರೀಮ್ ಅನ್ನು ಅನಿರೀಕ್ಷಿತವಾಗಿ ಮುಚ್ಚಲಾಗಿದೆ" + +#: ../libsoup/soup-cache-input-stream.c:290 +msgid "Failed to completely cache the resource" +msgstr "ಸಂಪನ್ಮೂಲವನ್ನು ಸಂಪೂರ್ಣವಾಗಿ ಕ್ಯಾಶ್ ಮಾಡುವಲ್ಲಿ ವಿಫಲಗೊಂಡಿದೆ" + +#: ../libsoup/soup-converter-wrapper.c:192 +#, c-format +msgid "Output buffer is too small" +msgstr "ಔಟ್‌ಪುಟ್ ಬಫರ್ ಬಹಳ ಚಿಕ್ಕದಾಗಿದೆ" + +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "HTTP ಪ್ರತ್ಯುತ್ತರವನ್ನು ಪಾರ್ಸ್ ಮಾಡಲಾಗಿಲ್ಲ" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "ಗುರುತಿಸಲಾಗದ HTTP ಪ್ರತಿಕ್ರಿಯೆ ಎನ್ಕೋಡಿಂಗ್" + +#: ../libsoup/soup-message-io.c:854 ../libsoup/soup-message-io.c:890 +msgid "Operation was cancelled" +msgstr "ಕಾರ್ಯಾಚರಣೆಯನ್ನು ರದ್ದುಗೊಳಿಸಲಾಗಿದೆ" + +#: ../libsoup/soup-message-io.c:901 +msgid "Operation would block" +msgstr "ಕಾರ್ಯಾಚರಣೆ ತಡೆಯಲ್ಪಡಬಹುದು" + +#: ../libsoup/soup-message-server-io.c:41 +msgid "Could not parse HTTP request" +msgstr "HTTP ಮನವಿಯನ್ನು ಪಾರ್ಸ್ ಮಾಡಲಾಗಿಲ್ಲ" + +#: ../libsoup/soup-request.c:140 +#, c-format +msgid "No URI provided" +msgstr "ಯಾವುದೆ URI ಅನ್ನು ಒದಗಿಸಲಾಗಿಲ್ಲ." + +#: ../libsoup/soup-request.c:150 +#, c-format +msgid "Invalid '%s' URI: %s" +msgstr "ಅಮಾನ್ಯವಾದ '%s' URI:'%s" + +#: ../libsoup/soup-server.c:1528 +msgid "Can't create a TLS server without a TLS certificate" +msgstr "ಒಂದು TLS ಪ್ರಮಾಣಪತ್ರವಿರದೆ TLS ಪೂರೈಕೆಗಣಕವನ್ನು ರಚಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ" + +#: ../libsoup/soup-server.c:1547 +#, c-format +msgid "Could not listen on address %s, port %d: " +msgstr "%s ವಿಳಾಸದಲ್ಲಿ, %d ಸಂಪರ್ಕಸ್ಥಾನದಲ್ಲಿ ಆಲಿಸಲು ಸಾಧ್ಯವಾಗಿಲ್ಲ:" + +#: ../libsoup/soup-session.c:4466 +#, c-format +msgid "Could not parse URI '%s'" +msgstr "'%s' URL ಅನ್ನು ಪಾರ್ಸ್ ಮಾಡಲಾಗಿಲ್ಲ" + +#: ../libsoup/soup-session.c:4503 +#, c-format +msgid "Unsupported URI scheme '%s'" +msgstr "ಬೆಂಬಲವಿಲ್ಲದ ಯುಆರ್ಐ ಮಾದರಿ '%s'" + +#: ../libsoup/soup-session.c:4525 +#, c-format +msgid "Not an HTTP URI" +msgstr "ಒಂದು HTTP URI ಅಲ್ಲ" + +#: ../libsoup/soup-socket.c:142 +msgid "Can't import non-socket as SoupSocket" +msgstr "SoupSocket ಆಗಿ ಸಾಕೆಟ್‌-ಅಲ್ಲದಿರುವುದನ್ನು ಆಮದು ಮಾಡಲು ಸಾಧ್ಯವಾಗಿಲ್ಲ" + +#: ../libsoup/soup-socket.c:160 +msgid "Could not import existing socket: " +msgstr "ಈಗಿರುವ ಸಾಕೆಟ್ ಅನ್ನು ಆಮದು ಮಾಡಲು ಸಾಧ್ಯವಾಗಿಲ್ಲ:" + +#: ../libsoup/soup-socket.c:169 +msgid "Can't import unconnected socket" +msgstr "ಸಂಪರ್ಕಜೋಡಿಸದೆ ಇರುವ ಸಾಕೆಟ್‌ ಅನ್ನು ಆಮದು ಮಾಡಲು ಸಾಧ್ಯವಾಗಿಲ್ಲ" + +#: ../libsoup/soup-tld.c:188 +msgid "Hostname is an IP address" +msgstr "ಆತಿಥೇಯವು ಒಂದು IP ವಿಳಾಸವಾಗಿದೆ" + +#: ../libsoup/soup-tld.c:198 ../libsoup/soup-tld.c:220 +msgid "Invalid hostname" +msgstr "ಅಮಾನ್ಯವಾದ ಅತಿಥೇಯದ ಹೆಸರು" + +#: ../libsoup/soup-tld.c:250 +msgid "Hostname has no base domain" +msgstr "ಆತಿಥೇಯದ ಹೆಸರಿನಲ್ಲಿ ಯಾವುದೆ ಮೂಲ ಡೊಮೈನ್ ಇಲ್ಲ" + +#: ../libsoup/soup-tld.c:304 +msgid "Not enough domains" +msgstr "ಬೇಕಾದಷ್ಟು ಡೊಮೈನ್‌ಗಳಿಲ್ಲ" + diff --git a/po/ko.po b/po/ko.po new file mode 100644 index 0000000..52982d9 --- /dev/null +++ b/po/ko.po @@ -0,0 +1,181 @@ +# Korean translation for libsoup. +# Copyright (C) 2012 libsoup's COPYRIGHT HOLDER +# This file is distributed under the same license as the libsoup package. +# +# eukim , 2012. +# Changwoo Ryu , 2013-2015, 2017-2018. +# +msgid "" +msgstr "" +"Project-Id-Version: libsoup master\n" +"Report-Msgid-Bugs-To: https://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=Misc\n" +"POT-Creation-Date: 2018-02-09 14:43+0000\n" +"PO-Revision-Date: 2018-02-23 11:27+0900\n" +"Last-Translator: Changwoo Ryu \n" +"Language-Team: Korean \n" +"Language: ko\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Lokalize 1.0\n" + +#: ../libsoup/soup-body-input-stream.c:139 +#: ../libsoup/soup-body-input-stream.c:170 +#: ../libsoup/soup-body-input-stream.c:203 ../libsoup/soup-message-io.c:238 +msgid "Connection terminated unexpectedly" +msgstr "예상치 않게 연결이 중지됨" + +#: ../libsoup/soup-body-input-stream.c:459 +msgid "Invalid seek request" +msgstr "탐색 요청이 잘못되었습니다" + +#: ../libsoup/soup-body-input-stream.c:487 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "SoupBodyInputStream을 자를 수 없습니다" + +#: ../libsoup/soup-cache-input-stream.c:76 +msgid "Network stream unexpectedly closed" +msgstr "네트워크 스트림이 예상치 못하게 닫혔습니다" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "리소스를 완전히 캐시에 저장하는데 실패했습니다" + +#: ../libsoup/soup-converter-wrapper.c:189 +#, c-format +msgid "Output buffer is too small" +msgstr "출력 버퍼가 너무 작습니다" + +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "HTTP 응답을 구문 분석할 수 없습니다" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "HTTP 응답 인코딩을 알 수 없습니다" + +#: ../libsoup/soup-message-io.c:263 +msgid "Header too big" +msgstr "헤더가 너무 큽니다" + +#: ../libsoup/soup-message-io.c:396 ../libsoup/soup-message-io.c:1024 +msgid "Operation would block" +msgstr "작업이 블럭되었습니다" + +#: ../libsoup/soup-message-io.c:976 ../libsoup/soup-message-io.c:1009 +msgid "Operation was cancelled" +msgstr "작업이 취소되었습니다" + +#: ../libsoup/soup-message-server-io.c:64 +msgid "Could not parse HTTP request" +msgstr "HTTP 요청을 구문 분석할 수 없습니다" + +#: ../libsoup/soup-request.c:141 +#, c-format +msgid "No URI provided" +msgstr "URI가 없습니다" + +#: ../libsoup/soup-request.c:151 +#, c-format +msgid "Invalid “%s” URI: %s" +msgstr "잘못된 “%s” URI: %s" + +#: ../libsoup/soup-server.c:1725 +msgid "Can’t create a TLS server without a TLS certificate" +msgstr "TLS 인증서 없이 TLS 서버를 만들 수 없습니다" + +#: ../libsoup/soup-server.c:1742 +#, c-format +msgid "Could not listen on address %s, port %d: " +msgstr "주소 %s, 포트 %d번에 연결을 받을 수 없습니다: " + +#: ../libsoup/soup-session.c:4524 +#, c-format +msgid "Could not parse URI “%s”" +msgstr "“%s” URI를 구문 분석할 수 없습니다" + +#: ../libsoup/soup-session.c:4561 +#, c-format +msgid "Unsupported URI scheme “%s”" +msgstr "“%s” URI 스킴을 지원하지 않습니다" + +#: ../libsoup/soup-session.c:4583 +#, c-format +msgid "Not an HTTP URI" +msgstr "HTTP URI가 아닙니다" + +#: ../libsoup/soup-session.c:4781 +msgid "The server did not accept the WebSocket handshake." +msgstr "서버에서 웹소켓 핸드셰이크를 받아들이지 않습니다." + +#: ../libsoup/soup-socket.c:148 +msgid "Can’t import non-socket as SoupSocket" +msgstr "소켓이 아닌 핸들을 SoupSocket으로 가져올 수 없습니다" + +#: ../libsoup/soup-socket.c:166 +msgid "Could not import existing socket: " +msgstr "기존 소켓을 가져올 수 없습니다: " + +#: ../libsoup/soup-socket.c:175 +msgid "Can’t import unconnected socket" +msgstr "연결하지 않은 소켓을 가져올 수 없습니다" + +#: ../libsoup/soup-websocket.c:338 ../libsoup/soup-websocket.c:347 +msgid "WebSocket handshake expected" +msgstr "웹소켓 핸드셰이크가 와야 합니다" + +#: ../libsoup/soup-websocket.c:355 +msgid "Unsupported WebSocket version" +msgstr "웹소켓 버전을 지원하지 않습니다" + +#: ../libsoup/soup-websocket.c:364 +msgid "Invalid WebSocket key" +msgstr "웹소켓 키가 올바르지 않습니다" + +#: ../libsoup/soup-websocket.c:374 +#, c-format +msgid "Incorrect WebSocket “%s” header" +msgstr "웹소켓 “%s” 헤더가 올바르지 않습니다" + +#: ../libsoup/soup-websocket.c:383 +msgid "Unsupported WebSocket subprotocol" +msgstr "웹소켓 서브프로토콜을 지원하지 않습니다" + +#: ../libsoup/soup-websocket.c:510 +msgid "Server rejected WebSocket handshake" +msgstr "서버에서 웹소켓 핸드셰이크를 거부했습니다" + +#: ../libsoup/soup-websocket.c:518 ../libsoup/soup-websocket.c:527 +msgid "Server ignored WebSocket handshake" +msgstr "서버에서 웹소켓 핸드셰이크를 무시헀습니다" + +#: ../libsoup/soup-websocket.c:539 +msgid "Server requested unsupported protocol" +msgstr "서버에서 지원하지 않는 프로토콜을 요청했습니다" + +#: ../libsoup/soup-websocket.c:549 +msgid "Server requested unsupported extension" +msgstr "서버에서 지원하지 않는 확장 기능을 요청했습니다" + +#: ../libsoup/soup-websocket.c:562 +#, c-format +msgid "Server returned incorrect “%s” key" +msgstr "서버에서 올바르지 않은 “%s” 키를 리턴했습니다" + +#: ../libsoup/soup-tld.c:188 +msgid "Hostname is an IP address" +msgstr "호스트 이름은 IP 주소입니다" + +#: ../libsoup/soup-tld.c:198 ../libsoup/soup-tld.c:220 +msgid "Invalid hostname" +msgstr "잘못된 호스트 이름입니다" + +#: ../libsoup/soup-tld.c:250 +msgid "Hostname has no base domain" +msgstr "호스트 이름에 기본 도메인이 없습니다" + +#: ../libsoup/soup-tld.c:304 +msgid "Not enough domains" +msgstr "도메인이 충분하지 않습니다" diff --git a/po/lt.po b/po/lt.po new file mode 100644 index 0000000..d13800c --- /dev/null +++ b/po/lt.po @@ -0,0 +1,180 @@ +# Lithuanian translation for libsoup. +# Copyright (C) 2012 libsoup's COPYRIGHT HOLDER +# This file is distributed under the same license as the libsoup package. +# Aurimas Černius , 2012, 2013, 2014, 2015. +# +msgid "" +msgstr "" +"Project-Id-Version: libsoup master\n" +"Report-Msgid-Bugs-To: https://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=Misc\n" +"POT-Creation-Date: 2018-03-01 21:42+0000\n" +"PO-Revision-Date: 2018-03-02 11:59+0200\n" +"Last-Translator: Moo\n" +"Language-Team: Lietuvių \n" +"Language: lt\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n" +"%100<10 || n%100>=20) ? 1 : 2);\n" +"X-Generator: Poedit 2.0.4\n" + +#: ../libsoup/soup-body-input-stream.c:139 +#: ../libsoup/soup-body-input-stream.c:170 +#: ../libsoup/soup-body-input-stream.c:203 ../libsoup/soup-message-io.c:238 +msgid "Connection terminated unexpectedly" +msgstr "Ryšys netikėtai nutrūko" + +#: ../libsoup/soup-body-input-stream.c:459 +msgid "Invalid seek request" +msgstr "Netinkama paieškos užklausa" + +#: ../libsoup/soup-body-input-stream.c:487 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "Negalima trumpinti SoupBodyInputStream" + +#: ../libsoup/soup-cache-input-stream.c:76 +msgid "Network stream unexpectedly closed" +msgstr "Tinklo srautas netikėtai užsivėrė" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "Nepavyko visiškai patalpinti resurso į podėlį" + +#: ../libsoup/soup-converter-wrapper.c:189 +#, c-format +msgid "Output buffer is too small" +msgstr "Išvesties buferis yra per mažas" + +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "Nepavyko perskaityti URI „%s“Nepavyko perskaityti HTTP atsako" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "Neatpažinta HTTP atsako koduotė" + +#: ../libsoup/soup-message-io.c:263 +msgid "Header too big" +msgstr "Antraštė yra per didelė" + +#: ../libsoup/soup-message-io.c:396 ../libsoup/soup-message-io.c:1024 +msgid "Operation would block" +msgstr "Veiksmas blokuosis" + +#: ../libsoup/soup-message-io.c:976 ../libsoup/soup-message-io.c:1009 +msgid "Operation was cancelled" +msgstr "Veiksmas buvo nutrauktas" + +#: ../libsoup/soup-message-server-io.c:64 +msgid "Could not parse HTTP request" +msgstr "Nepavyko perskaityti HTTP užklausos" + +#: ../libsoup/soup-request.c:141 +#, c-format +msgid "No URI provided" +msgstr "Nepateiktas URI" + +#: ../libsoup/soup-request.c:151 +#, c-format +msgid "Invalid “%s” URI: %s" +msgstr "Netinkamas „%s“ URI: %s" + +#: ../libsoup/soup-server.c:1725 +msgid "Can’t create a TLS server without a TLS certificate" +msgstr "Negalima sukurti TLS serverio be TLS liudijimo" + +#: ../libsoup/soup-server.c:1742 +#, c-format +msgid "Could not listen on address %s, port %d: " +msgstr "Nepavyksta klausytis adreso %s, prievadu %d: " + +#: ../libsoup/soup-session.c:4524 +#, c-format +msgid "Could not parse URI “%s”" +msgstr "Nepavyko išanalizuoti URI „%s“" + +#: ../libsoup/soup-session.c:4561 +#, c-format +msgid "Unsupported URI scheme “%s”" +msgstr "Nepalaikoma URI schema „%s“" + +#: ../libsoup/soup-session.c:4583 +#, c-format +msgid "Not an HTTP URI" +msgstr "Ne HTTP URI" + +#: ../libsoup/soup-session.c:4781 +msgid "The server did not accept the WebSocket handshake." +msgstr "Serveris nepriėmė WebSocket rankos paspaudimo." + +#: ../libsoup/soup-socket.c:148 +msgid "Can’t import non-socket as SoupSocket" +msgstr "Negalima importuoti ne lizdo kaip SoupSocket" + +#: ../libsoup/soup-socket.c:166 +msgid "Could not import existing socket: " +msgstr "Nepavyko importuoti esamo lizdo: " + +#: ../libsoup/soup-socket.c:175 +msgid "Can’t import unconnected socket" +msgstr "Negalima importuoti neprijungto lizdo" + +#: ../libsoup/soup-websocket.c:338 ../libsoup/soup-websocket.c:347 +msgid "WebSocket handshake expected" +msgstr "Tikėtasi WebSocket rankos paspaudimo" + +#: ../libsoup/soup-websocket.c:355 +msgid "Unsupported WebSocket version" +msgstr "Nepalaikoma WebSocket versija" + +#: ../libsoup/soup-websocket.c:364 +msgid "Invalid WebSocket key" +msgstr "Netinkamas WebSocket raktas" + +#: ../libsoup/soup-websocket.c:374 +#, c-format +msgid "Incorrect WebSocket “%s” header" +msgstr "Neteisinga WebSocket „%s“ antraštė" + +#: ../libsoup/soup-websocket.c:383 +msgid "Unsupported WebSocket subprotocol" +msgstr "Nepalaikomas WebSocket paprotokolis" + +#: ../libsoup/soup-websocket.c:510 +msgid "Server rejected WebSocket handshake" +msgstr "Serveris atmetė WebSocket rankos paspaudimą" + +#: ../libsoup/soup-websocket.c:518 ../libsoup/soup-websocket.c:527 +msgid "Server ignored WebSocket handshake" +msgstr "Serveris nepaisė WebSocket rankos paspaudimo" + +#: ../libsoup/soup-websocket.c:539 +msgid "Server requested unsupported protocol" +msgstr "Serveris paprašė nepalaikomo protokolo" + +#: ../libsoup/soup-websocket.c:549 +msgid "Server requested unsupported extension" +msgstr "Serveris paprašė nepalaikomo plėtinio" + +#: ../libsoup/soup-websocket.c:562 +#, c-format +msgid "Server returned incorrect “%s” key" +msgstr "Serveris grąžino neteisingą „%s“ raktą" + +#: ../libsoup/soup-tld.c:187 +msgid "Hostname is an IP address" +msgstr "Serverio vardas arba IP adresas" + +#: ../libsoup/soup-tld.c:197 ../libsoup/soup-tld.c:219 +msgid "Invalid hostname" +msgstr "Netinkamas serverio vardas" + +#: ../libsoup/soup-tld.c:249 +msgid "Hostname has no base domain" +msgstr "Serverio vardas neturi bazinio domeno" + +#: ../libsoup/soup-tld.c:303 +msgid "Not enough domains" +msgstr "Nepakanka domenų" diff --git a/po/lv.po b/po/lv.po new file mode 100644 index 0000000..696e8af --- /dev/null +++ b/po/lv.po @@ -0,0 +1,182 @@ +# Latvian translation for libsoup. +# Copyright (C) 2012 libsoup's COPYRIGHT HOLDER +# This file is distributed under the same license as the libsoup package. +# +# Tranzistors , 2012. +# Rūdolfs Mazurs , 2012, 2013, 2014, 2016, 2017, 2018. +msgid "" +msgstr "" +"Project-Id-Version: libsoup master\n" +"Report-Msgid-Bugs-To: https://bugzilla.gnome.org/enter_bug.cgi?product=libsoup" +"&keywords=I18N+L10N&component=Misc\n" +"POT-Creation-Date: 2018-02-09 14:43+0000\n" +"PO-Revision-Date: 2018-02-24 20:14+0200\n" +"Last-Translator: Rūdolfs Mazurs \n" +"Language-Team: Latvian \n" +"Language: lv\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 :" +" 2);\n" +"X-Generator: Lokalize 2.0\n" + +#: ../libsoup/soup-body-input-stream.c:139 +#: ../libsoup/soup-body-input-stream.c:170 +#: ../libsoup/soup-body-input-stream.c:203 ../libsoup/soup-message-io.c:238 +msgid "Connection terminated unexpectedly" +msgstr "Savienojums tika negaidīti pārtraukts" + +#: ../libsoup/soup-body-input-stream.c:459 +msgid "Invalid seek request" +msgstr "Nederīgs meklēšanas pieprasījums" + +#: ../libsoup/soup-body-input-stream.c:487 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "Nevar apraut SoupBodyInputStream" + +#: ../libsoup/soup-cache-input-stream.c:76 +msgid "Network stream unexpectedly closed" +msgstr "Tīkla straume negaidīti aizvērās" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "Neizdevās resursu pilnībā noglabāt kešatmiņā" + +#: ../libsoup/soup-converter-wrapper.c:189 +#, c-format +msgid "Output buffer is too small" +msgstr "Izvades buferis ir pārāk mazs" + +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "Nevarēja parsēt HTTP atbildi" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "Neatpazīts HTTP atbildes kodējums" + +#: ../libsoup/soup-message-io.c:263 +msgid "Header too big" +msgstr "Galvene ir pārāk liela" + +#: ../libsoup/soup-message-io.c:396 ../libsoup/soup-message-io.c:1024 +msgid "Operation would block" +msgstr "Darbība bloķētu" + +#: ../libsoup/soup-message-io.c:976 ../libsoup/soup-message-io.c:1009 +msgid "Operation was cancelled" +msgstr "Darbība tika atcelta" + +#: ../libsoup/soup-message-server-io.c:64 +msgid "Could not parse HTTP request" +msgstr "Nevarēja parsēt HTTP pieprasījumu" + +#: ../libsoup/soup-request.c:141 +#, c-format +msgid "No URI provided" +msgstr "Nav sniegts URI" + +#: ../libsoup/soup-request.c:151 +#, c-format +msgid "Invalid “%s” URI: %s" +msgstr "Nederīgs “%s” URI — %s" + +#: ../libsoup/soup-server.c:1725 +msgid "Can’t create a TLS server without a TLS certificate" +msgstr "Bez TLS sertifikāta nevar izveidot TLS serveri" + +#: ../libsoup/soup-server.c:1742 +#, c-format +msgid "Could not listen on address %s, port %d: " +msgstr "Nevarēja sākt klausīties adresi %s, portu %d: " + +#: ../libsoup/soup-session.c:4524 +#, c-format +msgid "Could not parse URI “%s”" +msgstr "Nevarēja parsēt URI “%s”" + +#: ../libsoup/soup-session.c:4561 +#, c-format +msgid "Unsupported URI scheme “%s”" +msgstr "Neatbalstīta URI shēma “%s”" + +#: ../libsoup/soup-session.c:4583 +#, c-format +msgid "Not an HTTP URI" +msgstr "Nav HTTP URI" + +#: ../libsoup/soup-session.c:4781 +msgid "The server did not accept the WebSocket handshake." +msgstr "Serveris nepieņēma WebSocket rokasspiedienu." + +#: ../libsoup/soup-socket.c:148 +msgid "Can’t import non-socket as SoupSocket" +msgstr "Nevar importēt ne-ligzdu kā SoupSocket" + +#: ../libsoup/soup-socket.c:166 +msgid "Could not import existing socket: " +msgstr "Nevarēja importēt esošu ligzdu: " + +#: ../libsoup/soup-socket.c:175 +msgid "Can’t import unconnected socket" +msgstr "Nevar importēt nesavienotu ligzdu" + +#: ../libsoup/soup-websocket.c:338 ../libsoup/soup-websocket.c:347 +msgid "WebSocket handshake expected" +msgstr "WebSocket rokasspiedienam beidzās termiņš" + +#: ../libsoup/soup-websocket.c:355 +msgid "Unsupported WebSocket version" +msgstr "Neatbalstīta WebSocket versija" + +#: ../libsoup/soup-websocket.c:364 +msgid "Invalid WebSocket key" +msgstr "Nederīga WebSocket atslēga" + +#: ../libsoup/soup-websocket.c:374 +#, c-format +msgid "Incorrect WebSocket “%s” header" +msgstr "Nederīga WebSocket “%s” galvene" + +#: ../libsoup/soup-websocket.c:383 +msgid "Unsupported WebSocket subprotocol" +msgstr "Neatbalstīts WebSocket apakšprotokols" + +#: ../libsoup/soup-websocket.c:510 +msgid "Server rejected WebSocket handshake" +msgstr "Serveris noraidīja WebSocket rokasspiedienu" + +#: ../libsoup/soup-websocket.c:518 ../libsoup/soup-websocket.c:527 +msgid "Server ignored WebSocket handshake" +msgstr "Serveris ignorēja WebSocket rokasspiedienu" + +#: ../libsoup/soup-websocket.c:539 +msgid "Server requested unsupported protocol" +msgstr "Serveris pieprasīja neatbalstītu protokolu" + +#: ../libsoup/soup-websocket.c:549 +msgid "Server requested unsupported extension" +msgstr "Serveris pieprasīja neatbalstītu paplašinājumu" + +#: ../libsoup/soup-websocket.c:562 +#, c-format +msgid "Server returned incorrect “%s” key" +msgstr "Serveris atgrieza nederīgu “%s” atslēgu" + +#: ../libsoup/soup-tld.c:188 +msgid "Hostname is an IP address" +msgstr "Datora nosaukums ir IP adrese" + +#: ../libsoup/soup-tld.c:198 ../libsoup/soup-tld.c:220 +msgid "Invalid hostname" +msgstr "Nederīgs datora nosaukums" + +#: ../libsoup/soup-tld.c:250 +msgid "Hostname has no base domain" +msgstr "Datora nosaukumam nav bāzes domēna" + +#: ../libsoup/soup-tld.c:304 +msgid "Not enough domains" +msgstr "Nepietiekami daudz domēnu" + diff --git a/po/ml.po b/po/ml.po new file mode 100644 index 0000000..4b51520 --- /dev/null +++ b/po/ml.po @@ -0,0 +1,109 @@ +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# Ani Peter , 2012, 2013. +# Anish A , 2013. +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2013-03-24 12:31+0000\n" +"PO-Revision-Date: 2013-03-25 11:40+0530\n" +"Last-Translator: Ani Peter \n" +"Language-Team: American English \n" +"Language: ml\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Lokalize 1.5\n" +"X-Project-Style: gnome\n" + +#: ../libsoup/soup-body-input-stream.c:141 +#: ../libsoup/soup-body-input-stream.c:172 +#: ../libsoup/soup-body-input-stream.c:205 ../libsoup/soup-message-io.c:191 +msgid "Connection terminated unexpectedly" +msgstr "കണക്ഷന്‍ അപ്രതീക്ഷതമായി അവസാനിയ്ക്കുന്നു" + +#: ../libsoup/soup-body-input-stream.c:463 +msgid "Invalid seek request" +msgstr "തെറ്റായ തെരച്ചില്‍ ആവശ്യം" + +#: ../libsoup/soup-body-input-stream.c:491 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "SoupBodyInputStream ട്രക്കേറ്റ് ചെയ്യുവാന്‍ സാധ്യമല്ല" + +#: ../libsoup/soup-cache-input-stream.c:74 +msgid "Network stream unexpectedly closed" +msgstr "ശൃംഖല സ്ട്രീം വിചാരിക്കാതെ അടച്ചു" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "ശ്രോതസ്സ് കാഷ് ചെയ്യുന്നതു് പൂര്‍ണ്ണമായി പരാജയപ്പെട്ടു" + +#: ../libsoup/soup-converter-wrapper.c:192 +#, c-format +msgid "Output buffer is too small" +msgstr "ഔട്ട്പുട്ട് ബഫര്‍ വളരെ ചെറുതാണു്" + +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "HTTP മറുപടി പാഴ്സ് ചെയ്യുവാന്‍ സാധ്യമായില്ല" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "HTTP മറുപടിയുടെ രൂപം തിരിച്ചറിയാനായില്ല" + +#: ../libsoup/soup-message-io.c:846 ../libsoup/soup-message-io.c:882 +msgid "Operation was cancelled" +msgstr "പ്രക്രിയ റദ്ദാക്കിയിരിയ്ക്കുന്നു" + +#: ../libsoup/soup-message-io.c:893 +msgid "Operation would block" +msgstr "പ്രക്രിയ തടസ്സപ്പെടുത്തുന്നു" + +#: ../libsoup/soup-message-server-io.c:40 +msgid "Could not parse HTTP request" +msgstr "HTTP മറുപടി പാഴ്സ് ചെയ്യുവാനായില്ല" + +#: ../libsoup/soup-request.c:140 +#, c-format +msgid "No URI provided" +msgstr "യുആര്‍ഐ ലഭ്യമാക്കിയിട്ടില്ല" + +#: ../libsoup/soup-request.c:150 +#, c-format +msgid "Invalid '%s' URI: %s" +msgstr "തെറ്റായ '%s' യുആര്‍ഐ: %s" + +#: ../libsoup/soup-session.c:4252 +#, c-format +msgid "Could not parse URI '%s'" +msgstr "യുആര്‍ഐ '%s' പാഴ്സ് ചെയ്യുവാനായില്ല" + +#: ../libsoup/soup-session.c:4289 +#, c-format +msgid "Unsupported URI scheme '%s'" +msgstr "പിന്തുണയില്ലാത്ത യുആര്‍ഐ സ്കീം '%s'" + +#: ../libsoup/soup-session.c:4311 +#, c-format +msgid "Not an HTTP URI" +msgstr "HTTP URI അല്ല" + +#: ../libsoup/soup-tld.c:185 +msgid "Hostname is an IP address" +msgstr "ഹോസ്റ്റ്നാമം ഒരു ഐപി വിലാസമാകുന്നു" + +#: ../libsoup/soup-tld.c:206 +msgid "Invalid hostname" +msgstr "തെറ്റായ ഹോസ്റ്റ്നാമം" + +#: ../libsoup/soup-tld.c:235 +msgid "Hostname has no base domain" +msgstr "ഹോസ്റ്റ്നാമത്തിനു് ബെയിസ് ഡൊമെയില്‍ ലഭ്യമല്ല" + +#: ../libsoup/soup-tld.c:257 +msgid "Not enough domains" +msgstr "ആവശ്യമായ ഡൊമെയിനുകള്‍ ലഭ്യമല്ല" + diff --git a/po/mr.po b/po/mr.po new file mode 100644 index 0000000..36f49cc --- /dev/null +++ b/po/mr.po @@ -0,0 +1,130 @@ +# Marathi translation for libsoup. +# Copyright (C) 2012 libsoup's COPYRIGHT HOLDER +# This file is distributed under the same license as the libsoup package. +# +# Sandeep Shedmake , 2012, 2013, 2014. +msgid "" +msgstr "" +"Project-Id-Version: libsoup master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2014-09-15 09:44+0000\n" +"PO-Revision-Date: 2014-09-15 15:54+0530\n" +"Last-Translator: Sandeep Shedmake \n" +"Language-Team: Marathi \n" +"Language: mr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Lokalize 1.5\n" + +#: ../libsoup/soup-body-input-stream.c:140 +#: ../libsoup/soup-body-input-stream.c:171 +#: ../libsoup/soup-body-input-stream.c:204 ../libsoup/soup-message-io.c:196 +msgid "Connection terminated unexpectedly" +msgstr "जोडणी अनपेक्षितपणे बंद झाली" + +#: ../libsoup/soup-body-input-stream.c:462 +msgid "Invalid seek request" +msgstr "अवैध सीक विनंती" + +#: ../libsoup/soup-body-input-stream.c:490 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "SoupBodyInputStream ट्रंकेट करणे अशक्य" + +#: ../libsoup/soup-cache-input-stream.c:73 +msgid "Network stream unexpectedly closed" +msgstr "नेटवर्क स्ट्रिम अनपेक्षितरित्या बंद झाले" + +#: ../libsoup/soup-cache-input-stream.c:290 +msgid "Failed to completely cache the resource" +msgstr "रिसोअर्स संपूर्णपणे कॅशे करण्यास अपयशी" + +#: ../libsoup/soup-converter-wrapper.c:192 +#, c-format +msgid "Output buffer is too small" +msgstr "आउटपुट बफर खूपच लहान आहे" + +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "HTTP प्रतिसाद वाचणे अशक्य" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "अपरिचीत HTTP प्रतिसाद एंकोडिंग" + +#: ../libsoup/soup-message-io.c:854 ../libsoup/soup-message-io.c:890 +msgid "Operation was cancelled" +msgstr "कार्य रद्द केले" + +#: ../libsoup/soup-message-io.c:901 +msgid "Operation would block" +msgstr "कार्य बंधिस्त करू शकते" + +#: ../libsoup/soup-message-server-io.c:41 +msgid "Could not parse HTTP request" +msgstr "HTTP विनंती वाचणे अशक्य" + +#: ../libsoup/soup-request.c:140 +#, c-format +msgid "No URI provided" +msgstr "URI पुरवले नाही" + +#: ../libsoup/soup-request.c:150 +#, c-format +msgid "Invalid '%s' URI: %s" +msgstr "अवैध '%s' URI: %s" + +#: ../libsoup/soup-server.c:1528 +msgid "Can't create a TLS server without a TLS certificate" +msgstr "TLS प्रमाणपत्रविना TLS सर्व्हर निर्माण करणे अशक्य" + +#: ../libsoup/soup-server.c:1547 +#, c-format +msgid "Could not listen on address %s, port %d: " +msgstr "पत्ता %s, पोर्ट %d वर ऐकणे अशक्य: " + +#: ../libsoup/soup-session.c:4466 +#, c-format +msgid "Could not parse URI '%s'" +msgstr "URI '%s' वाचणे अशक्य" + +#: ../libsoup/soup-session.c:4503 +#, c-format +msgid "Unsupported URI scheme '%s'" +msgstr "असमर्थीत URI सुत्रयोजना '%s'" + +#: ../libsoup/soup-session.c:4525 +#, c-format +msgid "Not an HTTP URI" +msgstr "HTTP URI नाही" + +#: ../libsoup/soup-socket.c:142 +msgid "Can't import non-socket as SoupSocket" +msgstr "विना-सॉकेटला SoupSocket म्हणून आयात करणे अशक्य" + +#: ../libsoup/soup-socket.c:160 +msgid "Could not import existing socket: " +msgstr "अस्तित्वातील सॉकेट आयात करणे अशक्य: " + +#: ../libsoup/soup-socket.c:169 +msgid "Can't import unconnected socket" +msgstr "विना जोडणी सॉकेट आयात करणे अशक्य" + +#: ../libsoup/soup-tld.c:188 +msgid "Hostname is an IP address" +msgstr "यजमाननाव IP पत्ता आहे" + +#: ../libsoup/soup-tld.c:198 ../libsoup/soup-tld.c:220 +msgid "Invalid hostname" +msgstr "अवैध यजमाननाव" + +#: ../libsoup/soup-tld.c:250 +msgid "Hostname has no base domain" +msgstr "यजमाननावात बेस डोमैन नाही" + +#: ../libsoup/soup-tld.c:304 +msgid "Not enough domains" +msgstr "अतिरिक्त डोमैन्स् आढळले नाही" + diff --git a/po/nb.po b/po/nb.po new file mode 100644 index 0000000..8d69ef4 --- /dev/null +++ b/po/nb.po @@ -0,0 +1,172 @@ +# Norwegian bokmål translation of libsoup. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# Kjartan Maraas , 2012-2017. +# +msgid "" +msgstr "" +"Project-Id-Version: libsoup 2.57.x\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=libsoup&keywords=I18N+L10N&component=Misc\n" +"POT-Creation-Date: 2016-10-27 12:38+0000\n" +"PO-Revision-Date: 2017-02-14 07:59+0100\n" +"Last-Translator: Kjartan Maraas \n" +"Language-Team: Norwegian bokmål \n" +"Language: nb\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: ../libsoup/soup-body-input-stream.c:140 +#: ../libsoup/soup-body-input-stream.c:171 +#: ../libsoup/soup-body-input-stream.c:204 ../libsoup/soup-message-io.c:235 +msgid "Connection terminated unexpectedly" +msgstr "Tilkoblingen ble brutt uventet" + +#: ../libsoup/soup-body-input-stream.c:462 +msgid "Invalid seek request" +msgstr "Ugyldig søkeforespørsel" + +#: ../libsoup/soup-body-input-stream.c:490 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "Kan ikke avkorte SoupBodyInputStream" + +#: ../libsoup/soup-cache-input-stream.c:74 +msgid "Network stream unexpectedly closed" +msgstr "Nettverksstrømmen ble lukket på uventet vis" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "Klarte ikke å mellomlagre ressursen fullt ut" + +#: ../libsoup/soup-converter-wrapper.c:192 +#, c-format +msgid "Output buffer is too small" +msgstr "Buffer for utdata er for liten" + +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "Kunne ikke tolke HTTP-svar" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "Ikke gjenkjent koding av HTTP-svar" + +#: ../libsoup/soup-message-io.c:392 ../libsoup/soup-message-io.c:1020 +msgid "Operation would block" +msgstr "Operasjonen ville blokkere" + +#: ../libsoup/soup-message-io.c:972 ../libsoup/soup-message-io.c:1005 +msgid "Operation was cancelled" +msgstr "Operasjonen ble avbrutt" + +#: ../libsoup/soup-message-server-io.c:64 +msgid "Could not parse HTTP request" +msgstr "Kunne ikke tolke HTTP-forespørsel" + +#: ../libsoup/soup-request.c:140 +#, c-format +msgid "No URI provided" +msgstr "Ingen URI ble oppgitt" + +#: ../libsoup/soup-request.c:150 +#, c-format +msgid "Invalid “%s” URI: %s" +msgstr "Ugyldig «%s» URI: %s" + +#: ../libsoup/soup-server.c:1727 +msgid "Can’t create a TLS server without a TLS certificate" +msgstr "Kan ikke lage en TLS-tjener uten et TLS-sertifikat" + +#: ../libsoup/soup-server.c:1744 +#, c-format +msgid "Could not listen on address %s, port %d: " +msgstr "Kunne ikke lytte på adresse %s, port %d: " + +#: ../libsoup/soup-session.c:4525 +#, c-format +msgid "Could not parse URI “%s”" +msgstr "Kunne ikke tolke URI «%s»" + +#: ../libsoup/soup-session.c:4562 +#, c-format +msgid "Unsupported URI scheme “%s”" +msgstr "URI-skjema «%s» er ikke støttet" + +#: ../libsoup/soup-session.c:4584 +#, c-format +msgid "Not an HTTP URI" +msgstr "Ikke en HTTP URI" + +#: ../libsoup/soup-session.c:4770 +msgid "The server did not accept the WebSocket handshake." +msgstr "Tjeneren godtok ikke WebSocket-håndtrykk." + +#: ../libsoup/soup-socket.c:148 +msgid "Can’t import non-socket as SoupSocket" +msgstr "Kan ikke importere noe som ikke er en socket som SoupSocket" + +#: ../libsoup/soup-socket.c:166 +msgid "Could not import existing socket: " +msgstr "Kunne ikke importere eksisterende socket: " + +#: ../libsoup/soup-socket.c:175 +msgid "Can’t import unconnected socket" +msgstr "Kan ikke importere ikke-tilkoblet socket" + +#: ../libsoup/soup-websocket.c:338 ../libsoup/soup-websocket.c:347 +msgid "WebSocket handshake expected" +msgstr "WebSocket-håndtrykk forventet" + +#: ../libsoup/soup-websocket.c:355 +msgid "Unsupported WebSocket version" +msgstr "WebSocket-versjon ikke støttet" + +#: ../libsoup/soup-websocket.c:364 +msgid "Invalid WebSocket key" +msgstr "Ugyldig WebSocket-nøkkel" + +#: ../libsoup/soup-websocket.c:374 +#, c-format +msgid "Incorrect WebSocket “%s” header" +msgstr "Ugyldig «%s»-hode for WebSocket" + +#: ../libsoup/soup-websocket.c:383 +msgid "Unsupported WebSocket subprotocol" +msgstr "Ikke støttet underprotokoll av WebSocket" + +#: ../libsoup/soup-websocket.c:510 +msgid "Server rejected WebSocket handshake" +msgstr "Tjener avviste håndtrykk for WebSocket" + +#: ../libsoup/soup-websocket.c:518 ../libsoup/soup-websocket.c:527 +msgid "Server ignored WebSocket handshake" +msgstr "Tjener overså håndtrykk fra WebSocket" + +#: ../libsoup/soup-websocket.c:539 +msgid "Server requested unsupported protocol" +msgstr "Tjener forespurte protokoll som ikke støttes" + +#: ../libsoup/soup-websocket.c:549 +msgid "Server requested unsupported extension" +msgstr "Tjener forespurte utvidelse som ikke støttes" + +#: ../libsoup/soup-websocket.c:562 +#, c-format +msgid "Server returned incorrect “%s” key" +msgstr "Tjener returnerte feil «%s»-nøkkel" + +#: ../libsoup/soup-tld.c:188 +msgid "Hostname is an IP address" +msgstr "Vertsnavnet er en IP-adresse" + +#: ../libsoup/soup-tld.c:198 ../libsoup/soup-tld.c:220 +msgid "Invalid hostname" +msgstr "Ugyldig vertsnavn" + +#: ../libsoup/soup-tld.c:250 +msgid "Hostname has no base domain" +msgstr "Vertsnavnet har ikke noe grunndomene" + +#: ../libsoup/soup-tld.c:304 +msgid "Not enough domains" +msgstr "Ikke mange nok domener" diff --git a/po/ne.po b/po/ne.po new file mode 100644 index 0000000..86ab8a5 --- /dev/null +++ b/po/ne.po @@ -0,0 +1,175 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: Gnome Nepali Translation Project\n" +"Report-Msgid-Bugs-To: https://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=Misc\n" +"POT-Creation-Date: 2017-08-10 12:33+0000\n" +"PO-Revision-Date: 2017-10-16 16:09+0545\n" +"Language-Team: Nepali Translation Team \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 2.0.4\n" +"Last-Translator: Pawan Chitrakar \n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"Language: ne\n" + +#: ../libsoup/soup-body-input-stream.c:139 +#: ../libsoup/soup-body-input-stream.c:170 +#: ../libsoup/soup-body-input-stream.c:203 ../libsoup/soup-message-io.c:237 +msgid "Connection terminated unexpectedly" +msgstr "जडान अप्रत्याशित रूपमा समाप्त भयो" + +#: ../libsoup/soup-body-input-stream.c:459 +msgid "Invalid seek request" +msgstr "अमान्य खोज अनुरोध" + +#: ../libsoup/soup-body-input-stream.c:487 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "सूपबडीइनपुटस्ट्रीम ट्रंक गर्न सकिँदैन" + +#: ../libsoup/soup-cache-input-stream.c:76 +msgid "Network stream unexpectedly closed" +msgstr "सञ्जाल स्ट्रीम अनपेक्षित रूपमा बन्द गरियो" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "संसाधन पुरा तरिकाले क्यास गर्न असफल भयो" + +#: ../libsoup/soup-converter-wrapper.c:189 +#, c-format +msgid "Output buffer is too small" +msgstr "निर्गत बफर धेरै सानो छ" + +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "HTTP प्रतिक्रिया पार्स गर्न सकिएन" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "अपरिचित HTTP प्रतिक्रिया इन्कोडिङ" + +#: ../libsoup/soup-message-io.c:387 ../libsoup/soup-message-io.c:1015 +msgid "Operation would block" +msgstr "सञ्चालन ब्लक हुनेछ" + +#: ../libsoup/soup-message-io.c:967 ../libsoup/soup-message-io.c:1000 +msgid "Operation was cancelled" +msgstr "सञ्चालन रद्द भएको छ" + +#: ../libsoup/soup-message-server-io.c:64 +msgid "Could not parse HTTP request" +msgstr "HTTP अनुरोध पार्स गर्न सकिएन" + +#: ../libsoup/soup-request.c:141 +#, c-format +msgid "No URI provided" +msgstr "कुनै URI प्रदान गरिएको छैन" + +#: ../libsoup/soup-request.c:151 +#, c-format +msgid "Invalid “%s” URI: %s" +msgstr "अमान्य \"%s\" URI:%s" + +#: ../libsoup/soup-server.c:1725 +msgid "Can’t create a TLS server without a TLS certificate" +msgstr "TLS प्रमाणपत्र बिना TLS सर्भर सिर्जना गर्न सक्दैन" + +#: ../libsoup/soup-server.c:1742 +#, c-format +msgid "Could not listen on address %s, port %d: " +msgstr "ठेगाना%s, पोर्ट%d मा सुन्न सकेन: " + +#: ../libsoup/soup-session.c:4517 +#, c-format +msgid "Could not parse URI “%s”" +msgstr "URI \"%s\" पार्स गर्न सकिएन" + +#: ../libsoup/soup-session.c:4554 +#, c-format +msgid "Unsupported URI scheme “%s”" +msgstr "असमर्थित यूआरआई योजना \"%s\"" + +#: ../libsoup/soup-session.c:4576 +#, c-format +msgid "Not an HTTP URI" +msgstr "HTTP URI होइन" + +#: ../libsoup/soup-session.c:4762 +msgid "The server did not accept the WebSocket handshake." +msgstr "सर्भरले वेबसकेट ह्यान्डशक स्वीकार गरेन।." + +#: ../libsoup/soup-socket.c:148 +msgid "Can’t import non-socket as SoupSocket" +msgstr "सूपसकेटको रूपमा गैर-सकेट आयात गर्न सकिँदैन" + +#: ../libsoup/soup-socket.c:166 +msgid "Could not import existing socket: " +msgstr "अवस्थित सकेट आयात गर्न सकिएन: " + +#: ../libsoup/soup-socket.c:175 +msgid "Can’t import unconnected socket" +msgstr "जडान नगरिएको सकेट सकिएन" + +#: ../libsoup/soup-websocket.c:338 ../libsoup/soup-websocket.c:347 +msgid "WebSocket handshake expected" +msgstr "वेबसकेट ह्यान्डशेक अपेक्षित" + +#: ../libsoup/soup-websocket.c:355 +msgid "Unsupported WebSocket version" +msgstr "असमर्थित वेबसकेट संस्करण" + +#: ../libsoup/soup-websocket.c:364 +msgid "Invalid WebSocket key" +msgstr "असमर्थित वेबसकेट सबप्रटोकल" + +#: ../libsoup/soup-websocket.c:374 +#, c-format +msgid "Incorrect WebSocket “%s” header" +msgstr "गलत वेबसकेट \"%s\" हेडर" + +#: ../libsoup/soup-websocket.c:383 +msgid "Unsupported WebSocket subprotocol" +msgstr "Unsupported WebSocket subprotocol" + +#: ../libsoup/soup-websocket.c:510 +msgid "Server rejected WebSocket handshake" +msgstr "सर्भरले वेबस्केट ह्यान्डशकलाई अस्वीकार गर्यो" + +#: ../libsoup/soup-websocket.c:518 ../libsoup/soup-websocket.c:527 +msgid "Server ignored WebSocket handshake" +msgstr "सर्भरले वेबस्केट ह्यान्डशेकलाई बेवास्ता गर्यो" + +#: ../libsoup/soup-websocket.c:539 +msgid "Server requested unsupported protocol" +msgstr "सर्भरले असमर्थित प्रोटोकल अनुरोध गर्यो" + +#: ../libsoup/soup-websocket.c:549 +msgid "Server requested unsupported extension" +msgstr "सर्भरले असमर्थित एक्सटेन्सन अनुरोध गर्यो" + +#: ../libsoup/soup-websocket.c:562 +#, c-format +msgid "Server returned incorrect “%s” key" +msgstr "सर्भरले गलत \"%s\" कुञ्जीलाई फर्कायो" + +#: ../libsoup/soup-tld.c:188 +msgid "Hostname is an IP address" +msgstr "होस्टनाम आईपी ठेगाना हो" + +#: ../libsoup/soup-tld.c:198 ../libsoup/soup-tld.c:220 +msgid "Invalid hostname" +msgstr "अवैध होस्टनाम" + +#: ../libsoup/soup-tld.c:250 +msgid "Hostname has no base domain" +msgstr "होस्टनामसँग कुनै आधार डोमेन छैन" + +#: ../libsoup/soup-tld.c:304 +msgid "Not enough domains" +msgstr "पर्याप्त डोमेनहरू छैनन्" diff --git a/po/nl.po b/po/nl.po new file mode 100644 index 0000000..7414db7 --- /dev/null +++ b/po/nl.po @@ -0,0 +1,181 @@ +# Dutch translation for libsoup. +# Copyright (C) 2013 libsoup's COPYRIGHT HOLDER +# This file is distributed under the same license as the libsoup package. +# Reinout van Schouwen , 2013. +# Reinout van Schouwen , 2013. +# Nathan Follens , 2015-2018. +msgid "" +msgstr "" +"Project-Id-Version: libsoup master\n" +"Report-Msgid-Bugs-To: https://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=Misc\n" +"POT-Creation-Date: 2018-02-09 14:43+0000\n" +"PO-Revision-Date: 2018-02-22 20:11+0100\n" +"Last-Translator: Nathan Follens \n" +"Language-Team: Dutch \n" +"Language: nl\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Poedit 2.0.6\n" +"X-Project-Style: gnome\n" + +#: ../libsoup/soup-body-input-stream.c:139 +#: ../libsoup/soup-body-input-stream.c:170 +#: ../libsoup/soup-body-input-stream.c:203 ../libsoup/soup-message-io.c:238 +msgid "Connection terminated unexpectedly" +msgstr "Verbinding werd onverwacht verbroken" + +#: ../libsoup/soup-body-input-stream.c:459 +msgid "Invalid seek request" +msgstr "Ongeldige zoekaanvraag" + +#: ../libsoup/soup-body-input-stream.c:487 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "Kan SoupBodyInputStream niet afkappen" + +#: ../libsoup/soup-cache-input-stream.c:76 +msgid "Network stream unexpectedly closed" +msgstr "Netwerkstroom onverwacht gesloten" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "Volledig bufferen van de bron is mislukt" + +#: ../libsoup/soup-converter-wrapper.c:189 +#, c-format +msgid "Output buffer is too small" +msgstr "Uitvoerbuffer is te klein" + +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "Kan HTTP-antwoord niet verwerken" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "Niet-herkende HTTP-antwoordcodering" + +#: ../libsoup/soup-message-io.c:263 +msgid "Header too big" +msgstr "Hoofding te groot" + +#: ../libsoup/soup-message-io.c:396 ../libsoup/soup-message-io.c:1024 +msgid "Operation would block" +msgstr "Bewerking zou blokkeren" + +#: ../libsoup/soup-message-io.c:976 ../libsoup/soup-message-io.c:1009 +msgid "Operation was cancelled" +msgstr "Bewerking is geannuleerd" + +#: ../libsoup/soup-message-server-io.c:64 +msgid "Could not parse HTTP request" +msgstr "Kan HTTP-aanvraag niet verwerken" + +#: ../libsoup/soup-request.c:141 +#, c-format +msgid "No URI provided" +msgstr "Geen URI aangeleverd" + +#: ../libsoup/soup-request.c:151 +#, c-format +msgid "Invalid “%s” URI: %s" +msgstr "Ongeldige ‘%s’-URI: %s" + +#: ../libsoup/soup-server.c:1725 +msgid "Can’t create a TLS server without a TLS certificate" +msgstr "Kan geen TLS-server aanmaken zonder een TLS-certificaat" + +#: ../libsoup/soup-server.c:1742 +#, c-format +msgid "Could not listen on address %s, port %d: " +msgstr "Kan niet luisteren op adres %s, poort %d: " + +#: ../libsoup/soup-session.c:4524 +#, c-format +msgid "Could not parse URI “%s”" +msgstr "Kon URI ‘%s’ niet verwerken" + +#: ../libsoup/soup-session.c:4561 +#, c-format +msgid "Unsupported URI scheme “%s”" +msgstr "Niet-ondersteund URI-schema ‘%s’" + +#: ../libsoup/soup-session.c:4583 +#, c-format +msgid "Not an HTTP URI" +msgstr "Geen HTTP-URI" + +#: ../libsoup/soup-session.c:4781 +msgid "The server did not accept the WebSocket handshake." +msgstr "De server aanvaardde de WebSocket-handdruk niet." + +#: ../libsoup/soup-socket.c:148 +msgid "Can’t import non-socket as SoupSocket" +msgstr "Kan niet-socket niet importeren als SoupSocket" + +#: ../libsoup/soup-socket.c:166 +msgid "Could not import existing socket: " +msgstr "Kan bestaande socket niet importeren: " + +#: ../libsoup/soup-socket.c:175 +msgid "Can’t import unconnected socket" +msgstr "Kan niet-verbonden socket niet importeren" + +#: ../libsoup/soup-websocket.c:338 ../libsoup/soup-websocket.c:347 +msgid "WebSocket handshake expected" +msgstr "WebSocket-handdruk verwacht" + +#: ../libsoup/soup-websocket.c:355 +msgid "Unsupported WebSocket version" +msgstr "Niet-ondersteunde WebSocket-versie" + +#: ../libsoup/soup-websocket.c:364 +msgid "Invalid WebSocket key" +msgstr "Ongeldige WebSocket-sleutel" + +#: ../libsoup/soup-websocket.c:374 +#, c-format +msgid "Incorrect WebSocket “%s” header" +msgstr "Onjuiste WebSocket ‘%s’-hoofding" + +#: ../libsoup/soup-websocket.c:383 +msgid "Unsupported WebSocket subprotocol" +msgstr "Niet-ondersteund WebSocket subprotocol" + +#: ../libsoup/soup-websocket.c:510 +msgid "Server rejected WebSocket handshake" +msgstr "WebSocket-handdruk geweigerd door server" + +#: ../libsoup/soup-websocket.c:518 ../libsoup/soup-websocket.c:527 +msgid "Server ignored WebSocket handshake" +msgstr "WebSocket-handdruk genegeerd door server" + +#: ../libsoup/soup-websocket.c:539 +msgid "Server requested unsupported protocol" +msgstr "Niet-ondersteund protocol aangevraagd door server" + +#: ../libsoup/soup-websocket.c:549 +msgid "Server requested unsupported extension" +msgstr "Niet-ondersteunde uitbreiding aangevraagd door server" + +#: ../libsoup/soup-websocket.c:562 +#, c-format +msgid "Server returned incorrect “%s” key" +msgstr "Onjuiste ‘%s’-sleutel weergegeven door server" + +#: ../libsoup/soup-tld.c:188 +msgid "Hostname is an IP address" +msgstr "Hostnaam is een IP-adres" + +#: ../libsoup/soup-tld.c:198 ../libsoup/soup-tld.c:220 +msgid "Invalid hostname" +msgstr "Ongeldige hostnaam" + +#: ../libsoup/soup-tld.c:250 +msgid "Hostname has no base domain" +msgstr "Hostnaam heeft geen basisdomein" + +#: ../libsoup/soup-tld.c:304 +msgid "Not enough domains" +msgstr "Niet genoeg domeinen" diff --git a/po/oc.po b/po/oc.po new file mode 100644 index 0000000..838e45f --- /dev/null +++ b/po/oc.po @@ -0,0 +1,177 @@ +# Occitan translation for libsoup. +# Copyright (C) 2012-2015 libsoup's COPYRIGHT HOLDER +# This file is distributed under the same license as the libsoup package. +# Cédric Valmary , 2015. +# Cédric Valmary (Tot en òc) , 2015. +# Cédric Valmary (totenoc.eu) , 2016. +msgid "" +msgstr "" +"Project-Id-Version: libsoup master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2016-05-05 20:07+0000\n" +"PO-Revision-Date: 2016-05-05 21:46+0200\n" +"Last-Translator: Cédric Valmary (totenoc.eu) \n" +"Language-Team: Tot En Òc\n" +"Language: oc\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" +"X-Generator: Virtaal 0.7.1\n" +"X-Project-Style: gnome\n" + +#: ../libsoup/soup-body-input-stream.c:140 +#: ../libsoup/soup-body-input-stream.c:171 +#: ../libsoup/soup-body-input-stream.c:204 ../libsoup/soup-message-io.c:235 +msgid "Connection terminated unexpectedly" +msgstr "La connexion es estada interrompuda d'un biais imprevist" + +#: ../libsoup/soup-body-input-stream.c:462 +msgid "Invalid seek request" +msgstr "Requèsta de recèrca invalida" + +#: ../libsoup/soup-body-input-stream.c:490 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "Impossible de trocejar lo SoupBodyInputStream" + +#: ../libsoup/soup-cache-input-stream.c:74 +msgid "Network stream unexpectedly closed" +msgstr "Lo flux ret s'es arrestat inopinèament" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "Impossible de metre la ressorsa totalament en cache" + +#: ../libsoup/soup-converter-wrapper.c:192 +#, c-format +msgid "Output buffer is too small" +msgstr "La memòria tampon de sortida es tròp pichona" + +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "Impossible d'analisar la responsa HTTP" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "Encodatge de responsa HTTP desconegut" + +#: ../libsoup/soup-message-io.c:392 ../libsoup/soup-message-io.c:1020 +msgid "Operation would block" +msgstr "L'operacion auriá blocat" + +#: ../libsoup/soup-message-io.c:972 ../libsoup/soup-message-io.c:1005 +msgid "Operation was cancelled" +msgstr "L'operacion es estada anullada" + +#: ../libsoup/soup-message-server-io.c:64 +msgid "Could not parse HTTP request" +msgstr "Impossible d'analisar la requèsta HTTP" + +#: ../libsoup/soup-request.c:140 +#, c-format +msgid "No URI provided" +msgstr "Cap d'URI pas provesit" + +#: ../libsoup/soup-request.c:150 +#, c-format +msgid "Invalid '%s' URI: %s" +msgstr "URI « %s » invalid : %s" + +#: ../libsoup/soup-server.c:1720 +msgid "Can't create a TLS server without a TLS certificate" +msgstr "Impossible de crear un servidor TLS sens un certificat TLS" + +#: ../libsoup/soup-server.c:1737 +#, c-format +msgid "Could not listen on address %s, port %d: " +msgstr "Impossible d'escotar l'adreça %s sul pòrt %d: " + +#: ../libsoup/soup-session.c:4525 +#, c-format +msgid "Could not parse URI '%s'" +msgstr "Impossible d'analisar l'URI « %s »" + +#: ../libsoup/soup-session.c:4562 +#, c-format +msgid "Unsupported URI scheme '%s'" +msgstr "L'esquèma d'URI « %s » es pas pres en carga" + +#: ../libsoup/soup-session.c:4584 +#, c-format +msgid "Not an HTTP URI" +msgstr "Es pas un URI HTTP" + +#: ../libsoup/soup-session.c:4770 +msgid "The server did not accept the WebSocket handshake." +msgstr "Lo servidor a pas acceptat la negociacion WebSocket." + +#: ../libsoup/soup-socket.c:148 +msgid "Can't import non-socket as SoupSocket" +msgstr "Impossible d'importar de contengut non-socket coma SoupSocket" + +#: ../libsoup/soup-socket.c:166 +msgid "Could not import existing socket: " +msgstr "Impossible d'importar lo connectador ret existent : " + +#: ../libsoup/soup-socket.c:175 +msgid "Can't import unconnected socket" +msgstr "Impossible d'importar lo connectador ret non connectat" + +#: ../libsoup/soup-websocket.c:338 ../libsoup/soup-websocket.c:347 +msgid "WebSocket handshake expected" +msgstr "Negociacion WebSocket esperada" + +#: ../libsoup/soup-websocket.c:355 +msgid "Unsupported WebSocket version" +msgstr "Version de WebSocket pas presa en carga" + +#: ../libsoup/soup-websocket.c:364 +msgid "Invalid WebSocket key" +msgstr "Clau WebSocket pas valabla" + +#: ../libsoup/soup-websocket.c:374 +#, c-format +msgid "Incorrect WebSocket \"%s\" header" +msgstr "Entèsta WebSocket « %s » incorrècta" + +#: ../libsoup/soup-websocket.c:383 +msgid "Unsupported WebSocket subprotocol" +msgstr "Sosprotocòl de WebSocket pas pres en carga" + +#: ../libsoup/soup-websocket.c:510 +msgid "Server rejected WebSocket handshake" +msgstr "Lo servidor a regetat la negociacion WebSocket" + +#: ../libsoup/soup-websocket.c:518 ../libsoup/soup-websocket.c:527 +msgid "Server ignored WebSocket handshake" +msgstr "Lo servidor a ignorat la negociacion WebSocket" + +#: ../libsoup/soup-websocket.c:539 +msgid "Server requested unsupported protocol" +msgstr "Lo servidor a demandat un protocòl pas pres en carga" + +#: ../libsoup/soup-websocket.c:549 +msgid "Server requested unsupported extension" +msgstr "Lo servidor a demandat una extension pas presa en carga" + +#: ../libsoup/soup-websocket.c:562 +#, c-format +msgid "Server returned incorrect \"%s\" key" +msgstr "Lo servidor a renviat una clau « %s » incorrècta" + +#: ../libsoup/soup-tld.c:188 +msgid "Hostname is an IP address" +msgstr "Lo nom d'òste es una adreça IP" + +#: ../libsoup/soup-tld.c:198 ../libsoup/soup-tld.c:220 +msgid "Invalid hostname" +msgstr "Nom d'òste invalid" + +#: ../libsoup/soup-tld.c:250 +msgid "Hostname has no base domain" +msgstr "Lo nom d'òste a pas de domeni de basa" + +#: ../libsoup/soup-tld.c:304 +msgid "Not enough domains" +msgstr "Pas pro de domenis" diff --git a/po/or.po b/po/or.po new file mode 100644 index 0000000..6ae2f33 --- /dev/null +++ b/po/or.po @@ -0,0 +1,129 @@ +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Manoj Kumar Giri , 2012, 2013, 2014. +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2014-09-15 09:44+0000\n" +"PO-Revision-Date: 2014-09-15 18:37+0530\n" +"Last-Translator: Manoj Kumar Giri \n" +"Language-Team: Oriya \n" +"Language: or\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Lokalize 1.5\n" + +#: ../libsoup/soup-body-input-stream.c:140 +#: ../libsoup/soup-body-input-stream.c:171 +#: ../libsoup/soup-body-input-stream.c:204 ../libsoup/soup-message-io.c:196 +msgid "Connection terminated unexpectedly" +msgstr "ସଂଯୋଗଟି ଅପ୍ରତ୍ୟାଶିତ ଭାବରେ ବନ୍ଦ ହୋଇଛି" + +#: ../libsoup/soup-body-input-stream.c:462 +msgid "Invalid seek request" +msgstr "ଅବୈଧ ଅନୁସନ୍ଧାନ ଅନୁରୋଧ" + +#: ../libsoup/soup-body-input-stream.c:490 +msgid "Cannot truncate SoupBodyInputStream" +msgstr " SoupBodyInputStream କୁ ବିଚ୍ଛିନ୍ନ କରିହେବ ନାହିଁ " + +#: ../libsoup/soup-cache-input-stream.c:73 +msgid "Network stream unexpectedly closed" +msgstr "ନେଟୱର୍କ୍‌ ଧାରା ଅପ୍ରତ୍ୟାଶିତ ଭାବରେ ବନ୍ଦ ହୋଇଛି" + +#: ../libsoup/soup-cache-input-stream.c:290 +msgid "Failed to completely cache the resource" +msgstr "ଉତ୍ସକୁ ସମ୍ପୂର୍ଣ୍ଣ ଭାବରେ କ୍ୟାଶେ କରିବାରେ ବିଫଳ" + +#: ../libsoup/soup-converter-wrapper.c:192 +#, c-format +msgid "Output buffer is too small" +msgstr "ଫଳାଫଳ ବଫରଟି ଅତି ଛୋଟ ଅଟେ" + +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "HTTP ଉତ୍ତର ବିଶ୍ଳେଷଣ କରିପାରିଲା ନାହିଁ" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "ଅଚିହ୍ନା HTTP ଉତ୍ତର ସାଙ୍କେତିକରଣ" + +#: ../libsoup/soup-message-io.c:854 ../libsoup/soup-message-io.c:890 +msgid "Operation was cancelled" +msgstr "ପ୍ରୟୋଗକୁ ବାତିଲ କରାଯାଇଛି" + +#: ../libsoup/soup-message-io.c:901 +msgid "Operation would block" +msgstr "ପ୍ରୟୋଗଟି ବନ୍ଦ ହୋଇପାରେ" + +#: ../libsoup/soup-message-server-io.c:41 +msgid "Could not parse HTTP request" +msgstr "HTTP ଅନୁରୋଧକୁ ବିଶ୍ଳେଷଣ କରିପାରିଲା ନାହିଁ" + +#: ../libsoup/soup-request.c:140 +#, c-format +msgid "No URI provided" +msgstr "କୌଣସି URI ଦିଆଯାଇ ନାହିଁ" + +#: ../libsoup/soup-request.c:150 +#, c-format +msgid "Invalid '%s' URI: %s" +msgstr "ଅବୈଧ '%s' URI: %s" + +#: ../libsoup/soup-server.c:1528 +msgid "Can't create a TLS server without a TLS certificate" +msgstr "TLS ପ୍ରମାଣପତ୍ର ବିନା TLS ସର୍ଭର ସୃଷ୍ଟି କରିପାରିବେ ନାହିଁ" + +#: ../libsoup/soup-server.c:1547 +#, c-format +msgid "Could not listen on address %s, port %d: " +msgstr "ଠିକଣା %s, ପୋର୍ଟ %d ରେ ଶୁଣିପାରିବେ ନାହିଁ: " + +#: ../libsoup/soup-session.c:4466 +#, c-format +msgid "Could not parse URI '%s'" +msgstr "URI '%s'କୁ ବିଶ୍ଳେଷଣ କରିପାରିଲା ନାହିଁ" + +#: ../libsoup/soup-session.c:4503 +#, c-format +msgid "Unsupported URI scheme '%s'" +msgstr "ଅସମର୍ଥିତ URI ଯୋଜନା '%s'" + +#: ../libsoup/soup-session.c:4525 +#, c-format +msgid "Not an HTTP URI" +msgstr "ଏହା ଏକ HTTP URI ନୁହଁ" + +#: ../libsoup/soup-socket.c:142 +msgid "Can't import non-socket as SoupSocket" +msgstr "non-socket କୁ SoupSocket ଭାବରେ ଆମଦାନୀ କରିପାରିବେ ନାହିଁ" + +#: ../libsoup/soup-socket.c:160 +msgid "Could not import existing socket: " +msgstr "ସ୍ଥିତବାନ ସକେଟକୁ ଆମଦାନୀ କରିପାରିବେ ନାହିଁ: " + +#: ../libsoup/soup-socket.c:169 +msgid "Can't import unconnected socket" +msgstr "ଅସଂଯୁକ୍ତ ସକେଟକୁ ଆମଦାନୀ କରିପାରିବେ ନାହିଁ" + +#: ../libsoup/soup-tld.c:188 +msgid "Hostname is an IP address" +msgstr "ହୋଷ୍ଟନାମଟି ଏକ IP ଠିକଣା ଅଟେ" + +#: ../libsoup/soup-tld.c:198 ../libsoup/soup-tld.c:220 +msgid "Invalid hostname" +msgstr "ଅବୈଧ ହୋଷ୍ଟ ନାମ" + +#: ../libsoup/soup-tld.c:250 +msgid "Hostname has no base domain" +msgstr "ହୋଷ୍ଟ ନାମରେ କୌଣସି ମୂଳ ଡମେନ ନଥାଏ" + +#: ../libsoup/soup-tld.c:304 +msgid "Not enough domains" +msgstr "ଯଥେଷ୍ଟ ଡମେନ ନାହିଁ" + diff --git a/po/pa.po b/po/pa.po new file mode 100644 index 0000000..aaae94e --- /dev/null +++ b/po/pa.po @@ -0,0 +1,130 @@ +# Punjabi translation for libsoup. +# Copyright (C) 2012 libsoup's COPYRIGHT HOLDER +# This file is distributed under the same license as the libsoup package. +# +# A S Alam , 2012, 2013, 2014. +msgid "" +msgstr "" +"Project-Id-Version: libsoup master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2014-09-21 09:39+0000\n" +"PO-Revision-Date: 2014-09-21 08:57-0500\n" +"Last-Translator: A S Alam \n" +"Language-Team: Punjabi/Panjabi \n" +"Language: pa\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Lokalize 1.5\n" + +#: ../libsoup/soup-body-input-stream.c:140 +#: ../libsoup/soup-body-input-stream.c:171 +#: ../libsoup/soup-body-input-stream.c:204 ../libsoup/soup-message-io.c:196 +msgid "Connection terminated unexpectedly" +msgstr "ਕੁਨੈਕਸ਼ਨ ਅਚਾਨਕ ਬੰਦ ਹੋ ਗਿਆ" + +#: ../libsoup/soup-body-input-stream.c:462 +msgid "Invalid seek request" +msgstr "ਸੀਕ ਮੰਗ ਗਲਤ ਹੈ" + +#: ../libsoup/soup-body-input-stream.c:490 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "SoupBodyInputStream ਨੂੰ ਛੋਟਾ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ" + +#: ../libsoup/soup-cache-input-stream.c:73 +msgid "Network stream unexpectedly closed" +msgstr "ਨੈੱਟਵਰਕ ਸਟਰੀਮ ਅਚਾਨਕ ਬੰਦ ਹੋਈ" + +#: ../libsoup/soup-cache-input-stream.c:290 +msgid "Failed to completely cache the resource" +msgstr "ਸਰੋਤ ਨੂੰ ਪੂਰੀ ਕੈਸ਼ ਕਰਨ ਲਈ ਫੇਲ੍ਹ ਹੈ" + +#: ../libsoup/soup-converter-wrapper.c:192 +#, c-format +msgid "Output buffer is too small" +msgstr "ਆਉਟਪੁੱਟ ਬਫ਼ਰ ਬਹੁਤ ਛੋਟਾ ਹੈ" + +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "HTTP ਨੂੰ ਪਾਰਸ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "ਬੇਪਛਾਣ HTTP ਜਵਾਬ ਇੰਕੋਡਿੰਗ" + +#: ../libsoup/soup-message-io.c:854 ../libsoup/soup-message-io.c:890 +msgid "Operation was cancelled" +msgstr "ਕਾਰਵਾਈ ਰੱਦ ਕੀਤੀ ਗਈ" + +#: ../libsoup/soup-message-io.c:901 +msgid "Operation would block" +msgstr "ਕਾਰਵਾਈ ਉੱਤੇ ਪਾਬੰਦੀ ਹੋਵੇਗੀ" + +#: ../libsoup/soup-message-server-io.c:41 +msgid "Could not parse HTTP request" +msgstr "HTTP ਮੰਗ ਨੂੰ ਪਾਰਸ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ" + +#: ../libsoup/soup-request.c:140 +#, c-format +msgid "No URI provided" +msgstr "ਕੋਈ URI ਨਹੀਂ ਦਿੱਤਾ" + +#: ../libsoup/soup-request.c:150 +#, c-format +msgid "Invalid '%s' URI: %s" +msgstr "ਗਲਤ '%s' URI: %s" + +#: ../libsoup/soup-server.c:1528 +msgid "Can't create a TLS server without a TLS certificate" +msgstr "TLS ਸਰਟੀਫਿਕੇਟ ਦੇ ਬਿਨਾਂ TLS ਸਰਵਰ ਬਣਾਇਆ ਨਹੀਂ ਜਾ ਸਕਦਾ" + +#: ../libsoup/soup-server.c:1547 +#, c-format +msgid "Could not listen on address %s, port %d: " +msgstr "ਸਿਰਨਾਵਾਂ %s, ਪੋਰਟ %d ਉੱਤੇ ਸੁਣਿਆ ਨਹੀਂ ਜਾ ਸਕਿਆ: " + +#: ../libsoup/soup-session.c:4466 +#, c-format +msgid "Could not parse URI '%s'" +msgstr "URI '%s' ਨੂੰ ਪਾਰਸ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ" + +#: ../libsoup/soup-session.c:4503 +#, c-format +msgid "Unsupported URI scheme '%s'" +msgstr "ਗ਼ੈਰ-ਸਹਾਇਕ URI ਸਕੀਮ '%s'" + +#: ../libsoup/soup-session.c:4525 +#, c-format +msgid "Not an HTTP URI" +msgstr "HTTP URI ਨਹੀਂ ਹੈ" + +#: ../libsoup/soup-socket.c:142 +msgid "Can't import non-socket as SoupSocket" +msgstr "SoupSocket ਵਜੋਂ ਗ਼ੈਰ-ਸਾਕਟ ਨੂੰ ਦਰਾਮਦ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ" + +#: ../libsoup/soup-socket.c:160 +msgid "Could not import existing socket: " +msgstr "ਮੌਜੂਦਾ ਸਾਕਟ ਨੂੰ ਦਰਾਮਦ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ: " + +#: ../libsoup/soup-socket.c:169 +msgid "Can't import unconnected socket" +msgstr "ਨਾ-ਕੁਨੈਕਟ ਹੋਈ ਸਾਕਟ ਦਰਾਮਦ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕਦੀ" + +#: ../libsoup/soup-tld.c:188 +msgid "Hostname is an IP address" +msgstr "ਹੋਸਟ ਨਾਂ IP ਐਡਰੈਸ ਹੈ" + +#: ../libsoup/soup-tld.c:198 ../libsoup/soup-tld.c:220 +msgid "Invalid hostname" +msgstr "ਗਲਤ ਹੋਸਟ-ਨਾਂ" + +#: ../libsoup/soup-tld.c:250 +msgid "Hostname has no base domain" +msgstr "ਹੋਸਟ-ਨਾਂ ਲਈ ਬੇਸ ਡੋਮੇਮ ਨਹੀਂ ਹੈ" + +#: ../libsoup/soup-tld.c:304 +msgid "Not enough domains" +msgstr "ਲੋੜੀਦੀਆਂ ਡੋਮੇਨ ਨਹੀਂ ਹੈ" + diff --git a/po/pl.po b/po/pl.po new file mode 100644 index 0000000..84c1865 --- /dev/null +++ b/po/pl.po @@ -0,0 +1,179 @@ +# Polish translation for libsoup. +# Copyright © 2012-2018 the libsoup authors. +# This file is distributed under the same license as the libsoup package. +# Piotr Drąg , 2012-2018. +# Aviary.pl , 2012-2018. +# +msgid "" +msgstr "" +"Project-Id-Version: libsoup\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-02-10 14:42+0100\n" +"PO-Revision-Date: 2018-02-10 14:44+0100\n" +"Last-Translator: Piotr Drąg \n" +"Language-Team: Polish \n" +"Language: pl\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " +"|| n%100>=20) ? 1 : 2);\n" + +#: ../libsoup/soup-body-input-stream.c:139 +#: ../libsoup/soup-body-input-stream.c:170 +#: ../libsoup/soup-body-input-stream.c:203 ../libsoup/soup-message-io.c:238 +msgid "Connection terminated unexpectedly" +msgstr "Połączenie zostało nieoczekiwanie zakończone" + +#: ../libsoup/soup-body-input-stream.c:459 +msgid "Invalid seek request" +msgstr "Nieprawidłowe żądanie przewinięcia" + +#: ../libsoup/soup-body-input-stream.c:487 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "Nie można skrócić SoupBodyInputStream" + +#: ../libsoup/soup-cache-input-stream.c:76 +msgid "Network stream unexpectedly closed" +msgstr "Strumień sieciowy został nieoczekiwanie zamknięty" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "Całkowite umieszczenie zasobu w pamięci podręcznej się nie powiodło" + +#: ../libsoup/soup-converter-wrapper.c:189 +#, c-format +msgid "Output buffer is too small" +msgstr "Bufor wyjściowy jest za mały" + +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "Nie można przetworzyć odpowiedzi HTTP" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "Nierozpoznane kodowanie odpowiedzi HTTP" + +#: ../libsoup/soup-message-io.c:263 +msgid "Header too big" +msgstr "Nagłówek jest za duży" + +#: ../libsoup/soup-message-io.c:396 ../libsoup/soup-message-io.c:1024 +msgid "Operation would block" +msgstr "Działanie spowodowałoby zablokowanie" + +#: ../libsoup/soup-message-io.c:976 ../libsoup/soup-message-io.c:1009 +msgid "Operation was cancelled" +msgstr "Anulowano działanie" + +#: ../libsoup/soup-message-server-io.c:64 +msgid "Could not parse HTTP request" +msgstr "Nie można przetworzyć żądania HTTP" + +#: ../libsoup/soup-request.c:141 +#, c-format +msgid "No URI provided" +msgstr "Nie podano adresu URI" + +#: ../libsoup/soup-request.c:151 +#, c-format +msgid "Invalid “%s” URI: %s" +msgstr "Nieprawidłowy adres URI „%s”: %s" + +#: ../libsoup/soup-server.c:1725 +msgid "Can’t create a TLS server without a TLS certificate" +msgstr "Nie można utworzyć serwera TLS bez certyfikatu TLS" + +#: ../libsoup/soup-server.c:1742 +#, c-format +msgid "Could not listen on address %s, port %d: " +msgstr "Nie można nasłuchiwać na adresie %s, porcie %d: " + +#: ../libsoup/soup-session.c:4524 +#, c-format +msgid "Could not parse URI “%s”" +msgstr "Nie można przetworzyć adresu URI „%s”" + +#: ../libsoup/soup-session.c:4561 +#, c-format +msgid "Unsupported URI scheme “%s”" +msgstr "Nieobsługiwany schemat adresu URI „%s”" + +#: ../libsoup/soup-session.c:4583 +#, c-format +msgid "Not an HTTP URI" +msgstr "Nie jest adresem URI protokołu HTTP" + +#: ../libsoup/soup-session.c:4781 +msgid "The server did not accept the WebSocket handshake." +msgstr "Serwer nie przyjął powitania WebSocket." + +#: ../libsoup/soup-socket.c:148 +msgid "Can’t import non-socket as SoupSocket" +msgstr "Nie można zaimportować niegniazda jako SoupSocket" + +#: ../libsoup/soup-socket.c:166 +msgid "Could not import existing socket: " +msgstr "Nie można zaimportować istniejącego gniazda: " + +#: ../libsoup/soup-socket.c:175 +msgid "Can’t import unconnected socket" +msgstr "Nie można zaimportować niepołączonego gniazda" + +#: ../libsoup/soup-websocket.c:338 ../libsoup/soup-websocket.c:347 +msgid "WebSocket handshake expected" +msgstr "Oczekiwano powitania WebSocket" + +#: ../libsoup/soup-websocket.c:355 +msgid "Unsupported WebSocket version" +msgstr "Nieobsługiwana wersja WebSocket" + +#: ../libsoup/soup-websocket.c:364 +msgid "Invalid WebSocket key" +msgstr "Nieprawidłowy klucz WebSocket" + +#: ../libsoup/soup-websocket.c:374 +#, c-format +msgid "Incorrect WebSocket “%s” header" +msgstr "Niepoprawny nagłówek „%s” WebSocket" + +#: ../libsoup/soup-websocket.c:383 +msgid "Unsupported WebSocket subprotocol" +msgstr "Nieobsługiwany podprotokół WebSocket" + +#: ../libsoup/soup-websocket.c:510 +msgid "Server rejected WebSocket handshake" +msgstr "Serwer odrzucił powitanie WebSocket" + +#: ../libsoup/soup-websocket.c:518 ../libsoup/soup-websocket.c:527 +msgid "Server ignored WebSocket handshake" +msgstr "Serwer zignorował powitanie WebSocket" + +#: ../libsoup/soup-websocket.c:539 +msgid "Server requested unsupported protocol" +msgstr "Serwer zażądał nieobsługiwanego protokołu" + +#: ../libsoup/soup-websocket.c:549 +msgid "Server requested unsupported extension" +msgstr "Serwer zażądał nieobsługiwanego rozszerzenia" + +#: ../libsoup/soup-websocket.c:562 +#, c-format +msgid "Server returned incorrect “%s” key" +msgstr "Serwer zwrócił niepoprawny klucz „%s”" + +#: ../libsoup/soup-tld.c:188 +msgid "Hostname is an IP address" +msgstr "Nazwa komputera jest adresem IP" + +#: ../libsoup/soup-tld.c:198 ../libsoup/soup-tld.c:220 +msgid "Invalid hostname" +msgstr "Nieprawidłowa nazwa komputera" + +#: ../libsoup/soup-tld.c:250 +msgid "Hostname has no base domain" +msgstr "Nazwa komputera nie ma podstawowej domeny" + +#: ../libsoup/soup-tld.c:304 +msgid "Not enough domains" +msgstr "Brak wystarczającej liczby domen" diff --git a/po/pt.po b/po/pt.po new file mode 100644 index 0000000..adf94b1 --- /dev/null +++ b/po/pt.po @@ -0,0 +1,177 @@ +# libsoup's Portuguese translation. +# Copyright © 2012, 2013 libsoup +# This file is distributed under the same license as the libsoup package. +# Duarte Loreto , 2012, 2013. +# +# Pedro Albuquerque , 2015. +# +msgid "" +msgstr "" +"Project-Id-Version: 3.8\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2015-06-07 22:39+0000\n" +"PO-Revision-Date: 2015-06-24 09:25+0100\n" +"Last-Translator: Pedro Albuquerque \n" +"Language-Team: Português \n" +"Language: pt\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Gtranslator 2.91.6\n" + +#: ../libsoup/soup-body-input-stream.c:140 +#: ../libsoup/soup-body-input-stream.c:171 +#: ../libsoup/soup-body-input-stream.c:204 ../libsoup/soup-message-io.c:235 +msgid "Connection terminated unexpectedly" +msgstr "Ligação terminou inesperadamente" + +#: ../libsoup/soup-body-input-stream.c:462 +msgid "Invalid seek request" +msgstr "Pedido de procura inválido" + +#: ../libsoup/soup-body-input-stream.c:490 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "Impossível truncar SoupBodyInputStream" + +#: ../libsoup/soup-cache-input-stream.c:74 +msgid "Network stream unexpectedly closed" +msgstr "Fluxo de rede terminado inesperadamente" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "Falha ao colocar o recurso totalmente em cache" + +#: ../libsoup/soup-converter-wrapper.c:192 +#, c-format +msgid "Output buffer is too small" +msgstr "Buffer de resultado é demasiado pequeno" + +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "Impossível processar a resposta HTTP" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "Codificação de resposta HTTP desconhecida" + +#: ../libsoup/soup-message-io.c:392 ../libsoup/soup-message-io.c:1020 +msgid "Operation would block" +msgstr "A operação iria bloquear" + +#: ../libsoup/soup-message-io.c:972 ../libsoup/soup-message-io.c:1005 +msgid "Operation was cancelled" +msgstr "A operação foi cancelada" + +#: ../libsoup/soup-message-server-io.c:64 +msgid "Could not parse HTTP request" +msgstr "Impossível processar o pedido HTTP" + +#: ../libsoup/soup-request.c:140 +#, c-format +msgid "No URI provided" +msgstr "Nenhum URI especificado" + +#: ../libsoup/soup-request.c:150 +#, c-format +msgid "Invalid '%s' URI: %s" +msgstr "URI \"%s\" inválido: %s" + +#: ../libsoup/soup-server.c:1711 +msgid "Can't create a TLS server without a TLS certificate" +msgstr "Impossível criar um servidor TLS sem um certificado TLS" + +#: ../libsoup/soup-server.c:1730 +#, c-format +msgid "Could not listen on address %s, port %d: " +msgstr "Impossível ouvir no endereço %s, porta %d: " + +#: ../libsoup/soup-session.c:4554 +#, c-format +msgid "Could not parse URI '%s'" +msgstr "Impossível processar o URI \"%s\"" + +#: ../libsoup/soup-session.c:4591 +#, c-format +msgid "Unsupported URI scheme '%s'" +msgstr "Esquema de URI \"%s\" não suportado" + +#: ../libsoup/soup-session.c:4613 +#, c-format +msgid "Not an HTTP URI" +msgstr "Não é um URI HTTP" + +#: ../libsoup/soup-session.c:4797 +msgid "The server did not accept the WebSocket handshake." +msgstr "O servidor não aceitou o handshake WebSocket." + +#: ../libsoup/soup-socket.c:148 +msgid "Can't import non-socket as SoupSocket" +msgstr "Impossível importar não socket como SoupSocket" + +#: ../libsoup/soup-socket.c:166 +msgid "Could not import existing socket: " +msgstr "Impossível importar socket existente: " + +#: ../libsoup/soup-socket.c:175 +msgid "Can't import unconnected socket" +msgstr "Impossível importar socket desligado" + +#: ../libsoup/soup-websocket.c:336 ../libsoup/soup-websocket.c:345 +msgid "WebSocket handshake expected" +msgstr "Esperado handshake WebSocket" + +#: ../libsoup/soup-websocket.c:353 +msgid "Unsupported WebSocket version" +msgstr "Versão WebSocket não suportada" + +#: ../libsoup/soup-websocket.c:362 +msgid "Invalid WebSocket key" +msgstr "Chave WebSocket inválida" + +#: ../libsoup/soup-websocket.c:372 +#, c-format +msgid "Incorrect WebSocket \"%s\" header" +msgstr "Cabeçalho WebSocket \"%s\" incorreto" + +#: ../libsoup/soup-websocket.c:381 +msgid "Unsupported WebSocket subprotocol" +msgstr "Subprotocolo WebSocket não suportado" + +#: ../libsoup/soup-websocket.c:508 +msgid "Server rejected WebSocket handshake" +msgstr "O servidor rejeitou o handshake WebSocket" + +#: ../libsoup/soup-websocket.c:516 ../libsoup/soup-websocket.c:525 +msgid "Server ignored WebSocket handshake" +msgstr "O servidor ignorou o handshake WebSocket" + +#: ../libsoup/soup-websocket.c:537 +msgid "Server requested unsupported protocol" +msgstr "O servidor pediu um protocolo não suportado" + +#: ../libsoup/soup-websocket.c:547 +msgid "Server requested unsupported extension" +msgstr "O servidor pediu uma extensão não suportada" + +#: ../libsoup/soup-websocket.c:560 +#, c-format +msgid "Server returned incorrect \"%s\" key" +msgstr "O servidor devolveu uma chave \"%s\" incorreta" + +#: ../libsoup/soup-tld.c:188 +msgid "Hostname is an IP address" +msgstr "Nome da máquina é um endereço IP" + +#: ../libsoup/soup-tld.c:198 ../libsoup/soup-tld.c:220 +msgid "Invalid hostname" +msgstr "Nome de máquina inválido" + +#: ../libsoup/soup-tld.c:250 +msgid "Hostname has no base domain" +msgstr "Nome de máquina não possui domínio base" + +#: ../libsoup/soup-tld.c:304 +msgid "Not enough domains" +msgstr "Domínios insuficientes" diff --git a/po/pt_BR.po b/po/pt_BR.po new file mode 100644 index 0000000..f09b5a3 --- /dev/null +++ b/po/pt_BR.po @@ -0,0 +1,181 @@ +# Brazilian Portuguese translation for libsoup. +# Copyright (C) 2018 libsoup's COPYRIGHT HOLDER +# This file is distributed under the same license as the libsoup package. +# Gabriel F. Vilar , 2012. +# Enrico Nicoletto , 2013, 2014. +# Rafael Fontenelle , 2015, 2017, 2018. +msgid "" +msgstr "" +"Project-Id-Version: libsoup master\n" +"Report-Msgid-Bugs-To: https://bugzilla.gnome.org/enter_bug.cgi?product=libsou" +"p&keywords=I18N+L10N&component=Misc\n" +"POT-Creation-Date: 2018-02-09 14:43+0000\n" +"PO-Revision-Date: 2018-02-16 14:47-0200\n" +"Last-Translator: Rafael Fontenelle \n" +"Language-Team: Brazilian Portuguese \n" +"Language: pt_BR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" +"X-Generator: Virtaal 1.0.0-beta1\n" +"X-Project-Style: gnome\n" + +#: ../libsoup/soup-body-input-stream.c:139 +#: ../libsoup/soup-body-input-stream.c:170 +#: ../libsoup/soup-body-input-stream.c:203 ../libsoup/soup-message-io.c:238 +msgid "Connection terminated unexpectedly" +msgstr "A conexão terminou inesperadamente" + +#: ../libsoup/soup-body-input-stream.c:459 +msgid "Invalid seek request" +msgstr "Requisição de busca inválida" + +#: ../libsoup/soup-body-input-stream.c:487 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "Não foi possível truncar SoupBodyInputStream" + +#: ../libsoup/soup-cache-input-stream.c:76 +msgid "Network stream unexpectedly closed" +msgstr "O fluxo de rede fechou de forma inesperada" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "Falha ao armazenar completamente em cache o recurso" + +#: ../libsoup/soup-converter-wrapper.c:189 +#, c-format +msgid "Output buffer is too small" +msgstr "O buffer de saída é muito pequeno" + +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "Não foi possível analisar a resposta HTTP" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "Codificação de resposta HTTP não reconhecível" + +#: ../libsoup/soup-message-io.c:263 +msgid "Header too big" +msgstr "Cabeçalho grande demais" + +#: ../libsoup/soup-message-io.c:396 ../libsoup/soup-message-io.c:1024 +msgid "Operation would block" +msgstr "A operação será bloqueada" + +#: ../libsoup/soup-message-io.c:976 ../libsoup/soup-message-io.c:1009 +msgid "Operation was cancelled" +msgstr "A operação foi cancelada" + +#: ../libsoup/soup-message-server-io.c:64 +msgid "Could not parse HTTP request" +msgstr "Não foi possível analisar a solicitação HTTP" + +#: ../libsoup/soup-request.c:141 +#, c-format +msgid "No URI provided" +msgstr "Nenhuma URI foi fornecida" + +#: ../libsoup/soup-request.c:151 +#, c-format +msgid "Invalid “%s” URI: %s" +msgstr "URI “%s” inválida: %s" + +#: ../libsoup/soup-server.c:1725 +msgid "Can’t create a TLS server without a TLS certificate" +msgstr "Não foi possível criar um servidor TLS sem um certificado TLS" + +#: ../libsoup/soup-server.c:1742 +#, c-format +msgid "Could not listen on address %s, port %d: " +msgstr "Não foi possível escutar o endereço %s, porta %d: " + +#: ../libsoup/soup-session.c:4524 +#, c-format +msgid "Could not parse URI “%s”" +msgstr "Não foi possível analisar URI “%s”" + +#: ../libsoup/soup-session.c:4561 +#, c-format +msgid "Unsupported URI scheme “%s”" +msgstr "Esquema de URI não suportado “%s”" + +#: ../libsoup/soup-session.c:4583 +#, c-format +msgid "Not an HTTP URI" +msgstr "Não é um URI do tipo HTTP" + +#: ../libsoup/soup-session.c:4781 +msgid "The server did not accept the WebSocket handshake." +msgstr "O servidor não aceitou handshake de WebSocket." + +#: ../libsoup/soup-socket.c:148 +msgid "Can’t import non-socket as SoupSocket" +msgstr "Não foi possível importar um não-soquete como SoupSocket" + +#: ../libsoup/soup-socket.c:166 +msgid "Could not import existing socket: " +msgstr "Não foi possível importar o soquete existente: " + +#: ../libsoup/soup-socket.c:175 +msgid "Can’t import unconnected socket" +msgstr "Não foi possível importar soquete desconectado" + +#: ../libsoup/soup-websocket.c:338 ../libsoup/soup-websocket.c:347 +msgid "WebSocket handshake expected" +msgstr "Handshake de WebSocket esperado" + +#: ../libsoup/soup-websocket.c:355 +msgid "Unsupported WebSocket version" +msgstr "Sem suporte à versão WebSocket" + +#: ../libsoup/soup-websocket.c:364 +msgid "Invalid WebSocket key" +msgstr "Chave WebSocket inválida" + +#: ../libsoup/soup-websocket.c:374 +#, c-format +msgid "Incorrect WebSocket “%s” header" +msgstr "Cabeçalho WebSocket “%s” incorreto" + +#: ../libsoup/soup-websocket.c:383 +msgid "Unsupported WebSocket subprotocol" +msgstr "Sem suporte ao subprotocolo WebSocket" + +#: ../libsoup/soup-websocket.c:510 +msgid "Server rejected WebSocket handshake" +msgstr "O servidor rejeitou o handshake de WebSocket" + +#: ../libsoup/soup-websocket.c:518 ../libsoup/soup-websocket.c:527 +msgid "Server ignored WebSocket handshake" +msgstr "O servidor ignorou handshake de WebSocket" + +#: ../libsoup/soup-websocket.c:539 +msgid "Server requested unsupported protocol" +msgstr "O servidor requisitou um protocolo sem suporte" + +#: ../libsoup/soup-websocket.c:549 +msgid "Server requested unsupported extension" +msgstr "O servidor requisitou uma extensão sem suporte" + +#: ../libsoup/soup-websocket.c:562 +#, c-format +msgid "Server returned incorrect “%s” key" +msgstr "O servidor retornou chave “%s” incorreta" + +#: ../libsoup/soup-tld.c:188 +msgid "Hostname is an IP address" +msgstr "O nome da máquina é um endereço de IP" + +#: ../libsoup/soup-tld.c:198 ../libsoup/soup-tld.c:220 +msgid "Invalid hostname" +msgstr "O nome da máquina é inválido" + +#: ../libsoup/soup-tld.c:250 +msgid "Hostname has no base domain" +msgstr "O nome da máquina não está na base do domínio" + +#: ../libsoup/soup-tld.c:304 +msgid "Not enough domains" +msgstr "Não há domínios suficientes" diff --git a/po/ro.po b/po/ro.po new file mode 100644 index 0000000..d07bb72 --- /dev/null +++ b/po/ro.po @@ -0,0 +1,182 @@ +# Romanian translations for the libsoup package +# Traducerea în limba română pentru pachetul libsoup. +# Copyright (C) 2012 THE libsoup'S COPYRIGHT HOLDER +# This file is distributed under the same license as the libsoup package. +# Mișu Moldovan , 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: libsoup master\n" +"Report-Msgid-Bugs-To: https://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=Misc\n" +"POT-Creation-Date: 2018-04-06 15:20+0000\n" +"PO-Revision-Date: 2018-04-11 20:07+0300\n" +"Last-Translator: Florentina Mușat \n" +"Language-Team: Romanian \n" +"Language: ro\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < " +"20)) ? 1 : 2);;\n" +"X-Generator: Poedit 2.0.6\n" +"X-Project-Style: gnome\n" + +#: ../libsoup/soup-body-input-stream.c:139 +#: ../libsoup/soup-body-input-stream.c:170 +#: ../libsoup/soup-body-input-stream.c:203 ../libsoup/soup-message-io.c:238 +msgid "Connection terminated unexpectedly" +msgstr "Conexiunea s-a terminat neașteptat" + +#: ../libsoup/soup-body-input-stream.c:459 +msgid "Invalid seek request" +msgstr "Cerere de căutare nevalidă" + +#: ../libsoup/soup-body-input-stream.c:487 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "Nu se poate trunchia SoupBodyInputStream" + +#: ../libsoup/soup-cache-input-stream.c:76 +msgid "Network stream unexpectedly closed" +msgstr "Fluxul de rețea s-a închis neașteptat" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "Nu s-a putut adăuga complet la cache resursa" + +#: ../libsoup/soup-converter-wrapper.c:189 +#, c-format +msgid "Output buffer is too small" +msgstr "Preîncărcarea de rezultat este prea mică" + +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "Nu s-a putut parsa răspunsul HTTP" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "Codare de răspuns HTTP nerecunoscută" + +#: ../libsoup/soup-message-io.c:263 +msgid "Header too big" +msgstr "Antetul este prea mare" + +#: ../libsoup/soup-message-io.c:396 ../libsoup/soup-message-io.c:1024 +msgid "Operation would block" +msgstr "Operația ar bloca" + +#: ../libsoup/soup-message-io.c:976 ../libsoup/soup-message-io.c:1009 +msgid "Operation was cancelled" +msgstr "Operația a fost anulată" + +#: ../libsoup/soup-message-server-io.c:64 +msgid "Could not parse HTTP request" +msgstr "Nu s-a putut parsa cererea HTTP" + +#: ../libsoup/soup-request.c:141 +#, c-format +msgid "No URI provided" +msgstr "Nu s-a furnizat un URI" + +#: ../libsoup/soup-request.c:151 +#, c-format +msgid "Invalid “%s” URI: %s" +msgstr "URI nevalid „%s”: %s" + +#: ../libsoup/soup-server.c:1725 +msgid "Can’t create a TLS server without a TLS certificate" +msgstr "Nu se poate crea un server TLS fără un certificat TLS" + +#: ../libsoup/soup-server.c:1742 +#, c-format +msgid "Could not listen on address %s, port %d: " +msgstr "Nu s-a putut asculta la adresa %s, portul %d: " + +#: ../libsoup/soup-session.c:4534 +#, c-format +msgid "Could not parse URI “%s”" +msgstr "Nu s-a putut parsa URI „%s”" + +#: ../libsoup/soup-session.c:4571 +#, c-format +msgid "Unsupported URI scheme “%s”" +msgstr "Schemă de URI nesuportată „%s”" + +#: ../libsoup/soup-session.c:4593 +#, c-format +msgid "Not an HTTP URI" +msgstr "Nu este un URI HTTP" + +#: ../libsoup/soup-session.c:4791 +msgid "The server did not accept the WebSocket handshake." +msgstr "Serverul nu a acceptat conectarea WebSocket." + +#: ../libsoup/soup-socket.c:148 +msgid "Can’t import non-socket as SoupSocket" +msgstr "Nu se poate importa non-soclul ca SoupSocket" + +#: ../libsoup/soup-socket.c:166 +msgid "Could not import existing socket: " +msgstr "Nu s-a putut importa soclul existent: " + +#: ../libsoup/soup-socket.c:175 +msgid "Can’t import unconnected socket" +msgstr "Nu se poate importa soclul neconectat" + +#: ../libsoup/soup-websocket.c:338 ../libsoup/soup-websocket.c:347 +msgid "WebSocket handshake expected" +msgstr "S-a așteptat o conectare WebSocket" + +#: ../libsoup/soup-websocket.c:355 +msgid "Unsupported WebSocket version" +msgstr "Versiune de WebSocket nesuportată" + +#: ../libsoup/soup-websocket.c:364 +msgid "Invalid WebSocket key" +msgstr "Cheie de WebSocket nevalidă" + +#: ../libsoup/soup-websocket.c:374 +#, c-format +msgid "Incorrect WebSocket “%s” header" +msgstr "Antet „%s” de WebSocket incorect" + +#: ../libsoup/soup-websocket.c:383 +msgid "Unsupported WebSocket subprotocol" +msgstr "Subprotocol de WebSocket nesuportat" + +#: ../libsoup/soup-websocket.c:510 +msgid "Server rejected WebSocket handshake" +msgstr "Serverul a respins conectarea WebSocket" + +#: ../libsoup/soup-websocket.c:518 ../libsoup/soup-websocket.c:527 +msgid "Server ignored WebSocket handshake" +msgstr "Serverul a ignorat conectarea WebSocket" + +#: ../libsoup/soup-websocket.c:539 +msgid "Server requested unsupported protocol" +msgstr "Serverul a cerut un protocol nesuportat" + +#: ../libsoup/soup-websocket.c:549 +msgid "Server requested unsupported extension" +msgstr "Serverul a cerut o extensie nesuportată" + +#: ../libsoup/soup-websocket.c:562 +#, c-format +msgid "Server returned incorrect “%s” key" +msgstr "Serverul a întors cheia „%s” incorectă" + +#: ../libsoup/soup-tld.c:187 +msgid "Hostname is an IP address" +msgstr "Numele de gazdă este o adresă IP" + +#: ../libsoup/soup-tld.c:197 ../libsoup/soup-tld.c:219 +msgid "Invalid hostname" +msgstr "Nume de gazdă nevalid" + +#: ../libsoup/soup-tld.c:249 +msgid "Hostname has no base domain" +msgstr "Numele de gazdă nu are un domeniu de bază" + +#: ../libsoup/soup-tld.c:303 +msgid "Not enough domains" +msgstr "Nu sunt destule domenii" diff --git a/po/ru.po b/po/ru.po new file mode 100644 index 0000000..a3458b4 --- /dev/null +++ b/po/ru.po @@ -0,0 +1,179 @@ +# Russian translation for libsoup. +# Copyright (C) 2012 libsoup's COPYRIGHT HOLDER +# This file is distributed under the same license as the libsoup package. +# +# Yuri Myasoedov , 2012, 2013. +# Stas Solovey , 2015. +# +msgid "" +msgstr "" +"Project-Id-Version: libsoup master\n" +"Report-Msgid-Bugs-To: https://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=Misc\n" +"POT-Creation-Date: 2017-02-23 10:17+0000\n" +"PO-Revision-Date: 2017-03-17 19:33+0400\n" +"Last-Translator: Yuri Myasoedov \n" +"Language-Team: Русский \n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" +"X-Generator: Poedit 1.8.7.1\n" + +#: ../libsoup/soup-body-input-stream.c:139 +#: ../libsoup/soup-body-input-stream.c:170 +#: ../libsoup/soup-body-input-stream.c:203 ../libsoup/soup-message-io.c:235 +msgid "Connection terminated unexpectedly" +msgstr "Соединение было неожиданно разорвано" + +#: ../libsoup/soup-body-input-stream.c:459 +msgid "Invalid seek request" +msgstr "Неверный запрос поиска" + +#: ../libsoup/soup-body-input-stream.c:487 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "Не удалось отсечь SoupBodyInputStream" + +#: ../libsoup/soup-cache-input-stream.c:76 +msgid "Network stream unexpectedly closed" +msgstr "Сетевой поток неожиданно закрылся" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "Не удалось полностью закэшировать ресурс" + +#: ../libsoup/soup-converter-wrapper.c:189 +#, c-format +msgid "Output buffer is too small" +msgstr "Слишком маленький буфер вывода" + +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "Не удалось разобрать HTTP-ответ" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "Нераспознанная кодировка HTTP-ответа" + +#: ../libsoup/soup-message-io.c:392 ../libsoup/soup-message-io.c:1020 +msgid "Operation would block" +msgstr "Действие заблокировано" + +#: ../libsoup/soup-message-io.c:972 ../libsoup/soup-message-io.c:1005 +msgid "Operation was cancelled" +msgstr "Действие отменено" + +#: ../libsoup/soup-message-server-io.c:64 +msgid "Could not parse HTTP request" +msgstr "Не удалось разобрать HTTP-запрос" + +#: ../libsoup/soup-request.c:141 +#, c-format +msgid "No URI provided" +msgstr "Не указан URI" + +#: ../libsoup/soup-request.c:151 +#, c-format +msgid "Invalid “%s” URI: %s" +msgstr "Недопустимый URI «%s»: %s" + +#: ../libsoup/soup-server.c:1725 +msgid "Can’t create a TLS server without a TLS certificate" +msgstr "Невозможно создать TLS-сервер без TLS-сертификата" + +#: ../libsoup/soup-server.c:1742 +#, c-format +msgid "Could not listen on address %s, port %d: " +msgstr "Не удалось начать прослушивание по адресу %s (порт — %d): " + +#: ../libsoup/soup-session.c:4518 +#, c-format +msgid "Could not parse URI “%s”" +msgstr "Не удалось разобрать URI «%s»" + +#: ../libsoup/soup-session.c:4555 +#, c-format +msgid "Unsupported URI scheme “%s”" +msgstr "Неподдерживаемая схема URI «%s»" + +#: ../libsoup/soup-session.c:4577 +#, c-format +msgid "Not an HTTP URI" +msgstr "Формат URI отличается от HTTP" + +#: ../libsoup/soup-session.c:4763 +msgid "The server did not accept the WebSocket handshake." +msgstr "Сервер не принимает подтверждение связи WebSocket." + +#: ../libsoup/soup-socket.c:148 +msgid "Can’t import non-socket as SoupSocket" +msgstr "" +"Невозможно импортировать объект, отличный от сокета, в качестве SoupSocket" + +#: ../libsoup/soup-socket.c:166 +msgid "Could not import existing socket: " +msgstr "Не удалось импортировать существующий сокет: " + +#: ../libsoup/soup-socket.c:175 +msgid "Can’t import unconnected socket" +msgstr "Невозможно импортировать неподключенный сокет" + +#: ../libsoup/soup-websocket.c:338 ../libsoup/soup-websocket.c:347 +msgid "WebSocket handshake expected" +msgstr "Ожидается подтверждение связи WebSocket" + +#: ../libsoup/soup-websocket.c:355 +msgid "Unsupported WebSocket version" +msgstr "Неподдерживаемая версия WebSocket" + +#: ../libsoup/soup-websocket.c:364 +msgid "Invalid WebSocket key" +msgstr "Неверный ключ WebSocket" + +#: ../libsoup/soup-websocket.c:374 +#, c-format +msgid "Incorrect WebSocket “%s” header" +msgstr "Неправильный заголовок WebSocket «%s»" + +#: ../libsoup/soup-websocket.c:383 +msgid "Unsupported WebSocket subprotocol" +msgstr "Неподдерживаемый подпротокол WebSocket" + +#: ../libsoup/soup-websocket.c:510 +msgid "Server rejected WebSocket handshake" +msgstr "Сервер отклонил подтверждение связи WebSocket" + +#: ../libsoup/soup-websocket.c:518 ../libsoup/soup-websocket.c:527 +msgid "Server ignored WebSocket handshake" +msgstr "Сервер проигнорировал подтверждение связи WebSocket" + +#: ../libsoup/soup-websocket.c:539 +msgid "Server requested unsupported protocol" +msgstr "Сервер запросил неподдерживаемый протокол" + +#: ../libsoup/soup-websocket.c:549 +msgid "Server requested unsupported extension" +msgstr "Сервер запросил неподдерживаемое расширение" + +#: ../libsoup/soup-websocket.c:562 +#, c-format +msgid "Server returned incorrect “%s” key" +msgstr "Сервер вернул неправильный ключ «%s»" + +#: ../libsoup/soup-tld.c:188 +msgid "Hostname is an IP address" +msgstr "Имя компьютера является IP-адресом" + +#: ../libsoup/soup-tld.c:198 ../libsoup/soup-tld.c:220 +msgid "Invalid hostname" +msgstr "Неверное имя компьютера" + +#: ../libsoup/soup-tld.c:250 +msgid "Hostname has no base domain" +msgstr "Имя компьютера не содержит доменной части" + +#: ../libsoup/soup-tld.c:304 +msgid "Not enough domains" +msgstr "Недостаточно доменных имён в адресе" diff --git a/po/sk.po b/po/sk.po new file mode 100644 index 0000000..8e03e5a --- /dev/null +++ b/po/sk.po @@ -0,0 +1,185 @@ +# Slovak translation for libsoup. +# Copyright (C) 2012-2013 libsoup's COPYRIGHT HOLDER +# This file is distributed under the same license as the libsoup package. +# Pavol Klačanský , 2012-2013. +# +msgid "" +msgstr "" +"Project-Id-Version: libsoup\n" +"Report-Msgid-Bugs-To: https://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=Misc\n" +"POT-Creation-Date: 2018-02-09 14:43+0000\n" +"PO-Revision-Date: 2018-03-17 21:37+0100\n" +"Last-Translator: Dušan Kazik \n" +"Language-Team: Slovak \n" +"Language: sk\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n==1) ? 1 : (n>=2 && n<=4) ? 2 : 0;\n" +"X-Generator: Poedit 2.0.6\n" + +#: ../libsoup/soup-body-input-stream.c:139 +#: ../libsoup/soup-body-input-stream.c:170 +#: ../libsoup/soup-body-input-stream.c:203 ../libsoup/soup-message-io.c:238 +msgid "Connection terminated unexpectedly" +msgstr "Pripojenie bolo neočakávane ukončené" + +#: ../libsoup/soup-body-input-stream.c:459 +msgid "Invalid seek request" +msgstr "Neplatná požiadavka na posunutie" + +# struct +#: ../libsoup/soup-body-input-stream.c:487 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "SoupBodyInputStream sa nedá skrátiť" + +#: ../libsoup/soup-cache-input-stream.c:76 +msgid "Network stream unexpectedly closed" +msgstr "Sieťový prúd bol neočakávane uzavretý" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "Úplné načítanie zdroja do dočasnej pamäte zlyhalo" + +# PM: buffer by som preložil ako schránka +# PK: schranka je clipboard, buffer je jednoznacne vyrovnavacia pamet +#: ../libsoup/soup-converter-wrapper.c:189 +#, c-format +msgid "Output buffer is too small" +msgstr "Výstupná vyrovnávacia pamäť je príliš malá" + +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "Nepodarilo sa analyzovať odpoveď HTTP" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "Nerozpoznané kódovanie odpovede HTTP" + +#: ../libsoup/soup-message-io.c:263 +msgid "Header too big" +msgstr "Záhlavie je príliš veľké" + +# PK: tu neviem ako to povedat, malo by ist o to, ze proste ta operacia neni async +#: ../libsoup/soup-message-io.c:396 ../libsoup/soup-message-io.c:1024 +msgid "Operation would block" +msgstr "Operácia by blokovala spracovanie" + +#: ../libsoup/soup-message-io.c:976 ../libsoup/soup-message-io.c:1009 +msgid "Operation was cancelled" +msgstr "Operácia bola zrušená" + +#: ../libsoup/soup-message-server-io.c:64 +msgid "Could not parse HTTP request" +msgstr "Nepodarilo sa analyzovať požiadavku HTTP" + +# error +#: ../libsoup/soup-request.c:141 +#, c-format +msgid "No URI provided" +msgstr "Nebol poskytnutý identifikátor URI" + +# first %s - scheme (http, ftp, ...) +#: ../libsoup/soup-request.c:151 +#, c-format +msgid "Invalid “%s” URI: %s" +msgstr "Neplatná schéma „%s“ identifikátora URI: %s" + +#: ../libsoup/soup-server.c:1725 +msgid "Can’t create a TLS server without a TLS certificate" +msgstr "Nedá sa vytvoriť TLS server bez TLS certifikátu" + +#: ../libsoup/soup-server.c:1742 +#, c-format +msgid "Could not listen on address %s, port %d: " +msgstr "Nepodarilo sa počúvať na adrese %s, porte %d: " + +#: ../libsoup/soup-session.c:4524 +#, c-format +msgid "Could not parse URI “%s”" +msgstr "Nepodarilo sa analyzovať identifikátor URI „%s“" + +#: ../libsoup/soup-session.c:4561 +#, c-format +msgid "Unsupported URI scheme “%s”" +msgstr "Nepodporovaná schéma „%s“ pre identifikátor URI" + +#: ../libsoup/soup-session.c:4583 +#, c-format +msgid "Not an HTTP URI" +msgstr "Nie je HTTP URI" + +#: ../libsoup/soup-session.c:4781 +msgid "The server did not accept the WebSocket handshake." +msgstr "Server neprijal vyjednanie protokolu WebSocket." + +#: ../libsoup/soup-socket.c:148 +msgid "Can’t import non-socket as SoupSocket" +msgstr "Nedá sa importovať ne-soket ako SoupSocket" + +#: ../libsoup/soup-socket.c:166 +msgid "Could not import existing socket: " +msgstr "Nepodarilo sa importovať existujúci soket: " + +#: ../libsoup/soup-socket.c:175 +msgid "Can’t import unconnected socket" +msgstr "Nedá sa importovať nepripojený soket" + +#: ../libsoup/soup-websocket.c:338 ../libsoup/soup-websocket.c:347 +msgid "WebSocket handshake expected" +msgstr "Očakávalo sa vyjednanie protokolu WebSocket" + +#: ../libsoup/soup-websocket.c:355 +msgid "Unsupported WebSocket version" +msgstr "Nepodporovaná verzia protokolu WebSocket" + +#: ../libsoup/soup-websocket.c:364 +msgid "Invalid WebSocket key" +msgstr "Neplatný kľúč protokolu WebSocket" + +#: ../libsoup/soup-websocket.c:374 +#, c-format +msgid "Incorrect WebSocket “%s” header" +msgstr "Nesprávna hlavička „%s“ protokolu Websocket" + +#: ../libsoup/soup-websocket.c:383 +msgid "Unsupported WebSocket subprotocol" +msgstr "Nepodporovaný podprotokol protokolu WebSocket" + +#: ../libsoup/soup-websocket.c:510 +msgid "Server rejected WebSocket handshake" +msgstr "Server odmietol vyjednanie protokolu WebSocket" + +#: ../libsoup/soup-websocket.c:518 ../libsoup/soup-websocket.c:527 +msgid "Server ignored WebSocket handshake" +msgstr "Server ignoroval vyjednanie protokolu WebSocket" + +#: ../libsoup/soup-websocket.c:539 +msgid "Server requested unsupported protocol" +msgstr "Server si vyžiadal nepodporovaný protokol" + +#: ../libsoup/soup-websocket.c:549 +msgid "Server requested unsupported extension" +msgstr "Server si vyžiadal nepodporované rozšírenie" + +#: ../libsoup/soup-websocket.c:562 +#, c-format +msgid "Server returned incorrect “%s” key" +msgstr "Server vrátil nesprávny kľúč „%s“" + +#: ../libsoup/soup-tld.c:188 +msgid "Hostname is an IP address" +msgstr "Názov hostiteľa je adresa IP" + +#: ../libsoup/soup-tld.c:198 ../libsoup/soup-tld.c:220 +msgid "Invalid hostname" +msgstr "Neplatný názov hostiteľa" + +#: ../libsoup/soup-tld.c:250 +msgid "Hostname has no base domain" +msgstr "Názov hostiteľa neobsahuje základnú doménu" + +#: ../libsoup/soup-tld.c:304 +msgid "Not enough domains" +msgstr "Nedostatočný počet domén" diff --git a/po/sl.po b/po/sl.po new file mode 100644 index 0000000..ecded71 --- /dev/null +++ b/po/sl.po @@ -0,0 +1,209 @@ +# Slovenian translation for libsoup. +# Copyright (C) 2012 libsoup's COPYRIGHT HOLDER +# This file is distributed under the same license as the libsoup package. +# +# Matej Urbančič , 2012–2018. +# +msgid "" +msgstr "" +"Project-Id-Version: libsoup master\n" +"Report-Msgid-Bugs-To: https://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=Misc\n" +"POT-Creation-Date: 2018-03-05 17:45+0000\n" +"PO-Revision-Date: 2018-03-06 22:01+0100\n" +"Last-Translator: Matej Urbančič \n" +"Language-Team: Slovenian \n" +"Language: sl\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=4; plural=(n%100==1 ? 1 : n%100==2 ? 2 : n%100==3 || n" +"%100==4 ? 3 : 0);\n" +"X-Poedit-SourceCharset: utf-8\n" +"X-Generator: Poedit 2.0.4\n" + +#: ../libsoup/soup-body-input-stream.c:139 +#: ../libsoup/soup-body-input-stream.c:170 +#: ../libsoup/soup-body-input-stream.c:203 ../libsoup/soup-message-io.c:238 +msgid "Connection terminated unexpectedly" +msgstr "Povezava je nepričakovano končana" + +#: ../libsoup/soup-body-input-stream.c:459 +msgid "Invalid seek request" +msgstr "Neveljavna zahteva iskanja" + +#: ../libsoup/soup-body-input-stream.c:487 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "Ni mogoče porezati SoupBodyInputStream" + +#: ../libsoup/soup-cache-input-stream.c:76 +msgid "Network stream unexpectedly closed" +msgstr "Omrežni pretok se je nepričakovano zaprl" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "Ustvarjanje predpomnilnika vira je spodletelo" + +#: ../libsoup/soup-converter-wrapper.c:189 +#, c-format +msgid "Output buffer is too small" +msgstr "Odvodni medpomnilnik je premajhen." + +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "Odziva HTTP ni mogoče razčleniti" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "Neprepoznano kodiranje odziva HTTP" + +#: ../libsoup/soup-message-io.c:263 +msgid "Header too big" +msgstr "Glava je prevelika" + +#: ../libsoup/soup-message-io.c:396 ../libsoup/soup-message-io.c:1024 +msgid "Operation would block" +msgstr "Opravilo bi zaustavilo delovanje" + +#: ../libsoup/soup-message-io.c:976 ../libsoup/soup-message-io.c:1009 +msgid "Operation was cancelled" +msgstr "Opravilo je preklicano." + +#: ../libsoup/soup-message-server-io.c:64 +msgid "Could not parse HTTP request" +msgstr "Zahteve HTTP ni mogoče razčleniti" + +#: ../libsoup/soup-request.c:141 +#, c-format +msgid "No URI provided" +msgstr "Ni podanega naslova URI" + +#: ../libsoup/soup-request.c:151 +#, c-format +msgid "Invalid “%s” URI: %s" +msgstr "Neveljaven naslov URI “%s”: %s" + +#: ../libsoup/soup-server.c:1725 +msgid "Can’t create a TLS server without a TLS certificate" +msgstr "Ni mogoče ustvariti strežnika TLS brez ustreznega potrdila TLS." + +#: ../libsoup/soup-server.c:1742 +#, c-format +msgid "Could not listen on address %s, port %d: " +msgstr "Ni mogoče prisluhniti naslovu %s, vrata %d:" + +#: ../libsoup/soup-session.c:4524 +#, c-format +msgid "Could not parse URI “%s”" +msgstr "Ni mogoče razčleniti naslova URI “%s”" + +#: ../libsoup/soup-session.c:4561 +#, c-format +msgid "Unsupported URI scheme “%s”" +msgstr "Nepodprta shema naslova URI “%s”" + +#: ../libsoup/soup-session.c:4583 +#, c-format +msgid "Not an HTTP URI" +msgstr "Naslov ni v obliki HTTP URI" + +#: ../libsoup/soup-session.c:4781 +msgid "The server did not accept the WebSocket handshake." +msgstr "Strežnik ne podpira zahteve overitve WebSocket" + +#: ../libsoup/soup-socket.c:148 +msgid "Can’t import non-socket as SoupSocket" +msgstr "Ni mogoče uvoziti predmeta, ki ni vtič, kot SoupSocket" + +#: ../libsoup/soup-socket.c:166 +msgid "Could not import existing socket: " +msgstr "Ni mogoče uvoziti obstoječega vtiča:" + +#: ../libsoup/soup-socket.c:175 +msgid "Can’t import unconnected socket" +msgstr "Ni mogoče uvoziti nepovezanega vtiča" + +#: ../libsoup/soup-websocket.c:338 ../libsoup/soup-websocket.c:347 +msgid "WebSocket handshake expected" +msgstr "Pričakovana je zahteva overitve z WebSocket" + +#: ../libsoup/soup-websocket.c:355 +msgid "Unsupported WebSocket version" +msgstr "Nepodprta različica WebSocket" + +#: ../libsoup/soup-websocket.c:364 +msgid "Invalid WebSocket key" +msgstr "Neveljaven ključ WebSocket" + +#: ../libsoup/soup-websocket.c:374 +#, c-format +msgid "Incorrect WebSocket “%s” header" +msgstr "Neveljavna glava WebSocket \"%s\"" + +#: ../libsoup/soup-websocket.c:383 +msgid "Unsupported WebSocket subprotocol" +msgstr "Nepodprt podrejeni protokol WebSocket" + +#: ../libsoup/soup-websocket.c:510 +msgid "Server rejected WebSocket handshake" +msgstr "Strežnik je zavrnil zahtevo overitve WebSocket" + +#: ../libsoup/soup-websocket.c:518 ../libsoup/soup-websocket.c:527 +msgid "Server ignored WebSocket handshake" +msgstr "Strežnik je prezrl zahtevo overitve z WebSocket" + +#: ../libsoup/soup-websocket.c:539 +msgid "Server requested unsupported protocol" +msgstr "Strežnik zahteva nepodprt protokol" + +#: ../libsoup/soup-websocket.c:549 +msgid "Server requested unsupported extension" +msgstr "Strežnik zahteva nepodprto razširitev" + +#: ../libsoup/soup-websocket.c:562 +#, c-format +msgid "Server returned incorrect “%s” key" +msgstr "Strežnik je vrnil neveljaven ključ \"%s\"" + +#: ../libsoup/soup-tld.c:187 +msgid "Hostname is an IP address" +msgstr "Ime gostitelja je naslov IP" + +#: ../libsoup/soup-tld.c:197 ../libsoup/soup-tld.c:219 +msgid "Invalid hostname" +msgstr "Neveljavno ime gostitelja" + +#: ../libsoup/soup-tld.c:249 +msgid "Hostname has no base domain" +msgstr "Ime gostitelja je brez osnovne domene" + +#: ../libsoup/soup-tld.c:303 +msgid "Not enough domains" +msgstr "Ni dovolj domen" + +#~ msgid "Invalid '%s' URI: %s" +#~ msgstr "Neveljaven naslov URI '%s': %s" + +#~ msgid "Can't create a TLS server without a TLS certificate" +#~ msgstr "Ni mogoče ustvariti strežnika TLS brez ustreznega potrdila TLS." + +#~ msgid "Could not listen on address %s, port %d" +#~ msgstr "Ni mogoče prisluhniti naslovu %s, vrata %d" + +#~ msgid "Could not parse URI '%s'" +#~ msgstr "Ni mogoče razčleniti naslova URI '%s'" + +#~ msgid "Unsupported URI scheme '%s'" +#~ msgstr "Nepodprta shema URI '%s'" + +#~ msgid "Can't import non-socket as SoupSocket" +#~ msgstr "Ni mogoče uvoziti predmeta, ki ni vtič, kot SoupSocket" + +#~ msgid "Can't import unconnected socket" +#~ msgstr "Ni mogoče uvoziti nepovezanega vtiča" + +#~ msgid "Incorrect WebSocket \"%s\" header" +#~ msgstr "Neveljavna glava WebSocket \"%s\"" + +#~ msgid "Server returned incorrect \"%s\" key" +#~ msgstr "Strežnik je vrnil neveljavni ključ \"%s\"" diff --git a/po/sr.po b/po/sr.po new file mode 100644 index 0000000..0848f4c --- /dev/null +++ b/po/sr.po @@ -0,0 +1,180 @@ +# Serbian translation of libsoup. +# Courtesy of Prevod.org team (http://prevod.org/) -- 2012—2017. +# This file is distributed under the same license as the libsoup package. +# Мирослав Николић , 2011—2017. +msgid "" +msgstr "" +"Project-Id-Version: libsoup master\n" +"Report-Msgid-Bugs-To: https://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=Misc\n" +"POT-Creation-Date: 2018-02-09 14:43+0000\n" +"PO-Revision-Date: 2018-02-21 21:49+0100\n" +"Last-Translator: Марко М. Костић \n" +"Language-Team: Serbian <(nothing)>\n" +"Language: sr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=4; plural=n==1? 3 : n%10==1 && n%100!=11 ? 0 : n" +"%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" +"X-Project-Style: gnome\n" +"X-Generator: Poedit 2.0.6\n" + +#: ../libsoup/soup-body-input-stream.c:139 +#: ../libsoup/soup-body-input-stream.c:170 +#: ../libsoup/soup-body-input-stream.c:203 ../libsoup/soup-message-io.c:238 +msgid "Connection terminated unexpectedly" +msgstr "Веза је неочекивано затворена" + +#: ../libsoup/soup-body-input-stream.c:459 +msgid "Invalid seek request" +msgstr "Неисправан захтев претраге" + +#: ../libsoup/soup-body-input-stream.c:487 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "Не могу да скратим улазни ток тела Супице" + +#: ../libsoup/soup-cache-input-stream.c:76 +msgid "Network stream unexpectedly closed" +msgstr "Мрежни ток је изненадно затворен" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "Нисам успео у потпуности да сместим извориште у оставу" + +#: ../libsoup/soup-converter-wrapper.c:189 +#, c-format +msgid "Output buffer is too small" +msgstr "Међумеморија излаза је премала" + +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "Не могу да обрадим ХТТП одговор" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "Непознато кодирање ХТТП одговора" + +#: ../libsoup/soup-message-io.c:263 +msgid "Header too big" +msgstr "Заглавље је превелико" + +#: ../libsoup/soup-message-io.c:396 ../libsoup/soup-message-io.c:1024 +msgid "Operation would block" +msgstr "Поступак би блокирао" + +#: ../libsoup/soup-message-io.c:976 ../libsoup/soup-message-io.c:1009 +msgid "Operation was cancelled" +msgstr "Радња је отказана" + +#: ../libsoup/soup-message-server-io.c:64 +msgid "Could not parse HTTP request" +msgstr "Не могу да обрадим ХТТП захтев" + +#: ../libsoup/soup-request.c:141 +#, c-format +msgid "No URI provided" +msgstr "Није наведена путања" + +#: ../libsoup/soup-request.c:151 +#, c-format +msgid "Invalid “%s” URI: %s" +msgstr "Неисправна „%s“ путања: %s" + +#: ../libsoup/soup-server.c:1725 +msgid "Can’t create a TLS server without a TLS certificate" +msgstr "Не могу да направим ТЛС сервер без ТЛС уверења" + +#: ../libsoup/soup-server.c:1742 +#, c-format +msgid "Could not listen on address %s, port %d: " +msgstr "Не могу да ослушкујем на адреси „%s“, прикључник %d: " + +#: ../libsoup/soup-session.c:4524 +#, c-format +msgid "Could not parse URI “%s”" +msgstr "Не могу да обрадим путању „%s“" + +#: ../libsoup/soup-session.c:4561 +#, c-format +msgid "Unsupported URI scheme “%s”" +msgstr "Неподржана „%s“ шема путање" + +#: ../libsoup/soup-session.c:4583 +#, c-format +msgid "Not an HTTP URI" +msgstr "Није ХТТП путања" + +#: ../libsoup/soup-session.c:4781 +msgid "The server did not accept the WebSocket handshake." +msgstr "Сервер не прихвата руковање Веб прикључнице." + +#: ../libsoup/soup-socket.c:148 +msgid "Can’t import non-socket as SoupSocket" +msgstr "Не могу да увезем не-прикључницу на прикључници Супице" + +#: ../libsoup/soup-socket.c:166 +msgid "Could not import existing socket: " +msgstr "Не могу да увезем постојећу прикључницу: " + +#: ../libsoup/soup-socket.c:175 +msgid "Can’t import unconnected socket" +msgstr "Не могу да увезем неповезану прикључницу" + +#: ../libsoup/soup-websocket.c:338 ../libsoup/soup-websocket.c:347 +msgid "WebSocket handshake expected" +msgstr "Очекивано је руковање Веб прикључнице" + +#: ../libsoup/soup-websocket.c:355 +msgid "Unsupported WebSocket version" +msgstr "Неподржано издање Веб прикључнице" + +#: ../libsoup/soup-websocket.c:364 +msgid "Invalid WebSocket key" +msgstr "Неисправан кључ Веб прикључнице" + +#: ../libsoup/soup-websocket.c:374 +#, c-format +msgid "Incorrect WebSocket “%s” header" +msgstr "Неисправно заглавље „%s“ Веб прикључнице" + +#: ../libsoup/soup-websocket.c:383 +msgid "Unsupported WebSocket subprotocol" +msgstr "Неподржан подпротокол Веб прикључнице" + +#: ../libsoup/soup-websocket.c:510 +msgid "Server rejected WebSocket handshake" +msgstr "Сервер је одбацио руковање Веб прикључнице" + +#: ../libsoup/soup-websocket.c:518 ../libsoup/soup-websocket.c:527 +msgid "Server ignored WebSocket handshake" +msgstr "Сервер је занемарио руковање Веб прикључнице" + +#: ../libsoup/soup-websocket.c:539 +msgid "Server requested unsupported protocol" +msgstr "Сервер је затражио неподржани протокол" + +#: ../libsoup/soup-websocket.c:549 +msgid "Server requested unsupported extension" +msgstr "Сервер је затражио неподржано проширење" + +#: ../libsoup/soup-websocket.c:562 +#, c-format +msgid "Server returned incorrect “%s” key" +msgstr "Сервер је вратио неисправан кључ „%s“" + +#: ../libsoup/soup-tld.c:188 +msgid "Hostname is an IP address" +msgstr "Назив домаћина је ИП адреса" + +#: ../libsoup/soup-tld.c:198 ../libsoup/soup-tld.c:220 +msgid "Invalid hostname" +msgstr "Неисправан назив домаћина" + +#: ../libsoup/soup-tld.c:250 +msgid "Hostname has no base domain" +msgstr "Назив домаћина нема основни домен" + +#: ../libsoup/soup-tld.c:304 +msgid "Not enough domains" +msgstr "Нема довољно домена" diff --git a/po/sr@latin.po b/po/sr@latin.po new file mode 100644 index 0000000..f4cb5e3 --- /dev/null +++ b/po/sr@latin.po @@ -0,0 +1,180 @@ +# Serbian translation of libsoup. +# Courtesy of Prevod.org team (http://prevod.org/) -- 2012—2017. +# This file is distributed under the same license as the libsoup package. +# Miroslav Nikolić , 2011—2017. +msgid "" +msgstr "" +"Project-Id-Version: libsoup master\n" +"Report-Msgid-Bugs-To: https://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=Misc\n" +"POT-Creation-Date: 2018-02-21 17:01+0000\n" +"PO-Revision-Date: 2018-02-21 21:49+0100\n" +"Last-Translator: Marko M. Kostić \n" +"Language-Team: Serbian <(nothing)>\n" +"Language: sr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=4; plural=n==1? 3 : n%10==1 && n%100!=11 ? 0 : n" +"%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" +"X-Project-Style: gnome\n" +"X-Generator: Poedit 2.0.6\n" + +#: ../libsoup/soup-body-input-stream.c:139 +#: ../libsoup/soup-body-input-stream.c:170 +#: ../libsoup/soup-body-input-stream.c:203 ../libsoup/soup-message-io.c:238 +msgid "Connection terminated unexpectedly" +msgstr "Veza je neočekivano zatvorena" + +#: ../libsoup/soup-body-input-stream.c:459 +msgid "Invalid seek request" +msgstr "Neispravan zahtev pretrage" + +#: ../libsoup/soup-body-input-stream.c:487 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "Ne mogu da skratim ulazni tok tela Supice" + +#: ../libsoup/soup-cache-input-stream.c:76 +msgid "Network stream unexpectedly closed" +msgstr "Mrežni tok je iznenadno zatvoren" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "Nisam uspeo u potpunosti da smestim izvorište u ostavu" + +#: ../libsoup/soup-converter-wrapper.c:189 +#, c-format +msgid "Output buffer is too small" +msgstr "Međumemorija izlaza je premala" + +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "Ne mogu da obradim HTTP odgovor" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "Nepoznato kodiranje HTTP odgovora" + +#: ../libsoup/soup-message-io.c:263 +msgid "Header too big" +msgstr "Zaglavlje je preveliko" + +#: ../libsoup/soup-message-io.c:396 ../libsoup/soup-message-io.c:1024 +msgid "Operation would block" +msgstr "Postupak bi blokirao" + +#: ../libsoup/soup-message-io.c:976 ../libsoup/soup-message-io.c:1009 +msgid "Operation was cancelled" +msgstr "Radnja je otkazana" + +#: ../libsoup/soup-message-server-io.c:64 +msgid "Could not parse HTTP request" +msgstr "Ne mogu da obradim HTTP zahtev" + +#: ../libsoup/soup-request.c:141 +#, c-format +msgid "No URI provided" +msgstr "Nije navedena putanja" + +#: ../libsoup/soup-request.c:151 +#, c-format +msgid "Invalid “%s” URI: %s" +msgstr "Neispravna „%s“ putanja: %s" + +#: ../libsoup/soup-server.c:1725 +msgid "Can’t create a TLS server without a TLS certificate" +msgstr "Ne mogu da napravim TLS server bez TLS uverenja" + +#: ../libsoup/soup-server.c:1742 +#, c-format +msgid "Could not listen on address %s, port %d: " +msgstr "Ne mogu da osluškujem na adresi „%s“, priključnik %d: " + +#: ../libsoup/soup-session.c:4524 +#, c-format +msgid "Could not parse URI “%s”" +msgstr "Ne mogu da obradim putanju „%s“" + +#: ../libsoup/soup-session.c:4561 +#, c-format +msgid "Unsupported URI scheme “%s”" +msgstr "Nepodržana „%s“ šema putanje" + +#: ../libsoup/soup-session.c:4583 +#, c-format +msgid "Not an HTTP URI" +msgstr "Nije HTTP putanja" + +#: ../libsoup/soup-session.c:4781 +msgid "The server did not accept the WebSocket handshake." +msgstr "Server ne prihvata rukovanje Veb priključnice." + +#: ../libsoup/soup-socket.c:148 +msgid "Can’t import non-socket as SoupSocket" +msgstr "Ne mogu da uvezem ne-priključnicu na priključnici Supice" + +#: ../libsoup/soup-socket.c:166 +msgid "Could not import existing socket: " +msgstr "Ne mogu da uvezem postojeću priključnicu: " + +#: ../libsoup/soup-socket.c:175 +msgid "Can’t import unconnected socket" +msgstr "Ne mogu da uvezem nepovezanu priključnicu" + +#: ../libsoup/soup-websocket.c:338 ../libsoup/soup-websocket.c:347 +msgid "WebSocket handshake expected" +msgstr "Očekivano je rukovanje Veb priključnice" + +#: ../libsoup/soup-websocket.c:355 +msgid "Unsupported WebSocket version" +msgstr "Nepodržano izdanje Veb priključnice" + +#: ../libsoup/soup-websocket.c:364 +msgid "Invalid WebSocket key" +msgstr "Neispravan ključ Veb priključnice" + +#: ../libsoup/soup-websocket.c:374 +#, c-format +msgid "Incorrect WebSocket “%s” header" +msgstr "Neispravno zaglavlje „%s“ Veb priključnice" + +#: ../libsoup/soup-websocket.c:383 +msgid "Unsupported WebSocket subprotocol" +msgstr "Nepodržan podprotokol Veb priključnice" + +#: ../libsoup/soup-websocket.c:510 +msgid "Server rejected WebSocket handshake" +msgstr "Server je odbacio rukovanje Veb priključnice" + +#: ../libsoup/soup-websocket.c:518 ../libsoup/soup-websocket.c:527 +msgid "Server ignored WebSocket handshake" +msgstr "Server je zanemario rukovanje Veb priključnice" + +#: ../libsoup/soup-websocket.c:539 +msgid "Server requested unsupported protocol" +msgstr "Server je zatražio nepodržani protokol" + +#: ../libsoup/soup-websocket.c:549 +msgid "Server requested unsupported extension" +msgstr "Server je zatražio nepodržano proširenje" + +#: ../libsoup/soup-websocket.c:562 +#, c-format +msgid "Server returned incorrect “%s” key" +msgstr "Server je vratio neispravan ključ „%s“" + +#: ../libsoup/soup-tld.c:187 +msgid "Hostname is an IP address" +msgstr "Naziv domaćina je IP adresa" + +#: ../libsoup/soup-tld.c:197 ../libsoup/soup-tld.c:219 +msgid "Invalid hostname" +msgstr "Neispravan naziv domaćina" + +#: ../libsoup/soup-tld.c:249 +msgid "Hostname has no base domain" +msgstr "Naziv domaćina nema osnovni domen" + +#: ../libsoup/soup-tld.c:303 +msgid "Not enough domains" +msgstr "Nema dovoljno domena" diff --git a/po/sv.po b/po/sv.po new file mode 100644 index 0000000..d6ce9c7 --- /dev/null +++ b/po/sv.po @@ -0,0 +1,180 @@ +# Swedish translation for libsoup. +# Copyright © 2012-2018 Free Software Foundation, Inc. +# This file is distributed under the same license as the libsoup package. +# Daniel Nylander , 2012. +# Sebastian Rasmussen , 2015, 2016. +# Anders Jonsson , 2018. +# +msgid "" +msgstr "" +"Project-Id-Version: libsoup\n" +"Report-Msgid-Bugs-To: https://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=Misc\n" +"POT-Creation-Date: 2018-02-09 14:43+0000\n" +"PO-Revision-Date: 2018-02-09 16:11+0100\n" +"Last-Translator: Anders Jonsson \n" +"Language-Team: Swedish \n" +"Language: sv\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 2.0.5\n" + +#: ../libsoup/soup-body-input-stream.c:139 +#: ../libsoup/soup-body-input-stream.c:170 +#: ../libsoup/soup-body-input-stream.c:203 ../libsoup/soup-message-io.c:238 +msgid "Connection terminated unexpectedly" +msgstr "Anslutningen avslutades oväntat" + +#: ../libsoup/soup-body-input-stream.c:459 +msgid "Invalid seek request" +msgstr "Ogiltig ”seek”-förfrågan" + +#: ../libsoup/soup-body-input-stream.c:487 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "Kan inte trunkera ”SoupBodyInputStream”" + +#: ../libsoup/soup-cache-input-stream.c:76 +msgid "Network stream unexpectedly closed" +msgstr "Nätverksström stängdes oväntat" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "Misslyckades med att helt mellanlagra resursen" + +#: ../libsoup/soup-converter-wrapper.c:189 +#, c-format +msgid "Output buffer is too small" +msgstr "Utmatningsbufferten är för liten" + +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "Kunde inte tolka HTTP-svar" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "Okänd kodning på HTTP-svar" + +#: ../libsoup/soup-message-io.c:263 +msgid "Header too big" +msgstr "Huvudet är för stort" + +#: ../libsoup/soup-message-io.c:396 ../libsoup/soup-message-io.c:1024 +msgid "Operation would block" +msgstr "Åtgärden skulle blockera" + +#: ../libsoup/soup-message-io.c:976 ../libsoup/soup-message-io.c:1009 +msgid "Operation was cancelled" +msgstr "Åtgärden avbröts" + +#: ../libsoup/soup-message-server-io.c:64 +msgid "Could not parse HTTP request" +msgstr "Kunde inte tolka HTTP-förfrågan" + +#: ../libsoup/soup-request.c:141 +#, c-format +msgid "No URI provided" +msgstr "Ingen URI angavs" + +#: ../libsoup/soup-request.c:151 +#, c-format +msgid "Invalid “%s” URI: %s" +msgstr "Ogiltig ”%s”-URI: %s" + +#: ../libsoup/soup-server.c:1725 +msgid "Can’t create a TLS server without a TLS certificate" +msgstr "Kan inte skapa en TLS-server utan ett TLS-certifikat" + +#: ../libsoup/soup-server.c:1742 +#, c-format +msgid "Could not listen on address %s, port %d: " +msgstr "Kan inte lyssna på adress %s, port %d: " + +#: ../libsoup/soup-session.c:4524 +#, c-format +msgid "Could not parse URI “%s”" +msgstr "Kunde inte tolka URI:n ”%s”" + +#: ../libsoup/soup-session.c:4561 +#, c-format +msgid "Unsupported URI scheme “%s”" +msgstr "URI-schemat ”%s” stöds inte" + +#: ../libsoup/soup-session.c:4583 +#, c-format +msgid "Not an HTTP URI" +msgstr "Inte en HTTP-URI" + +#: ../libsoup/soup-session.c:4781 +msgid "The server did not accept the WebSocket handshake." +msgstr "Servern accepterade inte WebSocket-handskakningen." + +#: ../libsoup/soup-socket.c:148 +msgid "Can’t import non-socket as SoupSocket" +msgstr "Kan inte importera ett icke-uttag (non-socket) som ”SoupSocket”" + +#: ../libsoup/soup-socket.c:166 +msgid "Could not import existing socket: " +msgstr "Kan inte importera befintligt uttag (socket): " + +#: ../libsoup/soup-socket.c:175 +msgid "Can’t import unconnected socket" +msgstr "Kan inte importera ett icke anslutet uttag (socket)" + +#: ../libsoup/soup-websocket.c:338 ../libsoup/soup-websocket.c:347 +msgid "WebSocket handshake expected" +msgstr "WebSocket-handskakning förväntad" + +#: ../libsoup/soup-websocket.c:355 +msgid "Unsupported WebSocket version" +msgstr "WebSocket-version stöds ej" + +#: ../libsoup/soup-websocket.c:364 +msgid "Invalid WebSocket key" +msgstr "Ogiltig WebSocket-nyckel" + +#: ../libsoup/soup-websocket.c:374 +#, c-format +msgid "Incorrect WebSocket “%s” header" +msgstr "Felaktigt WebSocket ”%s”-huvud" + +#: ../libsoup/soup-websocket.c:383 +msgid "Unsupported WebSocket subprotocol" +msgstr "WebSocket-underprotokoll stöds ej" + +#: ../libsoup/soup-websocket.c:510 +msgid "Server rejected WebSocket handshake" +msgstr "Servern avböjde WebSocket-handskakning" + +#: ../libsoup/soup-websocket.c:518 ../libsoup/soup-websocket.c:527 +msgid "Server ignored WebSocket handshake" +msgstr "Servern ignorerade WebSocket-handskakning" + +#: ../libsoup/soup-websocket.c:539 +msgid "Server requested unsupported protocol" +msgstr "Servern begärde protokoll som ej stöds" + +#: ../libsoup/soup-websocket.c:549 +msgid "Server requested unsupported extension" +msgstr "Servern begärde tillägg som ej stöds" + +#: ../libsoup/soup-websocket.c:562 +#, c-format +msgid "Server returned incorrect “%s” key" +msgstr "Servern returnerade felaktig ”%s”-nyckel" + +#: ../libsoup/soup-tld.c:188 +msgid "Hostname is an IP address" +msgstr "Värdnamnet är en IP-adress" + +#: ../libsoup/soup-tld.c:198 ../libsoup/soup-tld.c:220 +msgid "Invalid hostname" +msgstr "Ogiltigt värdnamn" + +#: ../libsoup/soup-tld.c:250 +msgid "Hostname has no base domain" +msgstr "Värdnamnet har ingen basdomän" + +#: ../libsoup/soup-tld.c:304 +msgid "Not enough domains" +msgstr "Inte tillräckligt många domäner" diff --git a/po/ta.po b/po/ta.po new file mode 100644 index 0000000..69128b2 --- /dev/null +++ b/po/ta.po @@ -0,0 +1,133 @@ +# Tamil translation for libsoup. +# Copyright (C) 2012 libsoup's COPYRIGHT HOLDER +# This file is distributed under the same license as the libsoup package. +# +# Dr.T.Vasudevan , 2012. +# Shantha kumar , 2012, 2014. +msgid "" +msgstr "" +"Project-Id-Version: libsoup master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2014-07-19 15:23+0000\n" +"PO-Revision-Date: 2014-09-13 21:44+0630\n" +"Last-Translator: Shantha kumar \n" +"Language-Team: Tamil \n" +"Language: ta\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Lokalize 1.5\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +#: ../libsoup/soup-body-input-stream.c:140 +#: ../libsoup/soup-body-input-stream.c:171 +#: ../libsoup/soup-body-input-stream.c:204 ../libsoup/soup-message-io.c:196 +msgid "Connection terminated unexpectedly" +msgstr "இணைப்பு எதிர்பாராமல் துண்டிக்கப்பட்டது" + +#: ../libsoup/soup-body-input-stream.c:462 +msgid "Invalid seek request" +msgstr "தவறான தேடும் கோரிக்கை" + +#: ../libsoup/soup-body-input-stream.c:490 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "SoupBodyInputStream ஐ தசமிடமுடியவில்லை" + +#: ../libsoup/soup-cache-input-stream.c:73 +msgid "Network stream unexpectedly closed" +msgstr "பிணைய ஸ்ட்ரீம் எதிர்பாரா விதமாக மூடப்பட்டது" + +#: ../libsoup/soup-cache-input-stream.c:290 +msgid "Failed to completely cache the resource" +msgstr "வளத்தை முழுமையாக தேக்ககப்படுத்துதல் தோல்வியடைந்தது" + +#: ../libsoup/soup-converter-wrapper.c:192 +#, c-format +msgid "Output buffer is too small" +msgstr "வெளியீட்டு இடைநினைவு மிகச்சிறியது" + +#: ../libsoup/soup-message-client-io.c:41 +#| msgid "Could not parse URI '%s'" +msgid "Could not parse HTTP response" +msgstr "HTTP பதிலைப் பாகுபடுத்த முடியவில்லை" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "அறியப்படாத HTTP பதிலளிப்புக் குறியீடாக்கம்" + +#: ../libsoup/soup-message-io.c:854 ../libsoup/soup-message-io.c:890 +msgid "Operation was cancelled" +msgstr "செயல்பாடு ரத்து செய்யப்பட்டது" + +#: ../libsoup/soup-message-io.c:901 +msgid "Operation would block" +msgstr "செயல்பாடு தடை செய்யும்" + +#: ../libsoup/soup-message-server-io.c:41 +#| msgid "Could not parse URI '%s'" +msgid "Could not parse HTTP request" +msgstr "HTTP கோரிக்கையைப் பாகுபடுத்த முடியவில்லை" + +#: ../libsoup/soup-request.c:140 +#, c-format +msgid "No URI provided" +msgstr "யூஆர்ஐ ஏதும் தரப்படவில்லை" + +#: ../libsoup/soup-request.c:150 +#, c-format +msgid "Invalid '%s' URI: %s" +msgstr "செல்லுபடியாகாத '%s' URI: %s" + +#: ../libsoup/soup-server.c:1528 +msgid "Can't create a TLS server without a TLS certificate" +msgstr "TLS சான்றிதழ் இல்லாமல் TLS சேவையகத்தை உருவாக்க முடியாது" + +#: ../libsoup/soup-server.c:1547 +#, c-format +msgid "Could not listen on address %s, port %d" +msgstr "முகவரி %s, துறை %d இல் கவனிக்க முடியவில்லை" + +#: ../libsoup/soup-session.c:4466 +#, c-format +msgid "Could not parse URI '%s'" +msgstr "'%s' யூஆர்ஐ ஐ அலகிட முடியவில்லை" + +#: ../libsoup/soup-session.c:4503 +#, c-format +msgid "Unsupported URI scheme '%s'" +msgstr "ஆதரவு இல்லாத யூஆர்ஐ திட்டம் '%s'" + +#: ../libsoup/soup-session.c:4525 +#, c-format +msgid "Not an HTTP URI" +msgstr "HTTP URI அல்ல" + +#: ../libsoup/soup-socket.c:142 +msgid "Can't import non-socket as SoupSocket" +msgstr "நான் சாக்கெட்டை சூப்சாக்கெட்டாக இறக்குமதி செய்ய முடியாது" + +#: ../libsoup/soup-socket.c:160 +msgid "Could not import existing socket: " +msgstr "முன்பே உள்ள சாக்கெட்டை இறக்குமதி செய்ய முடியாது" + +#: ../libsoup/soup-socket.c:169 +msgid "Can't import unconnected socket" +msgstr "இணைக்கப்படாத சாக்கெட்டை இறக்குமதி செய்ய முடியாது" + +#: ../libsoup/soup-tld.c:188 +msgid "Hostname is an IP address" +msgstr "புரவலன் பெயர் ஒரு ஐபி முகவரி" + +#: ../libsoup/soup-tld.c:198 ../libsoup/soup-tld.c:220 +msgid "Invalid hostname" +msgstr "செல்லுபடியாகாத கணிணிப்பெயர்" + +#: ../libsoup/soup-tld.c:250 +msgid "Hostname has no base domain" +msgstr "புரவலன் பெயருக்கு ஒரு செயற்களம் இல்லை" + +#: ../libsoup/soup-tld.c:304 +msgid "Not enough domains" +msgstr "போதிய செயற்களம் இல்லை" + diff --git a/po/te.po b/po/te.po new file mode 100644 index 0000000..f66e4b6 --- /dev/null +++ b/po/te.po @@ -0,0 +1,131 @@ +# Telugu translation for libsoup. +# Copyright (C) 2012 libsoup's to Swecha Telugu localisation Team +# This file is distributed under the same license as the libsoup package. +# +# Sasi Bhushan Boddepalli , 2012. +# Krishnababu Krothapalli , 2012, 2013, 2014. +msgid "" +msgstr "" +"Project-Id-Version: libsoup master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2014-09-23 09:50+0000\n" +"PO-Revision-Date: 2014-09-23 16:55+0530\n" +"Last-Translator: Krishnababu Krothapalli \n" +"Language-Team: Telugu \n" +"Language: te\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Lokalize 1.5\n" + +#: ../libsoup/soup-body-input-stream.c:140 +#: ../libsoup/soup-body-input-stream.c:171 +#: ../libsoup/soup-body-input-stream.c:204 ../libsoup/soup-message-io.c:196 +msgid "Connection terminated unexpectedly" +msgstr "కనెక్షను అనుకోకుండా అంతమైంది" + +#: ../libsoup/soup-body-input-stream.c:462 +msgid "Invalid seek request" +msgstr "చెల్లని సీక్ అభ్యర్ధన" + +#: ../libsoup/soup-body-input-stream.c:490 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "SoupBodyInputStream ట్రంకేట్ చేయలేదు" + +#: ../libsoup/soup-cache-input-stream.c:73 +msgid "Network stream unexpectedly closed" +msgstr "నెట్వర్కు స్ట్రీమ్ అనుకోకుండా మూయబడింది" + +#: ../libsoup/soup-cache-input-stream.c:290 +msgid "Failed to completely cache the resource" +msgstr "వనరును సంపూర్ణంగా క్యాచీ చేయుటకు విఫలమైంది" + +#: ../libsoup/soup-converter-wrapper.c:192 +#, c-format +msgid "Output buffer is too small" +msgstr "అవుట్పుట్ బఫర్ మరీ చిన్నది" + +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "HTTP స్పందనను పార్శ్ చేయలేక పోయింది" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "గుర్తించని HTTP స్పందన యెన్కోడింగ్" + +#: ../libsoup/soup-message-io.c:854 ../libsoup/soup-message-io.c:890 +msgid "Operation was cancelled" +msgstr "ఆపరేషన్ రద్దు చేయబడింది" + +#: ../libsoup/soup-message-io.c:901 +msgid "Operation would block" +msgstr "ఆపరేషన్ బ్లాక్ చేస్తుంది" + +#: ../libsoup/soup-message-server-io.c:41 +msgid "Could not parse HTTP request" +msgstr "HTTP అభ్యర్ధనను పార్స్ చేయలేదు" + +#: ../libsoup/soup-request.c:140 +#, c-format +msgid "No URI provided" +msgstr "URl అందించబడలేదు" + +#: ../libsoup/soup-request.c:150 +#, c-format +msgid "Invalid '%s' URI: %s" +msgstr "చెల్లని '%s' URI: %s" + +#: ../libsoup/soup-server.c:1528 +msgid "Can't create a TLS server without a TLS certificate" +msgstr "TLS ధృవీకరణపత్రం లేకుండా TLS సేవిక సృష్టించలేదు" + +#: ../libsoup/soup-server.c:1547 +#, c-format +msgid "Could not listen on address %s, port %d: " +msgstr "చిరునామా %s పైన వినలేదు, పోర్ట్ %d: " + +#: ../libsoup/soup-session.c:4466 +#, c-format +msgid "Could not parse URI '%s'" +msgstr "URI '%s' అన్వయించడం సాధ్యం కాదు" + +#: ../libsoup/soup-session.c:4503 +#, c-format +msgid "Unsupported URI scheme '%s'" +msgstr "మద్దతు లేని URI స్కీమ్ '%s'" + +#: ../libsoup/soup-session.c:4525 +#, c-format +msgid "Not an HTTP URI" +msgstr "HTTP URI కాదు" + +#: ../libsoup/soup-socket.c:142 +msgid "Can't import non-socket as SoupSocket" +msgstr "నాన్-సాకెట్‌ను సూప్‌సాకెట్‌గా దిగుమతిచేయలేదు" + +#: ../libsoup/soup-socket.c:160 +msgid "Could not import existing socket: " +msgstr "ఉన్న సాకెట్‌ను దిగుమతిచేయలేదు: " + +#: ../libsoup/soup-socket.c:169 +msgid "Can't import unconnected socket" +msgstr "అనుసంధానించని సాకెట్‌ను దిగుమతిచేయలేదు" + +#: ../libsoup/soup-tld.c:188 +msgid "Hostname is an IP address" +msgstr "హోస్ట్ పేరు ఒక IP చిరునామా" + +#: ../libsoup/soup-tld.c:198 ../libsoup/soup-tld.c:220 +msgid "Invalid hostname" +msgstr "చెల్లని హోస్ట్ పేరు" + +#: ../libsoup/soup-tld.c:250 +msgid "Hostname has no base domain" +msgstr "అతిధేయిపేరు అధార డొమైన్ కలిగిలేదు" + +#: ../libsoup/soup-tld.c:304 +msgid "Not enough domains" +msgstr "సరిపోనన్ని డొమైన్ లు" + diff --git a/po/tg.po b/po/tg.po new file mode 100644 index 0000000..613771d --- /dev/null +++ b/po/tg.po @@ -0,0 +1,107 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# Victor Ibragimov , 2013. +# +msgid "" +msgstr "" +"Project-Id-Version: Tajik Gnome\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2013-07-28 11:48+0000\n" +"PO-Revision-Date: 2013-10-10 16:30+0500\n" +"Last-Translator: Victor Ibragimov \n" +"Language-Team: \n" +"Language: tg\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 1.5.7\n" + +#: ../libsoup/soup-body-input-stream.c:140 +#: ../libsoup/soup-body-input-stream.c:171 +#: ../libsoup/soup-body-input-stream.c:204 ../libsoup/soup-message-io.c:191 +msgid "Connection terminated unexpectedly" +msgstr "Пайвастшавӣ ногаҳон қатъ шудааст" + +#: ../libsoup/soup-body-input-stream.c:462 +msgid "Invalid seek request" +msgstr "Дархости ҷустуҷӯи нодуруст" + +#: ../libsoup/soup-body-input-stream.c:490 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "SoupBodyInputStream кӯтоҳ карда намешавад" + +#: ../libsoup/soup-cache-input-stream.c:73 +msgid "Network stream unexpectedly closed" +msgstr "Ҷараёни шабака ногаҳон манъ карда шудааст" + +#: ../libsoup/soup-cache-input-stream.c:290 +msgid "Failed to completely cache the resource" +msgstr "Зерҳофизаи манбаъ комилан захира карда нашуд" + +#: ../libsoup/soup-converter-wrapper.c:192 +#, c-format +msgid "Output buffer is too small" +msgstr "Миёнҷии барориш хеле хурд аст" + +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "Ҷавоби HTTP таҷзия карда намешавад" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "Рамзгузории ҷавоби HTTP шинохта нашудааст" + +#: ../libsoup/soup-message-io.c:846 ../libsoup/soup-message-io.c:882 +msgid "Operation was cancelled" +msgstr "Амалиёт бекор шудааст" + +#: ../libsoup/soup-message-io.c:893 +msgid "Operation would block" +msgstr "Амалиёт қатъ карда мешавад" + +#: ../libsoup/soup-message-server-io.c:40 +msgid "Could not parse HTTP request" +msgstr "Дархости HTTP таҷзия карда намешавад" + +#: ../libsoup/soup-request.c:140 +#, c-format +msgid "No URI provided" +msgstr "Ягон URI таъмин нашудааст" + +#: ../libsoup/soup-request.c:150 +#, c-format +msgid "Invalid '%s' URI: %s" +msgstr "Суроғаи '%s' URI нодуруст аст: %s" + +#: ../libsoup/soup-session.c:4301 +#, c-format +msgid "Could not parse URI '%s'" +msgstr "Суроғаи URI '%s' таҷзия карда нашуд" + +#: ../libsoup/soup-session.c:4338 +#, c-format +msgid "Unsupported URI scheme '%s'" +msgstr "Нақшаи суроғаи URI '%s' дастгирӣ намешавад" + +#: ../libsoup/soup-session.c:4360 +#, c-format +msgid "Not an HTTP URI" +msgstr "Суроғаи HTTP URI намебошад" + +#: ../libsoup/soup-tld.c:185 +msgid "Hostname is an IP address" +msgstr "Номи мизбон суроғаи IP мебошад" + +#: ../libsoup/soup-tld.c:206 +msgid "Invalid hostname" +msgstr "Номи мизбони нодуруст" + +#: ../libsoup/soup-tld.c:235 +msgid "Hostname has no base domain" +msgstr "Номи мизбон домени асосӣ надорад" + +#: ../libsoup/soup-tld.c:257 +msgid "Not enough domains" +msgstr "Доменҳои кофӣ надорад" diff --git a/po/th.po b/po/th.po new file mode 100644 index 0000000..28937e0 --- /dev/null +++ b/po/th.po @@ -0,0 +1,176 @@ +# Thai translation for libsoup. +# Copyright (C) 2012-2015 Free Software Foundation, Inc. +# This file is distributed under the same license as the libsoup package. +# Theppitak Karoonboonyanan , 2013. +# Akom Chotiphantawanon , 2012, 2015. +# +msgid "" +msgstr "" +"Project-Id-Version: libsoup master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2015-07-18 22:38+0000\n" +"PO-Revision-Date: 2015-07-31 10:55+0700\n" +"Last-Translator: Akom Chotiphantawanon \n" +"Language-Team: Thai \n" +"Language: th\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Gtranslator 2.91.6\n" + +#: ../libsoup/soup-body-input-stream.c:140 +#: ../libsoup/soup-body-input-stream.c:171 +#: ../libsoup/soup-body-input-stream.c:204 ../libsoup/soup-message-io.c:235 +msgid "Connection terminated unexpectedly" +msgstr "การเชื่อมต่อยุติกะทันหัน" + +#: ../libsoup/soup-body-input-stream.c:462 +msgid "Invalid seek request" +msgstr "การร้องขอการเลื่อนตำแหน่งไม่ถูกต้อง" + +#: ../libsoup/soup-body-input-stream.c:490 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "ไม่สามารถตัดท้าย SoupBodyInputStream" + +#: ../libsoup/soup-cache-input-stream.c:74 +msgid "Network stream unexpectedly closed" +msgstr "สตรีมเครือข่ายปิดกะทันหัน" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "ทำแคชทรัพยากรไม่เสร็จสมบูรณ์" + +#: ../libsoup/soup-converter-wrapper.c:192 +#, c-format +msgid "Output buffer is too small" +msgstr "บัฟเฟอร์ข้อมูลออกเล็กเกินไป" + +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "ไม่สามารถแจงคำตอบ HTTP" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "ไม่รู้จักรหัสอักขระของคำตอบ HTTP" + +#: ../libsoup/soup-message-io.c:392 ../libsoup/soup-message-io.c:1020 +msgid "Operation would block" +msgstr "การทำงานถูกบล็อค" + +#: ../libsoup/soup-message-io.c:972 ../libsoup/soup-message-io.c:1005 +msgid "Operation was cancelled" +msgstr "การทำงานถูกยกเลิก" + +#: ../libsoup/soup-message-server-io.c:64 +msgid "Could not parse HTTP request" +msgstr "ไม่สามารถแจงคำร้อง HTTP" + +#: ../libsoup/soup-request.c:140 +#, c-format +msgid "No URI provided" +msgstr "ไม่ได้ระบุ URI" + +#: ../libsoup/soup-request.c:150 +#, c-format +msgid "Invalid '%s' URI: %s" +msgstr "URI '%s' ไม่ถูกต้อง: %s" + +#: ../libsoup/soup-server.c:1711 +msgid "Can't create a TLS server without a TLS certificate" +msgstr "ไม่สามารถสร้างเซิร์ฟเวอร์ TLS โดยไม่มีใบรับรอง TLS" + +#: ../libsoup/soup-server.c:1730 +#, c-format +msgid "Could not listen on address %s, port %d: " +msgstr "ไม่สามารถรอรับการเชื่อมต่อที่ที่อยู่ %s, พอร์ต %d ได้: " + +#: ../libsoup/soup-session.c:4554 +#, c-format +msgid "Could not parse URI '%s'" +msgstr "ไม่สามารถแจง URI '%s'" + +#: ../libsoup/soup-session.c:4591 +#, c-format +msgid "Unsupported URI scheme '%s'" +msgstr "ไม่รองรับ URI แบบ '%s'" + +#: ../libsoup/soup-session.c:4613 +#, c-format +msgid "Not an HTTP URI" +msgstr "ไม่ใช่ URI ของ HTTP" + +#: ../libsoup/soup-session.c:4797 +msgid "The server did not accept the WebSocket handshake." +msgstr "เซิร์ฟเวอร์ไม่ยอมรับ WebSocket handshake" + +#: ../libsoup/soup-socket.c:148 +msgid "Can't import non-socket as SoupSocket" +msgstr "ไม่สามารถนำเข้าสิ่งที่ไม่ใช่ซ็อกเก็ตให้เป็น SoupSocket ได้" + +#: ../libsoup/soup-socket.c:166 +msgid "Could not import existing socket: " +msgstr "ไม่สามารถนำเข้าซ็อกเก็ตที่มีอยู่: " + +#: ../libsoup/soup-socket.c:175 +msgid "Can't import unconnected socket" +msgstr "ไม่สามารถนำเข้าซ็อกเก็ตที่ไม่ได้เชื่อมต่อ" + +#: ../libsoup/soup-websocket.c:336 ../libsoup/soup-websocket.c:345 +msgid "WebSocket handshake expected" +msgstr "ต้องการ WebSocket handshake" + +#: ../libsoup/soup-websocket.c:353 +msgid "Unsupported WebSocket version" +msgstr "ไม่รองรับ WebSocket รุ่นนี้" + +#: ../libsoup/soup-websocket.c:362 +msgid "Invalid WebSocket key" +msgstr "คีย์ WebSocket ไม่ถูกต้อง" + +#: ../libsoup/soup-websocket.c:372 +#, c-format +msgid "Incorrect WebSocket \"%s\" header" +msgstr "ส่วนหัว \"%s\" ของ WebSocket ไม่ถูกต้อง" + +#: ../libsoup/soup-websocket.c:381 +msgid "Unsupported WebSocket subprotocol" +msgstr "พบโพรโทคอลย่อยของ WebSocket ที่ไม่รองรับ" + +#: ../libsoup/soup-websocket.c:508 +msgid "Server rejected WebSocket handshake" +msgstr "เซิร์ฟเวอร์ปฏิเสธ WebSocket handshake" + +#: ../libsoup/soup-websocket.c:516 ../libsoup/soup-websocket.c:525 +msgid "Server ignored WebSocket handshake" +msgstr "เซิร์ฟเวอร์ไม่สนใจ WebSocket handshake" + +#: ../libsoup/soup-websocket.c:537 +msgid "Server requested unsupported protocol" +msgstr "เซิร์ฟเวอร์ร้องขอโพรโทคอลที่ไม่รองรับ" + +#: ../libsoup/soup-websocket.c:547 +msgid "Server requested unsupported extension" +msgstr "เซิร์ฟเวอร์ร้องขอส่วนขยายที่ไม่รองรับ" + +#: ../libsoup/soup-websocket.c:560 +#, c-format +msgid "Server returned incorrect \"%s\" key" +msgstr "เซิร์ฟเวอร์คืนค่าคีย์ \"%s\" ไม่ถูกต้อง" + +#: ../libsoup/soup-tld.c:188 +msgid "Hostname is an IP address" +msgstr "ชื่อโฮสต์เป็นหมายเลขไอพี" + +#: ../libsoup/soup-tld.c:198 ../libsoup/soup-tld.c:220 +msgid "Invalid hostname" +msgstr "ชื่อโฮสต์ผิดรูปแบบ" + +#: ../libsoup/soup-tld.c:250 +msgid "Hostname has no base domain" +msgstr "ชื่อโฮสต์ไม่มีโดเมนฐาน" + +#: ../libsoup/soup-tld.c:304 +msgid "Not enough domains" +msgstr "มีโดเมนน้อยเกินไป" diff --git a/po/tr.po b/po/tr.po new file mode 100644 index 0000000..79b7b60 --- /dev/null +++ b/po/tr.po @@ -0,0 +1,185 @@ +# Turkish translation for libsoup. +# Copyright (C) 2012 libsoup's COPYRIGHT HOLDER +# This file is distributed under the same license as the libsoup package. +# +# Ozan Çağlayan , 2013. +# Necdet Yücel , 2014, 2015. +# Furkan Ahmet Kara , 2017. +# Emin Tufan Çetin , 2017. +# Muhammet Kara , 2012, 2014, 2015, 2018. +# +msgid "" +msgstr "" +"Project-Id-Version: libsoup master\n" +"Report-Msgid-Bugs-To: https://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=Misc\n" +"POT-Creation-Date: 2018-02-09 14:43+0000\n" +"PO-Revision-Date: 2018-03-11 10:24+0300\n" +"Last-Translator: Muhammet Kara \n" +"Language-Team: Türkçe \n" +"Language: tr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Gtranslator 2.91.7\n" +"X-POOTLE-MTIME: 1433280627.000000\n" + +#: ../libsoup/soup-body-input-stream.c:139 +#: ../libsoup/soup-body-input-stream.c:170 +#: ../libsoup/soup-body-input-stream.c:203 ../libsoup/soup-message-io.c:238 +msgid "Connection terminated unexpectedly" +msgstr "Bağlantı beklenmeyen bir şekilde sonlandı" + +#: ../libsoup/soup-body-input-stream.c:459 +msgid "Invalid seek request" +msgstr "Geçersiz arama isteği" + +#: ../libsoup/soup-body-input-stream.c:487 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "SoupBodyInputStream kesilemiyor" + +#: ../libsoup/soup-cache-input-stream.c:76 +msgid "Network stream unexpectedly closed" +msgstr "Ağ akışı beklenmeyen bir şekilde sonlandı" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "Özkaynak tümüyle önbelleğe alınamadı" + +#: ../libsoup/soup-converter-wrapper.c:189 +#, c-format +msgid "Output buffer is too small" +msgstr "Çıkış arabelleği çok küçük" + +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "HTTP yanıtı ayrıştırılamadı" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "HTTP yanıtı tanınmayan bir şekilde kodlanmış" + +#: ../libsoup/soup-message-io.c:263 +msgid "Header too big" +msgstr "Başlık çok büyük" + +#: ../libsoup/soup-message-io.c:396 ../libsoup/soup-message-io.c:1024 +msgid "Operation would block" +msgstr "İşlem bloke edebilir" + +#: ../libsoup/soup-message-io.c:976 ../libsoup/soup-message-io.c:1009 +msgid "Operation was cancelled" +msgstr "İşlem iptal edildi" + +#: ../libsoup/soup-message-server-io.c:64 +msgid "Could not parse HTTP request" +msgstr "HTTP isteği ayrıştırılamadı" + +#: ../libsoup/soup-request.c:141 +#, c-format +msgid "No URI provided" +msgstr "URI verilmedi" + +#: ../libsoup/soup-request.c:151 +#, c-format +msgid "Invalid “%s” URI: %s" +msgstr "Geçersiz “%s” URI: %s" + +#: ../libsoup/soup-server.c:1725 +msgid "Can’t create a TLS server without a TLS certificate" +msgstr "Bir TLS sertifikası olmadan TLS sunucusu oluşturulamaz" + +#: ../libsoup/soup-server.c:1742 +#, c-format +msgid "Could not listen on address %s, port %d: " +msgstr "%s adresinin %d bağlantı noktası dinlenemedi: " + +#: ../libsoup/soup-session.c:4524 +#, c-format +msgid "Could not parse URI “%s”" +msgstr "URI “%s” ayrıştırılamadı" + +#: ../libsoup/soup-session.c:4561 +#, c-format +msgid "Unsupported URI scheme “%s”" +msgstr "Desteklenmeyen URI şeması “%s”" + +#: ../libsoup/soup-session.c:4583 +#, c-format +msgid "Not an HTTP URI" +msgstr "HTTP URI değil" + +#: ../libsoup/soup-session.c:4781 +msgid "The server did not accept the WebSocket handshake." +msgstr "Sunucu WebSocket el sıkışmasını kabul etmedi." + +#: ../libsoup/soup-socket.c:148 +msgid "Can’t import non-socket as SoupSocket" +msgstr "Non-socket, SoupSocket olarak içe aktarılamıyor" + +#: ../libsoup/soup-socket.c:166 +msgid "Could not import existing socket: " +msgstr "Mevcut soket içe aktarılamadı: " + +#: ../libsoup/soup-socket.c:175 +msgid "Can’t import unconnected socket" +msgstr "Bağlı olmayan soket içe aktarılamıyor" + +#: ../libsoup/soup-websocket.c:338 ../libsoup/soup-websocket.c:347 +msgid "WebSocket handshake expected" +msgstr "WebSocket el sıkışması bekleniyor" + +#: ../libsoup/soup-websocket.c:355 +msgid "Unsupported WebSocket version" +msgstr "Desteklenmeyen WebSocket sürümü" + +#: ../libsoup/soup-websocket.c:364 +msgid "Invalid WebSocket key" +msgstr "Geçersiz WebSocket anahtarı" + +#: ../libsoup/soup-websocket.c:374 +#, c-format +msgid "Incorrect WebSocket “%s” header" +msgstr "Hatalı WebSocket “%s” başlığı" + +#: ../libsoup/soup-websocket.c:383 +msgid "Unsupported WebSocket subprotocol" +msgstr "Desteklenmeyen WebSocket alt iletişim kuralı" + +#: ../libsoup/soup-websocket.c:510 +msgid "Server rejected WebSocket handshake" +msgstr "Sunucu WebSocket el sıkışmasını reddetti" + +#: ../libsoup/soup-websocket.c:518 ../libsoup/soup-websocket.c:527 +msgid "Server ignored WebSocket handshake" +msgstr "Sunucu WebSocket el sıkışmasını yoksaydı" + +#: ../libsoup/soup-websocket.c:539 +msgid "Server requested unsupported protocol" +msgstr "Sunucu desteklenmeyen iletişim kuralı isteğinde bulundu" + +#: ../libsoup/soup-websocket.c:549 +msgid "Server requested unsupported extension" +msgstr "Sunucu desteklenmeyen eklenti isteğinde bulundu" + +#: ../libsoup/soup-websocket.c:562 +#, c-format +msgid "Server returned incorrect “%s” key" +msgstr "Sunucu geçersiz “%s” anahtarı döndürdü" + +#: ../libsoup/soup-tld.c:188 +msgid "Hostname is an IP address" +msgstr "Makine adı bir IP adresi" + +#: ../libsoup/soup-tld.c:198 ../libsoup/soup-tld.c:220 +msgid "Invalid hostname" +msgstr "Geçersiz makine adı" + +#: ../libsoup/soup-tld.c:250 +msgid "Hostname has no base domain" +msgstr "Ana makinenin temel etki alanı yok" + +#: ../libsoup/soup-tld.c:304 +msgid "Not enough domains" +msgstr "Yeterli etki alanı yok" diff --git a/po/ug.po b/po/ug.po new file mode 100644 index 0000000..5144745 --- /dev/null +++ b/po/ug.po @@ -0,0 +1,105 @@ +# Uyghur translation for libsoup. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# Gheyret Kenji , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: libsoup\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=libsoup&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2013-02-18 10:20+0000\n" +"PO-Revision-Date: 2013-02-22 21:51+0900\n" +"Last-Translator: Gheyret Kenji \n" +"Language-Team: Uyghur Computer Science Association \n" +"Language: ug\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: ../libsoup/soup-body-input-stream.c:141 +#: ../libsoup/soup-body-input-stream.c:172 +#: ../libsoup/soup-body-input-stream.c:205 ../libsoup/soup-message-io.c:191 +msgid "Connection terminated unexpectedly" +msgstr "باغلىنىش تۇيۇقسىز توختاپ قالدى" + +#: ../libsoup/soup-body-input-stream.c:463 +msgid "Invalid seek request" +msgstr "ئىناۋەتسىز ئىزدەش ئىلتىماسى" + +#: ../libsoup/soup-body-input-stream.c:491 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "ئېقىم SoupBodyInputStream نى قىسقارتقىلى بولمىدى" + +#: ../libsoup/soup-cache-input-stream.c:74 +msgid "Network stream unexpectedly closed" +msgstr "تور ئېقىمى تۇيۇقسىز يېپىلدى" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "مەنبەنى تولۇق غەملىۋېلىش مەغلۇپ بولدى" + +#: ../libsoup/soup-converter-wrapper.c:192 +#, c-format +msgid "Output buffer is too small" +msgstr "چىقىرىش يىغلەكى بەك كىچىك" + +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "HTTP ئىنكاسىنى يېشەلمىدى" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "HTTP ئىنكاسىنىڭ كودلىنىشىنى بىلگىلى بولمىدى" + +#: ../libsoup/soup-message-io.c:846 ../libsoup/soup-message-io.c:882 +msgid "Operation was cancelled" +msgstr "مەشغۇلات بىكار قىلىندى" + +#: ../libsoup/soup-message-io.c:893 +msgid "Operation would block" +msgstr "مەشغۇلات توسۇلىدۇ" + +#: ../libsoup/soup-message-server-io.c:40 +msgid "Could not parse HTTP request" +msgstr "HTTP ئىلتىماسىنى يېشەلمىدى" + +#: ../libsoup/soup-request.c:140 +#, c-format +msgid "No URI provided" +msgstr "URI تەمىنلەنمىدى" + +#: ../libsoup/soup-request.c:150 +#, c-format +msgid "Invalid '%s' URI: %s" +msgstr "ئىناۋەتسىز ‹%s› URI: %s" + +#: ../libsoup/soup-session.c:4209 +#, c-format +msgid "Could not parse URI '%s'" +msgstr "URI «%s» نى تەھلىل قىلالمىدى" + +#: ../libsoup/soup-session.c:4246 +#, c-format +msgid "Unsupported URI scheme '%s'" +msgstr "قوللىمايدىغان URI لايىھە ‹%s›" + +#: ../libsoup/soup-session.c:4268 +#, c-format +msgid "Not an HTTP URI" +msgstr "بۇ HTTP URI ئەمەس" + +#: ../libsoup/soup-tld.c:185 +msgid "Hostname is an IP address" +msgstr "كومپيۇتېر ئاتى دېگەن بىر دانە IP ئادرېستۇر" + +#: ../libsoup/soup-tld.c:206 +msgid "Invalid hostname" +msgstr "باش ماشىنا ئاتى ئىناۋەتسىز" + +#: ../libsoup/soup-tld.c:235 +msgid "Hostname has no base domain" +msgstr "كومپيۇتېر ئاتىدا ئاساسىي دائىرە يوق" + +#: ../libsoup/soup-tld.c:257 +msgid "Not enough domains" +msgstr "يېتەرلىك دائىرە يوق" diff --git a/po/uk.po b/po/uk.po new file mode 100644 index 0000000..534da3e --- /dev/null +++ b/po/uk.po @@ -0,0 +1,132 @@ +# Ukrainian translation for libsoup. +# Copyright (C) 2012 libsoup's COPYRIGHT HOLDER +# This file is distributed under the same license as the libsoup package. +# Mykola Tkach , 2014. +msgid "" +msgstr "" +"Project-Id-Version: libsoup master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=libsoup&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2014-05-02 14:27+0000\n" +"PO-Revision-Date: 2014-10-17 17:43+0300\n" +"Last-Translator: Mykola Tkach \n" +"Language-Team: linux.org.ua\n" +"Language: uk\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" +"X-Generator: Virtaal 0.7.1\n" +"X-Project-Style: gnome\n" + +#: ../libsoup/soup-body-input-stream.c:140 +#: ../libsoup/soup-body-input-stream.c:171 +#: ../libsoup/soup-body-input-stream.c:204 +#: ../libsoup/soup-message-io.c:196 +msgid "Connection terminated unexpectedly" +msgstr "Несподівано зв'язок розірвано" + +#: ../libsoup/soup-body-input-stream.c:462 +msgid "Invalid seek request" +msgstr "Неправильний запит пошуку" + +#: ../libsoup/soup-body-input-stream.c:490 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "Неможливо вкоротити SoupBodyInputStream" + +#: ../libsoup/soup-cache-input-stream.c:73 +msgid "Network stream unexpectedly closed" +msgstr "Мережевий потік несподівано закрився" + +#: ../libsoup/soup-cache-input-stream.c:290 +msgid "Failed to completely cache the resource" +msgstr "Не вдалося повністю закешувати ресурс" + +#: ../libsoup/soup-converter-wrapper.c:192 +#, c-format +msgid "Output buffer is too small" +msgstr "Вихідний буфер замалий" + +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "Не вдалося розібрати відповідь HTTP" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "Нерозпізнане кодування відповіді HTTP" + +#: ../libsoup/soup-message-io.c:854 +#: ../libsoup/soup-message-io.c:890 +msgid "Operation was cancelled" +msgstr "Операцію скасовано" + +#: ../libsoup/soup-message-io.c:901 +msgid "Operation would block" +msgstr "Операція заблоковано" + +#: ../libsoup/soup-message-server-io.c:41 +msgid "Could not parse HTTP request" +msgstr "Не вдалося розібрати запит HTTP" + +#: ../libsoup/soup-request.c:140 +#, c-format +msgid "No URI provided" +msgstr "Не надано URI" + +#: ../libsoup/soup-request.c:150 +#, c-format +msgid "Invalid '%s' URI: %s" +msgstr "Неправильний «%s» URI: %s" + +#: ../libsoup/soup-server.c:1528 +msgid "Can't create a TLS server without a TLS certificate" +msgstr "Неможливо створити сервер TLS без сертифікату TLS" + +#: ../libsoup/soup-server.c:1547 +#, c-format +msgid "Could not listen on address %s, port %d: " +msgstr "Не вдалося почати прослуховування за адресою %s (порт — %d): " + +#: ../libsoup/soup-session.c:4424 +#, c-format +msgid "Could not parse URI '%s'" +msgstr "Неможливо розібрати URI «%s»" + +#: ../libsoup/soup-session.c:4461 +#, c-format +msgid "Unsupported URI scheme '%s'" +msgstr "Непідтримувана схема URI «%s»" + +#: ../libsoup/soup-session.c:4483 +#, c-format +msgid "Not an HTTP URI" +msgstr "Формат URI відрізняється від HTTP" + +#: ../libsoup/soup-socket.c:141 +msgid "Can't import non-socket as SoupSocket" +msgstr "Неможливо імпортувати об'єкт, що відрізняється від сокету, як SoupSocket" + +#: ../libsoup/soup-socket.c:159 +msgid "Could not import existing socket: " +msgstr "Не вдалося імпортувати наявний сокет: " + +#: ../libsoup/soup-socket.c:168 +msgid "Can't import unconnected socket" +msgstr "Неможливо імпортувати непід'єднаний сокет" + +#: ../libsoup/soup-tld.c:188 +msgid "Hostname is an IP address" +msgstr "Назва вузла — адреса IP" + +#: ../libsoup/soup-tld.c:198 +#: ../libsoup/soup-tld.c:220 +msgid "Invalid hostname" +msgstr "Неправильна назва вузла" + +#: ../libsoup/soup-tld.c:250 +msgid "Hostname has no base domain" +msgstr "Назва вузла не містить базового домену" + +#: ../libsoup/soup-tld.c:304 +msgid "Not enough domains" +msgstr "Не вистачає доменів" + diff --git a/po/uz@cyrillic.po b/po/uz@cyrillic.po new file mode 100644 index 0000000..7060d2f --- /dev/null +++ b/po/uz@cyrillic.po @@ -0,0 +1,82 @@ +# Uzbek (Cyrillic) translation for libsoup. +# Copyright (C) 2012 libsoup's COPYRIGHT HOLDER +# This file is distributed under the same license as the libsoup package. +# Bahodir Mansurov <6ahodir@gmail.com>, 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: libsoup gnome-3-6\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2012-10-16 12:52+0000\n" +"PO-Revision-Date: 2012-10-16 14:46-0500\n" +"Last-Translator: Bahodir Mansurov <6ahodir@gmail.com>\n" +"Language-Team: Uzbek (Cyrillic) \n" +"Language: uz@cyrillic\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#: ../libsoup/soup-body-input-stream.c:141 +#: ../libsoup/soup-body-input-stream.c:172 +#: ../libsoup/soup-body-input-stream.c:205 ../libsoup/soup-message-io.c:191 +msgid "Connection terminated unexpectedly" +msgstr "Алоқа кутилмаганда узилди" + +#: ../libsoup/soup-body-input-stream.c:461 +msgid "Invalid seek request" +msgstr "Нотўғри излаш сўрови" + +#: ../libsoup/soup-body-input-stream.c:489 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "SoupBodyInputStreamни тўхтатиб бўлмади" + +#: ../libsoup/soup-converter-wrapper.c:192 +#, c-format +msgid "Output buffer is too small" +msgstr "Чиқув буфери жуда кичик" + +#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 +msgid "Operation was cancelled" +msgstr "Амал инкор этилди" + +#: ../libsoup/soup-message-io.c:865 +msgid "Operation would block" +msgstr "Амал тўсиб қўяди" + +#: ../libsoup/soup-request.c:142 +#, c-format +msgid "No URI provided" +msgstr "URI кўрсатилмаган" + +#: ../libsoup/soup-request.c:152 +#, c-format +msgid "Invalid '%s' URI: %s" +msgstr "Нотўғри URI '%s': '%s'" + +#: ../libsoup/soup-requester.c:219 +#, c-format +msgid "Could not parse URI '%s'" +msgstr "URI '%s' таҳлил қилиб бўлмади" + +#: ../libsoup/soup-requester.c:253 +#, c-format +msgid "Unsupported URI scheme '%s'" +msgstr "Қўллаб қувватланмаган '%s' URI чизмаси" + +#: ../libsoup/soup-tld.c:154 +msgid "Hostname is an IP address" +msgstr "Компьютер номи IP адресдан иборат" + +#: ../libsoup/soup-tld.c:175 +msgid "Invalid hostname" +msgstr "Нотўғри компьютер номи" + +#: ../libsoup/soup-tld.c:204 +msgid "Hostname has no base domain" +msgstr "Компьютер номида домен қисми йўқ" + +#: ../libsoup/soup-tld.c:226 +msgid "Not enough domains" +msgstr "Домен исмлари етарли емас" diff --git a/po/vi.po b/po/vi.po new file mode 100644 index 0000000..5a59ed7 --- /dev/null +++ b/po/vi.po @@ -0,0 +1,177 @@ +# Vietnamese translation for libsoup. +# Bản dịch tiếng Việt dành cho libsoup. +# Copyright © 2015 GNOME i18n Project for Vietnamese. +# This file is distributed under the same license as the libsoup package. +# Nguyễn Thái Ngọc Duy , 2012-2013. +# Trần Ngọc Quân , 2015. +# +msgid "" +msgstr "" +"Project-Id-Version: libsoup master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2015-09-28 23:41+0000\n" +"PO-Revision-Date: 2015-09-29 07:41+0700\n" +"Last-Translator: Trần Ngọc Quân \n" +"Language-Team: Vietnamese \n" +"Language: vi\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Gtranslator 2.91.7\n" + +#: ../libsoup/soup-body-input-stream.c:140 +#: ../libsoup/soup-body-input-stream.c:171 +#: ../libsoup/soup-body-input-stream.c:204 ../libsoup/soup-message-io.c:235 +msgid "Connection terminated unexpectedly" +msgstr "Kết nối ngắt bất ngờ" + +#: ../libsoup/soup-body-input-stream.c:462 +msgid "Invalid seek request" +msgstr "Yêu cầu di chuyển vị trí đọc (seek) không hợp lệ" + +#: ../libsoup/soup-body-input-stream.c:490 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "Không thể cắt ngắn SoupBodyInputStream" + +#: ../libsoup/soup-cache-input-stream.c:74 +msgid "Network stream unexpectedly closed" +msgstr "Luồng dữ liệu mạng đã đóng bất ngờ" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "Gặp lỗi khi lưu tạm (cache) toàn bộ tài nguyên" + +#: ../libsoup/soup-converter-wrapper.c:192 +#, c-format +msgid "Output buffer is too small" +msgstr "Vùng đệm xuất quá nhỏ" + +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "Không thể phân tích phản hồi HTTP" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "Không nhận ra bảng mã phản hồi HTTP" + +#: ../libsoup/soup-message-io.c:392 ../libsoup/soup-message-io.c:1020 +msgid "Operation would block" +msgstr "Thao tác có thể treo" + +#: ../libsoup/soup-message-io.c:972 ../libsoup/soup-message-io.c:1005 +msgid "Operation was cancelled" +msgstr "Thao tác bị hủy" + +#: ../libsoup/soup-message-server-io.c:64 +msgid "Could not parse HTTP request" +msgstr "Không thể phân tích phản hồi HTTP" + +#: ../libsoup/soup-request.c:140 +#, c-format +msgid "No URI provided" +msgstr "Chưa có URI" + +#: ../libsoup/soup-request.c:150 +#, c-format +msgid "Invalid '%s' URI: %s" +msgstr "URI “%s” không hợp lệ: %s" + +#: ../libsoup/soup-server.c:1711 +msgid "Can't create a TLS server without a TLS certificate" +msgstr "Không thể tạo máy phục vụ TLS mà không có giấy chứng thực điện tử TLS" + +#: ../libsoup/soup-server.c:1730 +#, c-format +msgid "Could not listen on address %s, port %d: " +msgstr "Không thể lắng nghe trên địa chỉ %s, cổng %d: " + +#: ../libsoup/soup-session.c:4543 +#, c-format +msgid "Could not parse URI '%s'" +msgstr "Không thể phân tích URI “%s”" + +#: ../libsoup/soup-session.c:4580 +#, c-format +msgid "Unsupported URI scheme '%s'" +msgstr "Không hỗ trợ kiểu URI “%s”" + +#: ../libsoup/soup-session.c:4602 +#, c-format +msgid "Not an HTTP URI" +msgstr "Không phải URI của HTTP" + +#: ../libsoup/soup-session.c:4788 +msgid "The server did not accept the WebSocket handshake." +msgstr "Máy chủ đã không chấp nhận bắt tay WebSocket" + +#: ../libsoup/soup-socket.c:148 +msgid "Can't import non-socket as SoupSocket" +msgstr "Không thể nhập vào SoupSocket một non-socket" + +#: ../libsoup/soup-socket.c:166 +msgid "Could not import existing socket: " +msgstr "Không thể nhập vào ổ cắm mạng đã có: " + +#: ../libsoup/soup-socket.c:175 +msgid "Can't import unconnected socket" +msgstr "Không thể nhập vào một ổ cắm mạng mà nó chưa kết nối" + +#: ../libsoup/soup-websocket.c:338 ../libsoup/soup-websocket.c:347 +msgid "WebSocket handshake expected" +msgstr "Cần bắt tay WebSocket" + +#: ../libsoup/soup-websocket.c:355 +msgid "Unsupported WebSocket version" +msgstr "Phiên bản WebSocket không được hỗ trợ" + +#: ../libsoup/soup-websocket.c:364 +msgid "Invalid WebSocket key" +msgstr "Khóa WebSocket không hợp lệ" + +#: ../libsoup/soup-websocket.c:374 +#, c-format +msgid "Incorrect WebSocket \"%s\" header" +msgstr "Phần đầu WebSocket \"%s\" không hợp lệ" + +#: ../libsoup/soup-websocket.c:383 +msgid "Unsupported WebSocket subprotocol" +msgstr "Không hỗ trợ giao thức phụ WebSocket" + +#: ../libsoup/soup-websocket.c:510 +msgid "Server rejected WebSocket handshake" +msgstr "Máy phục vụ từ chối bắt tay WebSocket" + +#: ../libsoup/soup-websocket.c:518 ../libsoup/soup-websocket.c:527 +msgid "Server ignored WebSocket handshake" +msgstr "Máy phục vụ bỏ qua bắt tay WebSocket" + +#: ../libsoup/soup-websocket.c:539 +msgid "Server requested unsupported protocol" +msgstr "Máy phục vụ đã yêu cầu giao thức không được hỗ trợ" + +#: ../libsoup/soup-websocket.c:549 +msgid "Server requested unsupported extension" +msgstr "Máy phục vụ đã yêu cầu phần mở rộng không được hỗ trợ" + +#: ../libsoup/soup-websocket.c:562 +#, c-format +msgid "Server returned incorrect \"%s\" key" +msgstr "Máy phục vụ trả về khóa \"%s\" không hợp lệ" + +#: ../libsoup/soup-tld.c:188 +msgid "Hostname is an IP address" +msgstr "Tên máy là địa chỉ IP" + +#: ../libsoup/soup-tld.c:198 ../libsoup/soup-tld.c:220 +msgid "Invalid hostname" +msgstr "Tên máy không hợp lệ" + +#: ../libsoup/soup-tld.c:250 +msgid "Hostname has no base domain" +msgstr "Tên máy không có miền cơ sở" + +#: ../libsoup/soup-tld.c:304 +msgid "Not enough domains" +msgstr "Không đủ miền" diff --git a/po/zh_CN.po b/po/zh_CN.po new file mode 100644 index 0000000..e9493d7 --- /dev/null +++ b/po/zh_CN.po @@ -0,0 +1,184 @@ +# Chinese (China) translation for libsoup. +# Copyright (C) 2012-2018 libsoup's COPYRIGHT HOLDER +# This file is distributed under the same license as the libsoup package. +# hmasterwang , 2012. +# Alpha Cheng , 2012. +# Cheng Lu , 2012. +# YunQiang Su , 2012. +# Dingzhong Chen , 2017, 2018. +# Aron Xu , 2018. +# +msgid "" +msgstr "" +"Project-Id-Version: libsoup master\n" +"Report-Msgid-Bugs-To: https://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=Misc\n" +"POT-Creation-Date: 2018-03-03 11:33+0000\n" +"PO-Revision-Date: 2018-03-24 00:37+0800\n" +"Last-Translator: Dingzhong Chen \n" +"Language-Team: Chinese (China) \n" +"Language: zh_CN\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Gtranslator 2.91.7\n" + +#: ../libsoup/soup-body-input-stream.c:139 +#: ../libsoup/soup-body-input-stream.c:170 +#: ../libsoup/soup-body-input-stream.c:203 ../libsoup/soup-message-io.c:238 +msgid "Connection terminated unexpectedly" +msgstr "连接异常终止" + +#: ../libsoup/soup-body-input-stream.c:459 +msgid "Invalid seek request" +msgstr "无效的 seek 请求" + +#: ../libsoup/soup-body-input-stream.c:487 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "无法截断 (truncate) SoupBodyInputStream" + +#: ../libsoup/soup-cache-input-stream.c:76 +msgid "Network stream unexpectedly closed" +msgstr "网络流意外关闭" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "无法完全缓存该资源" + +#: ../libsoup/soup-converter-wrapper.c:189 +#, c-format +msgid "Output buffer is too small" +msgstr "输出缓冲区太小" + +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "无法解析 HTTP 响应" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "未识别的 HTTP 响应编码" + +#: ../libsoup/soup-message-io.c:263 +msgid "Header too big" +msgstr "Header 太大" + +#: ../libsoup/soup-message-io.c:396 ../libsoup/soup-message-io.c:1024 +msgid "Operation would block" +msgstr "操作将阻塞" + +#: ../libsoup/soup-message-io.c:976 ../libsoup/soup-message-io.c:1009 +msgid "Operation was cancelled" +msgstr "操作被取消" + +#: ../libsoup/soup-message-server-io.c:64 +msgid "Could not parse HTTP request" +msgstr "无法解析 HTTP 请求" + +#: ../libsoup/soup-request.c:141 +#, c-format +msgid "No URI provided" +msgstr "未提供 URI" + +#: ../libsoup/soup-request.c:151 +#, c-format +msgid "Invalid “%s” URI: %s" +msgstr "无效的“%s”URI:%s" + +#: ../libsoup/soup-server.c:1725 +msgid "Can’t create a TLS server without a TLS certificate" +msgstr "没有 TLS 证书不能创建 TLS 服务器" + +#: ../libsoup/soup-server.c:1742 +#, c-format +msgid "Could not listen on address %s, port %d: " +msgstr "不能监听 %s 地址的 %d 端口:" + +#: ../libsoup/soup-session.c:4524 +#, c-format +msgid "Could not parse URI “%s”" +msgstr "无法解析 URI“%s”" + +#: ../libsoup/soup-session.c:4561 +#, c-format +msgid "Unsupported URI scheme “%s”" +msgstr "不支持的 URI 方案“%s”" + +#: ../libsoup/soup-session.c:4583 +#, c-format +msgid "Not an HTTP URI" +msgstr "不是一个 HTTP URI" + +#: ../libsoup/soup-session.c:4781 +msgid "The server did not accept the WebSocket handshake." +msgstr "服务器不接受 WebSocket 握手。" + +#: ../libsoup/soup-socket.c:148 +msgid "Can’t import non-socket as SoupSocket" +msgstr "不能将 non-socket 作为 SoupSocket 导入" + +#: ../libsoup/soup-socket.c:166 +msgid "Could not import existing socket: " +msgstr "不能导入已存在的套接字:" + +#: ../libsoup/soup-socket.c:175 +msgid "Can’t import unconnected socket" +msgstr "不能导入未连接的套接字" + +#: ../libsoup/soup-websocket.c:338 ../libsoup/soup-websocket.c:347 +msgid "WebSocket handshake expected" +msgstr "期待 WebSocket 握手" + +#: ../libsoup/soup-websocket.c:355 +msgid "Unsupported WebSocket version" +msgstr "不支持的 WebSocket 版本" + +#: ../libsoup/soup-websocket.c:364 +msgid "Invalid WebSocket key" +msgstr "无效的 WebSocket 密钥" + +#: ../libsoup/soup-websocket.c:374 +#, c-format +msgid "Incorrect WebSocket “%s” header" +msgstr "不正确的 WebSocket “%s”头" + +#: ../libsoup/soup-websocket.c:383 +msgid "Unsupported WebSocket subprotocol" +msgstr "不支持的 WebSocket 子协议" + +#: ../libsoup/soup-websocket.c:510 +msgid "Server rejected WebSocket handshake" +msgstr "服务器拒绝 WebSocket 握手" + +#: ../libsoup/soup-websocket.c:518 ../libsoup/soup-websocket.c:527 +msgid "Server ignored WebSocket handshake" +msgstr "服务器忽略 WebSocket 握手" + +#: ../libsoup/soup-websocket.c:539 +msgid "Server requested unsupported protocol" +msgstr "服务器请求不支持的协议" + +#: ../libsoup/soup-websocket.c:549 +msgid "Server requested unsupported extension" +msgstr "服务器请求不支持的扩展" + +#: ../libsoup/soup-websocket.c:562 +#, c-format +msgid "Server returned incorrect “%s” key" +msgstr "服务器返回不正确的“%s”密钥" + +#: ../libsoup/soup-tld.c:187 +msgid "Hostname is an IP address" +msgstr "主机名是一个 IP 地址" + +#: ../libsoup/soup-tld.c:197 ../libsoup/soup-tld.c:219 +msgid "Invalid hostname" +msgstr "主机名无效" + +#: ../libsoup/soup-tld.c:249 +msgid "Hostname has no base domain" +msgstr "主机名没有基域" + +#: ../libsoup/soup-tld.c:303 +msgid "Not enough domains" +msgstr "没有足够的域" diff --git a/po/zh_HK.po b/po/zh_HK.po new file mode 100644 index 0000000..acaba22 --- /dev/null +++ b/po/zh_HK.po @@ -0,0 +1,128 @@ +# Chinese (Hong Kong) translation for libsoup. +# Copyright (C) 2012 libsoup's COPYRIGHT HOLDER +# This file is distributed under the same license as the libsoup package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: libsoup master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2014-08-20 21:41+0000\n" +"PO-Revision-Date: 2014-08-21 18:54+0800\n" +"Last-Translator: Chao-Hsiung Liao \n" +"Language-Team: Chinese (Hong Kong) \n" +"Language: zh_HK\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 1.6.5\n" + +#: ../libsoup/soup-body-input-stream.c:140 +#: ../libsoup/soup-body-input-stream.c:171 +#: ../libsoup/soup-body-input-stream.c:204 ../libsoup/soup-message-io.c:196 +msgid "Connection terminated unexpectedly" +msgstr "連線無預警的關閉了" + +#: ../libsoup/soup-body-input-stream.c:462 +msgid "Invalid seek request" +msgstr "無效的搜尋要求" + +#: ../libsoup/soup-body-input-stream.c:490 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "不能截短 SoupBodyInputStream" + +#: ../libsoup/soup-cache-input-stream.c:73 +msgid "Network stream unexpectedly closed" +msgstr "網絡串流無預警的關閉了" + +#: ../libsoup/soup-cache-input-stream.c:290 +msgid "Failed to completely cache the resource" +msgstr "無法完整快取資源" + +#: ../libsoup/soup-converter-wrapper.c:192 +#, c-format +msgid "Output buffer is too small" +msgstr "輸出緩衝區太小" + +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "無法解析 HTTP 回應" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "未辨識的 HTTP 回應編碼" + +#: ../libsoup/soup-message-io.c:854 ../libsoup/soup-message-io.c:890 +msgid "Operation was cancelled" +msgstr "操作已被取消" + +#: ../libsoup/soup-message-io.c:901 +msgid "Operation would block" +msgstr "操作會阻擋" + +#: ../libsoup/soup-message-server-io.c:41 +msgid "Could not parse HTTP request" +msgstr "無法解析 HTTP 要求" + +#: ../libsoup/soup-request.c:140 +#, c-format +msgid "No URI provided" +msgstr "未提供 URI" + +#: ../libsoup/soup-request.c:150 +#, c-format +msgid "Invalid '%s' URI: %s" +msgstr "無效的「%s」URI:%s" + +#: ../libsoup/soup-server.c:1528 +msgid "Can't create a TLS server without a TLS certificate" +msgstr "沒有 TLS 證書不能建立 TLS 伺服器" + +#: ../libsoup/soup-server.c:1547 +#, c-format +msgid "Could not listen on address %s, port %d: " +msgstr "無法聽取位址 %s,連接埠 %d:" + +#: ../libsoup/soup-session.c:4466 +#, c-format +msgid "Could not parse URI '%s'" +msgstr "無法解析 URI「%s」" + +#: ../libsoup/soup-session.c:4503 +#, c-format +msgid "Unsupported URI scheme '%s'" +msgstr "不支援的 URI scheme「%s」" + +#: ../libsoup/soup-session.c:4525 +#, c-format +msgid "Not an HTTP URI" +msgstr "並非 HTTP URI" + +#: ../libsoup/soup-socket.c:142 +msgid "Can't import non-socket as SoupSocket" +msgstr "不能匯入非-socket 做為 SoupSocket" + +#: ../libsoup/soup-socket.c:160 +msgid "Could not import existing socket: " +msgstr "無法匯入現有的 socket:" + +#: ../libsoup/soup-socket.c:169 +msgid "Can't import unconnected socket" +msgstr "不能匯入未連線的 socket" + +#: ../libsoup/soup-tld.c:188 +msgid "Hostname is an IP address" +msgstr "主機名稱是 IP 位址" + +#: ../libsoup/soup-tld.c:198 ../libsoup/soup-tld.c:220 +msgid "Invalid hostname" +msgstr "主機名稱無效" + +#: ../libsoup/soup-tld.c:250 +msgid "Hostname has no base domain" +msgstr "主機名稱沒有基礎網域" + +#: ../libsoup/soup-tld.c:304 +msgid "Not enough domains" +msgstr "沒有足夠的網域" diff --git a/po/zh_TW.po b/po/zh_TW.po new file mode 100644 index 0000000..cae00cd --- /dev/null +++ b/po/zh_TW.po @@ -0,0 +1,178 @@ +# Chinese (Taiwan) translation for libsoup. +# Copyright (C) 2012 libsoup's COPYRIGHT HOLDER +# This file is distributed under the same license as the libsoup package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: libsoup master\n" +"Report-Msgid-Bugs-To: https://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=Misc\n" +"POT-Creation-Date: 2018-02-26 07:58+0000\n" +"PO-Revision-Date: 2018-02-28 20:56+0800\n" +"Last-Translator: Chao-Hsiung Liao \n" +"Language-Team: Chinese (Taiwan) \n" +"Language: zh_TW\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 2.0.6\n" + +#: ../libsoup/soup-body-input-stream.c:139 +#: ../libsoup/soup-body-input-stream.c:170 +#: ../libsoup/soup-body-input-stream.c:203 ../libsoup/soup-message-io.c:238 +msgid "Connection terminated unexpectedly" +msgstr "連線無預警的關閉了" + +#: ../libsoup/soup-body-input-stream.c:459 +msgid "Invalid seek request" +msgstr "無效的搜尋要求" + +#: ../libsoup/soup-body-input-stream.c:487 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "不能截短 SoupBodyInputStream" + +#: ../libsoup/soup-cache-input-stream.c:76 +msgid "Network stream unexpectedly closed" +msgstr "網路串流無預警的關閉了" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "無法完整快取資源" + +#: ../libsoup/soup-converter-wrapper.c:189 +#, c-format +msgid "Output buffer is too small" +msgstr "輸出緩衝區太小" + +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "無法解析 HTTP 回應" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "未辨識的 HTTP 回應編碼" + +#: ../libsoup/soup-message-io.c:263 +msgid "Header too big" +msgstr "標頭太大" + +#: ../libsoup/soup-message-io.c:396 ../libsoup/soup-message-io.c:1024 +msgid "Operation would block" +msgstr "操作會阻擋" + +#: ../libsoup/soup-message-io.c:976 ../libsoup/soup-message-io.c:1009 +msgid "Operation was cancelled" +msgstr "操作已被取消" + +#: ../libsoup/soup-message-server-io.c:64 +msgid "Could not parse HTTP request" +msgstr "無法解析 HTTP 要求" + +#: ../libsoup/soup-request.c:141 +#, c-format +msgid "No URI provided" +msgstr "未提供 URI" + +#: ../libsoup/soup-request.c:151 +#, c-format +msgid "Invalid “%s” URI: %s" +msgstr "無效的「%s」URI:%s" + +#: ../libsoup/soup-server.c:1725 +msgid "Can’t create a TLS server without a TLS certificate" +msgstr "沒有 TLS 憑證不能建立 TLS 伺服器" + +#: ../libsoup/soup-server.c:1742 +#, c-format +msgid "Could not listen on address %s, port %d: " +msgstr "無法聽取位址 %s,連接埠 %d:" + +#: ../libsoup/soup-session.c:4524 +#, c-format +msgid "Could not parse URI “%s”" +msgstr "無法解析 URI「%s」" + +#: ../libsoup/soup-session.c:4561 +#, c-format +msgid "Unsupported URI scheme “%s”" +msgstr "不支援的 URI scheme「%s」" + +#: ../libsoup/soup-session.c:4583 +#, c-format +msgid "Not an HTTP URI" +msgstr "並非 HTTP URI" + +#: ../libsoup/soup-session.c:4781 +msgid "The server did not accept the WebSocket handshake." +msgstr "伺服器不接受 WebSocket 交握。" + +#: ../libsoup/soup-socket.c:148 +msgid "Can’t import non-socket as SoupSocket" +msgstr "不能匯入非-socket 做為 SoupSocket" + +#: ../libsoup/soup-socket.c:166 +msgid "Could not import existing socket: " +msgstr "無法匯入現有的 socket:" + +#: ../libsoup/soup-socket.c:175 +msgid "Can’t import unconnected socket" +msgstr "不能匯入未連線的 socket" + +#: ../libsoup/soup-websocket.c:338 ../libsoup/soup-websocket.c:347 +msgid "WebSocket handshake expected" +msgstr "預期有 WebSocket 交握" + +#: ../libsoup/soup-websocket.c:355 +msgid "Unsupported WebSocket version" +msgstr "不支援的 WebSocket 版本" + +#: ../libsoup/soup-websocket.c:364 +msgid "Invalid WebSocket key" +msgstr "無效的 WebSocket 金鑰是" + +#: ../libsoup/soup-websocket.c:374 +#, c-format +msgid "Incorrect WebSocket “%s” header" +msgstr "無效的 WebSocket「%s」標頭" + +#: ../libsoup/soup-websocket.c:383 +msgid "Unsupported WebSocket subprotocol" +msgstr "不支援的 WebSocket 子協定" + +#: ../libsoup/soup-websocket.c:510 +msgid "Server rejected WebSocket handshake" +msgstr "伺服器拒絕 WebSocket 交握" + +#: ../libsoup/soup-websocket.c:518 ../libsoup/soup-websocket.c:527 +msgid "Server ignored WebSocket handshake" +msgstr "伺服器忽略 WebSocket 交握" + +#: ../libsoup/soup-websocket.c:539 +msgid "Server requested unsupported protocol" +msgstr "伺服器要求不支援的網路通訊協定" + +#: ../libsoup/soup-websocket.c:549 +msgid "Server requested unsupported extension" +msgstr "伺服器要求不支援的擴充功能" + +#: ../libsoup/soup-websocket.c:562 +#, c-format +msgid "Server returned incorrect “%s” key" +msgstr "伺服器傳回不正確的「%s」金鑰" + +#: ../libsoup/soup-tld.c:187 +msgid "Hostname is an IP address" +msgstr "主機名稱是 IP 位址" + +#: ../libsoup/soup-tld.c:197 ../libsoup/soup-tld.c:219 +msgid "Invalid hostname" +msgstr "主機名稱無效" + +#: ../libsoup/soup-tld.c:249 +msgid "Hostname has no base domain" +msgstr "主機名稱沒有基礎網域" + +#: ../libsoup/soup-tld.c:303 +msgid "Not enough domains" +msgstr "沒有足夠的網域" diff --git a/tap-driver.sh b/tap-driver.sh new file mode 100755 index 0000000..19aa531 --- /dev/null +++ b/tap-driver.sh @@ -0,0 +1,652 @@ +#! /bin/sh +# Copyright (C) 2011-2013 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, 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 file is maintained in Automake, please report +# bugs to or send patches to +# . + +scriptversion=2011-12-27.17; # UTC + +# Make unconditional expansion of undefined variables an error. This +# helps a lot in preventing typo-related bugs. +set -u + +me=tap-driver.sh + +fatal () +{ + echo "$me: fatal: $*" >&2 + exit 1 +} + +usage_error () +{ + echo "$me: $*" >&2 + print_usage >&2 + exit 2 +} + +print_usage () +{ + cat < + # + trap : 1 3 2 13 15 + if test $merge -gt 0; then + exec 2>&1 + else + exec 2>&3 + fi + "$@" + echo $? + ) | LC_ALL=C ${AM_TAP_AWK-awk} \ + -v me="$me" \ + -v test_script_name="$test_name" \ + -v log_file="$log_file" \ + -v trs_file="$trs_file" \ + -v expect_failure="$expect_failure" \ + -v merge="$merge" \ + -v ignore_exit="$ignore_exit" \ + -v comments="$comments" \ + -v diag_string="$diag_string" \ +' +# FIXME: the usages of "cat >&3" below could be optimized when using +# FIXME: GNU awk, and/on on systems that supports /dev/fd/. + +# Implementation note: in what follows, `result_obj` will be an +# associative array that (partly) simulates a TAP result object +# from the `TAP::Parser` perl module. + +## ----------- ## +## FUNCTIONS ## +## ----------- ## + +function fatal(msg) +{ + print me ": " msg | "cat >&2" + exit 1 +} + +function abort(where) +{ + fatal("internal error " where) +} + +# Convert a boolean to a "yes"/"no" string. +function yn(bool) +{ + return bool ? "yes" : "no"; +} + +function add_test_result(result) +{ + if (!test_results_index) + test_results_index = 0 + test_results_list[test_results_index] = result + test_results_index += 1 + test_results_seen[result] = 1; +} + +# Whether the test script should be re-run by "make recheck". +function must_recheck() +{ + for (k in test_results_seen) + if (k != "XFAIL" && k != "PASS" && k != "SKIP") + return 1 + return 0 +} + +# Whether the content of the log file associated to this test should +# be copied into the "global" test-suite.log. +function copy_in_global_log() +{ + for (k in test_results_seen) + if (k != "PASS") + return 1 + return 0 +} + +# FIXME: this can certainly be improved ... +function get_global_test_result() +{ + if ("ERROR" in test_results_seen) + return "ERROR" + if ("FAIL" in test_results_seen || "XPASS" in test_results_seen) + return "FAIL" + all_skipped = 1 + for (k in test_results_seen) + if (k != "SKIP") + all_skipped = 0 + if (all_skipped) + return "SKIP" + return "PASS"; +} + +function stringify_result_obj(result_obj) +{ + if (result_obj["is_unplanned"] || result_obj["number"] != testno) + return "ERROR" + + if (plan_seen == LATE_PLAN) + return "ERROR" + + if (result_obj["directive"] == "TODO") + return result_obj["is_ok"] ? "XPASS" : "XFAIL" + + if (result_obj["directive"] == "SKIP") + return result_obj["is_ok"] ? "SKIP" : COOKED_FAIL; + + if (length(result_obj["directive"])) + abort("in function stringify_result_obj()") + + return result_obj["is_ok"] ? COOKED_PASS : COOKED_FAIL +} + +function decorate_result(result) +{ + color_name = color_for_result[result] + if (color_name) + return color_map[color_name] "" result "" color_map["std"] + # If we are not using colorized output, or if we do not know how + # to colorize the given result, we should return it unchanged. + return result +} + +function report(result, details) +{ + if (result ~ /^(X?(PASS|FAIL)|SKIP|ERROR)/) + { + msg = ": " test_script_name + add_test_result(result) + } + else if (result == "#") + { + msg = " " test_script_name ":" + } + else + { + abort("in function report()") + } + if (length(details)) + msg = msg " " details + # Output on console might be colorized. + print decorate_result(result) msg + # Log the result in the log file too, to help debugging (this is + # especially true when said result is a TAP error or "Bail out!"). + print result msg | "cat >&3"; +} + +function testsuite_error(error_message) +{ + report("ERROR", "- " error_message) +} + +function handle_tap_result() +{ + details = result_obj["number"]; + if (length(result_obj["description"])) + details = details " " result_obj["description"] + + if (plan_seen == LATE_PLAN) + { + details = details " # AFTER LATE PLAN"; + } + else if (result_obj["is_unplanned"]) + { + details = details " # UNPLANNED"; + } + else if (result_obj["number"] != testno) + { + details = sprintf("%s # OUT-OF-ORDER (expecting %d)", + details, testno); + } + else if (result_obj["directive"]) + { + details = details " # " result_obj["directive"]; + if (length(result_obj["explanation"])) + details = details " " result_obj["explanation"] + } + + report(stringify_result_obj(result_obj), details) +} + +# `skip_reason` should be empty whenever planned > 0. +function handle_tap_plan(planned, skip_reason) +{ + planned += 0 # Avoid getting confused if, say, `planned` is "00" + if (length(skip_reason) && planned > 0) + abort("in function handle_tap_plan()") + if (plan_seen) + { + # Error, only one plan per stream is acceptable. + testsuite_error("multiple test plans") + return; + } + planned_tests = planned + # The TAP plan can come before or after *all* the TAP results; we speak + # respectively of an "early" or a "late" plan. If we see the plan line + # after at least one TAP result has been seen, assume we have a late + # plan; in this case, any further test result seen after the plan will + # be flagged as an error. + plan_seen = (testno >= 1 ? LATE_PLAN : EARLY_PLAN) + # If testno > 0, we have an error ("too many tests run") that will be + # automatically dealt with later, so do not worry about it here. If + # $plan_seen is true, we have an error due to a repeated plan, and that + # has already been dealt with above. Otherwise, we have a valid "plan + # with SKIP" specification, and should report it as a particular kind + # of SKIP result. + if (planned == 0 && testno == 0) + { + if (length(skip_reason)) + skip_reason = "- " skip_reason; + report("SKIP", skip_reason); + } +} + +function extract_tap_comment(line) +{ + if (index(line, diag_string) == 1) + { + # Strip leading `diag_string` from `line`. + line = substr(line, length(diag_string) + 1) + # And strip any leading and trailing whitespace left. + sub("^[ \t]*", "", line) + sub("[ \t]*$", "", line) + # Return what is left (if any). + return line; + } + return ""; +} + +# When this function is called, we know that line is a TAP result line, +# so that it matches the (perl) RE "^(not )?ok\b". +function setup_result_obj(line) +{ + # Get the result, and remove it from the line. + result_obj["is_ok"] = (substr(line, 1, 2) == "ok" ? 1 : 0) + sub("^(not )?ok[ \t]*", "", line) + + # If the result has an explicit number, get it and strip it; otherwise, + # automatically assing the next progresive number to it. + if (line ~ /^[0-9]+$/ || line ~ /^[0-9]+[^a-zA-Z0-9_]/) + { + match(line, "^[0-9]+") + # The final `+ 0` is to normalize numbers with leading zeros. + result_obj["number"] = substr(line, 1, RLENGTH) + 0 + line = substr(line, RLENGTH + 1) + } + else + { + result_obj["number"] = testno + } + + if (plan_seen == LATE_PLAN) + # No further test results are acceptable after a "late" TAP plan + # has been seen. + result_obj["is_unplanned"] = 1 + else if (plan_seen && testno > planned_tests) + result_obj["is_unplanned"] = 1 + else + result_obj["is_unplanned"] = 0 + + # Strip trailing and leading whitespace. + sub("^[ \t]*", "", line) + sub("[ \t]*$", "", line) + + # This will have to be corrected if we have a "TODO"/"SKIP" directive. + result_obj["description"] = line + result_obj["directive"] = "" + result_obj["explanation"] = "" + + if (index(line, "#") == 0) + return # No possible directive, nothing more to do. + + # Directives are case-insensitive. + rx = "[ \t]*#[ \t]*([tT][oO][dD][oO]|[sS][kK][iI][pP])[ \t]*" + + # See whether we have the directive, and if yes, where. + pos = match(line, rx "$") + if (!pos) + pos = match(line, rx "[^a-zA-Z0-9_]") + + # If there was no TAP directive, we have nothing more to do. + if (!pos) + return + + # Let`s now see if the TAP directive has been escaped. For example: + # escaped: ok \# SKIP + # not escaped: ok \\# SKIP + # escaped: ok \\\\\# SKIP + # not escaped: ok \ # SKIP + if (substr(line, pos, 1) == "#") + { + bslash_count = 0 + for (i = pos; i > 1 && substr(line, i - 1, 1) == "\\"; i--) + bslash_count += 1 + if (bslash_count % 2) + return # Directive was escaped. + } + + # Strip the directive and its explanation (if any) from the test + # description. + result_obj["description"] = substr(line, 1, pos - 1) + # Now remove the test description from the line, that has been dealt + # with already. + line = substr(line, pos) + # Strip the directive, and save its value (normalized to upper case). + sub("^[ \t]*#[ \t]*", "", line) + result_obj["directive"] = toupper(substr(line, 1, 4)) + line = substr(line, 5) + # Now get the explanation for the directive (if any), with leading + # and trailing whitespace removed. + sub("^[ \t]*", "", line) + sub("[ \t]*$", "", line) + result_obj["explanation"] = line +} + +function get_test_exit_message(status) +{ + if (status == 0) + return "" + if (status !~ /^[1-9][0-9]*$/) + abort("getting exit status") + if (status < 127) + exit_details = "" + else if (status == 127) + exit_details = " (command not found?)" + else if (status >= 128 && status <= 255) + exit_details = sprintf(" (terminated by signal %d?)", status - 128) + else if (status > 256 && status <= 384) + # We used to report an "abnormal termination" here, but some Korn + # shells, when a child process die due to signal number n, can leave + # in $? an exit status of 256+n instead of the more standard 128+n. + # Apparently, both behaviours are allowed by POSIX (2008), so be + # prepared to handle them both. See also Austing Group report ID + # 0000051 + exit_details = sprintf(" (terminated by signal %d?)", status - 256) + else + # Never seen in practice. + exit_details = " (abnormal termination)" + return sprintf("exited with status %d%s", status, exit_details) +} + +function write_test_results() +{ + print ":global-test-result: " get_global_test_result() > trs_file + print ":recheck: " yn(must_recheck()) > trs_file + print ":copy-in-global-log: " yn(copy_in_global_log()) > trs_file + for (i = 0; i < test_results_index; i += 1) + print ":test-result: " test_results_list[i] > trs_file + close(trs_file); +} + +BEGIN { + +## ------- ## +## SETUP ## +## ------- ## + +'"$init_colors"' + +# Properly initialized once the TAP plan is seen. +planned_tests = 0 + +COOKED_PASS = expect_failure ? "XPASS": "PASS"; +COOKED_FAIL = expect_failure ? "XFAIL": "FAIL"; + +# Enumeration-like constants to remember which kind of plan (if any) +# has been seen. It is important that NO_PLAN evaluates "false" as +# a boolean. +NO_PLAN = 0 +EARLY_PLAN = 1 +LATE_PLAN = 2 + +testno = 0 # Number of test results seen so far. +bailed_out = 0 # Whether a "Bail out!" directive has been seen. + +# Whether the TAP plan has been seen or not, and if yes, which kind +# it is ("early" is seen before any test result, "late" otherwise). +plan_seen = NO_PLAN + +## --------- ## +## PARSING ## +## --------- ## + +is_first_read = 1 + +while (1) + { + # Involutions required so that we are able to read the exit status + # from the last input line. + st = getline + if (st < 0) # I/O error. + fatal("I/O error while reading from input stream") + else if (st == 0) # End-of-input + { + if (is_first_read) + abort("in input loop: only one input line") + break + } + if (is_first_read) + { + is_first_read = 0 + nextline = $0 + continue + } + else + { + curline = nextline + nextline = $0 + $0 = curline + } + # Copy any input line verbatim into the log file. + print | "cat >&3" + # Parsing of TAP input should stop after a "Bail out!" directive. + if (bailed_out) + continue + + # TAP test result. + if ($0 ~ /^(not )?ok$/ || $0 ~ /^(not )?ok[^a-zA-Z0-9_]/) + { + testno += 1 + setup_result_obj($0) + handle_tap_result() + } + # TAP plan (normal or "SKIP" without explanation). + else if ($0 ~ /^1\.\.[0-9]+[ \t]*$/) + { + # The next two lines will put the number of planned tests in $0. + sub("^1\\.\\.", "") + sub("[^0-9]*$", "") + handle_tap_plan($0, "") + continue + } + # TAP "SKIP" plan, with an explanation. + else if ($0 ~ /^1\.\.0+[ \t]*#/) + { + # The next lines will put the skip explanation in $0, stripping + # any leading and trailing whitespace. This is a little more + # tricky in truth, since we want to also strip a potential leading + # "SKIP" string from the message. + sub("^[^#]*#[ \t]*(SKIP[: \t][ \t]*)?", "") + sub("[ \t]*$", ""); + handle_tap_plan(0, $0) + } + # "Bail out!" magic. + # Older versions of prove and TAP::Harness (e.g., 3.17) did not + # recognize a "Bail out!" directive when preceded by leading + # whitespace, but more modern versions (e.g., 3.23) do. So we + # emulate the latter, "more modern" behaviour. + else if ($0 ~ /^[ \t]*Bail out!/) + { + bailed_out = 1 + # Get the bailout message (if any), with leading and trailing + # whitespace stripped. The message remains stored in `$0`. + sub("^[ \t]*Bail out![ \t]*", ""); + sub("[ \t]*$", ""); + # Format the error message for the + bailout_message = "Bail out!" + if (length($0)) + bailout_message = bailout_message " " $0 + testsuite_error(bailout_message) + } + # Maybe we have too look for dianogtic comments too. + else if (comments != 0) + { + comment = extract_tap_comment($0); + if (length(comment)) + report("#", comment); + } + } + +## -------- ## +## FINISH ## +## -------- ## + +# A "Bail out!" directive should cause us to ignore any following TAP +# error, as well as a non-zero exit status from the TAP producer. +if (!bailed_out) + { + if (!plan_seen) + { + testsuite_error("missing test plan") + } + else if (planned_tests != testno) + { + bad_amount = testno > planned_tests ? "many" : "few" + testsuite_error(sprintf("too %s tests run (expected %d, got %d)", + bad_amount, planned_tests, testno)) + } + if (!ignore_exit) + { + # Fetch exit status from the last line. + exit_message = get_test_exit_message(nextline) + if (exit_message) + testsuite_error(exit_message) + } + } + +write_test_results() + +exit 0 + +} # End of "BEGIN" block. +' + +# TODO: document that we consume the file descriptor 3 :-( +} 3>"$log_file" + +test $? -eq 0 || fatal "I/O or internal error" + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/tap-test b/tap-test new file mode 100755 index 0000000..481e333 --- /dev/null +++ b/tap-test @@ -0,0 +1,5 @@ +#! /bin/sh + +# run a GTest in tap mode. The test binary is passed as $1 + +$1 -k --tap diff --git a/tests/Makefile.am b/tests/Makefile.am new file mode 100644 index 0000000..81a72cb --- /dev/null +++ b/tests/Makefile.am @@ -0,0 +1,110 @@ +include $(top_srcdir)/glib-tap.mk + +AM_CPPFLAGS = \ + -I$(top_srcdir) \ + $(GLIB_CFLAGS) + +LIBS = \ + $(top_builddir)/libsoup/libsoup-2.4.la \ + $(GLIB_LIBS) + +test_programs = \ + auth-test \ + cache-test \ + chunk-test \ + chunk-io-test \ + coding-test \ + connection-test \ + context-test \ + continue-test \ + cookies-test \ + date \ + forms-test \ + header-parsing \ + misc-test \ + multipart-test \ + no-ssl-test \ + ntlm-test \ + proxy-test \ + pull-api \ + range-test \ + redirect-test \ + requester-test \ + resource-test \ + session-test \ + server-auth-test \ + server-test \ + sniffing-test \ + socket-test \ + ssl-test \ + streaming-test \ + timeout-test \ + tld-test \ + uri-parsing \ + websocket-test \ + xmlrpc-old-server-test \ + xmlrpc-old-test \ + xmlrpc-server-test \ + xmlrpc-test + +test_extra_programs = \ + ntlm-test-helper \ + $(TESTS) + +test_data = \ + index.txt \ + soup-tests.gresource \ + test-cert.pem \ + test-key.pem \ + xmlrpc-server.php + +noinst_LTLIBRARIES += libtest.la + +libtest_la_SOURCES = \ + test-utils.c \ + test-utils.h + +LDADD = libtest.la + +if HAVE_APACHE +test_data += \ + htdigest \ + htpasswd \ + httpd.conf +endif + +RESOURCES = $(shell $(GLIB_COMPILE_RESOURCES) --sourcedir=$(srcdir) --generate-dependencies $(srcdir)/soup-tests.gresource.xml) + +soup-tests.gresource: soup-tests.gresource.xml $(RESOURCES) + $(AM_V_GEN) $(GLIB_COMPILE_RESOURCES) --target=$@ --sourcedir=$(srcdir) $< + +EXTRA_DIST += \ + htdigest \ + htpasswd \ + httpd.conf.in \ + index.txt \ + libsoup.supp \ + soup-tests.gresource.xml \ + test-cert.pem \ + test-key.pem \ + xmlrpc-server.php \ + $(RESOURCES) + +DISTCLEANFILES += soup-tests.gresource httpd.conf + +TESTS_ENVIRONMENT += SOUP_TESTS_IN_MAKE_CHECK=1 + +check: start-httpd + +check-local: check-TESTS + @$(MAKE) kill-httpd + +.PHONY: start-httpd kill-httpd + +start-httpd: + @$(APACHE_HTTPD) -d $(abs_srcdir) -c "DefaultRuntimeDir `pwd`" -c "PidFile `pwd`/httpd.pid" -f `pwd`/httpd.conf -k start; + +kill-httpd: + @if [ -f httpd.pid ]; then \ + $(APACHE_HTTPD) -d $(abs_srcdir) -c "DefaultRuntimeDir `pwd`" -c "PidFile `pwd`/httpd.pid" -f `pwd`/httpd.conf -k stop; \ + fi diff --git a/tests/Makefile.in b/tests/Makefile.in new file mode 100644 index 0000000..91f5372 --- /dev/null +++ b/tests/Makefile.in @@ -0,0 +1,2087 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# GLIB - Library of useful C routines + + + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +TESTS = $(am__EXEEXT_1) +installed_test_PROGRAMS = $(am__EXEEXT_6) +noinst_PROGRAMS = $(am__EXEEXT_7) +check_PROGRAMS = $(am__EXEEXT_5) +@ENABLE_ALWAYS_BUILD_TESTS_TRUE@am__append_1 = $(all_test_ltlibs) +@ENABLE_ALWAYS_BUILD_TESTS_TRUE@am__append_2 = $(all_test_programs) +@ENABLE_ALWAYS_BUILD_TESTS_TRUE@am__append_3 = $(all_test_scripts) +@ENABLE_ALWAYS_BUILD_TESTS_TRUE@am__append_4 = $(all_test_data) +@ENABLE_ALWAYS_BUILD_TESTS_FALSE@am__append_5 = $(all_test_ltlibs) +@ENABLE_ALWAYS_BUILD_TESTS_FALSE@am__append_6 = $(all_test_programs) +@ENABLE_ALWAYS_BUILD_TESTS_FALSE@am__append_7 = $(all_test_scripts) +@ENABLE_ALWAYS_BUILD_TESTS_FALSE@am__append_8 = $(all_test_data) +@ENABLE_INSTALLED_TESTS_TRUE@am__append_9 = $(test_programs) $(installed_test_programs) \ +@ENABLE_INSTALLED_TESTS_TRUE@ $(test_extra_programs) $(installed_test_extra_programs) + +@ENABLE_INSTALLED_TESTS_TRUE@am__append_10 = $(test_scripts) \ +@ENABLE_INSTALLED_TESTS_TRUE@ $(installed_test_scripts) \ +@ENABLE_INSTALLED_TESTS_TRUE@ $(test_extra_scripts) \ +@ENABLE_INSTALLED_TESTS_TRUE@ $(test_installed_extra_scripts) \ +@ENABLE_INSTALLED_TESTS_TRUE@ $(dist_test_scripts) \ +@ENABLE_INSTALLED_TESTS_TRUE@ $(dist_test_extra_scripts) \ +@ENABLE_INSTALLED_TESTS_TRUE@ $(dist_installed_test_scripts) \ +@ENABLE_INSTALLED_TESTS_TRUE@ $(dist_installed_test_extra_scripts) +@ENABLE_INSTALLED_TESTS_TRUE@am__append_11 = $(test_data) \ +@ENABLE_INSTALLED_TESTS_TRUE@ $(installed_test_data) \ +@ENABLE_INSTALLED_TESTS_TRUE@ $(dist_test_data) \ +@ENABLE_INSTALLED_TESTS_TRUE@ $(dist_installed_test_data) +@ENABLE_INSTALLED_TESTS_TRUE@am__append_12 = $(test_ltlibraries) $(installed_test_ltlibraries) +@ENABLE_INSTALLED_TESTS_TRUE@am__append_13 = $(installed_test_meta_DATA) +@HAVE_APACHE_TRUE@am__append_14 = \ +@HAVE_APACHE_TRUE@ htdigest \ +@HAVE_APACHE_TRUE@ htpasswd \ +@HAVE_APACHE_TRUE@ httpd.conf + +subdir = tests +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_code_coverage.m4 \ + $(top_srcdir)/m4/glibtests.m4 $(top_srcdir)/m4/gtk-doc.m4 \ + $(top_srcdir)/m4/intltool.m4 $(top_srcdir)/m4/introspection.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/vapigen.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = httpd.conf +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(installed_testdir)" \ + "$(DESTDIR)$(installed_testdir)" \ + "$(DESTDIR)$(installed_testdir)" \ + "$(DESTDIR)$(installed_test_metadir)" \ + "$(DESTDIR)$(installed_testdir)" +LTLIBRARIES = $(installed_test_LTLIBRARIES) $(noinst_LTLIBRARIES) +libtest_la_LIBADD = +am_libtest_la_OBJECTS = test-utils.lo +libtest_la_OBJECTS = $(am_libtest_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +am__EXEEXT_1 = auth-test$(EXEEXT) cache-test$(EXEEXT) \ + chunk-test$(EXEEXT) chunk-io-test$(EXEEXT) \ + coding-test$(EXEEXT) connection-test$(EXEEXT) \ + context-test$(EXEEXT) continue-test$(EXEEXT) \ + cookies-test$(EXEEXT) date$(EXEEXT) forms-test$(EXEEXT) \ + header-parsing$(EXEEXT) misc-test$(EXEEXT) \ + multipart-test$(EXEEXT) no-ssl-test$(EXEEXT) \ + ntlm-test$(EXEEXT) proxy-test$(EXEEXT) pull-api$(EXEEXT) \ + range-test$(EXEEXT) redirect-test$(EXEEXT) \ + requester-test$(EXEEXT) resource-test$(EXEEXT) \ + session-test$(EXEEXT) server-auth-test$(EXEEXT) \ + server-test$(EXEEXT) sniffing-test$(EXEEXT) \ + socket-test$(EXEEXT) ssl-test$(EXEEXT) streaming-test$(EXEEXT) \ + timeout-test$(EXEEXT) tld-test$(EXEEXT) uri-parsing$(EXEEXT) \ + websocket-test$(EXEEXT) xmlrpc-old-server-test$(EXEEXT) \ + xmlrpc-old-test$(EXEEXT) xmlrpc-server-test$(EXEEXT) \ + xmlrpc-test$(EXEEXT) +am__EXEEXT_2 = $(am__EXEEXT_1) +am__EXEEXT_3 = ntlm-test-helper$(EXEEXT) $(am__EXEEXT_2) +am__EXEEXT_4 = $(am__EXEEXT_1) $(am__EXEEXT_3) +@ENABLE_ALWAYS_BUILD_TESTS_FALSE@am__EXEEXT_5 = $(am__EXEEXT_4) +@ENABLE_INSTALLED_TESTS_TRUE@am__EXEEXT_6 = $(am__EXEEXT_1) \ +@ENABLE_INSTALLED_TESTS_TRUE@ $(am__EXEEXT_3) +@ENABLE_ALWAYS_BUILD_TESTS_TRUE@am__EXEEXT_7 = $(am__EXEEXT_4) +PROGRAMS = $(installed_test_PROGRAMS) $(noinst_PROGRAMS) +auth_test_SOURCES = auth-test.c +auth_test_OBJECTS = auth-test.$(OBJEXT) +auth_test_LDADD = $(LDADD) +auth_test_DEPENDENCIES = libtest.la +cache_test_SOURCES = cache-test.c +cache_test_OBJECTS = cache-test.$(OBJEXT) +cache_test_LDADD = $(LDADD) +cache_test_DEPENDENCIES = libtest.la +chunk_io_test_SOURCES = chunk-io-test.c +chunk_io_test_OBJECTS = chunk-io-test.$(OBJEXT) +chunk_io_test_LDADD = $(LDADD) +chunk_io_test_DEPENDENCIES = libtest.la +chunk_test_SOURCES = chunk-test.c +chunk_test_OBJECTS = chunk-test.$(OBJEXT) +chunk_test_LDADD = $(LDADD) +chunk_test_DEPENDENCIES = libtest.la +coding_test_SOURCES = coding-test.c +coding_test_OBJECTS = coding-test.$(OBJEXT) +coding_test_LDADD = $(LDADD) +coding_test_DEPENDENCIES = libtest.la +connection_test_SOURCES = connection-test.c +connection_test_OBJECTS = connection-test.$(OBJEXT) +connection_test_LDADD = $(LDADD) +connection_test_DEPENDENCIES = libtest.la +context_test_SOURCES = context-test.c +context_test_OBJECTS = context-test.$(OBJEXT) +context_test_LDADD = $(LDADD) +context_test_DEPENDENCIES = libtest.la +continue_test_SOURCES = continue-test.c +continue_test_OBJECTS = continue-test.$(OBJEXT) +continue_test_LDADD = $(LDADD) +continue_test_DEPENDENCIES = libtest.la +cookies_test_SOURCES = cookies-test.c +cookies_test_OBJECTS = cookies-test.$(OBJEXT) +cookies_test_LDADD = $(LDADD) +cookies_test_DEPENDENCIES = libtest.la +date_SOURCES = date.c +date_OBJECTS = date.$(OBJEXT) +date_LDADD = $(LDADD) +date_DEPENDENCIES = libtest.la +forms_test_SOURCES = forms-test.c +forms_test_OBJECTS = forms-test.$(OBJEXT) +forms_test_LDADD = $(LDADD) +forms_test_DEPENDENCIES = libtest.la +header_parsing_SOURCES = header-parsing.c +header_parsing_OBJECTS = header-parsing.$(OBJEXT) +header_parsing_LDADD = $(LDADD) +header_parsing_DEPENDENCIES = libtest.la +misc_test_SOURCES = misc-test.c +misc_test_OBJECTS = misc-test.$(OBJEXT) +misc_test_LDADD = $(LDADD) +misc_test_DEPENDENCIES = libtest.la +multipart_test_SOURCES = multipart-test.c +multipart_test_OBJECTS = multipart-test.$(OBJEXT) +multipart_test_LDADD = $(LDADD) +multipart_test_DEPENDENCIES = libtest.la +no_ssl_test_SOURCES = no-ssl-test.c +no_ssl_test_OBJECTS = no-ssl-test.$(OBJEXT) +no_ssl_test_LDADD = $(LDADD) +no_ssl_test_DEPENDENCIES = libtest.la +ntlm_test_SOURCES = ntlm-test.c +ntlm_test_OBJECTS = ntlm-test.$(OBJEXT) +ntlm_test_LDADD = $(LDADD) +ntlm_test_DEPENDENCIES = libtest.la +ntlm_test_helper_SOURCES = ntlm-test-helper.c +ntlm_test_helper_OBJECTS = ntlm-test-helper.$(OBJEXT) +ntlm_test_helper_LDADD = $(LDADD) +ntlm_test_helper_DEPENDENCIES = libtest.la +proxy_test_SOURCES = proxy-test.c +proxy_test_OBJECTS = proxy-test.$(OBJEXT) +proxy_test_LDADD = $(LDADD) +proxy_test_DEPENDENCIES = libtest.la +pull_api_SOURCES = pull-api.c +pull_api_OBJECTS = pull-api.$(OBJEXT) +pull_api_LDADD = $(LDADD) +pull_api_DEPENDENCIES = libtest.la +range_test_SOURCES = range-test.c +range_test_OBJECTS = range-test.$(OBJEXT) +range_test_LDADD = $(LDADD) +range_test_DEPENDENCIES = libtest.la +redirect_test_SOURCES = redirect-test.c +redirect_test_OBJECTS = redirect-test.$(OBJEXT) +redirect_test_LDADD = $(LDADD) +redirect_test_DEPENDENCIES = libtest.la +requester_test_SOURCES = requester-test.c +requester_test_OBJECTS = requester-test.$(OBJEXT) +requester_test_LDADD = $(LDADD) +requester_test_DEPENDENCIES = libtest.la +resource_test_SOURCES = resource-test.c +resource_test_OBJECTS = resource-test.$(OBJEXT) +resource_test_LDADD = $(LDADD) +resource_test_DEPENDENCIES = libtest.la +server_auth_test_SOURCES = server-auth-test.c +server_auth_test_OBJECTS = server-auth-test.$(OBJEXT) +server_auth_test_LDADD = $(LDADD) +server_auth_test_DEPENDENCIES = libtest.la +server_test_SOURCES = server-test.c +server_test_OBJECTS = server-test.$(OBJEXT) +server_test_LDADD = $(LDADD) +server_test_DEPENDENCIES = libtest.la +session_test_SOURCES = session-test.c +session_test_OBJECTS = session-test.$(OBJEXT) +session_test_LDADD = $(LDADD) +session_test_DEPENDENCIES = libtest.la +sniffing_test_SOURCES = sniffing-test.c +sniffing_test_OBJECTS = sniffing-test.$(OBJEXT) +sniffing_test_LDADD = $(LDADD) +sniffing_test_DEPENDENCIES = libtest.la +socket_test_SOURCES = socket-test.c +socket_test_OBJECTS = socket-test.$(OBJEXT) +socket_test_LDADD = $(LDADD) +socket_test_DEPENDENCIES = libtest.la +ssl_test_SOURCES = ssl-test.c +ssl_test_OBJECTS = ssl-test.$(OBJEXT) +ssl_test_LDADD = $(LDADD) +ssl_test_DEPENDENCIES = libtest.la +streaming_test_SOURCES = streaming-test.c +streaming_test_OBJECTS = streaming-test.$(OBJEXT) +streaming_test_LDADD = $(LDADD) +streaming_test_DEPENDENCIES = libtest.la +timeout_test_SOURCES = timeout-test.c +timeout_test_OBJECTS = timeout-test.$(OBJEXT) +timeout_test_LDADD = $(LDADD) +timeout_test_DEPENDENCIES = libtest.la +tld_test_SOURCES = tld-test.c +tld_test_OBJECTS = tld-test.$(OBJEXT) +tld_test_LDADD = $(LDADD) +tld_test_DEPENDENCIES = libtest.la +uri_parsing_SOURCES = uri-parsing.c +uri_parsing_OBJECTS = uri-parsing.$(OBJEXT) +uri_parsing_LDADD = $(LDADD) +uri_parsing_DEPENDENCIES = libtest.la +websocket_test_SOURCES = websocket-test.c +websocket_test_OBJECTS = websocket-test.$(OBJEXT) +websocket_test_LDADD = $(LDADD) +websocket_test_DEPENDENCIES = libtest.la +xmlrpc_old_server_test_SOURCES = xmlrpc-old-server-test.c +xmlrpc_old_server_test_OBJECTS = xmlrpc-old-server-test.$(OBJEXT) +xmlrpc_old_server_test_LDADD = $(LDADD) +xmlrpc_old_server_test_DEPENDENCIES = libtest.la +xmlrpc_old_test_SOURCES = xmlrpc-old-test.c +xmlrpc_old_test_OBJECTS = xmlrpc-old-test.$(OBJEXT) +xmlrpc_old_test_LDADD = $(LDADD) +xmlrpc_old_test_DEPENDENCIES = libtest.la +xmlrpc_server_test_SOURCES = xmlrpc-server-test.c +xmlrpc_server_test_OBJECTS = xmlrpc-server-test.$(OBJEXT) +xmlrpc_server_test_LDADD = $(LDADD) +xmlrpc_server_test_DEPENDENCIES = libtest.la +xmlrpc_test_SOURCES = xmlrpc-test.c +xmlrpc_test_OBJECTS = xmlrpc-test.$(OBJEXT) +xmlrpc_test_LDADD = $(LDADD) +xmlrpc_test_DEPENDENCIES = libtest.la +SCRIPTS = $(installed_test_SCRIPTS) $(noinst_SCRIPTS) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libtest_la_SOURCES) auth-test.c cache-test.c \ + chunk-io-test.c chunk-test.c coding-test.c connection-test.c \ + context-test.c continue-test.c cookies-test.c date.c \ + forms-test.c header-parsing.c misc-test.c multipart-test.c \ + no-ssl-test.c ntlm-test.c ntlm-test-helper.c proxy-test.c \ + pull-api.c range-test.c redirect-test.c requester-test.c \ + resource-test.c server-auth-test.c server-test.c \ + session-test.c sniffing-test.c socket-test.c ssl-test.c \ + streaming-test.c timeout-test.c tld-test.c uri-parsing.c \ + websocket-test.c xmlrpc-old-server-test.c xmlrpc-old-test.c \ + xmlrpc-server-test.c xmlrpc-test.c +DIST_SOURCES = $(libtest_la_SOURCES) auth-test.c cache-test.c \ + chunk-io-test.c chunk-test.c coding-test.c connection-test.c \ + context-test.c continue-test.c cookies-test.c date.c \ + forms-test.c header-parsing.c misc-test.c multipart-test.c \ + no-ssl-test.c ntlm-test.c ntlm-test-helper.c proxy-test.c \ + pull-api.c range-test.c redirect-test.c requester-test.c \ + resource-test.c server-auth-test.c server-test.c \ + session-test.c sniffing-test.c socket-test.c ssl-test.c \ + streaming-test.c timeout-test.c tld-test.c uri-parsing.c \ + websocket-test.c xmlrpc-old-server-test.c xmlrpc-old-test.c \ + xmlrpc-server-test.c xmlrpc-test.c +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +DATA = $(installed_test_meta_DATA) $(nobase_installed_test_DATA) \ + $(noinst_DATA) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__tty_colors_dummy = \ + mgn= red= grn= lgn= blu= brg= std=; \ + am__color_tests=no +am__tty_colors = { \ + $(am__tty_colors_dummy); \ + if test "X$(AM_COLOR_TESTS)" = Xno; then \ + am__color_tests=no; \ + elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ + am__color_tests=yes; \ + elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ + am__color_tests=yes; \ + fi; \ + if test $$am__color_tests = yes; then \ + red=''; \ + grn=''; \ + lgn=''; \ + blu=''; \ + mgn=''; \ + brg=''; \ + std=''; \ + fi; \ +} +am__recheck_rx = ^[ ]*:recheck:[ ]* +am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* +am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* +# A command that, given a newline-separated list of test names on the +# standard input, print the name of the tests that are to be re-run +# upon "make recheck". +am__list_recheck_tests = $(AWK) '{ \ + recheck = 1; \ + while ((rc = (getline line < ($$0 ".trs"))) != 0) \ + { \ + if (rc < 0) \ + { \ + if ((getline line2 < ($$0 ".log")) < 0) \ + recheck = 0; \ + break; \ + } \ + else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ + { \ + recheck = 0; \ + break; \ + } \ + else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ + { \ + break; \ + } \ + }; \ + if (recheck) \ + print $$0; \ + close ($$0 ".trs"); \ + close ($$0 ".log"); \ +}' +# A command that, given a newline-separated list of test names on the +# standard input, create the global log from their .trs and .log files. +am__create_global_log = $(AWK) ' \ +function fatal(msg) \ +{ \ + print "fatal: making $@: " msg | "cat >&2"; \ + exit 1; \ +} \ +function rst_section(header) \ +{ \ + print header; \ + len = length(header); \ + for (i = 1; i <= len; i = i + 1) \ + printf "="; \ + printf "\n\n"; \ +} \ +{ \ + copy_in_global_log = 1; \ + global_test_result = "RUN"; \ + while ((rc = (getline line < ($$0 ".trs"))) != 0) \ + { \ + if (rc < 0) \ + fatal("failed to read from " $$0 ".trs"); \ + if (line ~ /$(am__global_test_result_rx)/) \ + { \ + sub("$(am__global_test_result_rx)", "", line); \ + sub("[ ]*$$", "", line); \ + global_test_result = line; \ + } \ + else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ + copy_in_global_log = 0; \ + }; \ + if (copy_in_global_log) \ + { \ + rst_section(global_test_result ": " $$0); \ + while ((rc = (getline line < ($$0 ".log"))) != 0) \ + { \ + if (rc < 0) \ + fatal("failed to read from " $$0 ".log"); \ + print line; \ + }; \ + printf "\n"; \ + }; \ + close ($$0 ".trs"); \ + close ($$0 ".log"); \ +}' +# Restructured Text title. +am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } +# Solaris 10 'make', and several other traditional 'make' implementations, +# pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it +# by disabling -e (using the XSI extension "set +e") if it's set. +am__sh_e_setup = case $$- in *e*) set +e;; esac +# Default flags passed to test drivers. +am__common_driver_flags = \ + --color-tests "$$am__color_tests" \ + --enable-hard-errors "$$am__enable_hard_errors" \ + --expect-failure "$$am__expect_failure" +# To be inserted before the command running the test. Creates the +# directory for the log if needed. Stores in $dir the directory +# containing $f, in $tst the test, in $log the log. Executes the +# developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and +# passes TESTS_ENVIRONMENT. Set up options for the wrapper that +# will run the test scripts (or their associated LOG_COMPILER, if +# thy have one). +am__check_pre = \ +$(am__sh_e_setup); \ +$(am__vpath_adj_setup) $(am__vpath_adj) \ +$(am__tty_colors); \ +srcdir=$(srcdir); export srcdir; \ +case "$@" in \ + */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ + *) am__odir=.;; \ +esac; \ +test "x$$am__odir" = x"." || test -d "$$am__odir" \ + || $(MKDIR_P) "$$am__odir" || exit $$?; \ +if test -f "./$$f"; then dir=./; \ +elif test -f "$$f"; then dir=; \ +else dir="$(srcdir)/"; fi; \ +tst=$$dir$$f; log='$@'; \ +if test -n '$(DISABLE_HARD_ERRORS)'; then \ + am__enable_hard_errors=no; \ +else \ + am__enable_hard_errors=yes; \ +fi; \ +case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ + am__expect_failure=yes;; \ + *) \ + am__expect_failure=no;; \ +esac; \ +$(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) +# A shell command to get the names of the tests scripts with any registered +# extension removed (i.e., equivalently, the names of the test logs, with +# the '.log' extension removed). The result is saved in the shell variable +# '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, +# we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", +# since that might cause problem with VPATH rewrites for suffix-less tests. +# See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. +am__set_TESTS_bases = \ + bases='$(TEST_LOGS)'; \ + bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ + bases=`echo $$bases` +RECHECK_LOGS = $(TEST_LOGS) +AM_RECURSIVE_TARGETS = check recheck +TEST_SUITE_LOG = test-suite.log +TEST_EXTENSIONS = @EXEEXT@ .test +LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) +am__set_b = \ + case '$@' in \ + */*) \ + case '$*' in \ + */*) b='$*';; \ + *) b=`echo '$@' | sed 's/\.log$$//'`; \ + esac;; \ + *) \ + b='$*';; \ + esac +am__test_logs1 = $(TESTS:=.log) +am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) +TEST_LOGS = $(am__test_logs2:.test.log=.log) +TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/build-aux/test-driver +TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ + $(TEST_LOG_FLAGS) +am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/httpd.conf.in \ + $(top_srcdir)/build-aux/depcomp \ + $(top_srcdir)/build-aux/test-driver $(top_srcdir)/glib-tap.mk +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALL_LINGUAS = @ALL_LINGUAS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +APACHE_HTTPD = @APACHE_HTTPD@ +APACHE_MODULE_DIR = @APACHE_MODULE_DIR@ +APACHE_PHP_MODULE_DIR = @APACHE_PHP_MODULE_DIR@ +APACHE_SSL_MODULE_DIR = @APACHE_SSL_MODULE_DIR@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CODE_COVERAGE_CFLAGS = @CODE_COVERAGE_CFLAGS@ +CODE_COVERAGE_CPPFLAGS = @CODE_COVERAGE_CPPFLAGS@ +CODE_COVERAGE_CXXFLAGS = @CODE_COVERAGE_CXXFLAGS@ +CODE_COVERAGE_ENABLED = @CODE_COVERAGE_ENABLED@ +CODE_COVERAGE_LDFLAGS = @CODE_COVERAGE_LDFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CURL = @CURL@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GCOV = @GCOV@ +GENHTML = @GENHTML@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_COMPILE_RESOURCES = @GLIB_COMPILE_RESOURCES@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MAKEFILE = @GLIB_MAKEFILE@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GMSGFMT = @GMSGFMT@ +GOBJECT_QUERY = @GOBJECT_QUERY@ +GREP = @GREP@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +HAVE_GNOME = @HAVE_GNOME@ +HTML_DIR = @HTML_DIR@ +IF_HAVE_MOD_UNIXD = @IF_HAVE_MOD_UNIXD@ +IF_HAVE_PHP = @IF_HAVE_PHP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ +INTLTOOL_MERGE = @INTLTOOL_MERGE@ +INTLTOOL_PERL = @INTLTOOL_PERL@ +INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ +INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@ +INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@ +INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@ +INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LCOV = @LCOV@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = \ + $(top_builddir)/libsoup/libsoup-2.4.la \ + $(GLIB_LIBS) + +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PHP = @PHP@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOUP_AGE = @SOUP_AGE@ +SOUP_API_VERSION = @SOUP_API_VERSION@ +SOUP_CURRENT = @SOUP_CURRENT@ +SOUP_DEBUG_FLAGS = @SOUP_DEBUG_FLAGS@ +SOUP_HIDDEN_VISIBILITY_CFLAGS = @SOUP_HIDDEN_VISIBILITY_CFLAGS@ +SOUP_MAJOR_VERSION = @SOUP_MAJOR_VERSION@ +SOUP_MICRO_VERSION = @SOUP_MICRO_VERSION@ +SOUP_MINOR_VERSION = @SOUP_MINOR_VERSION@ +SOUP_REVISION = @SOUP_REVISION@ +SQLITE_CFLAGS = @SQLITE_CFLAGS@ +SQLITE_LIBS = @SQLITE_LIBS@ +STRIP = @STRIP@ +USE_NLS = @USE_NLS@ +VALAC = @VALAC@ +VAPIDIR = @VAPIDIR@ +VAPIGEN = @VAPIGEN@ +VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@ +VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@ +VERSION = @VERSION@ +XGETTEXT = @XGETTEXT@ +XML_CFLAGS = @XML_CFLAGS@ +XML_LIBS = @XML_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +installed_test_metadir = @installed_test_metadir@ +installed_testdir = @installed_testdir@ +intltool__v_merge_options_ = @intltool__v_merge_options_@ +intltool__v_merge_options_0 = @intltool__v_merge_options_0@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +ntlm_auth = @ntlm_auth@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +TESTS_ENVIRONMENT = G_TEST_SRCDIR="$(abs_srcdir)" \ + G_TEST_BUILDDIR="$(abs_builddir)" G_DEBUG=gc-friendly \ + MALLOC_CHECK_=2 MALLOC_PERTURB_=$$(($${RANDOM:-256} % 256)) \ + SOUP_TESTS_IN_MAKE_CHECK=1 +LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) $(top_srcdir)/tap-driver.sh +LOG_COMPILER = $(top_srcdir)/tap-test +NULL = + +# initialize variables for unconditional += appending +BUILT_SOURCES = +BUILT_EXTRA_DIST = +CLEANFILES = *.log *.trs $(am__append_13) +DISTCLEANFILES = soup-tests.gresource httpd.conf +MAINTAINERCLEANFILES = +EXTRA_DIST = $(all_dist_test_scripts) $(all_dist_test_data) htdigest \ + htpasswd httpd.conf.in index.txt libsoup.supp \ + soup-tests.gresource.xml test-cert.pem test-key.pem \ + xmlrpc-server.php $(RESOURCES) +installed_test_LTLIBRARIES = $(am__append_12) +installed_test_SCRIPTS = $(am__append_10) +nobase_installed_test_DATA = $(am__append_11) +noinst_LTLIBRARIES = $(am__append_1) libtest.la +noinst_SCRIPTS = $(am__append_3) +noinst_DATA = $(am__append_4) +check_LTLIBRARIES = $(am__append_5) +check_SCRIPTS = $(am__append_7) +check_DATA = $(am__append_8) + +# Note: build even the installed-only targets during 'make check' to ensure that they still work. +# We need to do a bit of trickery here and manage disting via EXTRA_DIST instead of using dist_ prefixes to +# prevent automake from mistreating gmake functions like $(wildcard ...) and $(addprefix ...) as if they were +# filenames, including removing duplicate instances of the opening part before the space, eg. '$(addprefix'. +all_test_programs = $(test_programs) $(uninstalled_test_programs) $(installed_test_programs) \ + $(test_extra_programs) $(uninstalled_test_extra_programs) $(installed_test_extra_programs) + +all_test_scripts = $(test_scripts) $(uninstalled_test_scripts) \ + $(installed_test_scripts) $(test_extra_scripts) \ + $(uninstalled_test_extra_scripts) \ + $(installed_test_extra_scripts) $(all_dist_test_scripts) +all_dist_test_scripts = $(dist_test_scripts) $(dist_uninstalled_test_scripts) $(dist_installed_test_scripts) \ + $(dist_test_extra_scripts) $(dist_uninstalled_test_extra_scripts) $(dist_installed_test_extra_scripts) + +all_test_data = $(test_data) $(uninstalled_test_data) \ + $(installed_test_data) $(all_dist_test_data) +all_dist_test_data = $(dist_test_data) $(dist_uninstalled_test_data) $(dist_installed_test_data) +all_test_ltlibs = $(test_ltlibraries) $(uninstalled_test_ltlibraries) $(installed_test_ltlibraries) +@ENABLE_INSTALLED_TESTS_TRUE@installed_testcases = $(test_programs) $(installed_test_programs) \ +@ENABLE_INSTALLED_TESTS_TRUE@ $(test_scripts) $(installed_test_scripts) \ +@ENABLE_INSTALLED_TESTS_TRUE@ $(dist_test_scripts) $(dist_installed_test_scripts) + +@ENABLE_INSTALLED_TESTS_TRUE@installed_test_meta_DATA = $(installed_testcases:=.test) +AM_CPPFLAGS = \ + -I$(top_srcdir) \ + $(GLIB_CFLAGS) + +test_programs = \ + auth-test \ + cache-test \ + chunk-test \ + chunk-io-test \ + coding-test \ + connection-test \ + context-test \ + continue-test \ + cookies-test \ + date \ + forms-test \ + header-parsing \ + misc-test \ + multipart-test \ + no-ssl-test \ + ntlm-test \ + proxy-test \ + pull-api \ + range-test \ + redirect-test \ + requester-test \ + resource-test \ + session-test \ + server-auth-test \ + server-test \ + sniffing-test \ + socket-test \ + ssl-test \ + streaming-test \ + timeout-test \ + tld-test \ + uri-parsing \ + websocket-test \ + xmlrpc-old-server-test \ + xmlrpc-old-test \ + xmlrpc-server-test \ + xmlrpc-test + +test_extra_programs = \ + ntlm-test-helper \ + $(TESTS) + +test_data = index.txt soup-tests.gresource test-cert.pem test-key.pem \ + xmlrpc-server.php $(am__append_14) +libtest_la_SOURCES = \ + test-utils.c \ + test-utils.h + +LDADD = libtest.la +RESOURCES = $(shell $(GLIB_COMPILE_RESOURCES) --sourcedir=$(srcdir) --generate-dependencies $(srcdir)/soup-tests.gresource.xml) +all: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/glib-tap.mk $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tests/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign tests/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; +$(top_srcdir)/glib-tap.mk $(am__empty): + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +httpd.conf: $(top_builddir)/config.status $(srcdir)/httpd.conf.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ + +clean-checkLTLIBRARIES: + -test -z "$(check_LTLIBRARIES)" || rm -f $(check_LTLIBRARIES) + @list='$(check_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +install-installed_testLTLIBRARIES: $(installed_test_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(installed_test_LTLIBRARIES)'; test -n "$(installed_testdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(installed_testdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(installed_testdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(installed_testdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(installed_testdir)"; \ + } + +uninstall-installed_testLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(installed_test_LTLIBRARIES)'; test -n "$(installed_testdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(installed_testdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(installed_testdir)/$$f"; \ + done + +clean-installed_testLTLIBRARIES: + -test -z "$(installed_test_LTLIBRARIES)" || rm -f $(installed_test_LTLIBRARIES) + @list='$(installed_test_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libtest.la: $(libtest_la_OBJECTS) $(libtest_la_DEPENDENCIES) $(EXTRA_libtest_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libtest_la_OBJECTS) $(libtest_la_LIBADD) $(LIBS) + +clean-checkPROGRAMS: + @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list +install-installed_testPROGRAMS: $(installed_test_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(installed_test_PROGRAMS)'; test -n "$(installed_testdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(installed_testdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(installed_testdir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p \ + || test -f $$p1 \ + ; then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' \ + -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(installed_testdir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(installed_testdir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-installed_testPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(installed_test_PROGRAMS)'; test -n "$(installed_testdir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' \ + `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(installed_testdir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(installed_testdir)" && rm -f $$files + +clean-installed_testPROGRAMS: + @list='$(installed_test_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +auth-test$(EXEEXT): $(auth_test_OBJECTS) $(auth_test_DEPENDENCIES) $(EXTRA_auth_test_DEPENDENCIES) + @rm -f auth-test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(auth_test_OBJECTS) $(auth_test_LDADD) $(LIBS) + +cache-test$(EXEEXT): $(cache_test_OBJECTS) $(cache_test_DEPENDENCIES) $(EXTRA_cache_test_DEPENDENCIES) + @rm -f cache-test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(cache_test_OBJECTS) $(cache_test_LDADD) $(LIBS) + +chunk-io-test$(EXEEXT): $(chunk_io_test_OBJECTS) $(chunk_io_test_DEPENDENCIES) $(EXTRA_chunk_io_test_DEPENDENCIES) + @rm -f chunk-io-test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(chunk_io_test_OBJECTS) $(chunk_io_test_LDADD) $(LIBS) + +chunk-test$(EXEEXT): $(chunk_test_OBJECTS) $(chunk_test_DEPENDENCIES) $(EXTRA_chunk_test_DEPENDENCIES) + @rm -f chunk-test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(chunk_test_OBJECTS) $(chunk_test_LDADD) $(LIBS) + +coding-test$(EXEEXT): $(coding_test_OBJECTS) $(coding_test_DEPENDENCIES) $(EXTRA_coding_test_DEPENDENCIES) + @rm -f coding-test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(coding_test_OBJECTS) $(coding_test_LDADD) $(LIBS) + +connection-test$(EXEEXT): $(connection_test_OBJECTS) $(connection_test_DEPENDENCIES) $(EXTRA_connection_test_DEPENDENCIES) + @rm -f connection-test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(connection_test_OBJECTS) $(connection_test_LDADD) $(LIBS) + +context-test$(EXEEXT): $(context_test_OBJECTS) $(context_test_DEPENDENCIES) $(EXTRA_context_test_DEPENDENCIES) + @rm -f context-test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(context_test_OBJECTS) $(context_test_LDADD) $(LIBS) + +continue-test$(EXEEXT): $(continue_test_OBJECTS) $(continue_test_DEPENDENCIES) $(EXTRA_continue_test_DEPENDENCIES) + @rm -f continue-test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(continue_test_OBJECTS) $(continue_test_LDADD) $(LIBS) + +cookies-test$(EXEEXT): $(cookies_test_OBJECTS) $(cookies_test_DEPENDENCIES) $(EXTRA_cookies_test_DEPENDENCIES) + @rm -f cookies-test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(cookies_test_OBJECTS) $(cookies_test_LDADD) $(LIBS) + +date$(EXEEXT): $(date_OBJECTS) $(date_DEPENDENCIES) $(EXTRA_date_DEPENDENCIES) + @rm -f date$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(date_OBJECTS) $(date_LDADD) $(LIBS) + +forms-test$(EXEEXT): $(forms_test_OBJECTS) $(forms_test_DEPENDENCIES) $(EXTRA_forms_test_DEPENDENCIES) + @rm -f forms-test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(forms_test_OBJECTS) $(forms_test_LDADD) $(LIBS) + +header-parsing$(EXEEXT): $(header_parsing_OBJECTS) $(header_parsing_DEPENDENCIES) $(EXTRA_header_parsing_DEPENDENCIES) + @rm -f header-parsing$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(header_parsing_OBJECTS) $(header_parsing_LDADD) $(LIBS) + +misc-test$(EXEEXT): $(misc_test_OBJECTS) $(misc_test_DEPENDENCIES) $(EXTRA_misc_test_DEPENDENCIES) + @rm -f misc-test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(misc_test_OBJECTS) $(misc_test_LDADD) $(LIBS) + +multipart-test$(EXEEXT): $(multipart_test_OBJECTS) $(multipart_test_DEPENDENCIES) $(EXTRA_multipart_test_DEPENDENCIES) + @rm -f multipart-test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(multipart_test_OBJECTS) $(multipart_test_LDADD) $(LIBS) + +no-ssl-test$(EXEEXT): $(no_ssl_test_OBJECTS) $(no_ssl_test_DEPENDENCIES) $(EXTRA_no_ssl_test_DEPENDENCIES) + @rm -f no-ssl-test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(no_ssl_test_OBJECTS) $(no_ssl_test_LDADD) $(LIBS) + +ntlm-test$(EXEEXT): $(ntlm_test_OBJECTS) $(ntlm_test_DEPENDENCIES) $(EXTRA_ntlm_test_DEPENDENCIES) + @rm -f ntlm-test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(ntlm_test_OBJECTS) $(ntlm_test_LDADD) $(LIBS) + +ntlm-test-helper$(EXEEXT): $(ntlm_test_helper_OBJECTS) $(ntlm_test_helper_DEPENDENCIES) $(EXTRA_ntlm_test_helper_DEPENDENCIES) + @rm -f ntlm-test-helper$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(ntlm_test_helper_OBJECTS) $(ntlm_test_helper_LDADD) $(LIBS) + +proxy-test$(EXEEXT): $(proxy_test_OBJECTS) $(proxy_test_DEPENDENCIES) $(EXTRA_proxy_test_DEPENDENCIES) + @rm -f proxy-test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(proxy_test_OBJECTS) $(proxy_test_LDADD) $(LIBS) + +pull-api$(EXEEXT): $(pull_api_OBJECTS) $(pull_api_DEPENDENCIES) $(EXTRA_pull_api_DEPENDENCIES) + @rm -f pull-api$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(pull_api_OBJECTS) $(pull_api_LDADD) $(LIBS) + +range-test$(EXEEXT): $(range_test_OBJECTS) $(range_test_DEPENDENCIES) $(EXTRA_range_test_DEPENDENCIES) + @rm -f range-test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(range_test_OBJECTS) $(range_test_LDADD) $(LIBS) + +redirect-test$(EXEEXT): $(redirect_test_OBJECTS) $(redirect_test_DEPENDENCIES) $(EXTRA_redirect_test_DEPENDENCIES) + @rm -f redirect-test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(redirect_test_OBJECTS) $(redirect_test_LDADD) $(LIBS) + +requester-test$(EXEEXT): $(requester_test_OBJECTS) $(requester_test_DEPENDENCIES) $(EXTRA_requester_test_DEPENDENCIES) + @rm -f requester-test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(requester_test_OBJECTS) $(requester_test_LDADD) $(LIBS) + +resource-test$(EXEEXT): $(resource_test_OBJECTS) $(resource_test_DEPENDENCIES) $(EXTRA_resource_test_DEPENDENCIES) + @rm -f resource-test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(resource_test_OBJECTS) $(resource_test_LDADD) $(LIBS) + +server-auth-test$(EXEEXT): $(server_auth_test_OBJECTS) $(server_auth_test_DEPENDENCIES) $(EXTRA_server_auth_test_DEPENDENCIES) + @rm -f server-auth-test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(server_auth_test_OBJECTS) $(server_auth_test_LDADD) $(LIBS) + +server-test$(EXEEXT): $(server_test_OBJECTS) $(server_test_DEPENDENCIES) $(EXTRA_server_test_DEPENDENCIES) + @rm -f server-test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(server_test_OBJECTS) $(server_test_LDADD) $(LIBS) + +session-test$(EXEEXT): $(session_test_OBJECTS) $(session_test_DEPENDENCIES) $(EXTRA_session_test_DEPENDENCIES) + @rm -f session-test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(session_test_OBJECTS) $(session_test_LDADD) $(LIBS) + +sniffing-test$(EXEEXT): $(sniffing_test_OBJECTS) $(sniffing_test_DEPENDENCIES) $(EXTRA_sniffing_test_DEPENDENCIES) + @rm -f sniffing-test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(sniffing_test_OBJECTS) $(sniffing_test_LDADD) $(LIBS) + +socket-test$(EXEEXT): $(socket_test_OBJECTS) $(socket_test_DEPENDENCIES) $(EXTRA_socket_test_DEPENDENCIES) + @rm -f socket-test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(socket_test_OBJECTS) $(socket_test_LDADD) $(LIBS) + +ssl-test$(EXEEXT): $(ssl_test_OBJECTS) $(ssl_test_DEPENDENCIES) $(EXTRA_ssl_test_DEPENDENCIES) + @rm -f ssl-test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(ssl_test_OBJECTS) $(ssl_test_LDADD) $(LIBS) + +streaming-test$(EXEEXT): $(streaming_test_OBJECTS) $(streaming_test_DEPENDENCIES) $(EXTRA_streaming_test_DEPENDENCIES) + @rm -f streaming-test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(streaming_test_OBJECTS) $(streaming_test_LDADD) $(LIBS) + +timeout-test$(EXEEXT): $(timeout_test_OBJECTS) $(timeout_test_DEPENDENCIES) $(EXTRA_timeout_test_DEPENDENCIES) + @rm -f timeout-test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(timeout_test_OBJECTS) $(timeout_test_LDADD) $(LIBS) + +tld-test$(EXEEXT): $(tld_test_OBJECTS) $(tld_test_DEPENDENCIES) $(EXTRA_tld_test_DEPENDENCIES) + @rm -f tld-test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(tld_test_OBJECTS) $(tld_test_LDADD) $(LIBS) + +uri-parsing$(EXEEXT): $(uri_parsing_OBJECTS) $(uri_parsing_DEPENDENCIES) $(EXTRA_uri_parsing_DEPENDENCIES) + @rm -f uri-parsing$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(uri_parsing_OBJECTS) $(uri_parsing_LDADD) $(LIBS) + +websocket-test$(EXEEXT): $(websocket_test_OBJECTS) $(websocket_test_DEPENDENCIES) $(EXTRA_websocket_test_DEPENDENCIES) + @rm -f websocket-test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(websocket_test_OBJECTS) $(websocket_test_LDADD) $(LIBS) + +xmlrpc-old-server-test$(EXEEXT): $(xmlrpc_old_server_test_OBJECTS) $(xmlrpc_old_server_test_DEPENDENCIES) $(EXTRA_xmlrpc_old_server_test_DEPENDENCIES) + @rm -f xmlrpc-old-server-test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(xmlrpc_old_server_test_OBJECTS) $(xmlrpc_old_server_test_LDADD) $(LIBS) + +xmlrpc-old-test$(EXEEXT): $(xmlrpc_old_test_OBJECTS) $(xmlrpc_old_test_DEPENDENCIES) $(EXTRA_xmlrpc_old_test_DEPENDENCIES) + @rm -f xmlrpc-old-test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(xmlrpc_old_test_OBJECTS) $(xmlrpc_old_test_LDADD) $(LIBS) + +xmlrpc-server-test$(EXEEXT): $(xmlrpc_server_test_OBJECTS) $(xmlrpc_server_test_DEPENDENCIES) $(EXTRA_xmlrpc_server_test_DEPENDENCIES) + @rm -f xmlrpc-server-test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(xmlrpc_server_test_OBJECTS) $(xmlrpc_server_test_LDADD) $(LIBS) + +xmlrpc-test$(EXEEXT): $(xmlrpc_test_OBJECTS) $(xmlrpc_test_DEPENDENCIES) $(EXTRA_xmlrpc_test_DEPENDENCIES) + @rm -f xmlrpc-test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(xmlrpc_test_OBJECTS) $(xmlrpc_test_LDADD) $(LIBS) +install-installed_testSCRIPTS: $(installed_test_SCRIPTS) + @$(NORMAL_INSTALL) + @list='$(installed_test_SCRIPTS)'; test -n "$(installed_testdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(installed_testdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(installed_testdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n' \ + -e 'h;s|.*|.|' \ + -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) { files[d] = files[d] " " $$1; \ + if (++n[d] == $(am__install_max)) { \ + print "f", d, files[d]; n[d] = 0; files[d] = "" } } \ + else { print "f", d "/" $$4, $$1 } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(installed_testdir)$$dir'"; \ + $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(installed_testdir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-installed_testSCRIPTS: + @$(NORMAL_UNINSTALL) + @list='$(installed_test_SCRIPTS)'; test -n "$(installed_testdir)" || exit 0; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 's,.*/,,;$(transform)'`; \ + dir='$(DESTDIR)$(installed_testdir)'; $(am__uninstall_files_from_dir) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auth-test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cache-test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/chunk-io-test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/chunk-test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/coding-test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/connection-test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/context-test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/continue-test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cookies-test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/date.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/forms-test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/header-parsing.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/misc-test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/multipart-test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/no-ssl-test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntlm-test-helper.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntlm-test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proxy-test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pull-api.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/range-test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/redirect-test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/requester-test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/resource-test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/server-auth-test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/server-test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/session-test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sniffing-test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/socket-test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ssl-test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/streaming-test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-utils.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/timeout-test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tld-test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/uri-parsing.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/websocket-test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xmlrpc-old-server-test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xmlrpc-old-test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xmlrpc-server-test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xmlrpc-test.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-installed_test_metaDATA: $(installed_test_meta_DATA) + @$(NORMAL_INSTALL) + @list='$(installed_test_meta_DATA)'; test -n "$(installed_test_metadir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(installed_test_metadir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(installed_test_metadir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(installed_test_metadir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(installed_test_metadir)" || exit $$?; \ + done + +uninstall-installed_test_metaDATA: + @$(NORMAL_UNINSTALL) + @list='$(installed_test_meta_DATA)'; test -n "$(installed_test_metadir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(installed_test_metadir)'; $(am__uninstall_files_from_dir) +install-nobase_installed_testDATA: $(nobase_installed_test_DATA) + @$(NORMAL_INSTALL) + @list='$(nobase_installed_test_DATA)'; test -n "$(installed_testdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(installed_testdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(installed_testdir)" || exit 1; \ + fi; \ + $(am__nobase_list) | while read dir files; do \ + xfiles=; for file in $$files; do \ + if test -f "$$file"; then xfiles="$$xfiles $$file"; \ + else xfiles="$$xfiles $(srcdir)/$$file"; fi; done; \ + test -z "$$xfiles" || { \ + test "x$$dir" = x. || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(installed_testdir)/$$dir'"; \ + $(MKDIR_P) "$(DESTDIR)$(installed_testdir)/$$dir"; }; \ + echo " $(INSTALL_DATA) $$xfiles '$(DESTDIR)$(installed_testdir)/$$dir'"; \ + $(INSTALL_DATA) $$xfiles "$(DESTDIR)$(installed_testdir)/$$dir" || exit $$?; }; \ + done + +uninstall-nobase_installed_testDATA: + @$(NORMAL_UNINSTALL) + @list='$(nobase_installed_test_DATA)'; test -n "$(installed_testdir)" || list=; \ + $(am__nobase_strip_setup); files=`$(am__nobase_strip)`; \ + dir='$(DESTDIR)$(installed_testdir)'; $(am__uninstall_files_from_dir) + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +# Recover from deleted '.trs' file; this should ensure that +# "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create +# both 'foo.log' and 'foo.trs'. Break the recipe in two subshells +# to avoid problems with "make -n". +.log.trs: + rm -f $< $@ + $(MAKE) $(AM_MAKEFLAGS) $< + +# Leading 'am--fnord' is there to ensure the list of targets does not +# expand to empty, as could happen e.g. with make check TESTS=''. +am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) +am--force-recheck: + @: + +$(TEST_SUITE_LOG): $(TEST_LOGS) + @$(am__set_TESTS_bases); \ + am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ + redo_bases=`for i in $$bases; do \ + am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ + done`; \ + if test -n "$$redo_bases"; then \ + redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ + redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ + if $(am__make_dryrun); then :; else \ + rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ + fi; \ + fi; \ + if test -n "$$am__remaking_logs"; then \ + echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ + "recursion detected" >&2; \ + elif test -n "$$redo_logs"; then \ + am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ + fi; \ + if $(am__make_dryrun); then :; else \ + st=0; \ + errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ + for i in $$redo_bases; do \ + test -f $$i.trs && test -r $$i.trs \ + || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ + test -f $$i.log && test -r $$i.log \ + || { echo "$$errmsg $$i.log" >&2; st=1; }; \ + done; \ + test $$st -eq 0 || exit 1; \ + fi + @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ + ws='[ ]'; \ + results=`for b in $$bases; do echo $$b.trs; done`; \ + test -n "$$results" || results=/dev/null; \ + all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ + pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ + fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ + skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ + xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ + xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ + error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ + if test `expr $$fail + $$xpass + $$error` -eq 0; then \ + success=true; \ + else \ + success=false; \ + fi; \ + br='==================='; br=$$br$$br$$br$$br; \ + result_count () \ + { \ + if test x"$$1" = x"--maybe-color"; then \ + maybe_colorize=yes; \ + elif test x"$$1" = x"--no-color"; then \ + maybe_colorize=no; \ + else \ + echo "$@: invalid 'result_count' usage" >&2; exit 4; \ + fi; \ + shift; \ + desc=$$1 count=$$2; \ + if test $$maybe_colorize = yes && test $$count -gt 0; then \ + color_start=$$3 color_end=$$std; \ + else \ + color_start= color_end=; \ + fi; \ + echo "$${color_start}# $$desc $$count$${color_end}"; \ + }; \ + create_testsuite_report () \ + { \ + result_count $$1 "TOTAL:" $$all "$$brg"; \ + result_count $$1 "PASS: " $$pass "$$grn"; \ + result_count $$1 "SKIP: " $$skip "$$blu"; \ + result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ + result_count $$1 "FAIL: " $$fail "$$red"; \ + result_count $$1 "XPASS:" $$xpass "$$red"; \ + result_count $$1 "ERROR:" $$error "$$mgn"; \ + }; \ + { \ + echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ + $(am__rst_title); \ + create_testsuite_report --no-color; \ + echo; \ + echo ".. contents:: :depth: 2"; \ + echo; \ + for b in $$bases; do echo $$b; done \ + | $(am__create_global_log); \ + } >$(TEST_SUITE_LOG).tmp || exit 1; \ + mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ + if $$success; then \ + col="$$grn"; \ + else \ + col="$$red"; \ + test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ + fi; \ + echo "$${col}$$br$${std}"; \ + echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ + echo "$${col}$$br$${std}"; \ + create_testsuite_report --maybe-color; \ + echo "$$col$$br$$std"; \ + if $$success; then :; else \ + echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ + if test -n "$(PACKAGE_BUGREPORT)"; then \ + echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ + fi; \ + echo "$$col$$br$$std"; \ + fi; \ + $$success || exit 1 + +check-TESTS: + @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list + @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list + @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @set +e; $(am__set_TESTS_bases); \ + log_list=`for i in $$bases; do echo $$i.log; done`; \ + trs_list=`for i in $$bases; do echo $$i.trs; done`; \ + log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ + $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ + exit $$?; +recheck: all $(check_LTLIBRARIES) $(check_PROGRAMS) $(check_SCRIPTS) $(check_DATA) + @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @set +e; $(am__set_TESTS_bases); \ + bases=`for i in $$bases; do echo $$i; done \ + | $(am__list_recheck_tests)` || exit 1; \ + log_list=`for i in $$bases; do echo $$i.log; done`; \ + log_list=`echo $$log_list`; \ + $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ + am__force_recheck=am--force-recheck \ + TEST_LOGS="$$log_list"; \ + exit $$? +auth-test.log: auth-test$(EXEEXT) + @p='auth-test$(EXEEXT)'; \ + b='auth-test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +cache-test.log: cache-test$(EXEEXT) + @p='cache-test$(EXEEXT)'; \ + b='cache-test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +chunk-test.log: chunk-test$(EXEEXT) + @p='chunk-test$(EXEEXT)'; \ + b='chunk-test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +chunk-io-test.log: chunk-io-test$(EXEEXT) + @p='chunk-io-test$(EXEEXT)'; \ + b='chunk-io-test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +coding-test.log: coding-test$(EXEEXT) + @p='coding-test$(EXEEXT)'; \ + b='coding-test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +connection-test.log: connection-test$(EXEEXT) + @p='connection-test$(EXEEXT)'; \ + b='connection-test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +context-test.log: context-test$(EXEEXT) + @p='context-test$(EXEEXT)'; \ + b='context-test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +continue-test.log: continue-test$(EXEEXT) + @p='continue-test$(EXEEXT)'; \ + b='continue-test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +cookies-test.log: cookies-test$(EXEEXT) + @p='cookies-test$(EXEEXT)'; \ + b='cookies-test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +date.log: date$(EXEEXT) + @p='date$(EXEEXT)'; \ + b='date'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +forms-test.log: forms-test$(EXEEXT) + @p='forms-test$(EXEEXT)'; \ + b='forms-test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +header-parsing.log: header-parsing$(EXEEXT) + @p='header-parsing$(EXEEXT)'; \ + b='header-parsing'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +misc-test.log: misc-test$(EXEEXT) + @p='misc-test$(EXEEXT)'; \ + b='misc-test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +multipart-test.log: multipart-test$(EXEEXT) + @p='multipart-test$(EXEEXT)'; \ + b='multipart-test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +no-ssl-test.log: no-ssl-test$(EXEEXT) + @p='no-ssl-test$(EXEEXT)'; \ + b='no-ssl-test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +ntlm-test.log: ntlm-test$(EXEEXT) + @p='ntlm-test$(EXEEXT)'; \ + b='ntlm-test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +proxy-test.log: proxy-test$(EXEEXT) + @p='proxy-test$(EXEEXT)'; \ + b='proxy-test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +pull-api.log: pull-api$(EXEEXT) + @p='pull-api$(EXEEXT)'; \ + b='pull-api'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +range-test.log: range-test$(EXEEXT) + @p='range-test$(EXEEXT)'; \ + b='range-test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +redirect-test.log: redirect-test$(EXEEXT) + @p='redirect-test$(EXEEXT)'; \ + b='redirect-test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +requester-test.log: requester-test$(EXEEXT) + @p='requester-test$(EXEEXT)'; \ + b='requester-test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +resource-test.log: resource-test$(EXEEXT) + @p='resource-test$(EXEEXT)'; \ + b='resource-test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +session-test.log: session-test$(EXEEXT) + @p='session-test$(EXEEXT)'; \ + b='session-test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +server-auth-test.log: server-auth-test$(EXEEXT) + @p='server-auth-test$(EXEEXT)'; \ + b='server-auth-test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +server-test.log: server-test$(EXEEXT) + @p='server-test$(EXEEXT)'; \ + b='server-test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +sniffing-test.log: sniffing-test$(EXEEXT) + @p='sniffing-test$(EXEEXT)'; \ + b='sniffing-test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +socket-test.log: socket-test$(EXEEXT) + @p='socket-test$(EXEEXT)'; \ + b='socket-test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +ssl-test.log: ssl-test$(EXEEXT) + @p='ssl-test$(EXEEXT)'; \ + b='ssl-test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +streaming-test.log: streaming-test$(EXEEXT) + @p='streaming-test$(EXEEXT)'; \ + b='streaming-test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +timeout-test.log: timeout-test$(EXEEXT) + @p='timeout-test$(EXEEXT)'; \ + b='timeout-test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +tld-test.log: tld-test$(EXEEXT) + @p='tld-test$(EXEEXT)'; \ + b='tld-test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +uri-parsing.log: uri-parsing$(EXEEXT) + @p='uri-parsing$(EXEEXT)'; \ + b='uri-parsing'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +websocket-test.log: websocket-test$(EXEEXT) + @p='websocket-test$(EXEEXT)'; \ + b='websocket-test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +xmlrpc-old-server-test.log: xmlrpc-old-server-test$(EXEEXT) + @p='xmlrpc-old-server-test$(EXEEXT)'; \ + b='xmlrpc-old-server-test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +xmlrpc-old-test.log: xmlrpc-old-test$(EXEEXT) + @p='xmlrpc-old-test$(EXEEXT)'; \ + b='xmlrpc-old-test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +xmlrpc-server-test.log: xmlrpc-server-test$(EXEEXT) + @p='xmlrpc-server-test$(EXEEXT)'; \ + b='xmlrpc-server-test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +xmlrpc-test.log: xmlrpc-test$(EXEEXT) + @p='xmlrpc-test$(EXEEXT)'; \ + b='xmlrpc-test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +.test.log: + @p='$<'; \ + $(am__set_b); \ + $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +@am__EXEEXT_TRUE@.test$(EXEEXT).log: +@am__EXEEXT_TRUE@ @p='$<'; \ +@am__EXEEXT_TRUE@ $(am__set_b); \ +@am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ +@am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ +@am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ +@am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) $(check_LTLIBRARIES) $(check_PROGRAMS) \ + $(check_SCRIPTS) $(check_DATA) + $(MAKE) $(AM_MAKEFLAGS) check-TESTS check-local +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-am +all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(SCRIPTS) $(DATA) +installdirs: + for dir in "$(DESTDIR)$(installed_testdir)" "$(DESTDIR)$(installed_testdir)" "$(DESTDIR)$(installed_testdir)" "$(DESTDIR)$(installed_test_metadir)" "$(DESTDIR)$(installed_testdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) + -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) + -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) + -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) +clean: clean-am + +clean-am: clean-checkLTLIBRARIES clean-checkPROGRAMS clean-generic \ + clean-installed_testLTLIBRARIES clean-installed_testPROGRAMS \ + clean-libtool clean-noinstLTLIBRARIES clean-noinstPROGRAMS \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-installed_testLTLIBRARIES \ + install-installed_testPROGRAMS install-installed_testSCRIPTS \ + install-installed_test_metaDATA \ + install-nobase_installed_testDATA + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-installed_testLTLIBRARIES \ + uninstall-installed_testPROGRAMS \ + uninstall-installed_testSCRIPTS \ + uninstall-installed_test_metaDATA \ + uninstall-nobase_installed_testDATA + +.MAKE: all check check-am install install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am \ + check-local clean clean-checkLTLIBRARIES clean-checkPROGRAMS \ + clean-generic clean-installed_testLTLIBRARIES \ + clean-installed_testPROGRAMS clean-libtool \ + clean-noinstLTLIBRARIES clean-noinstPROGRAMS cscopelist-am \ + ctags ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-installed_testLTLIBRARIES \ + install-installed_testPROGRAMS install-installed_testSCRIPTS \ + install-installed_test_metaDATA install-man \ + install-nobase_installed_testDATA install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + recheck tags tags-am uninstall uninstall-am \ + uninstall-installed_testLTLIBRARIES \ + uninstall-installed_testPROGRAMS \ + uninstall-installed_testSCRIPTS \ + uninstall-installed_test_metaDATA \ + uninstall-nobase_installed_testDATA + +.PRECIOUS: Makefile + + +@ENABLE_INSTALLED_TESTS_TRUE@%.test: %$(EXEEXT) Makefile +@ENABLE_INSTALLED_TESTS_TRUE@ $(AM_V_GEN) (echo '[Test]' > $@.tmp; \ +@ENABLE_INSTALLED_TESTS_TRUE@ echo 'Type=session' >> $@.tmp; \ +@ENABLE_INSTALLED_TESTS_TRUE@ echo 'Exec=$(installed_testdir)/$<' >> $@.tmp; \ +@ENABLE_INSTALLED_TESTS_TRUE@ mv $@.tmp $@) + +soup-tests.gresource: soup-tests.gresource.xml $(RESOURCES) + $(AM_V_GEN) $(GLIB_COMPILE_RESOURCES) --target=$@ --sourcedir=$(srcdir) $< + +check: start-httpd + +check-local: check-TESTS + @$(MAKE) kill-httpd + +.PHONY: start-httpd kill-httpd + +start-httpd: + @$(APACHE_HTTPD) -d $(abs_srcdir) -c "DefaultRuntimeDir `pwd`" -c "PidFile `pwd`/httpd.pid" -f `pwd`/httpd.conf -k start; + +kill-httpd: + @if [ -f httpd.pid ]; then \ + $(APACHE_HTTPD) -d $(abs_srcdir) -c "DefaultRuntimeDir `pwd`" -c "PidFile `pwd`/httpd.pid" -f `pwd`/httpd.conf -k stop; \ + fi + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/tests/auth-test.c b/tests/auth-test.c new file mode 100644 index 0000000..1144dec --- /dev/null +++ b/tests/auth-test.c @@ -0,0 +1,1524 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ + +#include "test-utils.h" + +static const char *base_uri; +static GMainLoop *loop; + +typedef struct { + /* Explanation of what you should see */ + const char *explanation; + + /* URL to test against */ + const char *url; + + /* Provided passwords, 1 character each. ('1', '2', and '3' + * mean the correct passwords for "realm1", "realm2", and + * "realm3" respectively. '4' means "use the wrong password".) + * The first password (if present) will be used by + * authenticate(), and the second (if present) will be used by + * reauthenticate(). + */ + const char *provided; + + /* Whether to pass user and password in the URL or not. + */ + gboolean url_auth; + + /* Expected passwords, 1 character each. (As with the provided + * passwords, with the addition that '0' means "no + * Authorization header expected".) Used to verify that soup + * used the password it was supposed to at each step. + */ + const char *expected; + + /* What the final status code should be. */ + guint final_status; +} SoupAuthTest; + +static SoupAuthTest main_tests[] = { + { "No auth available, should fail", + "Basic/realm1/", "", FALSE, "0", SOUP_STATUS_UNAUTHORIZED }, + + { "Should fail with no auth, fail again with bad password, and give up", + "Basic/realm2/", "4", FALSE, "04", SOUP_STATUS_UNAUTHORIZED }, + + { "Auth provided this time, so should succeed", + "Basic/realm1/", "1", FALSE, "01", SOUP_STATUS_OK }, + + { "Now should automatically reuse previous auth", + "Basic/realm1/", "", FALSE, "1", SOUP_STATUS_OK }, + + { "Subdir should also automatically reuse auth", + "Basic/realm1/subdir/", "", FALSE, "1", SOUP_STATUS_OK }, + + { "Subdir should retry last auth, but will fail this time", + "Basic/realm1/realm2/", "", FALSE, "1", SOUP_STATUS_UNAUTHORIZED }, + + { "Now should use provided auth", + "Basic/realm1/realm2/", "2", FALSE, "02", SOUP_STATUS_OK }, + + { "Reusing last auth. Should succeed on first try", + "Basic/realm1/realm2/", "", FALSE, "2", SOUP_STATUS_OK }, + + { "Reuse will fail, but 2nd try will succeed because it's a known realm", + "Basic/realm1/realm2/realm1/", "", FALSE, "21", SOUP_STATUS_OK }, + + { "Should succeed on first try. (Known realm with cached password)", + "Basic/realm2/", "", FALSE, "2", SOUP_STATUS_OK }, + + { "Fail once, then use typoed password, then use right password", + "Basic/realm3/", "43", FALSE, "043", SOUP_STATUS_OK }, + + + { "No auth available, should fail", + "Digest/realm1/", "", FALSE, "0", SOUP_STATUS_UNAUTHORIZED }, + + { "Should fail with no auth, fail again with bad password, and give up", + "Digest/realm2/", "4", FALSE, "04", SOUP_STATUS_UNAUTHORIZED }, + + { "Known realm, auth provided, so should succeed", + "Digest/realm1/", "1", FALSE, "01", SOUP_STATUS_OK }, + + { "Now should automatically reuse previous auth", + "Digest/realm1/", "", FALSE, "1", SOUP_STATUS_OK }, + + { "Subdir should also automatically reuse auth", + "Digest/realm1/subdir/", "", FALSE, "1", SOUP_STATUS_OK }, + + { "Password provided, should succeed", + "Digest/realm2/", "2", FALSE, "02", SOUP_STATUS_OK }, + + { "Should already know correct domain and use provided auth on first try", + "Digest/realm1/realm2/", "2", FALSE, "2", SOUP_STATUS_OK }, + + { "Reusing last auth. Should succeed on first try", + "Digest/realm1/realm2/", "", FALSE, "2", SOUP_STATUS_OK }, + + { "Should succeed on first try because of earlier domain directive", + "Digest/realm1/realm2/realm1/", "", FALSE, "1", SOUP_STATUS_OK }, + + { "Fail once, then use typoed password, then use right password", + "Digest/realm3/", "43", FALSE, "043", SOUP_STATUS_OK }, + + + { "Make sure we haven't forgotten anything", + "Basic/realm1/", "", FALSE, "1", SOUP_STATUS_OK }, + + { "Make sure we haven't forgotten anything", + "Basic/realm1/realm2/", "", FALSE, "2", SOUP_STATUS_OK }, + + { "Make sure we haven't forgotten anything", + "Basic/realm1/realm2/realm1/", "", FALSE, "1", SOUP_STATUS_OK }, + + { "Make sure we haven't forgotten anything", + "Basic/realm2/", "", FALSE, "2", SOUP_STATUS_OK }, + + { "Make sure we haven't forgotten anything", + "Basic/realm3/", "", FALSE, "3", SOUP_STATUS_OK }, + + + { "Make sure we haven't forgotten anything", + "Digest/realm1/", "", FALSE, "1", SOUP_STATUS_OK }, + + { "Make sure we haven't forgotten anything", + "Digest/realm1/realm2/", "", FALSE, "2", SOUP_STATUS_OK }, + + { "Make sure we haven't forgotten anything", + "Digest/realm1/realm2/realm1/", "", FALSE, "1", SOUP_STATUS_OK }, + + { "Make sure we haven't forgotten anything", + "Digest/realm2/", "", FALSE, "2", SOUP_STATUS_OK }, + + { "Make sure we haven't forgotten anything", + "Digest/realm3/", "", FALSE, "3", SOUP_STATUS_OK }, + + { "Now the server will reject the formerly-good password", + "Basic/realm1/not/", "1", FALSE, /* should not be used */ "1", SOUP_STATUS_UNAUTHORIZED }, + + { "Make sure we've forgotten it", + "Basic/realm1/", "", FALSE, "0", SOUP_STATUS_UNAUTHORIZED }, + + { "Likewise, reject the formerly-good Digest password", + "Digest/realm1/not/", "1", FALSE, /* should not be used */ "1", SOUP_STATUS_UNAUTHORIZED }, + + { "Make sure we've forgotten it", + "Digest/realm1/", "", FALSE, "0", SOUP_STATUS_UNAUTHORIZED }, + + { "Fail with URI-embedded password, then use right password in the authenticate signal", + "Basic/realm3/", "43", TRUE, "43", SOUP_STATUS_OK }, + + { NULL } +}; + +static const char *auths[] = { + "no password", "password 1", + "password 2", "password 3", + "intentionally wrong password", +}; + +static int +identify_auth (SoupMessage *msg) +{ + const char *header; + int num; + + header = soup_message_headers_get_one (msg->request_headers, + "Authorization"); + if (!header) + return 0; + + if (!g_ascii_strncasecmp (header, "Basic ", 6)) { + char *token; + gsize len; + + token = (char *)g_base64_decode (header + 6, &len); + num = token[len - 1] - '0'; + g_free (token); + } else { + const char *user; + + user = strstr (header, "username=\"user"); + if (user) + num = user[14] - '0'; + else + num = 0; + } + + g_assert (num >= 0 && num <= 4); + + return num; +} + +static void +handler (SoupMessage *msg, gpointer data) +{ + char *expected = data; + int auth, exp; + + auth = identify_auth (msg); + + debug_printf (1, " %d %s (using %s)\n", + msg->status_code, msg->reason_phrase, + auths[auth]); + + if (*expected) { + exp = *expected - '0'; + soup_test_assert (auth == exp, + "expected %s", auths[exp]); + memmove (expected, expected + 1, strlen (expected)); + } else { + soup_test_assert (*expected, + "expected to be finished"); + } +} + +static void +authenticate (SoupSession *session, SoupMessage *msg, + SoupAuth *auth, gboolean retrying, gpointer data) +{ + SoupAuthTest *test = data; + char *username, *password; + char num; + + if (!test->provided[0]) + return; + if (retrying) { + if (!test->provided[1]) + return; + num = test->provided[1]; + } else + num = test->provided[0]; + + username = g_strdup_printf ("user%c", num); + password = g_strdup_printf ("realm%c", num); + soup_auth_authenticate (auth, username, password); + g_free (username); + g_free (password); +} + +static void +bug271540_sent (SoupMessage *msg, gpointer data) +{ + int n = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (msg), "#")); + gboolean *authenticated = data; + int auth = identify_auth (msg); + + soup_test_assert (*authenticated || !auth, + "using auth on message %d before authenticating", n); + soup_test_assert (!*authenticated || auth, + "sent unauthenticated message %d after authenticating", n); +} + +static void +bug271540_authenticate (SoupSession *session, SoupMessage *msg, + SoupAuth *auth, gboolean retrying, gpointer data) +{ + int n = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (msg), "#")); + gboolean *authenticated = data; + + if (strcmp (soup_auth_get_scheme_name (auth), "Basic") != 0 || + strcmp (soup_auth_get_realm (auth), "realm1") != 0) + return; + + if (!*authenticated) { + debug_printf (1, " authenticating message %d\n", n); + soup_auth_authenticate (auth, "user1", "realm1"); + *authenticated = TRUE; + } else { + soup_test_assert (!*authenticated, + "asked to authenticate message %d after authenticating", n); + } +} + +static void +bug271540_finished (SoupSession *session, SoupMessage *msg, gpointer data) +{ + int *left = data; + + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + + (*left)--; + if (!*left) + g_main_loop_quit (loop); +} + +static void +do_pipelined_auth_test (void) +{ + SoupSession *session; + SoupMessage *msg; + gboolean authenticated; + char *uri; + int i; + + g_test_bug ("271540"); + + SOUP_TEST_SKIP_IF_NO_APACHE; + + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + + authenticated = FALSE; + g_signal_connect (session, "authenticate", + G_CALLBACK (bug271540_authenticate), &authenticated); + + uri = g_strconcat (base_uri, "Basic/realm1/", NULL); + for (i = 0; i < 10; i++) { + msg = soup_message_new (SOUP_METHOD_GET, uri); + g_object_set_data (G_OBJECT (msg), "#", GINT_TO_POINTER (i + 1)); + g_signal_connect (msg, "wrote_headers", + G_CALLBACK (bug271540_sent), &authenticated); + + soup_session_queue_message (session, msg, + bug271540_finished, &i); + } + g_free (uri); + + loop = g_main_loop_new (NULL, TRUE); + g_main_loop_run (loop); + g_main_loop_unref (loop); + + soup_test_session_abort_unref (session); +} + +/* We test two different things here: + * + * 1. If we get a 401 response with "WWW-Authenticate: Digest + * stale=true...", we should retry and succeed *without* the + * session asking for a password again. + * + * 2. If we get a successful response with "Authentication-Info: + * nextnonce=...", we should update the nonce automatically so as + * to avoid getting a stale nonce error on the next request. + * + * In our Apache config, /Digest/realm1 and /Digest/realm1/expire are + * set up to use the same auth info, but only the latter has an + * AuthDigestNonceLifetime (of 2 seconds). The way nonces work in + * Apache, a nonce received from /Digest/realm1 will still expire in + * /Digest/realm1/expire, but it won't issue a nextnonce for a request + * in /Digest/realm1. This lets us test both behaviors. + * + * The expected conversation is: + * + * First message + * GET /Digest/realm1 + * + * 401 Unauthorized + * WWW-Authenticate: Digest nonce=A + * + * [emit 'authenticate'] + * + * GET /Digest/realm1 + * Authorization: Digest nonce=A + * + * 200 OK + * [No Authentication-Info] + * + * [sleep 2 seconds: nonce A is no longer valid, but we have no + * way of knowing that] + * + * Second message + * GET /Digest/realm1/expire/ + * Authorization: Digest nonce=A + * + * 401 Unauthorized + * WWW-Authenticate: Digest stale=true nonce=B + * + * GET /Digest/realm1/expire/ + * Authorization: Digest nonce=B + * + * 200 OK + * Authentication-Info: nextnonce=C + * + * [sleep 1 second] + * + * Third message + * GET /Digest/realm1/expire/ + * Authorization: Digest nonce=C + * [nonce=B would work here too] + * + * 200 OK + * Authentication-Info: nextnonce=D + * + * [sleep 1 second; nonces B and C are no longer valid, but D is] + * + * Fourth message + * GET /Digest/realm1/expire/ + * Authorization: Digest nonce=D + * + * 200 OK + * Authentication-Info: nextnonce=D + * + */ + +static void +digest_nonce_authenticate (SoupSession *session, SoupMessage *msg, + SoupAuth *auth, gboolean retrying, gpointer data) +{ + if (retrying) + return; + + if (strcmp (soup_auth_get_scheme_name (auth), "Digest") != 0 || + strcmp (soup_auth_get_realm (auth), "realm1") != 0) + return; + + soup_auth_authenticate (auth, "user1", "realm1"); +} + +static void +digest_nonce_unauthorized (SoupMessage *msg, gpointer data) +{ + gboolean *got_401 = data; + *got_401 = TRUE; +} + +static void +do_digest_nonce_test (SoupSession *session, + const char *nth, const char *uri, gboolean use_auth_cache, + gboolean expect_401, gboolean expect_signal) +{ + SoupMessage *msg; + gboolean got_401; + + msg = soup_message_new (SOUP_METHOD_GET, uri); + if (!use_auth_cache) { + SoupMessageFlags flags = soup_message_get_flags (msg); + + soup_message_set_flags (msg, flags | SOUP_MESSAGE_DO_NOT_USE_AUTH_CACHE); + } + if (expect_signal) { + g_signal_connect (session, "authenticate", + G_CALLBACK (digest_nonce_authenticate), + NULL); + } + soup_message_add_status_code_handler (msg, "got_headers", + SOUP_STATUS_UNAUTHORIZED, + G_CALLBACK (digest_nonce_unauthorized), + &got_401); + got_401 = FALSE; + soup_session_send_message (session, msg); + soup_test_assert (got_401 == expect_401, + "%s request %s a 401 Unauthorized!\n", nth, + got_401 ? "got" : "did not get"); + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + + if (expect_signal) { + g_signal_handlers_disconnect_by_func (session, + G_CALLBACK (digest_nonce_authenticate), + NULL); + } + + g_object_unref (msg); +} + +static void +do_digest_expiration_test (void) +{ + SoupSession *session; + char *uri; + + SOUP_TEST_SKIP_IF_NO_APACHE; + + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + + uri = g_strconcat (base_uri, "Digest/realm1/", NULL); + do_digest_nonce_test (session, "First", uri, TRUE, TRUE, TRUE); + g_free (uri); + sleep (2); + uri = g_strconcat (base_uri, "Digest/realm1/expire/", NULL); + do_digest_nonce_test (session, "Second", uri, TRUE, TRUE, FALSE); + sleep (1); + do_digest_nonce_test (session, "Third", uri, TRUE, FALSE, FALSE); + sleep (1); + do_digest_nonce_test (session, "Fourth", uri, TRUE, FALSE, FALSE); + g_free (uri); + + soup_test_session_abort_unref (session); +} + +/* Async auth test. We queue three requests to /Basic/realm1, ensuring + * that they are sent in order. The first and third ones will be + * paused from the authentication callback. The second will be allowed + * to fail. Shortly after the third one requests auth, we'll provide + * the auth and unpause the two remaining messages, allowing them to + * succeed. + */ + +static void +async_authenticate (SoupSession *session, SoupMessage *msg, + SoupAuth *auth, gboolean retrying, gpointer data) +{ + SoupAuth **saved_auth = data; + int id = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (msg), "id")); + + debug_printf (2, " async_authenticate msg%d\n", id); + + /* The session will try to authenticate msg3 *before* sending + * it, because it already knows it's going to need the auth. + * Ignore that. + */ + if (msg->status_code != SOUP_STATUS_UNAUTHORIZED) { + debug_printf (2, " (ignoring)\n"); + return; + } + + soup_session_pause_message (session, msg); + if (saved_auth) + *saved_auth = g_object_ref (auth); + g_main_loop_quit (loop); +} + +static void +async_finished (SoupSession *session, SoupMessage *msg, gpointer user_data) +{ + int *remaining = user_data; + int id = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (msg), "id")); + + debug_printf (2, " async_finished msg%d\n", id); + + (*remaining)--; + if (!*remaining) + g_main_loop_quit (loop); +} + +static void +async_authenticate_assert_once (SoupSession *session, SoupMessage *msg, + SoupAuth *auth, gboolean retrying, gpointer data) +{ + gboolean *been_here = data; + + debug_printf (2, " async_authenticate_assert_once\n"); + + soup_test_assert (!*been_here, + "async_authenticate_assert_once called twice"); + *been_here = TRUE; +} + +static void +async_authenticate_assert_once_and_stop (SoupSession *session, SoupMessage *msg, + SoupAuth *auth, gboolean retrying, gpointer data) +{ + gboolean *been_here = data; + + debug_printf (2, " async_authenticate_assert_once_and_stop\n"); + + soup_test_assert (!*been_here, + "async_authenticate_assert_once called twice"); + *been_here = TRUE; + + soup_session_pause_message (session, msg); + g_main_loop_quit (loop); +} + +static void +do_async_auth_good_password_test (void) +{ + SoupSession *session; + SoupMessage *msg1, *msg2, *msg3, msg2_bak; + guint auth_id; + char *uri; + SoupAuth *auth = NULL; + int remaining; + + SOUP_TEST_SKIP_IF_NO_APACHE; + + loop = g_main_loop_new (NULL, TRUE); + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + uri = g_strconcat (base_uri, "Basic/realm1/", NULL); + remaining = 0; + + msg1 = soup_message_new ("GET", uri); + g_object_set_data (G_OBJECT (msg1), "id", GINT_TO_POINTER (1)); + auth_id = g_signal_connect (session, "authenticate", + G_CALLBACK (async_authenticate), &auth); + g_object_ref (msg1); + remaining++; + soup_session_queue_message (session, msg1, async_finished, &remaining); + g_main_loop_run (loop); + g_signal_handler_disconnect (session, auth_id); + + /* async_authenticate will pause msg1 and quit loop */ + + msg2 = soup_message_new ("GET", uri); + g_object_set_data (G_OBJECT (msg2), "id", GINT_TO_POINTER (2)); + soup_session_send_message (session, msg2); + + soup_test_assert_message_status (msg2, SOUP_STATUS_UNAUTHORIZED); + + /* msg2 should be done at this point; assuming everything is + * working correctly, the session won't look at it again; we + * ensure that if it does, it will crash the test program. + */ + memcpy (&msg2_bak, msg2, sizeof (SoupMessage)); + memset (msg2, 0, sizeof (SoupMessage)); + + msg3 = soup_message_new ("GET", uri); + g_object_set_data (G_OBJECT (msg3), "id", GINT_TO_POINTER (3)); + auth_id = g_signal_connect (session, "authenticate", + G_CALLBACK (async_authenticate), NULL); + g_object_ref (msg3); + remaining++; + soup_session_queue_message (session, msg3, async_finished, &remaining); + g_main_loop_run (loop); + g_signal_handler_disconnect (session, auth_id); + + /* async_authenticate will pause msg3 and quit loop */ + + /* Now do the auth, and restart */ + if (auth) { + soup_auth_authenticate (auth, "user1", "realm1"); + g_object_unref (auth); + soup_session_unpause_message (session, msg1); + soup_session_unpause_message (session, msg3); + + g_main_loop_run (loop); + + /* async_finished will quit the loop */ + } else + soup_test_assert (auth, "msg1 didn't get authenticate signal"); + + soup_test_assert_message_status (msg1, SOUP_STATUS_OK); + soup_test_assert_message_status (msg3, SOUP_STATUS_OK); + + soup_test_session_abort_unref (session); + + g_object_unref (msg1); + g_object_unref (msg3); + memcpy (msg2, &msg2_bak, sizeof (SoupMessage)); + g_object_unref (msg2); + + g_free (uri); + g_main_loop_unref (loop); +} + +static void +do_async_auth_bad_password_test (void) +{ + SoupSession *session; + SoupMessage *msg; + guint auth_id; + char *uri; + SoupAuth *auth = NULL; + int remaining; + gboolean been_there; + + /* Test that giving the wrong password doesn't cause multiple + * authenticate signals the second time. + */ + g_test_bug ("522601"); + + SOUP_TEST_SKIP_IF_NO_APACHE; + + loop = g_main_loop_new (NULL, TRUE); + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + uri = g_strconcat (base_uri, "Basic/realm1/", NULL); + remaining = 0; + auth = NULL; + + msg = soup_message_new ("GET", uri); + g_object_set_data (G_OBJECT (msg), "id", GINT_TO_POINTER (1)); + auth_id = g_signal_connect (session, "authenticate", + G_CALLBACK (async_authenticate), &auth); + g_object_ref (msg); + remaining++; + soup_session_queue_message (session, msg, async_finished, &remaining); + g_main_loop_run (loop); + g_signal_handler_disconnect (session, auth_id); + soup_auth_authenticate (auth, "user1", "wrong"); + g_object_unref (auth); + soup_session_unpause_message (session, msg); + + been_there = FALSE; + auth_id = g_signal_connect (session, "authenticate", + G_CALLBACK (async_authenticate_assert_once), + &been_there); + g_main_loop_run (loop); + g_signal_handler_disconnect (session, auth_id); + + soup_test_assert (been_there, + "authenticate not emitted"); + + soup_test_session_abort_unref (session); + g_object_unref (msg); + + g_free (uri); + g_main_loop_unref (loop); +} + +static void +do_async_auth_no_password_test (void) +{ + SoupSession *session; + SoupMessage *msg; + guint auth_id; + char *uri; + int remaining; + gboolean been_there; + + /* Test that giving no password doesn't cause multiple + * authenticate signals the second time. + */ + g_test_bug ("583462"); + + SOUP_TEST_SKIP_IF_NO_APACHE; + + loop = g_main_loop_new (NULL, TRUE); + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + uri = g_strconcat (base_uri, "Basic/realm1/", NULL); + remaining = 0; + + /* Send a message that doesn't actually authenticate + */ + msg = soup_message_new ("GET", uri); + g_object_set_data (G_OBJECT (msg), "id", GINT_TO_POINTER (1)); + auth_id = g_signal_connect (session, "authenticate", + G_CALLBACK (async_authenticate), NULL); + g_object_ref (msg); + remaining++; + soup_session_queue_message (session, msg, async_finished, &remaining); + g_main_loop_run (loop); + g_signal_handler_disconnect (session, auth_id); + soup_session_unpause_message (session, msg); + g_main_loop_run (loop); + g_object_unref(msg); + + /* Now send a second message */ + msg = soup_message_new ("GET", uri); + g_object_set_data (G_OBJECT (msg), "id", GINT_TO_POINTER (2)); + g_object_ref (msg); + been_there = FALSE; + auth_id = g_signal_connect (session, "authenticate", + G_CALLBACK (async_authenticate_assert_once_and_stop), + &been_there); + remaining++; + soup_session_queue_message (session, msg, async_finished, &remaining); + g_main_loop_run (loop); + soup_session_unpause_message (session, msg); + + g_main_loop_run (loop); + g_signal_handler_disconnect (session, auth_id); + + soup_test_session_abort_unref (session); + g_object_unref (msg); + + g_free (uri); + g_main_loop_unref (loop); +} + +typedef struct { + const char *password; + struct { + const char *headers; + const char *response; + } round[2]; +} SelectAuthData; + +static void +select_auth_authenticate (SoupSession *session, SoupMessage *msg, + SoupAuth *auth, gboolean retrying, gpointer data) +{ + SelectAuthData *sad = data; + const char *header, *basic, *digest; + int round = retrying ? 1 : 0; + + header = soup_message_headers_get_list (msg->response_headers, + "WWW-Authenticate"); + basic = strstr (header, "Basic"); + digest = strstr (header, "Digest"); + if (basic && digest) { + if (basic < digest) + sad->round[round].headers = "Basic, Digest"; + else + sad->round[round].headers = "Digest, Basic"; + } else if (basic) + sad->round[round].headers = "Basic"; + else if (digest) + sad->round[round].headers = "Digest"; + + sad->round[round].response = soup_auth_get_scheme_name (auth); + if (sad->password && !retrying) + soup_auth_authenticate (auth, "user", sad->password); +} + +static void +select_auth_test_one (SoupURI *uri, + gboolean disable_digest, const char *password, + const char *first_headers, const char *first_response, + const char *second_headers, const char *second_response, + guint final_status) +{ + SelectAuthData sad; + SoupMessage *msg; + SoupSession *session; + + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + if (disable_digest) + soup_session_remove_feature_by_type (session, SOUP_TYPE_AUTH_DIGEST); + + g_signal_connect (session, "authenticate", + G_CALLBACK (select_auth_authenticate), &sad); + memset (&sad, 0, sizeof (sad)); + sad.password = password; + + msg = soup_message_new_from_uri ("GET", uri); + soup_session_send_message (session, msg); + + soup_test_assert (strcmp (sad.round[0].headers, first_headers) == 0, + "Header order wrong: expected %s, got %s", + first_headers, sad.round[0].headers); + soup_test_assert (strcmp (sad.round[0].response, first_response) == 0, + "Selected auth type wrong: expected %s, got %s", + first_response, sad.round[0].response); + + soup_test_assert (sad.round[1].headers || !second_headers, + "Expected a second round"); + soup_test_assert (!sad.round[1].headers || second_headers, + "Didn't expect a second round"); + if (second_headers && second_response) { + soup_test_assert (strcmp (sad.round[1].headers, second_headers) == 0, + "Second round header order wrong: expected %s, got %s\n", + second_headers, sad.round[1].headers); + soup_test_assert (strcmp (sad.round[1].response, second_response) == 0, + "Second round selected auth type wrong: expected %s, got %s\n", + second_response, sad.round[1].response); + } + + soup_test_assert_message_status (msg, final_status); + + g_object_unref (msg); + soup_test_session_abort_unref (session); +} + +static void +server_callback (SoupServer *server, SoupMessage *msg, + const char *path, GHashTable *query, + SoupClientContext *context, gpointer data) +{ + soup_message_set_response (msg, "text/plain", + SOUP_MEMORY_STATIC, + "OK\r\n", 4); + soup_message_set_status (msg, SOUP_STATUS_OK); +} + +static gboolean +server_basic_auth_callback (SoupAuthDomain *auth_domain, SoupMessage *msg, + const char *username, const char *password, gpointer data) +{ + if (strcmp (username, "user") != 0) + return FALSE; + return strcmp (password, "good-basic") == 0; +} + +static char * +server_digest_auth_callback (SoupAuthDomain *auth_domain, SoupMessage *msg, + const char *username, gpointer data) +{ + if (strcmp (username, "user") != 0) + return NULL; + return soup_auth_domain_digest_encode_password ("user", + "auth-test", + "good"); +} + +static void +do_select_auth_test (void) +{ + SoupServer *server; + SoupAuthDomain *basic_auth_domain, *digest_auth_domain; + SoupURI *uri; + + g_test_bug ("562339"); + + /* It doesn't seem to be possible to configure Apache to serve + * multiple auth types for a single URL. So we have to use + * SoupServer here. We know that SoupServer handles the server + * side of this scenario correctly, because we test it against + * curl in server-auth-test. + */ + server = soup_test_server_new (SOUP_TEST_SERVER_IN_THREAD); + soup_server_add_handler (server, NULL, + server_callback, NULL, NULL); + uri = soup_test_server_get_uri (server, "http", NULL); + + basic_auth_domain = soup_auth_domain_basic_new ( + SOUP_AUTH_DOMAIN_REALM, "auth-test", + SOUP_AUTH_DOMAIN_ADD_PATH, "/", + SOUP_AUTH_DOMAIN_BASIC_AUTH_CALLBACK, server_basic_auth_callback, + NULL); + soup_server_add_auth_domain (server, basic_auth_domain); + + digest_auth_domain = soup_auth_domain_digest_new ( + SOUP_AUTH_DOMAIN_REALM, "auth-test", + SOUP_AUTH_DOMAIN_ADD_PATH, "/", + SOUP_AUTH_DOMAIN_DIGEST_AUTH_CALLBACK, server_digest_auth_callback, + NULL); + soup_server_add_auth_domain (server, digest_auth_domain); + + debug_printf (1, " Testing with no auth\n"); + select_auth_test_one (uri, FALSE, NULL, + "Basic, Digest", "Digest", + NULL, NULL, + SOUP_STATUS_UNAUTHORIZED); + + debug_printf (1, " Testing with bad password\n"); + select_auth_test_one (uri, FALSE, "bad", + "Basic, Digest", "Digest", + "Basic, Digest", "Digest", + SOUP_STATUS_UNAUTHORIZED); + + debug_printf (1, " Testing with good password\n"); + select_auth_test_one (uri, FALSE, "good", + "Basic, Digest", "Digest", + NULL, NULL, + SOUP_STATUS_OK); + + /* Test with Digest disabled in the client. */ + debug_printf (1, " Testing without Digest with no auth\n"); + select_auth_test_one (uri, TRUE, NULL, + "Basic, Digest", "Basic", + NULL, NULL, + SOUP_STATUS_UNAUTHORIZED); + + debug_printf (1, " Testing without Digest with bad password\n"); + select_auth_test_one (uri, TRUE, "bad", + "Basic, Digest", "Basic", + "Basic, Digest", "Basic", + SOUP_STATUS_UNAUTHORIZED); + + debug_printf (1, " Testing without Digest with good password\n"); + select_auth_test_one (uri, TRUE, "good-basic", + "Basic, Digest", "Basic", + NULL, NULL, + SOUP_STATUS_OK); + + /* Now flip the order of the domains, verify that this flips + * the order of the headers, and make sure that digest auth + * *still* gets used. + */ + + soup_server_remove_auth_domain (server, basic_auth_domain); + soup_server_remove_auth_domain (server, digest_auth_domain); + soup_server_add_auth_domain (server, digest_auth_domain); + soup_server_add_auth_domain (server, basic_auth_domain); + + debug_printf (1, " Testing flipped with no auth\n"); + select_auth_test_one (uri, FALSE, NULL, + "Digest, Basic", "Digest", + NULL, NULL, + SOUP_STATUS_UNAUTHORIZED); + + debug_printf (1, " Testing flipped with bad password\n"); + select_auth_test_one (uri, FALSE, "bad", + "Digest, Basic", "Digest", + "Digest, Basic", "Digest", + SOUP_STATUS_UNAUTHORIZED); + + debug_printf (1, " Testing flipped with good password\n"); + select_auth_test_one (uri, FALSE, "good", + "Digest, Basic", "Digest", + NULL, NULL, + SOUP_STATUS_OK); + + g_object_unref (basic_auth_domain); + g_object_unref (digest_auth_domain); + soup_uri_free (uri); + soup_test_server_quit_unref (server); +} + +static void +sneakily_close_connection (SoupMessage *msg, gpointer user_data) +{ + /* Sneakily close the connection after the response, by + * tricking soup-message-io into thinking that had been + * the plan all along. + */ + soup_message_headers_append (msg->response_headers, + "Connection", "close"); +} + +static void +auth_close_request_started (SoupServer *server, SoupMessage *msg, + SoupClientContext *client, gpointer user_data) +{ + g_signal_connect (msg, "wrote-headers", + G_CALLBACK (sneakily_close_connection), NULL); +} + +typedef struct { + SoupSession *session; + SoupMessage *msg; + SoupAuth *auth; +} AuthCloseData; + +static gboolean +auth_close_idle_authenticate (gpointer user_data) +{ + AuthCloseData *acd = user_data; + + soup_auth_authenticate (acd->auth, "user", "good-basic"); + soup_session_unpause_message (acd->session, acd->msg); + + g_object_unref (acd->auth); + return FALSE; +} + +static void +auth_close_authenticate (SoupSession *session, SoupMessage *msg, + SoupAuth *auth, gboolean retrying, gpointer data) +{ + AuthCloseData *acd = data; + + soup_session_pause_message (session, msg); + acd->auth = g_object_ref (auth); + g_idle_add (auth_close_idle_authenticate, acd); +} + +static void +do_auth_close_test (void) +{ + SoupServer *server; + SoupAuthDomain *basic_auth_domain; + SoupURI *uri; + AuthCloseData acd; + + server = soup_test_server_new (SOUP_TEST_SERVER_DEFAULT); + soup_server_add_handler (server, NULL, + server_callback, NULL, NULL); + + uri = soup_test_server_get_uri (server, "http", NULL); + soup_uri_set_path (uri, "/close"); + + basic_auth_domain = soup_auth_domain_basic_new ( + SOUP_AUTH_DOMAIN_REALM, "auth-test", + SOUP_AUTH_DOMAIN_ADD_PATH, "/", + SOUP_AUTH_DOMAIN_BASIC_AUTH_CALLBACK, server_basic_auth_callback, + NULL); + soup_server_add_auth_domain (server, basic_auth_domain); + g_object_unref (basic_auth_domain); + + g_signal_connect (server, "request-started", + G_CALLBACK (auth_close_request_started), NULL); + + acd.session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + g_signal_connect (acd.session, "authenticate", + G_CALLBACK (auth_close_authenticate), &acd); + + acd.msg = soup_message_new_from_uri ("GET", uri); + soup_uri_free (uri); + soup_session_send_message (acd.session, acd.msg); + + soup_test_assert_message_status (acd.msg, SOUP_STATUS_OK); + + g_object_unref (acd.msg); + soup_test_session_abort_unref (acd.session); + soup_test_server_quit_unref (server); +} + +static gboolean +infinite_cancel (gpointer session) +{ + soup_session_abort (session); + return FALSE; +} + +static void +infinite_authenticate (SoupSession *session, SoupMessage *msg, + SoupAuth *auth, gboolean retrying, gpointer data) +{ + soup_auth_authenticate (auth, "user", "bad"); +} + +static void +do_infinite_auth_test (void) +{ + SoupSession *session; + SoupMessage *msg; + char *uri; + int timeout; + + SOUP_TEST_SKIP_IF_NO_APACHE; + + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + g_signal_connect (session, "authenticate", + G_CALLBACK (infinite_authenticate), NULL); + + uri = g_strconcat (base_uri, "Basic/realm1/", NULL); + msg = soup_message_new ("GET", uri); + g_free (uri); + + timeout = g_timeout_add (500, infinite_cancel, session); + g_test_expect_message ("libsoup", G_LOG_LEVEL_WARNING, + "*stuck in infinite loop*"); + soup_session_send_message (session, msg); + g_test_assert_expected_messages (); + + soup_test_assert (msg->status_code != SOUP_STATUS_CANCELLED, + "Got stuck in loop"); + soup_test_assert_message_status (msg, SOUP_STATUS_UNAUTHORIZED); + + g_source_remove (timeout); + soup_test_session_abort_unref (session); + g_object_unref (msg); +} + +static void +disappear_request_read (SoupServer *server, SoupMessage *msg, + SoupClientContext *context, gpointer user_data) +{ + /* Remove the WWW-Authenticate header if this was a failed attempt */ + if (soup_message_headers_get_one (msg->request_headers, "Authorization") && + msg->status_code == SOUP_STATUS_UNAUTHORIZED) + soup_message_headers_remove (msg->response_headers, "WWW-Authenticate"); +} + +static void +disappear_authenticate (SoupSession *session, SoupMessage *msg, + SoupAuth *auth, gboolean retrying, gpointer data) +{ + int *counter = data; + + (*counter)++; + if (!retrying) + soup_auth_authenticate (auth, "user", "bad"); +} + +static void +do_disappearing_auth_test (void) +{ + SoupServer *server; + SoupAuthDomain *auth_domain; + SoupURI *uri; + SoupMessage *msg; + SoupSession *session; + int counter; + + g_test_bug_base ("https://bugzilla.redhat.com/"); + g_test_bug ("916224"); + + server = soup_test_server_new (FALSE); + soup_server_add_handler (server, NULL, + server_callback, NULL, NULL); + uri = soup_test_server_get_uri (server, "http", NULL); + + auth_domain = soup_auth_domain_basic_new ( + SOUP_AUTH_DOMAIN_REALM, "auth-test", + SOUP_AUTH_DOMAIN_ADD_PATH, "/", + SOUP_AUTH_DOMAIN_BASIC_AUTH_CALLBACK, server_basic_auth_callback, + NULL); + soup_server_add_auth_domain (server, auth_domain); + g_signal_connect (server, "request-read", + G_CALLBACK (disappear_request_read), NULL); + + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + + counter = 0; + g_signal_connect (session, "authenticate", + G_CALLBACK (disappear_authenticate), &counter); + + msg = soup_message_new_from_uri ("GET", uri); + soup_session_send_message (session, msg); + + soup_test_assert (counter <= 2, + "Got stuck in loop"); + soup_test_assert_message_status (msg, SOUP_STATUS_UNAUTHORIZED); + + g_object_unref (msg); + soup_test_session_abort_unref (session); + + g_object_unref (auth_domain); + soup_uri_free (uri); + soup_test_server_quit_unref (server); +} + +static SoupAuthTest relogin_tests[] = { + { "Auth provided via URL, should succeed", + "Basic/realm12/", "1", TRUE, "01", SOUP_STATUS_OK }, + + { "Now should automatically reuse previous auth", + "Basic/realm12/", "", FALSE, "1", SOUP_STATUS_OK }, + + { "Different auth provided via URL for the same realm, should succeed", + "Basic/realm12/", "2", TRUE, "2", SOUP_STATUS_OK }, + + { "Subdir should also automatically reuse auth", + "Basic/realm12/subdir/", "", FALSE, "2", SOUP_STATUS_OK }, + + { "Should fail with no auth", + "Basic/realm12/", "4", TRUE, "4", SOUP_STATUS_UNAUTHORIZED }, + + { "Make sure we've forgotten it", + "Basic/realm12/", "", FALSE, "0", SOUP_STATUS_UNAUTHORIZED }, + + { "Should fail with no auth, fail again with bad password, and give up", + "Basic/realm12/", "3", FALSE, "03", SOUP_STATUS_UNAUTHORIZED }, + + { NULL } +}; + +/* https://bugzilla.gnome.org/show_bug.cgi?id=755617 */ +static SoupAuthTest basic_root_pspace_test[] = { + { "Auth provided via URL, should succeed", + "BasicRoot", "1", TRUE, "01", SOUP_STATUS_OK }, + + { "Parent dir should automatically reuse auth", + "/", "1", FALSE, "1", SOUP_STATUS_OK }, + + { NULL } +}; + +static void +do_batch_tests (gconstpointer data) +{ + const SoupAuthTest *current_tests = data; + SoupSession *session; + SoupMessage *msg; + char *expected, *uristr; + SoupURI *base; + guint signal; + int i; + + SOUP_TEST_SKIP_IF_NO_APACHE; + + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + base = soup_uri_new (base_uri); + + for (i = 0; current_tests[i].url; i++) { + SoupURI *soup_uri = soup_uri_new_with_base (base, current_tests[i].url); + + debug_printf (1, "Test %d: %s\n", i + 1, current_tests[i].explanation); + + if (current_tests[i].url_auth) { + gchar *username = g_strdup_printf ("user%c", current_tests[i].provided[0]); + gchar *password = g_strdup_printf ("realm%c", current_tests[i].provided[0]); + soup_uri_set_user (soup_uri, username); + soup_uri_set_password (soup_uri, password); + g_free (username); + g_free (password); + } + + msg = soup_message_new_from_uri (SOUP_METHOD_GET, soup_uri); + soup_uri_free (soup_uri); + if (!msg) { + g_printerr ("auth-test: Could not parse URI\n"); + exit (1); + } + + uristr = soup_uri_to_string (soup_message_get_uri (msg), FALSE); + debug_printf (1, " GET %s\n", uristr); + g_free (uristr); + + expected = g_strdup (current_tests[i].expected); + soup_message_add_status_code_handler ( + msg, "got_headers", SOUP_STATUS_UNAUTHORIZED, + G_CALLBACK (handler), expected); + soup_message_add_status_code_handler ( + msg, "got_headers", SOUP_STATUS_OK, + G_CALLBACK (handler), expected); + + signal = g_signal_connect (session, "authenticate", + G_CALLBACK (authenticate), + (gpointer)¤t_tests[i]); + soup_session_send_message (session, msg); + g_signal_handler_disconnect (session, signal); + + soup_test_assert_message_status (msg, current_tests[i].final_status); + soup_test_assert (!*expected, + "expected %d more round(s)\n", + (int)strlen (expected)); + + g_free (expected); + debug_printf (1, "\n"); + + g_object_unref (msg); + } + soup_uri_free (base); + + soup_test_session_abort_unref (session); +} + +static void +do_clear_credentials_test (void) +{ + SoupSession *session; + SoupAuthManager *manager; + char *uri; + + SOUP_TEST_SKIP_IF_NO_APACHE; + + session = soup_test_session_new (SOUP_TYPE_SESSION, NULL); + + uri = g_strconcat (base_uri, "Digest/realm1/", NULL); + do_digest_nonce_test (session, "First", uri, TRUE, TRUE, TRUE); + + manager = SOUP_AUTH_MANAGER (soup_session_get_feature (session, SOUP_TYPE_AUTH_MANAGER)); + soup_auth_manager_clear_cached_credentials (manager); + + do_digest_nonce_test (session, "Second", uri, TRUE, TRUE, TRUE); + g_free (uri); + + soup_test_session_abort_unref (session); +} + +static void +do_message_do_not_use_auth_cache_test (void) +{ + SoupSession *session; + SoupAuthManager *manager; + SoupMessage *msg; + SoupMessageFlags flags; + SoupURI *soup_uri; + char *uri; + + SOUP_TEST_SKIP_IF_NO_APACHE; + + session = soup_test_session_new (SOUP_TYPE_SESSION, NULL); + + uri = g_strconcat (base_uri, "Digest/realm1/", NULL); + + /* First check that cached credentials are not used */ + do_digest_nonce_test (session, "First", uri, TRUE, TRUE, TRUE); + do_digest_nonce_test (session, "Second", uri, TRUE, FALSE, FALSE); + do_digest_nonce_test (session, "Third", uri, FALSE, TRUE, TRUE); + + /* Passing credentials in the URI should always authenticate + * no matter whether the cache is used or not + */ + soup_uri = soup_uri_new (uri); + soup_uri_set_user (soup_uri, "user1"); + soup_uri_set_password (soup_uri, "realm1"); + msg = soup_message_new_from_uri (SOUP_METHOD_GET, soup_uri); + flags = soup_message_get_flags (msg); + soup_message_set_flags (msg, flags | SOUP_MESSAGE_DO_NOT_USE_AUTH_CACHE); + soup_session_send_message (session, msg); + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + g_object_unref (msg); + soup_uri_free (soup_uri); + + manager = SOUP_AUTH_MANAGER (soup_session_get_feature (session, SOUP_TYPE_AUTH_MANAGER)); + + soup_auth_manager_clear_cached_credentials (manager); + + /* Now check that credentials are not stored */ + do_digest_nonce_test (session, "First", uri, FALSE, TRUE, TRUE); + do_digest_nonce_test (session, "Second", uri, TRUE, TRUE, TRUE); + do_digest_nonce_test (session, "Third", uri, TRUE, FALSE, FALSE); + + /* Credentials were stored for uri, but if we set SOUP_MESSAGE_DO_NOT_USE_AUTH_CACHE flag, + * and we don't have the authenticate signal, it should respond with 401 + */ + msg = soup_message_new (SOUP_METHOD_GET, uri); + flags = soup_message_get_flags (msg); + soup_message_set_flags (msg, flags | SOUP_MESSAGE_DO_NOT_USE_AUTH_CACHE); + soup_session_send_message (session, msg); + soup_test_assert_message_status (msg, SOUP_STATUS_UNAUTHORIZED); + g_object_unref (msg); + g_free (uri); + + soup_test_session_abort_unref (session); +} + +static void +async_no_auth_cache_authenticate (SoupSession *session, SoupMessage *msg, + SoupAuth *auth, gboolean retrying, SoupAuth **auth_out) +{ + debug_printf (1, " async_no_auth_cache_authenticate\n"); + + soup_session_pause_message (session, msg); + *auth_out = g_object_ref (auth); + g_main_loop_quit (loop); +} + +static void +async_no_auth_cache_finished (SoupSession *session, SoupMessage *msg, gpointer user_data) +{ + debug_printf (1, " async_no_auth_cache_finished\n"); + + g_main_loop_quit (loop); +} + +static void +do_async_message_do_not_use_auth_cache_test (void) +{ + SoupSession *session; + SoupMessage *msg; + char *uri; + SoupAuth *auth = NULL; + SoupMessageFlags flags; + + SOUP_TEST_SKIP_IF_NO_APACHE; + + loop = g_main_loop_new (NULL, TRUE); + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + uri = g_strconcat (base_uri, "Basic/realm1/", NULL); + + msg = soup_message_new ("GET", uri); + g_free (uri); + g_signal_connect (session, "authenticate", + G_CALLBACK (async_no_auth_cache_authenticate), &auth); + flags = soup_message_get_flags (msg); + soup_message_set_flags (msg, flags | SOUP_MESSAGE_DO_NOT_USE_AUTH_CACHE); + g_object_ref (msg); + soup_session_queue_message (session, msg, async_no_auth_cache_finished, NULL); + g_main_loop_run (loop); + + soup_test_assert_message_status (msg, SOUP_STATUS_UNAUTHORIZED); + + soup_test_assert (auth, "msg didn't get authenticate signal"); + soup_auth_authenticate (auth, "user1", "realm1"); + g_object_unref (auth); + + soup_session_unpause_message (session, msg); + g_main_loop_run (loop); + + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + + soup_test_session_abort_unref (session); + g_object_unref (msg); + g_main_loop_unref (loop); +} + +static void +has_authorization_header_authenticate (SoupSession *session, SoupMessage *msg, + SoupAuth *auth, gboolean retrying, gpointer data) +{ + SoupAuth **saved_auth = data; + + soup_auth_authenticate (auth, "user1", "realm1"); + *saved_auth = g_object_ref (auth); +} + +static void +has_authorization_header_authenticate_assert (SoupSession *session, SoupMessage *msg, + SoupAuth *auth, gboolean retrying, gpointer data) +{ + soup_test_assert (FALSE, "authenticate emitted unexpectedly"); +} + +static void +do_message_has_authorization_header_test (void) +{ + SoupSession *session; + SoupMessage *msg; + SoupAuthManager *manager; + SoupAuth *auth = NULL; + char *token; + guint auth_id; + char *uri; + + g_test_bug ("775882"); + + SOUP_TEST_SKIP_IF_NO_APACHE; + + session = soup_test_session_new (SOUP_TYPE_SESSION, NULL); + uri = g_strconcat (base_uri, "Digest/realm1/", NULL); + + msg = soup_message_new ("GET", uri); + auth_id = g_signal_connect (session, "authenticate", + G_CALLBACK (has_authorization_header_authenticate), &auth); + soup_session_send_message (session, msg); + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + soup_test_assert (SOUP_IS_AUTH (auth), "Expected a SoupAuth"); + token = soup_auth_get_authorization (auth, msg); + g_object_unref (auth); + g_object_unref (msg); + g_signal_handler_disconnect (session, auth_id); + + manager = SOUP_AUTH_MANAGER (soup_session_get_feature (session, SOUP_TYPE_AUTH_MANAGER)); + soup_auth_manager_clear_cached_credentials (manager); + + msg = soup_message_new ("GET", uri); + soup_message_headers_replace (msg->request_headers, "Authorization", token); + auth_id = g_signal_connect (session, "authenticate", + G_CALLBACK (has_authorization_header_authenticate_assert), + NULL); + soup_session_send_message (session, msg); + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + g_object_unref (msg); + + /* Check that we can also provide our own Authorization header when not using credentials cache. */ + soup_auth_manager_clear_cached_credentials (manager); + msg = soup_message_new ("GET", uri); + soup_message_headers_replace (msg->request_headers, "Authorization", token); + soup_message_set_flags (msg, soup_message_get_flags (msg) | SOUP_MESSAGE_DO_NOT_USE_AUTH_CACHE); + soup_session_send_message (session, msg); + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + g_object_unref (msg); + g_free (token); + g_signal_handler_disconnect (session, auth_id); + + g_free (uri); + soup_test_session_abort_unref (session); +} + +int +main (int argc, char **argv) +{ + int ret; + + test_init (argc, argv, NULL); + apache_init (); + + base_uri = "http://127.0.0.1:47524/"; + + g_test_add_data_func ("/auth/main-tests", main_tests, do_batch_tests); + g_test_add_data_func ("/auth/relogin-tests", relogin_tests, do_batch_tests); + g_test_add_data_func ("/auth/basic-root-pspec-test", basic_root_pspace_test, do_batch_tests); + g_test_add_func ("/auth/pipelined-auth", do_pipelined_auth_test); + g_test_add_func ("/auth/digest-expiration", do_digest_expiration_test); + g_test_add_func ("/auth/async-auth/good-password", do_async_auth_good_password_test); + g_test_add_func ("/auth/async-auth/bad-password", do_async_auth_bad_password_test); + g_test_add_func ("/auth/async-auth/no-password", do_async_auth_no_password_test); + g_test_add_func ("/auth/select-auth", do_select_auth_test); + g_test_add_func ("/auth/auth-close", do_auth_close_test); + g_test_add_func ("/auth/infinite-auth", do_infinite_auth_test); + g_test_add_func ("/auth/disappearing-auth", do_disappearing_auth_test); + g_test_add_func ("/auth/clear-credentials", do_clear_credentials_test); + g_test_add_func ("/auth/message-do-not-use-auth-cache", do_message_do_not_use_auth_cache_test); + g_test_add_func ("/auth/async-message-do-not-use-auth-cache", do_async_message_do_not_use_auth_cache_test); + g_test_add_func ("/auth/authorization-header-request", do_message_has_authorization_header_test); + + ret = g_test_run (); + + test_cleanup (); + return ret; +} diff --git a/tests/cache-test.c b/tests/cache-test.c new file mode 100644 index 0000000..7d5897c --- /dev/null +++ b/tests/cache-test.c @@ -0,0 +1,793 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright 2012 Red Hat, Inc. + */ + +#include "test-utils.h" + +static void +server_callback (SoupServer *server, SoupMessage *msg, + const char *path, GHashTable *query, + SoupClientContext *context, gpointer data) +{ + const char *last_modified, *etag; + const char *header; + guint status = SOUP_STATUS_OK; + + if (msg->method != SOUP_METHOD_GET && msg->method != SOUP_METHOD_POST) { + soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED); + return; + } + + header = soup_message_headers_get_one (msg->request_headers, + "Test-Set-Expires"); + if (header) { + soup_message_headers_append (msg->response_headers, + "Expires", + header); + } + + header = soup_message_headers_get_one (msg->request_headers, + "Test-Set-Cache-Control"); + if (header) { + soup_message_headers_append (msg->response_headers, + "Cache-Control", + header); + } + + last_modified = soup_message_headers_get_one (msg->request_headers, + "Test-Set-Last-Modified"); + if (last_modified) { + soup_message_headers_append (msg->response_headers, + "Last-Modified", + last_modified); + } + + etag = soup_message_headers_get_one (msg->request_headers, + "Test-Set-ETag"); + if (etag) { + soup_message_headers_append (msg->response_headers, + "ETag", + etag); + } + + + header = soup_message_headers_get_one (msg->request_headers, + "If-Modified-Since"); + if (header && last_modified) { + SoupDate *date; + time_t lastmod, check; + + date = soup_date_new_from_string (last_modified); + lastmod = soup_date_to_time_t (date); + soup_date_free (date); + + date = soup_date_new_from_string (header); + check = soup_date_to_time_t (date); + soup_date_free (date); + + if (lastmod <= check) + status = SOUP_STATUS_NOT_MODIFIED; + } + + header = soup_message_headers_get_one (msg->request_headers, + "If-None-Match"); + if (header && etag) { + if (!strcmp (header, etag)) + status = SOUP_STATUS_NOT_MODIFIED; + } + + header = soup_message_headers_get_one (msg->request_headers, + "Test-Set-My-Header"); + if (header) { + soup_message_headers_append (msg->response_headers, + "My-Header", + header); + } + + if (status == SOUP_STATUS_OK) { + GChecksum *sum; + const char *body; + + sum = g_checksum_new (G_CHECKSUM_SHA256); + g_checksum_update (sum, (guchar *)path, strlen (path)); + if (last_modified) + g_checksum_update (sum, (guchar *)last_modified, strlen (last_modified)); + if (etag) + g_checksum_update (sum, (guchar *)etag, strlen (etag)); + body = g_checksum_get_string (sum); + soup_message_set_response (msg, "text/plain", + SOUP_MEMORY_COPY, + body, strlen (body) + 1); + g_checksum_free (sum); + } + soup_message_set_status (msg, status); +} + +static gboolean +is_network_stream (GInputStream *stream) +{ + while (G_IS_FILTER_INPUT_STREAM (stream)) + stream = G_FILTER_INPUT_STREAM (stream)->base_stream; + + return !G_IS_FILE_INPUT_STREAM (stream); +} + +static char *do_request (SoupSession *session, + SoupURI *base_uri, + const char *method, + const char *path, + SoupMessageHeaders *response_headers, + ...) G_GNUC_NULL_TERMINATED; + +static gboolean last_request_hit_network; +static gboolean last_request_validated; +static gboolean last_request_unqueued; +static guint cancelled_requests; + +static void +copy_headers (const char *name, + const char *value, + gpointer user_data) +{ + SoupMessageHeaders *headers = (SoupMessageHeaders *) user_data; + soup_message_headers_append (headers, name, value); +} + +static char * +do_request (SoupSession *session, + SoupURI *base_uri, + const char *method, + const char *path, + SoupMessageHeaders *response_headers, + ...) +{ + SoupRequestHTTP *req; + SoupMessage *msg; + GInputStream *stream; + SoupURI *uri; + va_list ap; + const char *header, *value; + char buf[256]; + gsize nread; + GError *error = NULL; + + last_request_validated = last_request_hit_network = FALSE; + last_request_unqueued = FALSE; + + uri = soup_uri_new_with_base (base_uri, path); + req = soup_session_request_http_uri (session, method, uri, NULL); + soup_uri_free (uri); + msg = soup_request_http_get_message (req); + + va_start (ap, response_headers); + while ((header = va_arg (ap, const char *))) { + value = va_arg (ap, const char *); + soup_message_headers_append (msg->request_headers, + header, value); + } + va_end (ap); + + stream = soup_test_request_send (SOUP_REQUEST (req), NULL, 0, &error); + if (!stream) { + debug_printf (1, " could not send request: %s\n", + error->message); + g_error_free (error); + g_object_unref (req); + g_object_unref (msg); + return NULL; + } + + if (response_headers) + soup_message_headers_foreach (msg->response_headers, copy_headers, response_headers); + + g_object_unref (msg); + + if (last_request_validated) + last_request_unqueued = FALSE; + else + soup_test_assert (!last_request_unqueued, + "Request unqueued before finishing"); + + last_request_hit_network = is_network_stream (stream); + + g_input_stream_read_all (stream, buf, sizeof (buf), &nread, + NULL, &error); + if (error) { + debug_printf (1, " could not read response: %s\n", + error->message); + g_clear_error (&error); + } + soup_test_request_close_stream (SOUP_REQUEST (req), stream, + NULL, &error); + if (error) { + debug_printf (1, " could not close stream: %s\n", + error->message); + g_clear_error (&error); + } + g_object_unref (stream); + g_object_unref (req); + + /* Cache writes are G_PRIORITY_LOW, so they won't have happened yet... */ + soup_cache_flush ((SoupCache *)soup_session_get_feature (session, SOUP_TYPE_CACHE)); + + return nread ? g_memdup (buf, nread) : g_strdup (""); +} + +static void +do_request_with_cancel (SoupSession *session, + SoupURI *base_uri, + const char *method, + const char *path, + SoupTestRequestFlags flags) +{ + SoupRequestHTTP *req; + GInputStream *stream; + SoupURI *uri; + GError *error = NULL; + GCancellable *cancellable; + + last_request_validated = last_request_hit_network = last_request_unqueued = FALSE; + cancelled_requests = 0; + + uri = soup_uri_new_with_base (base_uri, path); + req = soup_session_request_http_uri (session, method, uri, NULL); + soup_uri_free (uri); + cancellable = flags & SOUP_TEST_REQUEST_CANCEL_CANCELLABLE ? g_cancellable_new () : NULL; + stream = soup_test_request_send (SOUP_REQUEST (req), cancellable, flags, &error); + if (stream) { + debug_printf (1, " could not cancel the request\n"); + g_object_unref (stream); + g_object_unref (req); + return; + } else + g_clear_error (&error); + + g_clear_object (&cancellable); + g_clear_object (&stream); + g_clear_object (&req); + + soup_cache_flush ((SoupCache *)soup_session_get_feature (session, SOUP_TYPE_CACHE)); +} + +static void +message_starting (SoupMessage *msg, gpointer data) +{ + if (soup_message_headers_get_one (msg->request_headers, + "If-Modified-Since") || + soup_message_headers_get_one (msg->request_headers, + "If-None-Match")) { + debug_printf (2, " Conditional request for %s\n", + soup_message_get_uri (msg)->path); + last_request_validated = TRUE; + } +} + +static void +request_queued (SoupSession *session, SoupMessage *msg, + gpointer data) +{ + g_signal_connect (msg, "starting", + G_CALLBACK (message_starting), + data); +} + +static void +request_unqueued (SoupSession *session, SoupMessage *msg, + gpointer data) +{ + if (msg->status_code == SOUP_STATUS_CANCELLED) + cancelled_requests++; + last_request_unqueued = TRUE; +} + +static void +do_basics_test (gconstpointer data) +{ + SoupURI *base_uri = (SoupURI *)data; + SoupSession *session; + SoupCache *cache; + char *cache_dir; + char *body1, *body2, *body3, *body4, *body5, *cmp; + + cache_dir = g_dir_make_tmp ("cache-test-XXXXXX", NULL); + debug_printf (2, " Caching to %s\n", cache_dir); + cache = soup_cache_new (cache_dir, SOUP_CACHE_SINGLE_USER); + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, + SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, + SOUP_SESSION_ADD_FEATURE, cache, + NULL); + + g_signal_connect (session, "request-queued", + G_CALLBACK (request_queued), NULL); + g_signal_connect (session, "request-unqueued", + G_CALLBACK (request_unqueued), NULL); + + debug_printf (2, " Initial requests\n"); + body1 = do_request (session, base_uri, "GET", "/1", NULL, + "Test-Set-Expires", "Fri, 01 Jan 2100 00:00:00 GMT", + NULL); + body2 = do_request (session, base_uri, "GET", "/2", NULL, + "Test-Set-Last-Modified", "Fri, 01 Jan 2010 00:00:00 GMT", + "Test-Set-Cache-Control", "must-revalidate", + NULL); + body3 = do_request (session, base_uri, "GET", "/3", NULL, + "Test-Set-Last-Modified", "Fri, 01 Jan 2010 00:00:00 GMT", + "Test-Set-Expires", "Sat, 02 Jan 2011 00:00:00 GMT", + "Test-Set-Cache-Control", "must-revalidate", + NULL); + body4 = do_request (session, base_uri, "GET", "/4", NULL, + "Test-Set-ETag", "\"abcdefg\"", + "Test-Set-Cache-Control", "must-revalidate", + NULL); + body5 = do_request (session, base_uri, "GET", "/5", NULL, + "Test-Set-Cache-Control", "no-cache", + NULL); + + + /* Resource with future Expires should have been cached */ + debug_printf (1, " Fresh cached resource\n"); + cmp = do_request (session, base_uri, "GET", "/1", NULL, + NULL); + soup_test_assert (!last_request_hit_network, + "Request for /1 not filled from cache"); + soup_test_assert (last_request_unqueued, + "Cached resource /1 not unqueued"); + g_assert_cmpstr (body1, ==, cmp); + g_free (cmp); + + + /* Resource with long-ago Last-Modified should have been cached */ + debug_printf (1, " Heuristically-fresh cached resource\n"); + cmp = do_request (session, base_uri, "GET", "/2", NULL, + NULL); + /* Not validated even if it has must-revalidate, because it hasn't expired */ + soup_test_assert (!last_request_validated, + "Request for /2 was validated"); + soup_test_assert (!last_request_hit_network, + "Request for /2 not filled from cache"); + soup_test_assert (last_request_unqueued, + "Cached resource /2 not unqueued"); + g_assert_cmpstr (body2, ==, cmp); + g_free (cmp); + + + /* Adding a query string should bypass the cache but not invalidate it */ + debug_printf (1, " Fresh cached resource with a query\n"); + cmp = do_request (session, base_uri, "GET", "/1?attr=value", NULL, + NULL); + soup_test_assert (last_request_hit_network, + "Request for /1?attr=value filled from cache"); + soup_test_assert (last_request_unqueued, + "Cached resource /1?attr=value not unqueued"); + g_free (cmp); + debug_printf (2, " Second request\n"); + cmp = do_request (session, base_uri, "GET", "/1", NULL, + NULL); + soup_test_assert (!last_request_hit_network, + "Second request for /1 not filled from cache"); + soup_test_assert (last_request_unqueued, + "Request for /1 not unqueued"); + g_assert_cmpstr (body1, ==, cmp); + g_free (cmp); + + + /* Expired + must-revalidate causes a conditional request */ + debug_printf (1, " Unchanged must-revalidate resource w/ Last-Modified\n"); + cmp = do_request (session, base_uri, "GET", "/3", NULL, + "Test-Set-Last-Modified", "Fri, 01 Jan 2010 00:00:00 GMT", + "Test-Set-Expires", "Sat, 02 Jan 2011 00:00:00 GMT", + "Test-Set-Cache-Control", "must-revalidate", + NULL); + soup_test_assert (last_request_validated, + "Request for /3 not validated"); + soup_test_assert (!last_request_hit_network, + "Request for /3 not filled from cache"); + soup_test_assert (last_request_unqueued, + "Cached resource /3 not unqueued"); + g_assert_cmpstr (body3, ==, cmp); + g_free (cmp); + + + /* Validation failure should update cache */ + debug_printf (1, " Changed must-revalidate resource w/ Last-Modified\n"); + cmp = do_request (session, base_uri, "GET", "/3", NULL, + "Test-Set-Last-Modified", "Sat, 02 Jan 2010 00:00:00 GMT", + "Test-Set-Expires", "Sat, 02 Jan 2011 00:00:00 GMT", + "Test-Set-Cache-Control", "must-revalidate", + NULL); + soup_test_assert (last_request_validated, + "Request for /3 not validated"); + soup_test_assert (last_request_hit_network, + "Request for /3 filled from cache"); + soup_test_assert (last_request_unqueued, + "Request for /3 not unqueued"); + g_assert_cmpstr (body3, !=, cmp); + g_free (cmp); + + debug_printf (2, " Second request\n"); + cmp = do_request (session, base_uri, "GET", "/3", NULL, + "Test-Set-Last-Modified", "Sat, 02 Jan 2010 00:00:00 GMT", + "Test-Set-Cache-Control", "must-revalidate", + NULL); + soup_test_assert (last_request_validated, + "Second request for /3 not validated"); + soup_test_assert (!last_request_hit_network, + "Second request for /3 not filled from cache"); + soup_test_assert (last_request_unqueued, + "Cached resource /3 not unqueued"); + g_assert_cmpstr (body3, !=, cmp); + g_free (cmp); + + /* ETag + must-revalidate causes a conditional request */ + debug_printf (1, " Unchanged must-revalidate resource w/ ETag\n"); + cmp = do_request (session, base_uri, "GET", "/4", NULL, + "Test-Set-ETag", "\"abcdefg\"", + NULL); + soup_test_assert (last_request_validated, + "Request for /4 not validated"); + soup_test_assert (!last_request_hit_network, + "Request for /4 not filled from cache"); + soup_test_assert (last_request_unqueued, + "Cached resource /4 not unqueued"); + g_assert_cmpstr (body4, ==, cmp); + g_free (cmp); + + + /* Cache-Control: no-cache prevents caching */ + debug_printf (1, " Uncacheable resource\n"); + cmp = do_request (session, base_uri, "GET", "/5", NULL, + "Test-Set-Cache-Control", "no-cache", + NULL); + soup_test_assert (last_request_hit_network, + "Request for /5 filled from cache"); + soup_test_assert (last_request_unqueued, + "Request for /5 not unqueued"); + g_assert_cmpstr (body5, ==, cmp); + g_free (cmp); + + + /* PUT to a URI invalidates the cache entry */ + debug_printf (1, " Invalidating and re-requesting a cached resource\n"); + cmp = do_request (session, base_uri, "PUT", "/1", NULL, + NULL); + soup_test_assert (last_request_hit_network, + "PUT filled from cache"); + g_free (cmp); + cmp = do_request (session, base_uri, "GET", "/1", NULL, + NULL); + soup_test_assert (last_request_hit_network, + "PUT failed to invalidate cache entry"); + g_assert_true (last_request_hit_network); + g_free (cmp); + + + soup_test_session_abort_unref (session); + g_object_unref (cache); + + g_free (cache_dir); + g_free (body1); + g_free (body2); + g_free (body3); + g_free (body4); + g_free (body5); +} + +static void +do_cancel_test (gconstpointer data) +{ + SoupURI *base_uri = (SoupURI *)data; + SoupSession *session; + SoupCache *cache; + char *cache_dir; + char *body1, *body2; + guint flags; + + g_test_bug ("692310"); + + cache_dir = g_dir_make_tmp ("cache-test-XXXXXX", NULL); + debug_printf (2, " Caching to %s\n", cache_dir); + cache = soup_cache_new (cache_dir, SOUP_CACHE_SINGLE_USER); + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, + SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, + SOUP_SESSION_ADD_FEATURE, cache, + NULL); + g_signal_connect (session, "request-unqueued", + G_CALLBACK (request_unqueued), NULL); + + debug_printf (2, " Initial requests\n"); + body1 = do_request (session, base_uri, "GET", "/1", NULL, + "Test-Set-Expires", "Fri, 01 Jan 2100 00:00:00 GMT", + NULL); + body2 = do_request (session, base_uri, "GET", "/2", NULL, + "Test-Set-Last-Modified", "Fri, 01 Jan 2010 00:00:00 GMT", + "Test-Set-Expires", "Fri, 01 Jan 2011 00:00:00 GMT", + "Test-Set-Cache-Control", "must-revalidate", + NULL); + + /* Check that messages are correctly processed on cancellations. */ + debug_printf (1, " Cancel fresh resource with soup_session_message_cancel()\n"); + flags = SOUP_TEST_REQUEST_CANCEL_MESSAGE | SOUP_TEST_REQUEST_CANCEL_IMMEDIATE; + do_request_with_cancel (session, base_uri, "GET", "/1", flags); + g_assert_cmpint (cancelled_requests, ==, 1); + soup_test_assert (last_request_unqueued, + "Cancelled request /1 not unqueued"); + + debug_printf (1, " Cancel fresh resource with g_cancellable_cancel()\n"); + flags = SOUP_TEST_REQUEST_CANCEL_CANCELLABLE | SOUP_TEST_REQUEST_CANCEL_IMMEDIATE; + do_request_with_cancel (session, base_uri, "GET", "/1", flags); + g_assert_cmpint (cancelled_requests, ==, 1); + soup_test_assert (last_request_unqueued, + "Cancelled request /1 not unqueued"); + + soup_test_session_abort_unref (session); + + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, + SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, + SOUP_SESSION_ADD_FEATURE, cache, + NULL); + g_signal_connect (session, "request-unqueued", + G_CALLBACK (request_unqueued), NULL); + + /* Check that messages are correctly processed on cancellations. */ + debug_printf (1, " Cancel a revalidating resource with soup_session_message_cancel()\n"); + flags = SOUP_TEST_REQUEST_CANCEL_MESSAGE | SOUP_TEST_REQUEST_CANCEL_IMMEDIATE; + do_request_with_cancel (session, base_uri, "GET", "/2", flags); + g_assert_cmpint (cancelled_requests, ==, 2); + soup_test_assert (last_request_unqueued, + "Cancelled request /2 not unqueued"); + + debug_printf (1, " Cancel a revalidating resource with g_cancellable_cancel()\n"); + flags = SOUP_TEST_REQUEST_CANCEL_CANCELLABLE | SOUP_TEST_REQUEST_CANCEL_IMMEDIATE; + do_request_with_cancel (session, base_uri, "GET", "/2", flags); + g_assert_cmpint (cancelled_requests, ==, 2); + soup_test_assert (last_request_unqueued, + "Cancelled request /2 not unqueued"); + + soup_test_session_abort_unref (session); + + g_object_unref (cache); + g_free (cache_dir); + g_free (body1); + g_free (body2); +} + +static gboolean +unref_stream (gpointer stream) +{ + g_object_unref (stream); + return FALSE; +} + +static void +base_stream_unreffed (gpointer loop, GObject *ex_base_stream) +{ + g_main_loop_quit (loop); +} + +static void +do_refcounting_test (gconstpointer data) +{ + SoupURI *base_uri = (SoupURI *)data; + SoupSession *session; + SoupCache *cache; + char *cache_dir; + SoupRequestHTTP *req; + GInputStream *stream, *base_stream; + SoupURI *uri; + GError *error = NULL; + guint flags; + GMainLoop *loop; + + g_test_bug ("682527"); + + cache_dir = g_dir_make_tmp ("cache-test-XXXXXX", NULL); + debug_printf (2, " Caching to %s\n", cache_dir); + cache = soup_cache_new (cache_dir, SOUP_CACHE_SINGLE_USER); + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, + SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, + SOUP_SESSION_ADD_FEATURE, cache, + NULL); + + last_request_validated = last_request_hit_network = FALSE; + cancelled_requests = 0; + + uri = soup_uri_new_with_base (base_uri, "/1"); + req = soup_session_request_http_uri (session, "GET", uri, NULL); + soup_uri_free (uri); + + flags = SOUP_TEST_REQUEST_CANCEL_AFTER_SEND_FINISH | SOUP_TEST_REQUEST_CANCEL_MESSAGE; + stream = soup_test_request_send (SOUP_REQUEST (req), NULL, flags, &error); + if (!stream) { + debug_printf (1, " could not send request: %s\n", + error->message); + g_error_free (error); + g_object_unref (req); + return; + } + g_object_unref (req); + + base_stream = g_filter_input_stream_get_base_stream (G_FILTER_INPUT_STREAM (stream)); + + debug_printf (1, " Checking that the base stream is properly unref'ed\n"); + loop = g_main_loop_new (NULL, FALSE); + g_object_weak_ref (G_OBJECT (base_stream), base_stream_unreffed, loop); + g_idle_add (unref_stream, stream); + g_main_loop_run (loop); + g_main_loop_unref (loop); + + soup_cache_flush ((SoupCache *)soup_session_get_feature (session, SOUP_TYPE_CACHE)); + + soup_test_session_abort_unref (session); + + g_object_unref (cache); + g_free (cache_dir); +} + +static void +do_headers_test (gconstpointer data) +{ + SoupURI *base_uri = (SoupURI *)data; + SoupSession *session; + SoupMessageHeaders *headers; + SoupCache *cache; + char *cache_dir; + char *body1, *cmp; + const char *header_value; + + cache_dir = g_dir_make_tmp ("cache-test-XXXXXX", NULL); + debug_printf (2, " Caching to %s\n", cache_dir); + cache = soup_cache_new (cache_dir, SOUP_CACHE_SINGLE_USER); + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, + SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, + SOUP_SESSION_ADD_FEATURE, cache, + NULL); + + g_signal_connect (session, "request-queued", + G_CALLBACK (request_queued), NULL); + + debug_printf (2, " Initial requests\n"); + body1 = do_request (session, base_uri, "GET", "/1", NULL, + "Test-Set-Last-Modified", "Fri, 01 Jan 2100 00:00:00 GMT", + "Test-Set-My-Header", "My header value", + NULL); + + /* My-Header new value should be updated in cache */ + debug_printf (2, " Fresh cached resource which updates My-Header\n"); + cmp = do_request (session, base_uri, "GET", "/1", NULL, + "Test-Set-Last-Modified", "Fri, 01 Jan 2010 00:00:00 GMT", + "Test-Set-My-Header", "My header NEW value", + NULL); + soup_test_assert (last_request_validated, + "Request for /1 not validated"); + soup_test_assert (!last_request_hit_network, + "Request for /1 not filled from cache"); + g_free (cmp); + + /* Check that cache returns the updated header */ + debug_printf (2, " Fresh cached resource with new value for My-Header\n"); + headers = soup_message_headers_new (SOUP_MESSAGE_HEADERS_RESPONSE); + cmp = do_request (session, base_uri, "GET", "/1", headers, + "Test-Set-Last-Modified", "Fri, 01 Jan 2010 00:00:00 GMT", + NULL); + soup_test_assert (!last_request_hit_network, + "Request for /1 not filled from cache"); + g_free (cmp); + + header_value = soup_message_headers_get_list (headers, "My-Header"); + g_assert_cmpstr (header_value, ==, "My header NEW value"); + soup_message_headers_free (headers); + + soup_test_session_abort_unref (session); + g_object_unref (cache); + + g_free (cache_dir); + g_free (body1); +} + +static guint +count_cached_resources_in_dir (const char *cache_dir) +{ + GDir *dir; + const char *name; + guint retval = 0; + + dir = g_dir_open (cache_dir, 0, NULL); + while ((name = g_dir_read_name (dir))) { + if (g_str_has_prefix (name, "soup.")) + continue; + + retval++; + } + g_dir_close (dir); + + return retval; +} + +static void +do_leaks_test (gconstpointer data) +{ + SoupURI *base_uri = (SoupURI *)data; + SoupSession *session; + SoupCache *cache; + char *cache_dir; + char *body; + + cache_dir = g_dir_make_tmp ("cache-test-XXXXXX", NULL); + debug_printf (2, " Caching to %s\n", cache_dir); + cache = soup_cache_new (cache_dir, SOUP_CACHE_SINGLE_USER); + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, + SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, + SOUP_SESSION_ADD_FEATURE, cache, + NULL); + + debug_printf (2, " Initial requests\n"); + body = do_request (session, base_uri, "GET", "/1", NULL, + "Test-Set-Expires", "Fri, 01 Jan 2100 00:00:00 GMT", + NULL); + g_free (body); + body = do_request (session, base_uri, "GET", "/2", NULL, + "Test-Set-Expires", "Fri, 01 Jan 2100 00:00:00 GMT", + NULL); + g_free (body); + body = do_request (session, base_uri, "GET", "/3", NULL, + "Test-Set-Expires", "Fri, 01 Jan 2100 00:00:00 GMT", + NULL); + g_free (body); + + debug_printf (2, " Dumping the cache\n"); + soup_cache_dump (cache); + + g_assert_cmpuint (count_cached_resources_in_dir (cache_dir), ==, 3); + + body = do_request (session, base_uri, "GET", "/4", NULL, + "Test-Set-Expires", "Fri, 01 Jan 2100 00:00:00 GMT", + NULL); + g_free (body); + body = do_request (session, base_uri, "GET", "/5", NULL, + "Test-Set-Expires", "Fri, 01 Jan 2100 00:00:00 GMT", + NULL); + g_free (body); + + /* Destroy the cache without dumping the last two resources */ + soup_test_session_abort_unref (session); + g_object_unref (cache); + + cache = soup_cache_new (cache_dir, SOUP_CACHE_SINGLE_USER); + + debug_printf (2, " Loading the cache\n"); + g_assert_cmpuint (count_cached_resources_in_dir (cache_dir), ==, 5); + soup_cache_load (cache); + g_assert_cmpuint (count_cached_resources_in_dir (cache_dir), ==, 3); + + g_object_unref (cache); + g_free (cache_dir); +} + +int +main (int argc, char **argv) +{ + SoupServer *server; + SoupURI *base_uri; + int ret; + + test_init (argc, argv, NULL); + + server = soup_test_server_new (TRUE); + soup_server_add_handler (server, NULL, server_callback, NULL, NULL); + base_uri = soup_test_server_get_uri (server, "http", NULL); + + g_test_add_data_func ("/cache/basics", base_uri, do_basics_test); + g_test_add_data_func ("/cache/cancellation", base_uri, do_cancel_test); + g_test_add_data_func ("/cache/refcounting", base_uri, do_refcounting_test); + g_test_add_data_func ("/cache/headers", base_uri, do_headers_test); + g_test_add_data_func ("/cache/leaks", base_uri, do_leaks_test); + + ret = g_test_run (); + + soup_uri_free (base_uri); + soup_test_server_quit_unref (server); + + test_cleanup (); + return ret; +} diff --git a/tests/chunk-io-test.c b/tests/chunk-io-test.c new file mode 100644 index 0000000..4746ea6 --- /dev/null +++ b/tests/chunk-io-test.c @@ -0,0 +1,606 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright 2013 Red Hat, Inc. + */ + +#include "test-utils.h" + +static void +force_io_streams_init (void) +{ + SoupServer *server; + SoupSession *session; + SoupURI *base_uri; + SoupMessage *msg; + + /* Poke libsoup enough to cause SoupBodyInputStream and + * SoupBodyOutputStream to get defined, so we can find them + * via g_type_from_name() later. + */ + + server = soup_test_server_new (TRUE); + base_uri = soup_test_server_get_uri (server, "http", NULL); + + session = soup_test_session_new (SOUP_TYPE_SESSION, NULL); + msg = soup_message_new_from_uri ("POST", base_uri); + soup_session_send_message (session, msg); + g_object_unref (msg); + soup_test_session_abort_unref (session); + + soup_uri_free (base_uri); + soup_test_server_quit_unref (server); +} + +typedef struct { + GFilterInputStream grandparent; + + gpointer *soup_filter_input_stream_private; + + gboolean is_readable; +} SlowInputStream; + +typedef struct { + GFilterInputStreamClass grandparent; +} SlowInputStreamClass; + +GType slow_input_stream_get_type (void); +static void slow_pollable_input_stream_init (GPollableInputStreamInterface *pollable_interface, + gpointer interface_data); + +G_DEFINE_TYPE_WITH_CODE (SlowInputStream, slow_input_stream, + g_type_from_name ("SoupFilterInputStream"), + G_IMPLEMENT_INTERFACE (G_TYPE_POLLABLE_INPUT_STREAM, slow_pollable_input_stream_init); + ) + +static void +slow_input_stream_init (SlowInputStream *sis) +{ +} + +static gssize +slow_input_stream_read (GInputStream *stream, + void *buffer, + gsize count, + GCancellable *cancellable, + GError **error) +{ + return g_input_stream_read (G_FILTER_INPUT_STREAM (stream)->base_stream, + buffer, 1, cancellable, error); +} + +static void +slow_input_stream_class_init (SlowInputStreamClass *sisclass) +{ + GInputStreamClass *input_stream_class = G_INPUT_STREAM_CLASS (sisclass); + + input_stream_class->read_fn = slow_input_stream_read; +} + +static gboolean +slow_input_stream_is_readable (GPollableInputStream *stream) +{ + return ((SlowInputStream *)stream)->is_readable; +} + +static gssize +slow_input_stream_read_nonblocking (GPollableInputStream *stream, + void *buffer, + gsize count, + GError **error) +{ + if (((SlowInputStream *)stream)->is_readable) { + ((SlowInputStream *)stream)->is_readable = FALSE; + return slow_input_stream_read (G_INPUT_STREAM (stream), buffer, count, + NULL, error); + } else { + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK, + "would block"); + return -1; + } +} + +static GSource * +slow_input_stream_create_source (GPollableInputStream *stream, + GCancellable *cancellable) +{ + GSource *base_source, *pollable_source; + + ((SlowInputStream *)stream)->is_readable = TRUE; + base_source = g_timeout_source_new (0); + g_source_set_dummy_callback (base_source); + + pollable_source = g_pollable_source_new (G_OBJECT (stream)); + g_source_add_child_source (pollable_source, base_source); + g_source_unref (base_source); + + return pollable_source; +} + +static void +slow_pollable_input_stream_init (GPollableInputStreamInterface *pollable_interface, + gpointer interface_data) +{ + pollable_interface->is_readable = slow_input_stream_is_readable; + pollable_interface->read_nonblocking = slow_input_stream_read_nonblocking; + pollable_interface->create_source = slow_input_stream_create_source; +} + +typedef struct { + GFilterOutputStream parent; + + gboolean is_writable; +} SlowOutputStream; + +typedef struct { + GFilterOutputStreamClass parent; +} SlowOutputStreamClass; + +GType slow_output_stream_get_type (void); + +static void slow_pollable_output_stream_init (GPollableOutputStreamInterface *pollable_interface, + gpointer interface_data); + +G_DEFINE_TYPE_WITH_CODE (SlowOutputStream, slow_output_stream, + g_type_from_name ("GFilterOutputStream"), + G_IMPLEMENT_INTERFACE (G_TYPE_POLLABLE_OUTPUT_STREAM, slow_pollable_output_stream_init); + ) + +static void +slow_output_stream_init (SlowOutputStream *sis) +{ +} + +static gssize +slow_output_stream_write (GOutputStream *stream, + const void *buffer, + gsize count, + GCancellable *cancellable, + GError **error) +{ + return g_output_stream_write (G_FILTER_OUTPUT_STREAM (stream)->base_stream, + buffer, 1, cancellable, error); +} + +static void +slow_output_stream_class_init (SlowOutputStreamClass *sisclass) +{ + GOutputStreamClass *output_stream_class = G_OUTPUT_STREAM_CLASS (sisclass); + + output_stream_class->write_fn = slow_output_stream_write; +} + +static gboolean +slow_output_stream_is_writable (GPollableOutputStream *stream) +{ + return ((SlowOutputStream *)stream)->is_writable; +} + +static gssize +slow_output_stream_write_nonblocking (GPollableOutputStream *stream, + const void *buffer, + gsize count, + GError **error) +{ + if (((SlowOutputStream *)stream)->is_writable) { + ((SlowOutputStream *)stream)->is_writable = FALSE; + return slow_output_stream_write (G_OUTPUT_STREAM (stream), buffer, count, + NULL, error); + } else { + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK, + "would block"); + return -1; + } +} + +static GSource * +slow_output_stream_create_source (GPollableOutputStream *stream, + GCancellable *cancellable) +{ + GSource *base_source, *pollable_source; + + ((SlowOutputStream *)stream)->is_writable = TRUE; + base_source = g_timeout_source_new (0); + g_source_set_dummy_callback (base_source); + + pollable_source = g_pollable_source_new (G_OBJECT (stream)); + g_source_add_child_source (pollable_source, base_source); + g_source_unref (base_source); + + return pollable_source; +} + +static void +slow_pollable_output_stream_init (GPollableOutputStreamInterface *pollable_interface, + gpointer interface_data) +{ + pollable_interface->is_writable = slow_output_stream_is_writable; + pollable_interface->write_nonblocking = slow_output_stream_write_nonblocking; + pollable_interface->create_source = slow_output_stream_create_source; +} + +typedef struct { + GFilterOutputStream parent; + + gboolean is_broken; +} BreakingOutputStream; + +typedef struct { + GFilterOutputStreamClass parent; +} BreakingOutputStreamClass; + +GType breaking_output_stream_get_type (void); + +static void breaking_pollable_output_stream_init (GPollableOutputStreamInterface *pollable_interface, + gpointer interface_data); + +G_DEFINE_TYPE_WITH_CODE (BreakingOutputStream, breaking_output_stream, + g_type_from_name ("GFilterOutputStream"), + G_IMPLEMENT_INTERFACE (G_TYPE_POLLABLE_OUTPUT_STREAM, breaking_pollable_output_stream_init); + ) + +static void +breaking_output_stream_init (BreakingOutputStream *sis) +{ +} + +static gssize +breaking_output_stream_write (GOutputStream *stream, + const void *buffer, + gsize count, + GCancellable *cancellable, + GError **error) +{ + if (((BreakingOutputStream *)stream)->is_broken) { + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, "failed"); + return -1; + } + + if (count > 128) { + ((BreakingOutputStream *)stream)->is_broken = TRUE; + count /= 2; + } + return g_output_stream_write (G_FILTER_OUTPUT_STREAM (stream)->base_stream, + buffer, count, cancellable, error); +} + +static void +breaking_output_stream_class_init (BreakingOutputStreamClass *sisclass) +{ + GOutputStreamClass *output_stream_class = G_OUTPUT_STREAM_CLASS (sisclass); + + output_stream_class->write_fn = breaking_output_stream_write; +} + +static gboolean +breaking_output_stream_is_writable (GPollableOutputStream *stream) +{ + return TRUE; +} + +static gssize +breaking_output_stream_write_nonblocking (GPollableOutputStream *stream, + const void *buffer, + gsize count, + GError **error) +{ + if (((BreakingOutputStream *)stream)->is_broken) { + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, "failed"); + return -1; + } + + if (count > 128) { + ((BreakingOutputStream *)stream)->is_broken = TRUE; + count /= 2; + } + return g_pollable_output_stream_write_nonblocking (G_POLLABLE_OUTPUT_STREAM (G_FILTER_OUTPUT_STREAM (stream)->base_stream), + buffer, count, NULL, error); +} + +static GSource * +breaking_output_stream_create_source (GPollableOutputStream *stream, + GCancellable *cancellable) +{ + GSource *base_source, *pollable_source; + + base_source = g_timeout_source_new (0); + g_source_set_dummy_callback (base_source); + + pollable_source = g_pollable_source_new (G_OBJECT (stream)); + g_source_add_child_source (pollable_source, base_source); + g_source_unref (base_source); + + return pollable_source; +} + +static void +breaking_pollable_output_stream_init (GPollableOutputStreamInterface *pollable_interface, + gpointer interface_data) +{ + pollable_interface->is_writable = breaking_output_stream_is_writable; + pollable_interface->write_nonblocking = breaking_output_stream_write_nonblocking; + pollable_interface->create_source = breaking_output_stream_create_source; +} + +#define CHUNK_SIZE 1024 + +static GString * +chunkify (const char *str, gsize length) +{ + GString *gstr; + int i, size; + + gstr = g_string_new (NULL); + for (i = 0; i < length; i += CHUNK_SIZE) { + size = MIN (CHUNK_SIZE, length - i); + g_string_append_printf (gstr, "%x\r\n", size); + g_string_append_len (gstr, str + i, size); + g_string_append (gstr, "\r\n"); + } + g_string_append (gstr, "0\r\n\r\n"); + + return gstr; +} + +static void +do_io_tests (void) +{ + GInputStream *imem, *islow, *in; + GOutputStream *omem, *oslow, *out; + GMemoryOutputStream *mem; + SoupBuffer *raw_contents; + char *buf; + GString *chunkified; + GError *error = NULL; + gssize nread, nwrote, total; + gssize chunk_length, chunk_total; + + raw_contents = soup_test_get_index (); + chunkified = chunkify (raw_contents->data, raw_contents->length); + + debug_printf (1, " sync read\n"); + + imem = g_memory_input_stream_new_from_data (chunkified->str, chunkified->len, NULL); + islow = g_object_new (slow_input_stream_get_type (), + "base-stream", imem, + "close-base-stream", TRUE, + NULL); + in = g_object_new (g_type_from_name ("SoupBodyInputStream"), + "base-stream", islow, + "close-base-stream", TRUE, + "encoding", SOUP_ENCODING_CHUNKED, + NULL); + g_object_unref (imem); + g_object_unref (islow); + + buf = g_malloc (raw_contents->length); + total = 0; + while (TRUE) { + nread = g_input_stream_read (in, buf + total, + raw_contents->length - total, + NULL, &error); + g_assert_no_error (error); + g_clear_error (&error); + if (nread > 0) + total += nread; + else + break; + } + + g_input_stream_close (in, NULL, &error); + g_assert_no_error (error); + g_clear_error (&error); + g_object_unref (in); + + soup_assert_cmpmem (buf, total, raw_contents->data, raw_contents->length); + g_free (buf); + + debug_printf (1, " async read\n"); + + imem = g_memory_input_stream_new_from_data (chunkified->str, chunkified->len, NULL); + islow = g_object_new (slow_input_stream_get_type (), + "base-stream", imem, + "close-base-stream", TRUE, + NULL); + in = g_object_new (g_type_from_name ("SoupBodyInputStream"), + "base-stream", islow, + "close-base-stream", TRUE, + "encoding", SOUP_ENCODING_CHUNKED, + NULL); + g_object_unref (imem); + g_object_unref (islow); + + buf = g_malloc (raw_contents->length); + total = 0; + while (TRUE) { + nread = g_pollable_input_stream_read_nonblocking (G_POLLABLE_INPUT_STREAM (in), + buf + total, + raw_contents->length - total, + NULL, &error); + if (nread == -1 && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) { + GSource *source; + + g_clear_error (&error); + source = g_pollable_input_stream_create_source (G_POLLABLE_INPUT_STREAM (in), NULL); + g_source_set_dummy_callback (source); + g_source_attach (source, NULL); + while (!g_pollable_input_stream_is_readable (G_POLLABLE_INPUT_STREAM (in))) + g_main_context_iteration (NULL, TRUE); + g_source_destroy (source); + g_source_unref (source); + continue; + } else if (nread == -1) { + g_assert_no_error (error); + g_clear_error (&error); + break; + } else if (nread == 0) + break; + else + total += nread; + } + + g_input_stream_close (in, NULL, &error); + g_assert_no_error (error); + g_clear_error (&error); + g_object_unref (in); + + soup_assert_cmpmem (buf, total, raw_contents->data, raw_contents->length); + g_free (buf); + + debug_printf (1, " sync write\n"); + + buf = g_malloc (chunkified->len); + omem = g_memory_output_stream_new (buf, chunkified->len, NULL, NULL); + oslow = g_object_new (slow_output_stream_get_type (), + "base-stream", omem, + "close-base-stream", TRUE, + NULL); + out = g_object_new (g_type_from_name ("SoupBodyOutputStream"), + "base-stream", oslow, + "close-base-stream", TRUE, + "encoding", SOUP_ENCODING_CHUNKED, + NULL); + g_object_unref (omem); + g_object_unref (oslow); + + total = chunk_length = chunk_total = 0; + while (total < raw_contents->length) { + if (chunk_total == chunk_length) { + chunk_length = MIN (CHUNK_SIZE, raw_contents->length - total); + chunk_total = 0; + } + nwrote = g_output_stream_write (out, raw_contents->data + total, + chunk_length - chunk_total, NULL, &error); + g_assert_no_error (error); + g_clear_error (&error); + if (nwrote > 0) { + total += nwrote; + chunk_total += nwrote; + } else + break; + } + + g_output_stream_close (out, NULL, &error); + g_assert_no_error (error); + g_clear_error (&error); + + mem = G_MEMORY_OUTPUT_STREAM (omem); + soup_assert_cmpmem (g_memory_output_stream_get_data (mem), + g_memory_output_stream_get_data_size (mem), + chunkified->str, chunkified->len); + + g_object_unref (out); + g_free (buf); + + debug_printf (1, " async write\n"); + + buf = g_malloc (chunkified->len); + omem = g_memory_output_stream_new (buf, chunkified->len, NULL, NULL); + oslow = g_object_new (slow_output_stream_get_type (), + "base-stream", omem, + "close-base-stream", TRUE, + NULL); + out = g_object_new (g_type_from_name ("SoupBodyOutputStream"), + "base-stream", oslow, + "close-base-stream", TRUE, + "encoding", SOUP_ENCODING_CHUNKED, + NULL); + g_object_unref (omem); + g_object_unref (oslow); + + total = chunk_length = chunk_total = 0; + while (total < raw_contents->length) { + if (chunk_total == chunk_length) { + chunk_length = MIN (CHUNK_SIZE, raw_contents->length - total); + chunk_total = 0; + } + nwrote = g_pollable_output_stream_write_nonblocking (G_POLLABLE_OUTPUT_STREAM (out), + raw_contents->data + total, + chunk_length - chunk_total, + NULL, &error); + if (nwrote == -1 && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) { + GSource *source; + + g_clear_error (&error); + source = g_pollable_output_stream_create_source (G_POLLABLE_OUTPUT_STREAM (out), NULL); + g_source_set_dummy_callback (source); + g_source_attach (source, NULL); + while (!g_pollable_output_stream_is_writable (G_POLLABLE_OUTPUT_STREAM (out))) + g_main_context_iteration (NULL, TRUE); + g_source_destroy (source); + g_source_unref (source); + continue; + } else if (nwrote == -1) { + g_assert_no_error (error); + g_clear_error (&error); + break; + } else { + total += nwrote; + chunk_total += nwrote; + } + } + + g_output_stream_close (out, NULL, &error); + g_assert_no_error (error); + g_clear_error (&error); + + mem = G_MEMORY_OUTPUT_STREAM (omem); + soup_assert_cmpmem (g_memory_output_stream_get_data (mem), + g_memory_output_stream_get_data_size (mem), + chunkified->str, chunkified->len); + + g_object_unref (out); + g_free (buf); + + debug_printf (1, " failed write\n"); + /* this succeeds if it doesn't critical */ + + buf = g_malloc (chunkified->len); + omem = g_memory_output_stream_new (buf, chunkified->len, NULL, NULL); + oslow = g_object_new (breaking_output_stream_get_type (), + "base-stream", omem, + "close-base-stream", TRUE, + NULL); + out = g_object_new (g_type_from_name ("SoupBodyOutputStream"), + "base-stream", oslow, + "close-base-stream", TRUE, + "encoding", SOUP_ENCODING_CHUNKED, + NULL); + g_object_unref (omem); + g_object_unref (oslow); + + total = 0; + while (total < raw_contents->length) { + nwrote = g_output_stream_write (out, raw_contents->data + total, + raw_contents->length - total, NULL, NULL); + if (nwrote == -1) + break; + else + total += nwrote; + } + + g_assert_cmpint (total, !=, raw_contents->length); + + g_output_stream_close (out, NULL, NULL); + g_object_unref (out); + + g_free (buf); + + g_string_free (chunkified, TRUE); +} + +int +main (int argc, char **argv) +{ + int ret; + + test_init (argc, argv, NULL); + + force_io_streams_init (); + + g_test_add_func ("/chunk-io", do_io_tests); + + ret = g_test_run (); + + test_cleanup (); + return ret; +} diff --git a/tests/chunk-test.c b/tests/chunk-test.c new file mode 100644 index 0000000..c658cbd --- /dev/null +++ b/tests/chunk-test.c @@ -0,0 +1,464 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2008 Red Hat, Inc. + */ + +#include "test-utils.h" + +static SoupSession *session; +static SoupURI *base_uri; + +typedef struct { + SoupSession *session; + SoupBuffer *chunks[3]; + int next, nwrote, nfreed; + gboolean streaming; +} PutTestData; + +static void +write_next_chunk (SoupMessage *msg, gpointer user_data) +{ + PutTestData *ptd = user_data; + + debug_printf (2, " writing chunk %d\n", ptd->next); + + if (ptd->streaming && ptd->next > 0) { + soup_test_assert (ptd->chunks[ptd->next - 1] == NULL, + "next chunk requested before last one freed"); + } + + if (ptd->next < G_N_ELEMENTS (ptd->chunks)) { + soup_message_body_append_buffer (msg->request_body, + ptd->chunks[ptd->next]); + soup_buffer_free (ptd->chunks[ptd->next]); + ptd->next++; + } else + soup_message_body_complete (msg->request_body); + soup_session_unpause_message (ptd->session, msg); +} + +/* This is not a supported part of the API. Use SOUP_MESSAGE_CAN_REBUILD + * instead. + */ +static void +write_next_chunk_streaming_hack (SoupMessage *msg, gpointer user_data) +{ + PutTestData *ptd = user_data; + SoupBuffer *chunk; + + debug_printf (2, " freeing chunk at %d\n", ptd->nfreed); + chunk = soup_message_body_get_chunk (msg->request_body, ptd->nfreed); + if (chunk) { + ptd->nfreed += chunk->length; + soup_message_body_wrote_chunk (msg->request_body, chunk); + soup_buffer_free (chunk); + } else { + soup_test_assert (chunk, + "written chunk does not exist"); + } + write_next_chunk (msg, user_data); +} + +static void +wrote_body_data (SoupMessage *msg, SoupBuffer *chunk, gpointer user_data) +{ + PutTestData *ptd = user_data; + + debug_printf (2, " wrote_body_data, %d bytes\n", + (int)chunk->length); + ptd->nwrote += chunk->length; +} + +static void +clear_buffer_ptr (gpointer data) +{ + SoupBuffer **buffer_ptr = data; + + debug_printf (2, " clearing chunk\n"); + if (*buffer_ptr) { + (*buffer_ptr)->length = 0; + g_free ((char *)(*buffer_ptr)->data); + *buffer_ptr = NULL; + } else { + soup_test_assert (*buffer_ptr, + "chunk is already clear"); + } +} + +/* Put a chunk containing @text into *@buffer, set up so that it will + * clear out *@buffer when the chunk is freed, allowing us to make sure + * the set_accumulate(FALSE) is working. + */ +static void +make_put_chunk (SoupBuffer **buffer, const char *text) +{ + *buffer = soup_buffer_new_with_owner (g_strdup (text), strlen (text), + buffer, clear_buffer_ptr); +} + +static void +setup_request_body (PutTestData *ptd) +{ + make_put_chunk (&ptd->chunks[0], "one\r\n"); + make_put_chunk (&ptd->chunks[1], "two\r\n"); + make_put_chunk (&ptd->chunks[2], "three\r\n"); + ptd->next = ptd->nwrote = ptd->nfreed = 0; +} + +static void +restarted_streaming (SoupMessage *msg, gpointer user_data) +{ + PutTestData *ptd = user_data; + + debug_printf (2, " --restarting--\n"); + + /* We're streaming, and we had to restart. So the data need + * to be regenerated. + */ + setup_request_body (ptd); + + /* The 302 redirect will turn it into a GET request and + * reset the body encoding back to "NONE". Fix that. + */ + soup_message_headers_set_encoding (msg->request_headers, + SOUP_ENCODING_CHUNKED); + msg->method = SOUP_METHOD_PUT; +} + +static void +restarted_streaming_hack (SoupMessage *msg, gpointer user_data) +{ + restarted_streaming (msg, user_data); + soup_message_body_truncate (msg->request_body); +} + +typedef enum { + HACKY_STREAMING = (1 << 0), + PROPER_STREAMING = (1 << 1), + RESTART = (1 << 2) +} RequestTestFlags; + +static void +do_request_test (gconstpointer data) +{ + RequestTestFlags flags = GPOINTER_TO_UINT (data); + SoupURI *uri; + PutTestData ptd; + SoupMessage *msg; + const char *client_md5, *server_md5; + GChecksum *check; + int i, length; + + if (flags & RESTART) + uri = soup_uri_new_with_base (base_uri, "/redirect"); + else + uri = soup_uri_copy (base_uri); + + ptd.session = session; + setup_request_body (&ptd); + ptd.streaming = flags & (HACKY_STREAMING | PROPER_STREAMING); + + check = g_checksum_new (G_CHECKSUM_MD5); + length = 0; + for (i = 0; i < 3; i++) { + g_checksum_update (check, (guchar *)ptd.chunks[i]->data, + ptd.chunks[i]->length); + length += ptd.chunks[i]->length; + } + client_md5 = g_checksum_get_string (check); + + msg = soup_message_new_from_uri ("PUT", uri); + soup_message_headers_set_encoding (msg->request_headers, SOUP_ENCODING_CHUNKED); + soup_message_body_set_accumulate (msg->request_body, FALSE); + if (flags & HACKY_STREAMING) { + g_signal_connect (msg, "wrote_chunk", + G_CALLBACK (write_next_chunk_streaming_hack), &ptd); + if (flags & RESTART) { + g_signal_connect (msg, "restarted", + G_CALLBACK (restarted_streaming_hack), &ptd); + } + } else { + g_signal_connect (msg, "wrote_chunk", + G_CALLBACK (write_next_chunk), &ptd); + } + + if (flags & PROPER_STREAMING) { + soup_message_set_flags (msg, SOUP_MESSAGE_CAN_REBUILD); + if (flags & RESTART) { + g_signal_connect (msg, "restarted", + G_CALLBACK (restarted_streaming), &ptd); + } + } + + g_signal_connect (msg, "wrote_headers", + G_CALLBACK (write_next_chunk), &ptd); + g_signal_connect (msg, "wrote_body_data", + G_CALLBACK (wrote_body_data), &ptd); + soup_session_send_message (session, msg); + + soup_test_assert_message_status (msg, SOUP_STATUS_CREATED); + g_assert_null (msg->request_body->data); + g_assert_cmpint (msg->request_body->length, ==, length); + g_assert_cmpint (length, ==, ptd.nwrote); + + server_md5 = soup_message_headers_get_one (msg->response_headers, + "Content-MD5"); + g_assert_cmpstr (client_md5, ==, server_md5); + + g_object_unref (msg); + g_checksum_free (check); + + soup_uri_free (uri); +} + +typedef struct { + SoupBuffer *current_chunk; + GChecksum *check; + int length; +} GetTestData; + +static SoupBuffer * +chunk_allocator (SoupMessage *msg, gsize max_len, gpointer user_data) +{ + GetTestData *gtd = user_data; + + debug_printf (2, " allocating chunk\n"); + + soup_test_assert (gtd->current_chunk == NULL, + "error: next chunk allocated before last one freed"); + gtd->current_chunk = soup_buffer_new_with_owner (g_malloc (6), 6, + >d->current_chunk, + clear_buffer_ptr); + return gtd->current_chunk; +} + +static void +got_chunk (SoupMessage *msg, SoupBuffer *chunk, gpointer user_data) +{ + GetTestData *gtd = user_data; + + debug_printf (2, " got chunk, %d bytes\n", + (int)chunk->length); + if (chunk != gtd->current_chunk) { + debug_printf (1, "chunk mismatch! %p vs %p\n", + chunk, gtd->current_chunk); + } + + g_checksum_update (gtd->check, (guchar *)chunk->data, chunk->length); + gtd->length += chunk->length; +} + +static void +do_response_test (void) +{ + GetTestData gtd; + SoupMessage *msg; + const char *client_md5, *server_md5; + + gtd.current_chunk = NULL; + gtd.length = 0; + gtd.check = g_checksum_new (G_CHECKSUM_MD5); + + msg = soup_message_new_from_uri ("GET", base_uri); + soup_message_body_set_accumulate (msg->response_body, FALSE); + G_GNUC_BEGIN_IGNORE_DEPRECATIONS; + soup_message_set_chunk_allocator (msg, chunk_allocator, >d, NULL); + G_GNUC_END_IGNORE_DEPRECATIONS; + g_signal_connect (msg, "got_chunk", + G_CALLBACK (got_chunk), >d); + soup_session_send_message (session, msg); + + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + g_assert_null (msg->response_body->data); + g_assert_cmpint (soup_message_headers_get_content_length (msg->response_headers), ==, gtd.length); + + client_md5 = g_checksum_get_string (gtd.check); + server_md5 = soup_message_headers_get_one (msg->response_headers, + "Content-MD5"); + g_assert_cmpstr (client_md5, ==, server_md5); + + g_object_unref (msg); + g_checksum_free (gtd.check); +} + +/* Make sure TEMPORARY buffers are handled properly with non-accumulating + * message bodies. + */ + +static void +temp_test_wrote_chunk (SoupMessage *msg, gpointer session) +{ + SoupBuffer *chunk; + + chunk = soup_message_body_get_chunk (msg->request_body, 5); + + /* When the bug is present, the second chunk will also be + * discarded after the first is written, which will cause + * the I/O to stall since soup-message-io will think it's + * done, but it hasn't written Content-Length bytes yet. + */ + if (chunk) + soup_buffer_free (chunk); + else { + soup_test_assert (chunk, "Lost second chunk"); + soup_session_abort (session); + } + + g_signal_handlers_disconnect_by_func (msg, temp_test_wrote_chunk, session); +} + +static void +do_temporary_test (void) +{ + SoupMessage *msg; + char *client_md5; + const char *server_md5; + + g_test_bug_base ("https://bugs.webkit.org/"); + g_test_bug ("18343"); + + msg = soup_message_new_from_uri ("PUT", base_uri); + soup_message_body_append (msg->request_body, SOUP_MEMORY_TEMPORARY, + "one\r\n", 5); + soup_message_body_append (msg->request_body, SOUP_MEMORY_STATIC, + "two\r\n", 5); + soup_message_body_set_accumulate (msg->request_body, FALSE); + + client_md5 = g_compute_checksum_for_string (G_CHECKSUM_MD5, + "one\r\ntwo\r\n", 10); + g_signal_connect (msg, "wrote_chunk", + G_CALLBACK (temp_test_wrote_chunk), session); + soup_session_send_message (session, msg); + + soup_test_assert_message_status (msg, SOUP_STATUS_CREATED); + + server_md5 = soup_message_headers_get_one (msg->response_headers, + "Content-MD5"); + g_assert_cmpstr (client_md5, ==, server_md5); + + g_free (client_md5); + g_object_unref (msg); +} + +#define LARGE_CHUNK_SIZE 1000000 + +typedef struct { + SoupBuffer *buf; + gsize offset; +} LargeChunkData; + +static void +large_wrote_body_data (SoupMessage *msg, SoupBuffer *chunk, gpointer user_data) +{ + LargeChunkData *lcd = user_data; + + soup_assert_cmpmem (chunk->data, chunk->length, + lcd->buf->data + lcd->offset, + chunk->length); + lcd->offset += chunk->length; +} + +static void +do_large_chunk_test (void) +{ + SoupMessage *msg; + char *buf_data; + int i; + LargeChunkData lcd; + + msg = soup_message_new_from_uri ("PUT", base_uri); + + buf_data = g_malloc0 (LARGE_CHUNK_SIZE); + for (i = 0; i < LARGE_CHUNK_SIZE; i++) + buf_data[i] = i & 0xFF; + lcd.buf = soup_buffer_new (SOUP_MEMORY_TAKE, buf_data, LARGE_CHUNK_SIZE); + lcd.offset = 0; + soup_message_body_append_buffer (msg->request_body, lcd.buf); + soup_message_body_set_accumulate (msg->request_body, FALSE); + + g_signal_connect (msg, "wrote_body_data", + G_CALLBACK (large_wrote_body_data), &lcd); + soup_session_send_message (session, msg); + + soup_test_assert_message_status (msg, SOUP_STATUS_CREATED); + + soup_buffer_free (lcd.buf); + g_object_unref (msg); +} + +static void +server_callback (SoupServer *server, SoupMessage *msg, + const char *path, GHashTable *query, + SoupClientContext *context, gpointer data) +{ + SoupMessageBody *md5_body; + char *md5; + + if (g_str_has_prefix (path, "/redirect")) { + soup_message_set_redirect (msg, SOUP_STATUS_FOUND, "/"); + return; + } + + if (msg->method == SOUP_METHOD_GET) { + soup_message_set_response (msg, "text/plain", + SOUP_MEMORY_STATIC, + "three\r\ntwo\r\none\r\n", + strlen ("three\r\ntwo\r\none\r\n")); + soup_buffer_free (soup_message_body_flatten (msg->response_body)); + md5_body = msg->response_body; + soup_message_set_status (msg, SOUP_STATUS_OK); + } else if (msg->method == SOUP_METHOD_PUT) { + soup_message_set_status (msg, SOUP_STATUS_CREATED); + md5_body = msg->request_body; + } else { + soup_message_set_status (msg, SOUP_STATUS_METHOD_NOT_ALLOWED); + return; + } + + md5 = g_compute_checksum_for_data (G_CHECKSUM_MD5, + (guchar *)md5_body->data, + md5_body->length); + soup_message_headers_append (msg->response_headers, + "Content-MD5", md5); + g_free (md5); +} + +int +main (int argc, char **argv) +{ + GMainLoop *loop; + SoupServer *server; + int ret; + + test_init (argc, argv, NULL); + + server = soup_test_server_new (SOUP_TEST_SERVER_IN_THREAD); + soup_server_add_handler (server, NULL, + server_callback, NULL, NULL); + + loop = g_main_loop_new (NULL, TRUE); + + base_uri = soup_test_server_get_uri (server, "http", NULL); + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + + g_test_add_data_func ("/chunks/request/unstreamed", GINT_TO_POINTER (0), do_request_test); + g_test_add_data_func ("/chunks/request/proper-streaming", GINT_TO_POINTER (PROPER_STREAMING), do_request_test); + g_test_add_data_func ("/chunks/request/proper-streaming/restart", GINT_TO_POINTER (PROPER_STREAMING | RESTART), do_request_test); + g_test_add_data_func ("/chunks/request/hacky-streaming", GINT_TO_POINTER (HACKY_STREAMING), do_request_test); + g_test_add_data_func ("/chunks/request/hacky-streaming/restart", GINT_TO_POINTER (HACKY_STREAMING | RESTART), do_request_test); + g_test_add_func ("/chunks/response", do_response_test); + g_test_add_func ("/chunks/temporary", do_temporary_test); + g_test_add_func ("/chunks/large", do_large_chunk_test); + + ret = g_test_run (); + + soup_test_session_abort_unref (session); + + soup_uri_free (base_uri); + + g_main_loop_unref (loop); + soup_test_server_quit_unref (server); + + test_cleanup (); + return ret; +} diff --git a/tests/coding-test.c b/tests/coding-test.c new file mode 100644 index 0000000..de2949b --- /dev/null +++ b/tests/coding-test.c @@ -0,0 +1,563 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2007 Red Hat, Inc. + * Copyright (C) 2011 Igalia, S.L. + */ + +#include "test-utils.h" + +SoupServer *server; +SoupURI *base_uri; + +static void +server_callback (SoupServer *server, SoupMessage *msg, + const char *path, GHashTable *query, + SoupClientContext *context, gpointer data) +{ + const char *accept_encoding, *options; + GSList *codings; + SoupBuffer *response = NULL; + + options = soup_message_headers_get_one (msg->request_headers, + "X-Test-Options"); + if (!options) + options = ""; + + accept_encoding = soup_message_headers_get_list (msg->request_headers, + "Accept-Encoding"); + if (accept_encoding && !soup_header_contains (options, "force-encode")) + codings = soup_header_parse_quality_list (accept_encoding, NULL); + else + codings = NULL; + + if (codings) { + gboolean claim_deflate, claim_gzip; + const char *extension = NULL, *encoding = NULL; + + claim_deflate = g_slist_find_custom (codings, "deflate", (GCompareFunc)g_ascii_strcasecmp) != NULL; + claim_gzip = g_slist_find_custom (codings, "gzip", (GCompareFunc)g_ascii_strcasecmp) != NULL; + + if (claim_gzip && (!claim_deflate || + (!soup_header_contains (options, "prefer-deflate-zlib") && + !soup_header_contains (options, "prefer-deflate-raw")))) { + extension = "gz"; + encoding = "gzip"; + } else if (claim_deflate) { + if (soup_header_contains (options, "prefer-deflate-raw")) { + extension = "raw"; + encoding = "deflate"; + } else { + extension = "zlib"; + encoding = "deflate"; + } + } + if (extension && encoding) { + char *resource; + + resource = g_strdup_printf ("%s.%s", path, extension); + response = soup_test_load_resource (resource, NULL); + + if (response) { + soup_message_headers_append (msg->response_headers, + "Content-Encoding", + encoding); + } + g_free (resource); + } + } + + soup_header_free_list (codings); + + if (!response) + response = soup_test_load_resource (path, NULL); + if (!response) { + /* If path.gz exists but can't be read, we'll send back + * the error with "Content-Encoding: gzip" but there's + * no body, so, eh. + */ + soup_message_set_status (msg, SOUP_STATUS_NOT_FOUND); + return; + } + + if (soup_header_contains (options, "force-encode")) { + const gchar *encoding = "gzip"; + + if (soup_header_contains (options, "prefer-deflate-zlib") || + soup_header_contains (options, "prefer-deflate-raw")) + encoding = "deflate"; + + soup_message_headers_replace (msg->response_headers, + "Content-Encoding", + encoding); + } + + /* Content-Type matches the "real" format, not the sent format */ + if (g_str_has_suffix (path, ".gz")) { + soup_message_headers_append (msg->response_headers, + "Content-Type", + "application/gzip"); + } else { + soup_message_headers_append (msg->response_headers, + "Content-Type", + "text/plain"); + } + + soup_message_set_status (msg, SOUP_STATUS_OK); + soup_message_headers_set_encoding (msg->response_headers, SOUP_ENCODING_CHUNKED); + + if (!soup_header_contains (options, "empty")) + soup_message_body_append_buffer (msg->response_body, response); + soup_buffer_free (response); + + if (soup_header_contains (options, "trailing-junk")) { + soup_message_body_append (msg->response_body, SOUP_MEMORY_COPY, + options, strlen (options)); + } + soup_message_body_complete (msg->response_body); +} + +typedef struct { + SoupSession *session; + SoupMessage *msg; + SoupRequest *req; + SoupBuffer *response; +} CodingTestData; + +typedef enum { + CODING_TEST_DEFAULT = 0, + CODING_TEST_NO_DECODER = (1 << 0), + CODING_TEST_REQUEST_API = (1 << 1), + CODING_TEST_EMPTY = (1 << 2) +} CodingTestType; + +typedef enum { + NO_CHECK, + EXPECT_DECODED, + EXPECT_NOT_DECODED +} MessageContentStatus; + +static void +check_response (CodingTestData *data, + const char *expected_encoding, + const char *expected_content_type, + MessageContentStatus status, + GByteArray *body) +{ + const char *coding, *type; + + soup_test_assert_message_status (data->msg, SOUP_STATUS_OK); + + coding = soup_message_headers_get_one (data->msg->response_headers, "Content-Encoding"); + g_assert_cmpstr (coding, ==, expected_encoding); + + if (status != NO_CHECK) { + if (status == EXPECT_DECODED) + g_assert_true (soup_message_get_flags (data->msg) & SOUP_MESSAGE_CONTENT_DECODED); + else + g_assert_false (soup_message_get_flags (data->msg) & SOUP_MESSAGE_CONTENT_DECODED); + } + + type = soup_message_headers_get_one (data->msg->response_headers, "Content-Type"); + g_assert_cmpstr (type, ==, expected_content_type); + + if (body) { + soup_assert_cmpmem (body->data, + body->len, + data->response->data, + data->response->length); + } else { + soup_assert_cmpmem (data->msg->response_body->data, + data->msg->response_body->length, + data->response->data, + data->response->length); + } +} + +static void +setup_coding_test (CodingTestData *data, gconstpointer test_data) +{ + CodingTestType test_type = GPOINTER_TO_INT (test_data); + SoupMessage *msg; + SoupURI *uri; + + data->session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, + SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, + NULL); + + uri = soup_uri_new_with_base (base_uri, "/mbox"); + + if (test_type & CODING_TEST_EMPTY) + data->response = soup_buffer_new (SOUP_MEMORY_STATIC, "", 0); + else { + msg = soup_message_new_from_uri ("GET", uri); + soup_session_send_message (data->session, msg); + + data->response = soup_message_body_flatten (msg->response_body); + g_object_unref (msg); + } + + if (test_type & CODING_TEST_REQUEST_API) { + SoupRequestHTTP *reqh; + + reqh = soup_session_request_http_uri (data->session, "GET", uri, NULL); + data->req = SOUP_REQUEST (reqh); + data->msg = soup_request_http_get_message (reqh); + } else + data->msg = soup_message_new_from_uri ("GET", uri); + soup_uri_free (uri); + + if (! (test_type & CODING_TEST_NO_DECODER)) + soup_session_add_feature_by_type (data->session, SOUP_TYPE_CONTENT_DECODER); +} + +static void +teardown_coding_test (CodingTestData *data, gconstpointer test_data) +{ + soup_buffer_free (data->response); + + g_clear_object (&data->req); + g_object_unref (data->msg); + + soup_test_session_abort_unref (data->session); +} + +static void +do_coding_test_plain (CodingTestData *data, gconstpointer test_data) +{ + soup_session_send_message (data->session, data->msg); + check_response (data, NULL, "text/plain", EXPECT_NOT_DECODED, NULL); +} + +static void +do_coding_test_gzip (CodingTestData *data, gconstpointer test_data) +{ + soup_session_send_message (data->session, data->msg); + check_response (data, "gzip", "text/plain", EXPECT_DECODED, NULL); +} + +static void +do_coding_test_gzip_with_junk (CodingTestData *data, gconstpointer test_data) +{ + g_test_bug ("606352"); + g_test_bug ("676477"); + + soup_message_headers_append (data->msg->request_headers, + "X-Test-Options", "trailing-junk"); + + soup_session_send_message (data->session, data->msg); + check_response (data, "gzip", "text/plain", EXPECT_DECODED, NULL); +} + +static void +do_coding_test_gzip_bad_server (CodingTestData *data, gconstpointer test_data) +{ + g_test_bug ("613361"); + + soup_message_headers_append (data->msg->request_headers, + "X-Test-Options", "force-encode"); + + soup_session_send_message (data->session, data->msg); + + /* Failed content-decoding should have left the body untouched + * from what the server sent... which happens to be the + * uncompressed data. + */ + check_response (data, "gzip", "text/plain", EXPECT_NOT_DECODED, NULL); +} + +static void +do_coding_test_deflate (CodingTestData *data, gconstpointer test_data) +{ + soup_message_headers_append (data->msg->request_headers, + "X-Test-Options", "prefer-deflate-zlib"); + soup_session_send_message (data->session, data->msg); + + check_response (data, "deflate", "text/plain", EXPECT_DECODED, NULL); +} + +static void +do_coding_test_deflate_with_junk (CodingTestData *data, gconstpointer test_data) +{ + g_test_bug ("606352"); + g_test_bug ("676477"); + + soup_message_headers_append (data->msg->request_headers, + "X-Test-Options", "prefer-deflate-zlib, trailing-junk"); + soup_session_send_message (data->session, data->msg); + + check_response (data, "deflate", "text/plain", EXPECT_DECODED, NULL); +} + +static void +do_coding_test_deflate_bad_server (CodingTestData *data, gconstpointer test_data) +{ + g_test_bug ("613361"); + + soup_message_headers_append (data->msg->request_headers, + "X-Test-Options", "force-encode, prefer-deflate-zlib"); + soup_session_send_message (data->session, data->msg); + + check_response (data, "deflate", "text/plain", EXPECT_NOT_DECODED, NULL); +} + +static void +do_coding_test_deflate_raw (CodingTestData *data, gconstpointer test_data) +{ + soup_message_headers_append (data->msg->request_headers, + "X-Test-Options", "prefer-deflate-raw"); + soup_session_send_message (data->session, data->msg); + + check_response (data, "deflate", "text/plain", EXPECT_DECODED, NULL); +} + +static void +do_coding_test_deflate_raw_bad_server (CodingTestData *data, gconstpointer test_data) +{ + g_test_bug ("613361"); + + soup_message_headers_append (data->msg->request_headers, + "X-Test-Options", "force-encode, prefer-deflate-raw"); + soup_session_send_message (data->session, data->msg); + + check_response (data, "deflate", "text/plain", EXPECT_NOT_DECODED, NULL); +} + +static void +read_finished (GObject *stream, GAsyncResult *result, gpointer user_data) +{ + gssize *nread = user_data; + GError *error = NULL; + + *nread = g_input_stream_read_finish (G_INPUT_STREAM (stream), + result, &error); + g_assert_no_error (error); + g_clear_error (&error); +} + +static void +do_single_coding_req_test (CodingTestData *data, + const char *expected_encoding, + const char *expected_content_type, + MessageContentStatus status) +{ + GInputStream *stream; + GByteArray *body; + guchar buf[1024]; + gssize nread; + GError *error = NULL; + + body = g_byte_array_new (); + + stream = soup_test_request_send (data->req, NULL, 0, &error); + if (!stream) { + g_assert_no_error (error); + g_error_free (error); + return; + } + + do { + nread = -2; + g_input_stream_read_async (stream, buf, sizeof (buf), + G_PRIORITY_DEFAULT, + NULL, read_finished, &nread); + while (nread == -2) + g_main_context_iteration (NULL, TRUE); + + if (nread > 0) + g_byte_array_append (body, buf, nread); + } while (nread > 0); + + soup_test_request_close_stream (data->req, stream, NULL, &error); + g_assert_no_error (error); + g_clear_error (&error); + g_object_unref (stream); + + check_response (data, expected_encoding, expected_content_type, status, body); + g_byte_array_free (body, TRUE); +} + +static void +do_coding_req_test_plain (CodingTestData *data, gconstpointer test_data) +{ + do_single_coding_req_test (data, NULL, "text/plain", EXPECT_NOT_DECODED); +} + +static void +do_coding_req_test_gzip (CodingTestData *data, gconstpointer test_data) +{ + do_single_coding_req_test (data, "gzip", "text/plain", EXPECT_DECODED); +} + +static void +do_coding_req_test_gzip_with_junk (CodingTestData *data, gconstpointer test_data) +{ + g_test_bug ("606352"); + g_test_bug ("676477"); + + soup_message_headers_append (data->msg->request_headers, + "X-Test-Options", "trailing-junk"); + + do_single_coding_req_test (data, "gzip", "text/plain", EXPECT_DECODED); +} + +static void +do_coding_req_test_gzip_bad_server (CodingTestData *data, gconstpointer test_data) +{ + g_test_bug ("613361"); + + soup_message_headers_append (data->msg->request_headers, + "X-Test-Options", "force-encode"); + do_single_coding_req_test (data, "gzip", "text/plain", EXPECT_NOT_DECODED); +} + +static void +do_coding_req_test_deflate (CodingTestData *data, gconstpointer test_data) +{ + soup_message_headers_append (data->msg->request_headers, + "X-Test-Options", "prefer-deflate-zlib"); + do_single_coding_req_test (data, "deflate", "text/plain", EXPECT_DECODED); +} + +static void +do_coding_req_test_deflate_with_junk (CodingTestData *data, gconstpointer test_data) +{ + g_test_bug ("606352"); + g_test_bug ("676477"); + + soup_message_headers_append (data->msg->request_headers, + "X-Test-Options", "prefer-deflate-zlib, trailing-junk"); + do_single_coding_req_test (data, "deflate", "text/plain", EXPECT_DECODED); +} + +static void +do_coding_req_test_deflate_bad_server (CodingTestData *data, gconstpointer test_data) +{ + g_test_bug ("613361"); + + soup_message_headers_append (data->msg->request_headers, + "X-Test-Options", "force-encode, prefer-deflate-zlib"); + do_single_coding_req_test (data, "deflate", "text/plain", EXPECT_NOT_DECODED); +} + +static void +do_coding_req_test_deflate_raw (CodingTestData *data, gconstpointer test_data) +{ + soup_message_headers_append (data->msg->request_headers, + "X-Test-Options", "prefer-deflate-raw"); + do_single_coding_req_test (data, "deflate", "text/plain", EXPECT_DECODED); +} + +static void +do_coding_req_test_deflate_raw_bad_server (CodingTestData *data, gconstpointer test_data) +{ + g_test_bug ("613361"); + + soup_message_headers_append (data->msg->request_headers, + "X-Test-Options", "force-encode, prefer-deflate-raw"); + do_single_coding_req_test (data, "deflate", "text/plain", EXPECT_NOT_DECODED); +} + +static void +do_coding_msg_empty_test (CodingTestData *data, gconstpointer test_data) +{ + g_test_bug ("697527"); + + soup_message_headers_append (data->msg->request_headers, + "X-Test-Options", "empty"); + soup_session_send_message (data->session, data->msg); + + check_response (data, "gzip", "text/plain", EXPECT_NOT_DECODED, NULL); +} + +static void +do_coding_req_empty_test (CodingTestData *data, gconstpointer test_data) +{ + g_test_bug ("697527"); + + soup_message_headers_append (data->msg->request_headers, + "X-Test-Options", "empty"); + do_single_coding_req_test (data, "gzip", "text/plain", EXPECT_NOT_DECODED); +} + +int +main (int argc, char **argv) +{ + int ret; + + test_init (argc, argv, NULL); + + server = soup_test_server_new (SOUP_TEST_SERVER_IN_THREAD); + soup_server_add_handler (server, NULL, server_callback, NULL, NULL); + base_uri = soup_test_server_get_uri (server, "http", NULL); + + g_test_add ("/coding/message/plain", CodingTestData, + GINT_TO_POINTER (CODING_TEST_NO_DECODER), + setup_coding_test, do_coding_test_plain, teardown_coding_test); + g_test_add ("/coding/message/gzip", CodingTestData, + GINT_TO_POINTER (CODING_TEST_DEFAULT), + setup_coding_test, do_coding_test_gzip, teardown_coding_test); + g_test_add ("/coding/message/gzip/with-junk", CodingTestData, + GINT_TO_POINTER (CODING_TEST_DEFAULT), + setup_coding_test, do_coding_test_gzip_with_junk, teardown_coding_test); + g_test_add ("/coding/message/gzip/bad-server", CodingTestData, + GINT_TO_POINTER (CODING_TEST_DEFAULT), + setup_coding_test, do_coding_test_gzip_bad_server, teardown_coding_test); + g_test_add ("/coding/message/deflate", CodingTestData, + GINT_TO_POINTER (CODING_TEST_DEFAULT), + setup_coding_test, do_coding_test_deflate, teardown_coding_test); + g_test_add ("/coding/message/deflate/with-junk", CodingTestData, + GINT_TO_POINTER (CODING_TEST_DEFAULT), + setup_coding_test, do_coding_test_deflate_with_junk, teardown_coding_test); + g_test_add ("/coding/message/deflate/bad-server", CodingTestData, + GINT_TO_POINTER (CODING_TEST_DEFAULT), + setup_coding_test, do_coding_test_deflate_bad_server, teardown_coding_test); + g_test_add ("/coding/message/deflate-raw", CodingTestData, + GINT_TO_POINTER (CODING_TEST_DEFAULT), + setup_coding_test, do_coding_test_deflate_raw, teardown_coding_test); + g_test_add ("/coding/message/deflate-raw/bad-server", CodingTestData, + GINT_TO_POINTER (CODING_TEST_DEFAULT), + setup_coding_test, do_coding_test_deflate_raw_bad_server, teardown_coding_test); + + g_test_add ("/coding/request/plain", CodingTestData, + GINT_TO_POINTER (CODING_TEST_NO_DECODER | CODING_TEST_REQUEST_API), + setup_coding_test, do_coding_req_test_plain, teardown_coding_test); + g_test_add ("/coding/request/gzip", CodingTestData, + GINT_TO_POINTER (CODING_TEST_REQUEST_API), + setup_coding_test, do_coding_req_test_gzip, teardown_coding_test); + g_test_add ("/coding/request/gzip/with-junk", CodingTestData, + GINT_TO_POINTER (CODING_TEST_REQUEST_API), + setup_coding_test, do_coding_req_test_gzip_with_junk, teardown_coding_test); + g_test_add ("/coding/request/gzip/bad-server", CodingTestData, + GINT_TO_POINTER (CODING_TEST_REQUEST_API), + setup_coding_test, do_coding_req_test_gzip_bad_server, teardown_coding_test); + g_test_add ("/coding/request/deflate", CodingTestData, + GINT_TO_POINTER (CODING_TEST_REQUEST_API), + setup_coding_test, do_coding_req_test_deflate, teardown_coding_test); + g_test_add ("/coding/request/deflate/with-junk", CodingTestData, + GINT_TO_POINTER (CODING_TEST_REQUEST_API), + setup_coding_test, do_coding_req_test_deflate_with_junk, teardown_coding_test); + g_test_add ("/coding/request/deflate/bad-server", CodingTestData, + GINT_TO_POINTER (CODING_TEST_REQUEST_API), + setup_coding_test, do_coding_req_test_deflate_bad_server, teardown_coding_test); + g_test_add ("/coding/request/deflate-raw", CodingTestData, + GINT_TO_POINTER (CODING_TEST_REQUEST_API), + setup_coding_test, do_coding_req_test_deflate_raw, teardown_coding_test); + g_test_add ("/coding/request/deflate-raw/bad-server", CodingTestData, + GINT_TO_POINTER (CODING_TEST_REQUEST_API), + setup_coding_test, do_coding_req_test_deflate_raw_bad_server, teardown_coding_test); + + g_test_add ("/coding/message/empty", CodingTestData, + GINT_TO_POINTER (CODING_TEST_EMPTY), + setup_coding_test, do_coding_msg_empty_test, teardown_coding_test); + g_test_add ("/coding/request/empty", CodingTestData, + GINT_TO_POINTER (CODING_TEST_REQUEST_API | CODING_TEST_EMPTY), + setup_coding_test, do_coding_req_empty_test, teardown_coding_test); + + ret = g_test_run (); + + soup_uri_free (base_uri); + soup_test_server_quit_unref (server); + + test_cleanup (); + return ret; +} diff --git a/tests/connection-test.c b/tests/connection-test.c new file mode 100644 index 0000000..ec54dae --- /dev/null +++ b/tests/connection-test.c @@ -0,0 +1,1125 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright 2007-2012 Red Hat, Inc. + */ + +#include "test-utils.h" + +#include + +SoupServer *server; +SoupURI *base_uri; +GMutex server_mutex; + +static void +forget_close (SoupMessage *msg, gpointer user_data) +{ + soup_message_headers_remove (msg->response_headers, "Connection"); +} + +static void +close_socket (SoupMessage *msg, gpointer user_data) +{ + SoupSocket *sock = user_data; + int sockfd; + + /* Actually calling soup_socket_disconnect() here would cause + * us to leak memory, so just shutdown the socket instead. + */ + sockfd = soup_socket_get_fd (sock); +#ifdef G_OS_WIN32 + shutdown (sockfd, SD_SEND); +#else + shutdown (sockfd, SHUT_WR); +#endif + + /* Then add the missing data to the message now, so SoupServer + * can clean up after itself properly. + */ + soup_message_body_append (msg->response_body, SOUP_MEMORY_STATIC, + "foo", 3); +} + +static void +timeout_socket (SoupSocket *sock, gpointer user_data) +{ + soup_socket_disconnect (sock); +} + +static void +timeout_request_started (SoupServer *server, SoupMessage *msg, + SoupClientContext *client, gpointer user_data) +{ + SoupSocket *sock; + GMainContext *context = g_main_context_get_thread_default (); + guint readable; + + g_signal_handlers_disconnect_by_func (server, timeout_request_started, NULL); + + G_GNUC_BEGIN_IGNORE_DEPRECATIONS; + sock = soup_client_context_get_socket (client); + G_GNUC_END_IGNORE_DEPRECATIONS; + readable = g_signal_connect (sock, "readable", + G_CALLBACK (timeout_socket), NULL); + + g_mutex_unlock (&server_mutex); + while (soup_socket_is_connected (sock)) + g_main_context_iteration (context, TRUE); + g_signal_handler_disconnect (sock, readable); +} + +static void +setup_timeout_persistent (SoupServer *server, SoupSocket *sock) +{ + char buf[1]; + gsize nread; + + /* In order for the test to work correctly, we have to + * close the connection *after* the client side writes + * the request. To ensure that this happens reliably, + * regardless of thread scheduling, we: + * + * 1. Try to read off the socket now, knowing it will + * fail (since the client is waiting for us to + * return a response). This will cause it to + * emit "readable" later. + * 2. Wait for the server to finish this request and + * start reading the next one (and lock server_mutex + * to interlock with the client and ensure that it + * doesn't start writing its next request until + * that point). + * 3. Block until "readable" is emitted, meaning the + * client has written its request. + * 4. Close the socket. + */ + + soup_socket_read (sock, buf, 1, &nread, NULL, NULL); + g_mutex_lock (&server_mutex); + g_signal_connect (server, "request-started", + G_CALLBACK (timeout_request_started), NULL); +} + +static void +server_callback (SoupServer *server, SoupMessage *msg, + const char *path, GHashTable *query, + SoupClientContext *context, gpointer data) +{ + /* The way this gets used in the tests, we don't actually + * need to hold it through the whole function, so it's simpler + * to just release it right away. + */ + g_mutex_lock (&server_mutex); + g_mutex_unlock (&server_mutex); + + if (msg->method != SOUP_METHOD_GET && msg->method != SOUP_METHOD_POST) { + soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED); + return; + } + + if (g_str_has_prefix (path, "/content-length/")) { + gboolean too_long = strcmp (path, "/content-length/long") == 0; + gboolean no_close = strcmp (path, "/content-length/noclose") == 0; + + soup_message_set_status (msg, SOUP_STATUS_OK); + soup_message_set_response (msg, "text/plain", + SOUP_MEMORY_STATIC, "foobar", 6); + if (too_long) + soup_message_headers_set_content_length (msg->response_headers, 9); + soup_message_headers_append (msg->response_headers, + "Connection", "close"); + + if (too_long) { + SoupSocket *sock; + + /* soup-message-io will wait for us to add + * another chunk after the first, to fill out + * the declared Content-Length. Instead, we + * forcibly close the socket at that point. + */ + G_GNUC_BEGIN_IGNORE_DEPRECATIONS; + sock = soup_client_context_get_socket (context); + G_GNUC_END_IGNORE_DEPRECATIONS; + g_signal_connect (msg, "wrote-chunk", + G_CALLBACK (close_socket), sock); + } else if (no_close) { + /* Remove the 'Connection: close' after writing + * the headers, so that when we check it after + * writing the body, we'll think we aren't + * supposed to close it. + */ + g_signal_connect (msg, "wrote-headers", + G_CALLBACK (forget_close), NULL); + } + return; + } + + if (!strcmp (path, "/timeout-persistent")) { + SoupSocket *sock; + + G_GNUC_BEGIN_IGNORE_DEPRECATIONS; + sock = soup_client_context_get_socket (context); + G_GNUC_END_IGNORE_DEPRECATIONS; + setup_timeout_persistent (server, sock); + } + + soup_message_set_status (msg, SOUP_STATUS_OK); + soup_message_set_response (msg, "text/plain", + SOUP_MEMORY_STATIC, "index", 5); + return; +} + +static void +do_content_length_framing_test (void) +{ + SoupSession *session; + SoupMessage *msg; + SoupURI *request_uri; + goffset declared_length; + + g_test_bug ("611481"); + + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + + debug_printf (1, " Content-Length larger than message body length\n"); + request_uri = soup_uri_new_with_base (base_uri, "/content-length/long"); + msg = soup_message_new_from_uri ("GET", request_uri); + soup_session_send_message (session, msg); + + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + + declared_length = soup_message_headers_get_content_length (msg->response_headers); + debug_printf (2, " Content-Length: %lu, body: %s\n", + (gulong)declared_length, msg->response_body->data); + g_assert_cmpint (msg->response_body->length, <, declared_length); + + soup_uri_free (request_uri); + g_object_unref (msg); + + debug_printf (1, " Server claims 'Connection: close' but doesn't\n"); + request_uri = soup_uri_new_with_base (base_uri, "/content-length/noclose"); + msg = soup_message_new_from_uri ("GET", request_uri); + soup_session_send_message (session, msg); + + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + + declared_length = soup_message_headers_get_content_length (msg->response_headers); + g_assert_cmpint (msg->response_body->length, ==, declared_length); + + soup_uri_free (request_uri); + g_object_unref (msg); + + soup_test_session_abort_unref (session); +} + +static void +request_started_socket_collector (SoupSession *session, SoupMessage *msg, + SoupSocket *socket, gpointer user_data) +{ + SoupSocket **sockets = user_data; + int i; + + debug_printf (2, " msg %p => socket %p\n", msg, socket); + for (i = 0; i < 4; i++) { + if (!sockets[i]) { + /* We ref the socket to make sure that even if + * it gets disconnected, it doesn't get freed, + * since our checks would get messed up if the + * slice allocator reused the same address for + * two consecutive sockets. + */ + sockets[i] = g_object_ref (socket); + break; + } + } + + soup_test_assert (i < 4, "socket queue overflowed"); +} + +static void +do_timeout_test_for_session (SoupSession *session) +{ + SoupMessage *msg; + SoupSocket *sockets[4] = { NULL, NULL, NULL, NULL }; + SoupURI *timeout_uri; + int i; + + g_signal_connect (session, "request-started", + G_CALLBACK (request_started_socket_collector), + &sockets); + + debug_printf (1, " First message\n"); + timeout_uri = soup_uri_new_with_base (base_uri, "/timeout-persistent"); + msg = soup_message_new_from_uri ("GET", timeout_uri); + soup_uri_free (timeout_uri); + soup_session_send_message (session, msg); + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + + if (sockets[1]) { + soup_test_assert (sockets[1] == NULL, "Message was retried"); + sockets[1] = sockets[2] = sockets[3] = NULL; + } + g_object_unref (msg); + + /* The server will grab server_mutex before returning the response, + * and release it when it's ready for us to send the second request. + */ + g_mutex_lock (&server_mutex); + g_mutex_unlock (&server_mutex); + + debug_printf (1, " Second message\n"); + msg = soup_message_new_from_uri ("GET", base_uri); + soup_session_send_message (session, msg); + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + + soup_test_assert (sockets[1] == sockets[0], + "Message was not retried on existing connection"); + soup_test_assert (sockets[2] != NULL, + "Message was not retried after disconnect"); + soup_test_assert (sockets[2] != sockets[1], + "Message was retried on closed connection"); + soup_test_assert (sockets[3] == NULL, + "Message was retried again"); + g_object_unref (msg); + + for (i = 0; sockets[i]; i++) + g_object_unref (sockets[i]); +} + +static void +do_timeout_req_test_for_session (SoupSession *session) +{ + SoupRequest *req; + SoupMessage *msg; + GInputStream *stream; + SoupSocket *sockets[4] = { NULL, NULL, NULL, NULL }; + SoupURI *timeout_uri; + GError *error = NULL; + int i; + + g_signal_connect (session, "request-started", + G_CALLBACK (request_started_socket_collector), + &sockets); + + debug_printf (1, " First request\n"); + timeout_uri = soup_uri_new_with_base (base_uri, "/timeout-persistent"); + req = soup_session_request_uri (session, timeout_uri, NULL); + soup_uri_free (timeout_uri); + + stream = soup_test_request_send (req, NULL, 0, &error); + if (error) { + g_assert_no_error (error); + g_clear_error (&error); + } else { + soup_test_request_read_all (req, stream, NULL, &error); + if (error) { + g_assert_no_error (error); + g_clear_error (&error); + } + + soup_test_request_close_stream (req, stream, NULL, &error); + if (error) { + g_assert_no_error (error); + g_clear_error (&error); + } + g_object_unref (stream); + } + + if (sockets[1]) { + soup_test_assert (sockets[1] == NULL, "Message was retried"); + sockets[1] = sockets[2] = sockets[3] = NULL; + } + g_object_unref (req); + + /* The server will grab server_mutex before returning the response, + * and release it when it's ready for us to send the second request. + */ + g_mutex_lock (&server_mutex); + g_mutex_unlock (&server_mutex); + + debug_printf (1, " Second request\n"); + req = soup_session_request_uri (session, base_uri, NULL); + + stream = soup_test_request_send (req, NULL, 0, &error); + if (error) { + g_assert_no_error (error); + g_clear_error (&error); + } else { + soup_test_request_close_stream (req, stream, NULL, &error); + if (error) { + g_assert_no_error (error); + g_clear_error (&error); + } + g_object_unref (stream); + } + + msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (req)); + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + + soup_test_assert (sockets[1] == sockets[0], + "Message was not retried on existing connection"); + soup_test_assert (sockets[2] != NULL, + "Message was not retried after disconnect"); + soup_test_assert (sockets[2] != sockets[1], + "Message was retried on closed connection"); + soup_test_assert (sockets[3] == NULL, + "Message was retried again"); + g_object_unref (msg); + g_object_unref (req); + + for (i = 0; sockets[i]; i++) + g_object_unref (sockets[i]); +} + +static void +do_persistent_connection_timeout_test (void) +{ + SoupSession *session; + + g_test_bug ("631525"); + + debug_printf (1, " Async session, message API\n"); + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + do_timeout_test_for_session (session); + soup_test_session_abort_unref (session); + + debug_printf (1, " Async session, request API\n"); + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, + SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, + NULL); + do_timeout_req_test_for_session (session); + soup_test_session_abort_unref (session); + + debug_printf (1, " Sync session, message API\n"); + session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL); + do_timeout_test_for_session (session); + soup_test_session_abort_unref (session); + + debug_printf (1, " Sync session, request API\n"); + session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL); + do_timeout_req_test_for_session (session); + soup_test_session_abort_unref (session); +} + +static GMainLoop *max_conns_loop; +static int msgs_done; +static guint quit_loop_timeout; +#define MAX_CONNS 2 +#define TEST_CONNS (MAX_CONNS * 2) + 1 + +static gboolean +idle_start_server (gpointer data) +{ + g_mutex_unlock (&server_mutex); + return FALSE; +} + +static gboolean +quit_loop (gpointer data) +{ + quit_loop_timeout = 0; + g_main_loop_quit (max_conns_loop); + return FALSE; +} + +static void +max_conns_request_started (SoupSession *session, SoupMessage *msg, + SoupSocket *socket, gpointer user_data) +{ + if (++msgs_done >= MAX_CONNS) { + if (quit_loop_timeout) + g_source_remove (quit_loop_timeout); + quit_loop_timeout = g_timeout_add (100, quit_loop, NULL); + } +} + +static void +max_conns_message_complete (SoupSession *session, SoupMessage *msg, gpointer user_data) +{ + if (++msgs_done == TEST_CONNS) + g_main_loop_quit (max_conns_loop); +} + +static void +do_max_conns_test_for_session (SoupSession *session) +{ + SoupMessage *msgs[TEST_CONNS + 1]; + SoupMessageFlags flags; + int i; + + max_conns_loop = g_main_loop_new (NULL, TRUE); + + g_mutex_lock (&server_mutex); + + g_signal_connect (session, "request-started", + G_CALLBACK (max_conns_request_started), NULL); + msgs_done = 0; + for (i = 0; i < TEST_CONNS - 1; i++) { + msgs[i] = soup_message_new_from_uri ("GET", base_uri); + g_object_ref (msgs[i]); + soup_session_queue_message (session, msgs[i], + max_conns_message_complete, NULL); + } + + g_main_loop_run (max_conns_loop); + g_assert_cmpint (msgs_done, ==, MAX_CONNS); + + if (quit_loop_timeout) + g_source_remove (quit_loop_timeout); + quit_loop_timeout = g_timeout_add (1000, quit_loop, NULL); + + /* Message with SOUP_MESSAGE_IGNORE_CONNECTION_LIMITS should start */ + msgs[i] = soup_message_new_from_uri ("GET", base_uri); + flags = soup_message_get_flags (msgs[i]); + soup_message_set_flags (msgs[i], flags | SOUP_MESSAGE_IGNORE_CONNECTION_LIMITS); + g_object_ref (msgs[i]); + soup_session_queue_message (session, msgs[i], + max_conns_message_complete, NULL); + + g_main_loop_run (max_conns_loop); + g_assert_cmpint (msgs_done, ==, MAX_CONNS + 1); + g_signal_handlers_disconnect_by_func (session, max_conns_request_started, NULL); + + msgs_done = 0; + g_idle_add (idle_start_server, NULL); + if (quit_loop_timeout) + g_source_remove (quit_loop_timeout); + quit_loop_timeout = g_timeout_add (1000, quit_loop, NULL); + g_main_loop_run (max_conns_loop); + + for (i = 0; i < TEST_CONNS; i++) + soup_test_assert_message_status (msgs[i], SOUP_STATUS_OK); + + if (msgs_done != TEST_CONNS) { + /* Clean up so we don't get a spurious "Leaked + * session" error. + */ + for (i = 0; i < TEST_CONNS; i++) + soup_session_cancel_message (session, msgs[i], SOUP_STATUS_CANCELLED); + g_main_loop_run (max_conns_loop); + } + + g_main_loop_unref (max_conns_loop); + if (quit_loop_timeout) { + g_source_remove (quit_loop_timeout); + quit_loop_timeout = 0; + } + + for (i = 0; i < TEST_CONNS; i++) + g_object_unref (msgs[i]); +} + +static void +do_max_conns_test (void) +{ + SoupSession *session; + + g_test_bug ("634422"); + + debug_printf (1, " Async session\n"); + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, + SOUP_SESSION_MAX_CONNS, MAX_CONNS, + NULL); + do_max_conns_test_for_session (session); + soup_test_session_abort_unref (session); + + debug_printf (1, " Sync session\n"); + session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, + SOUP_SESSION_MAX_CONNS, MAX_CONNS, + NULL); + do_max_conns_test_for_session (session); + soup_test_session_abort_unref (session); +} + +static void +np_request_started (SoupSession *session, SoupMessage *msg, + SoupSocket *socket, gpointer user_data) +{ + SoupSocket **save_socket = user_data; + + *save_socket = g_object_ref (socket); +} + +static void +np_request_unqueued (SoupSession *session, SoupMessage *msg, + gpointer user_data) +{ + SoupSocket *socket = *(SoupSocket **)user_data; + + g_assert_false (soup_socket_is_connected (socket)); +} + +static void +np_request_finished (SoupSession *session, SoupMessage *msg, + gpointer user_data) +{ + GMainLoop *loop = user_data; + + g_main_loop_quit (loop); +} + +static void +do_non_persistent_test_for_session (SoupSession *session) +{ + SoupMessage *msg; + SoupSocket *socket = NULL; + GMainLoop *loop; + + loop = g_main_loop_new (NULL, FALSE); + + g_signal_connect (session, "request-started", + G_CALLBACK (np_request_started), + &socket); + g_signal_connect (session, "request-unqueued", + G_CALLBACK (np_request_unqueued), + &socket); + + msg = soup_message_new_from_uri ("GET", base_uri); + soup_message_headers_append (msg->request_headers, "Connection", "close"); + g_object_ref (msg); + soup_session_queue_message (session, msg, + np_request_finished, loop); + g_main_loop_run (loop); + g_main_loop_unref (loop); + + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + + g_object_unref (msg); + g_object_unref (socket); +} + +static void +do_non_persistent_connection_test (void) +{ + SoupSession *session; + + g_test_bug ("578990"); + + debug_printf (1, " Async session\n"); + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + do_non_persistent_test_for_session (session); + soup_test_session_abort_unref (session); + + debug_printf (1, " Sync session\n"); + session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL); + do_non_persistent_test_for_session (session); + soup_test_session_abort_unref (session); +} + +static void +do_non_idempotent_test_for_session (SoupSession *session) +{ + SoupMessage *msg; + SoupSocket *sockets[4] = { NULL, NULL, NULL, NULL }; + int i; + + g_signal_connect (session, "request-started", + G_CALLBACK (request_started_socket_collector), + &sockets); + + debug_printf (2, " GET\n"); + msg = soup_message_new_from_uri ("GET", base_uri); + soup_session_send_message (session, msg); + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + if (sockets[1]) { + soup_test_assert (sockets[1] == NULL, "Message was retried"); + sockets[1] = sockets[2] = sockets[3] = NULL; + } + g_object_unref (msg); + + debug_printf (2, " POST\n"); + msg = soup_message_new_from_uri ("POST", base_uri); + soup_session_send_message (session, msg); + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + soup_test_assert (sockets[1] != sockets[0], + "Message was sent on existing connection"); + soup_test_assert (sockets[2] == NULL, + "Too many connections used"); + + g_object_unref (msg); + + for (i = 0; sockets[i]; i++) + g_object_unref (sockets[i]); +} + +static void +do_non_idempotent_connection_test (void) +{ + SoupSession *session; + + debug_printf (1, " Async session\n"); + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + do_non_idempotent_test_for_session (session); + soup_test_session_abort_unref (session); + + debug_printf (1, " Sync session\n"); + session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL); + do_non_idempotent_test_for_session (session); + soup_test_session_abort_unref (session); +} + +#define HTTP_SERVER "http://127.0.0.1:47524" +#define HTTPS_SERVER "https://127.0.0.1:47525" +#define HTTP_PROXY "http://127.0.0.1:47526" + +static SoupConnectionState state_transitions[] = { + /* NEW -> */ SOUP_CONNECTION_CONNECTING, + /* CONNECTING -> */ SOUP_CONNECTION_IN_USE, + /* IDLE -> */ SOUP_CONNECTION_DISCONNECTED, + /* IN_USE -> */ SOUP_CONNECTION_IDLE, + + /* REMOTE_DISCONNECTED */ -1, + /* DISCONNECTED */ -1, +}; + +static const char *state_names[] = { + "NEW", "CONNECTING", "IDLE", "IN_USE", + "REMOTE_DISCONNECTED", "DISCONNECTED" +}; + +static void +connection_state_changed (GObject *object, GParamSpec *param, + gpointer user_data) +{ + SoupConnectionState *state = user_data; + SoupConnectionState new_state; + + g_object_get (object, "state", &new_state, NULL); + debug_printf (2, " %s -> %s\n", + state_names[*state], state_names[new_state]); + soup_test_assert (state_transitions[*state] == new_state, + "Unexpected transition: %s -> %s\n", + state_names[*state], state_names[new_state]); + *state = new_state; +} + +static void +connection_created (SoupSession *session, GObject *conn, + gpointer user_data) +{ + SoupConnectionState *state = user_data; + + g_object_get (conn, "state", state, NULL); + g_assert_cmpint (*state, ==, SOUP_CONNECTION_NEW); + + g_signal_connect (conn, "notify::state", + G_CALLBACK (connection_state_changed), + state); +} + +static void +do_one_connection_state_test (SoupSession *session, const char *uri) +{ + SoupMessage *msg; + + msg = soup_message_new ("GET", uri); + soup_session_send_message (session, msg); + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + g_object_unref (msg); + soup_session_abort (session); +} + +static void +do_connection_state_test_for_session (SoupSession *session) +{ + SoupConnectionState state; + SoupURI *proxy_uri; + + g_signal_connect (session, "connection-created", + G_CALLBACK (connection_created), + &state); + + debug_printf (1, " http\n"); + do_one_connection_state_test (session, HTTP_SERVER); + + if (tls_available) { + debug_printf (1, " https\n"); + do_one_connection_state_test (session, HTTPS_SERVER); + } else + debug_printf (1, " https -- SKIPPING\n"); + + proxy_uri = soup_uri_new (HTTP_PROXY); + g_object_set (G_OBJECT (session), + SOUP_SESSION_PROXY_URI, proxy_uri, + NULL); + soup_uri_free (proxy_uri); + + debug_printf (1, " http with proxy\n"); + do_one_connection_state_test (session, HTTP_SERVER); + + if (tls_available) { + debug_printf (1, " https with proxy\n"); + do_one_connection_state_test (session, HTTPS_SERVER); + } else + debug_printf (1, " https with proxy -- SKIPPING\n"); +} + +static void +do_connection_state_test (void) +{ + SoupSession *session; + + SOUP_TEST_SKIP_IF_NO_APACHE; + + debug_printf (1, " Async session\n"); + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + do_connection_state_test_for_session (session); + soup_test_session_abort_unref (session); + + debug_printf (1, " Sync session\n"); + session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL); + do_connection_state_test_for_session (session); + soup_test_session_abort_unref (session); +} + + +static const char *event_names[] = { + "RESOLVING", "RESOLVED", "CONNECTING", "CONNECTED", + "PROXY_NEGOTIATING", "PROXY_NEGOTIATED", + "TLS_HANDSHAKING", "TLS_HANDSHAKED", "COMPLETE" +}; + +static const char event_abbrevs[] = { + 'r', 'R', 'c', 'C', 'p', 'P', 't', 'T', 'x', '\0' +}; + +static const char * +event_name_from_abbrev (char abbrev) +{ + int evt; + + for (evt = 0; event_abbrevs[evt]; evt++) { + if (event_abbrevs[evt] == abbrev) + return event_names[evt]; + } + return "???"; +} + +static void +network_event (SoupMessage *msg, GSocketClientEvent event, + GIOStream *connection, gpointer user_data) +{ + const char **events = user_data; + + debug_printf (2, " %s\n", event_names[event]); + soup_test_assert (**events == event_abbrevs[event], + "Unexpected event: %s (expected %s)", + event_names[event], + event_name_from_abbrev (**events)); + + if (**events == event_abbrevs[event]) { + if (event == G_SOCKET_CLIENT_RESOLVING || + event == G_SOCKET_CLIENT_RESOLVED) { + soup_test_assert (connection == NULL, + "Unexpectedly got connection (%s) with '%s' event", + G_OBJECT_TYPE_NAME (connection), + event_names[event]); + } else if (event < G_SOCKET_CLIENT_TLS_HANDSHAKING) { + soup_test_assert (G_IS_SOCKET_CONNECTION (connection), + "Unexpectedly got %s with '%s' event", + G_OBJECT_TYPE_NAME (connection), + event_names[event]); + } else if (event == G_SOCKET_CLIENT_TLS_HANDSHAKING || + event == G_SOCKET_CLIENT_TLS_HANDSHAKED) { + soup_test_assert (G_IS_TLS_CLIENT_CONNECTION (connection), + "Unexpectedly got %s with '%s' event", + G_OBJECT_TYPE_NAME (connection), + event_names[event]); + } else if (event == G_SOCKET_CLIENT_COMPLETE) { + /* See if the previous expected event was TLS_HANDSHAKED */ + if ((*events)[-1] == 'T') { + soup_test_assert (G_IS_TLS_CLIENT_CONNECTION (connection), + "Unexpectedly got %s with '%s' event", + G_OBJECT_TYPE_NAME (connection), + event_names[event]); + } else { + soup_test_assert (G_IS_SOCKET_CONNECTION (connection), + "Unexpectedly got %s with '%s' event", + G_OBJECT_TYPE_NAME (connection), + event_names[event]); + } + } + } + + *events = *events + 1; +} + +static void +do_one_connection_event_test (SoupSession *session, const char *uri, + const char *events) +{ + SoupMessage *msg; + + msg = soup_message_new ("GET", uri); + g_signal_connect (msg, "network-event", + G_CALLBACK (network_event), + &events); + soup_session_send_message (session, msg); + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + while (*events) { + soup_test_assert (!*events, + "Expected %s", + event_name_from_abbrev (*events)); + events++; + } + + g_object_unref (msg); + soup_session_abort (session); +} + +static void +do_connection_event_test_for_session (SoupSession *session) +{ + SoupURI *proxy_uri; + + debug_printf (1, " http\n"); + do_one_connection_event_test (session, HTTP_SERVER, "rRcCx"); + + if (tls_available) { + debug_printf (1, " https\n"); + do_one_connection_event_test (session, HTTPS_SERVER, "rRcCtTx"); + } else + debug_printf (1, " https -- SKIPPING\n"); + + proxy_uri = soup_uri_new (HTTP_PROXY); + g_object_set (G_OBJECT (session), + SOUP_SESSION_PROXY_URI, proxy_uri, + NULL); + soup_uri_free (proxy_uri); + + debug_printf (1, " http with proxy\n"); + do_one_connection_event_test (session, HTTP_SERVER, "rRcCx"); + + if (tls_available) { + debug_printf (1, " https with proxy\n"); + do_one_connection_event_test (session, HTTPS_SERVER, "rRcCpPtTx"); + } else + debug_printf (1, " https with proxy -- SKIPPING\n"); +} + +static void +do_connection_event_test (void) +{ + SoupSession *session; + + SOUP_TEST_SKIP_IF_NO_APACHE; + + debug_printf (1, " Async session\n"); + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + do_connection_event_test_for_session (session); + soup_test_session_abort_unref (session); + + debug_printf (1, " Sync session\n"); + session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL); + do_connection_event_test_for_session (session); + soup_test_session_abort_unref (session); +} + +typedef struct { + GMainLoop *loop; + GIOStream *stream; + GError *error; + const char *events; +} ConnectTestData; + +static void +connect_progress (SoupSession *session, GSocketClientEvent event, GIOStream *connection, ConnectTestData *data) +{ + soup_test_assert (*data->events == event_abbrevs[event], + "Unexpected event: %s (expected %s)", + event_names[event], + event_name_from_abbrev (*data->events)); + data->events = data->events + 1; +} + +static void +connect_finished (SoupSession *session, GAsyncResult *result, ConnectTestData *data) +{ + data->stream = soup_session_connect_finish (session, result, &data->error); + g_main_loop_quit (data->loop); +} + +static void +do_one_connection_connect_test (SoupSession *session, SoupURI *uri, const char *response, const char *events) +{ + ConnectTestData data = { NULL, NULL, NULL, events }; + static const char *request = "GET / HTTP/1.1\r\nHost: localhost\r\n\r\n"; + gsize bytes = 0; + char buffer[128]; + + data.loop = g_main_loop_new (NULL, FALSE); + soup_session_connect_async (session, uri, NULL, + (SoupSessionConnectProgressCallback)connect_progress, + (GAsyncReadyCallback)connect_finished, + &data); + g_main_loop_run (data.loop); + + g_assert (G_IS_IO_STREAM (data.stream)); + g_assert_no_error (data.error); + g_assert (g_output_stream_write_all (g_io_stream_get_output_stream (data.stream), + request, strlen (request), &bytes, NULL, NULL)); + g_assert (g_input_stream_read_all (g_io_stream_get_input_stream (data.stream), + buffer, sizeof (buffer), &bytes, NULL, NULL)); + buffer[strlen (response)] = '\0'; + g_assert_cmpstr (buffer, ==, response); + + while (*data.events) { + soup_test_assert (!*data.events, + "Expected %s", + event_name_from_abbrev (*data.events)); + data.events++; + } + + g_object_unref (data.stream); + g_main_loop_unref (data.loop); +} + +static void +do_one_connection_connect_fail_test (SoupSession *session, SoupURI *uri, GQuark domain, gint code, const char *events) +{ + ConnectTestData data = { NULL, NULL, NULL, events }; + + data.loop = g_main_loop_new (NULL, FALSE); + soup_session_connect_async (session, uri, NULL, + (SoupSessionConnectProgressCallback)connect_progress, + (GAsyncReadyCallback)connect_finished, + &data); + g_main_loop_run (data.loop); + + g_assert (!data.stream); + g_assert_error (data.error, domain, code); + + while (*data.events) { + soup_test_assert (!*data.events, + "Expected %s", + event_name_from_abbrev (*data.events)); + data.events++; + } +} + +static void +do_connection_connect_test (void) +{ + SoupSession *session; + SoupURI *http_uri; + SoupURI *https_uri = NULL; + SoupURI *ws_uri; + SoupURI *wss_uri = NULL; + SoupURI *file_uri; + SoupURI *wrong_http_uri; + SoupURI *proxy_uri; + + SOUP_TEST_SKIP_IF_NO_APACHE; + + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, + SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, + NULL); + + debug_printf (1, " http\n"); + http_uri = soup_uri_new (HTTP_SERVER); + do_one_connection_connect_test (session, http_uri, + "HTTP/1.1 200 OK", "rRcCx"); + + if (tls_available) { + debug_printf (1, " https\n"); + https_uri = soup_uri_new (HTTPS_SERVER); + do_one_connection_connect_test (session, https_uri, + "HTTP/1.1 200 OK", "rRcCtTx"); + } else + debug_printf (1, " https -- SKIPPING\n"); + + debug_printf (1, " ws\n"); + ws_uri = soup_uri_new (HTTP_SERVER); + ws_uri->scheme = SOUP_URI_SCHEME_WS; + do_one_connection_connect_test (session, ws_uri, + "HTTP/1.1 200 OK", "rRcCx"); + + if (tls_available) { + debug_printf (1, " wss\n"); + wss_uri = soup_uri_new (HTTPS_SERVER); + do_one_connection_connect_test (session, wss_uri, + "HTTP/1.1 200 OK", "rRcCtTx"); + } else + debug_printf (1, " wss -- SKIPPING\n"); + + debug_printf (1, " file\n"); + file_uri = soup_uri_new ("file:///foo/bar"); + do_one_connection_connect_fail_test (session, file_uri, + G_RESOLVER_ERROR, G_RESOLVER_ERROR_NOT_FOUND, + "r"); + + debug_printf (1, " wrong http (invalid port)\n"); + wrong_http_uri = soup_uri_new (HTTP_SERVER); + wrong_http_uri->port = 1234; + do_one_connection_connect_fail_test (session, wrong_http_uri, + G_IO_ERROR, G_IO_ERROR_CONNECTION_REFUSED, + "rRcr"); /* FIXME: why r again? GLib bug? */ + + proxy_uri = soup_uri_new (HTTP_PROXY); + g_object_set (G_OBJECT (session), + SOUP_SESSION_PROXY_URI, proxy_uri, + NULL); + + debug_printf (1, " http with proxy\n"); + do_one_connection_connect_test (session, http_uri, + "HTTP/1.1 403 Forbidden", "rRcCx"); + + if (tls_available) { + debug_printf (1, " https with proxy\n"); + do_one_connection_connect_test (session, https_uri, + "HTTP/1.1 200 OK", "rRcCpPtTx"); + } else + debug_printf (1, " https with proxy -- SKIPPING\n"); + + debug_printf (1, " ws with proxy\n"); + do_one_connection_connect_test (session, ws_uri, + "HTTP/1.1 403 Forbidden", "rRcCx"); + + if (tls_available) { + debug_printf (1, " wss with proxy\n"); + do_one_connection_connect_test (session, wss_uri, + "HTTP/1.1 200 OK", "rRcCpPtTx"); + } else + debug_printf (1, " wss with proxy -- SKIPPING\n"); + + soup_uri_free (http_uri); + if (https_uri) + soup_uri_free (https_uri); + soup_uri_free (ws_uri); + if (wss_uri) + soup_uri_free (wss_uri); + soup_uri_free (file_uri); + soup_uri_free (wrong_http_uri); + soup_uri_free (proxy_uri); + + soup_test_session_abort_unref (session); +} + +int +main (int argc, char **argv) +{ + int ret; + + test_init (argc, argv, NULL); + apache_init (); + + server = soup_test_server_new (SOUP_TEST_SERVER_IN_THREAD); + soup_server_add_handler (server, NULL, server_callback, "http", NULL); + base_uri = soup_test_server_get_uri (server, "http", NULL); + + g_test_add_func ("/connection/content-length-framing", do_content_length_framing_test); + g_test_add_func ("/connection/persistent-connection-timeout", do_persistent_connection_timeout_test); + g_test_add_func ("/connection/max-conns", do_max_conns_test); + g_test_add_func ("/connection/non-persistent", do_non_persistent_connection_test); + g_test_add_func ("/connection/non-idempotent", do_non_idempotent_connection_test); + g_test_add_func ("/connection/state", do_connection_state_test); + g_test_add_func ("/connection/event", do_connection_event_test); + g_test_add_func ("/connection/connect", do_connection_connect_test); + + ret = g_test_run (); + + soup_uri_free (base_uri); + soup_test_server_quit_unref (server); + + test_cleanup (); + return ret; +} diff --git a/tests/context-test.c b/tests/context-test.c new file mode 100644 index 0000000..567512f --- /dev/null +++ b/tests/context-test.c @@ -0,0 +1,357 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2007 Red Hat, Inc. + */ + +#include "test-utils.h" + +static char *base_uri; + +typedef struct { + SoupServer *server; + SoupMessage *msg; + GSource *timeout; +} SlowData; + +static void +request_finished (SoupMessage *msg, gpointer data) +{ + SlowData *sd = data; + + g_source_destroy (sd->timeout); + g_source_unref (sd->timeout); + g_free (sd); +} + +static gboolean +add_body_chunk (gpointer data) +{ + SlowData *sd = data; + + soup_message_body_append (sd->msg->response_body, + SOUP_MEMORY_STATIC, "OK\r\n", 4); + soup_message_body_complete (sd->msg->response_body); + soup_server_unpause_message (sd->server, sd->msg); + g_object_unref (sd->msg); + + return FALSE; +} + +static void +server_callback (SoupServer *server, SoupMessage *msg, + const char *path, GHashTable *query, + SoupClientContext *context, gpointer data) +{ + SlowData *sd; + + if (msg->method != SOUP_METHOD_GET) { + soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED); + return; + } + + soup_message_set_status (msg, SOUP_STATUS_OK); + if (!strcmp (path, "/fast")) { + soup_message_set_response (msg, "text/plain", + SOUP_MEMORY_STATIC, "OK\r\n", 4); + return; + } + + soup_message_headers_set_encoding (msg->response_headers, + SOUP_ENCODING_CHUNKED); + g_object_ref (msg); + soup_server_pause_message (server, msg); + + sd = g_new (SlowData, 1); + sd->server = server; + sd->msg = msg; + sd->timeout = soup_add_timeout ( + g_main_context_get_thread_default (), + 200, add_body_chunk, sd); + g_source_ref (sd->timeout); + g_signal_connect (msg, "finished", + G_CALLBACK (request_finished), sd); +} + +/* Test 1: An async session in another thread with its own + * async_context can complete a request while the main thread's main + * loop is stopped. + */ + +static gboolean idle_start_test1_thread (gpointer loop); +static gpointer test1_thread (gpointer user_data); + +static GCond test1_cond; +static GMutex test1_mutex; +static GMainLoop *test1_loop; + +static void +do_test1 (gconstpointer data) +{ + gboolean use_thread_context = GPOINTER_TO_INT (data); + + test1_loop = g_main_loop_new (NULL, FALSE); + g_idle_add (idle_start_test1_thread, GINT_TO_POINTER (use_thread_context)); + g_main_loop_run (test1_loop); + g_main_loop_unref (test1_loop); +} + +static gboolean +idle_start_test1_thread (gpointer use_thread_context) +{ + guint64 time; + GThread *thread; + + g_mutex_lock (&test1_mutex); + thread = g_thread_new ("test1_thread", test1_thread, use_thread_context); + + time = g_get_monotonic_time () + 5000000; + if (g_cond_wait_until (&test1_cond, &test1_mutex, time)) + g_thread_join (thread); + else { + soup_test_assert (FALSE, "timeout"); + g_thread_unref (thread); + } + + g_mutex_unlock (&test1_mutex); + g_main_loop_quit (test1_loop); + return FALSE; +} + +static void +test1_finished (SoupSession *session, SoupMessage *msg, gpointer loop) +{ + g_main_loop_quit (loop); +} + +static gpointer +test1_thread (gpointer use_thread_context) +{ + SoupSession *session; + GMainContext *async_context; + char *uri; + SoupMessage *msg; + GMainLoop *loop; + + /* Wait for main thread to be waiting on test1_cond */ + g_mutex_lock (&test1_mutex); + g_mutex_unlock (&test1_mutex); + + async_context = g_main_context_new (); + if (use_thread_context) { + g_main_context_push_thread_default (async_context); + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, + SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, + NULL); + } else { + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, + SOUP_SESSION_ASYNC_CONTEXT, async_context, + NULL); + } + g_main_context_unref (async_context); + + uri = g_build_filename (base_uri, "slow", NULL); + + debug_printf (1, " send_message\n"); + msg = soup_message_new ("GET", uri); + soup_session_send_message (session, msg); + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + g_object_unref (msg); + + debug_printf (1, " queue_message\n"); + msg = soup_message_new ("GET", uri); + loop = g_main_loop_new (async_context, FALSE); + g_object_ref (msg); + soup_session_queue_message (session, msg, test1_finished, loop); + g_main_loop_run (loop); + g_main_loop_unref (loop); + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + g_object_unref (msg); + + soup_test_session_abort_unref (session); + g_free (uri); + + g_cond_signal (&test1_cond); + + if (use_thread_context) + g_main_context_pop_thread_default (async_context); + return NULL; +} + +/* Test 2: An async session in the main thread with its own + * async_context runs independently of the default main loop. + */ + +static gboolean idle_test2_fail (gpointer user_data); + +static void +do_test2 (gconstpointer data) +{ + gboolean use_thread_context = GPOINTER_TO_INT (data); + guint idle; + GMainContext *async_context; + SoupSession *session; + char *uri; + SoupMessage *msg; + + idle = g_idle_add_full (G_PRIORITY_HIGH, idle_test2_fail, NULL, NULL); + + async_context = g_main_context_new (); + if (use_thread_context) { + g_main_context_push_thread_default (async_context); + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, + SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, + NULL); + } else { + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, + SOUP_SESSION_ASYNC_CONTEXT, async_context, + NULL); + } + g_main_context_unref (async_context); + + uri = g_build_filename (base_uri, "slow", NULL); + + debug_printf (1, " send_message\n"); + msg = soup_message_new ("GET", uri); + soup_session_send_message (session, msg); + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + g_object_unref (msg); + + soup_test_session_abort_unref (session); + g_free (uri); + + g_source_remove (idle); + + if (use_thread_context) + g_main_context_pop_thread_default (async_context); +} + +static gboolean +idle_test2_fail (gpointer user_data) +{ + soup_test_assert (FALSE, "idle ran"); + return FALSE; +} + +static void +multi_request_started (SoupSession *session, SoupMessage *msg, + SoupSocket *socket, gpointer user_data) +{ + g_object_set_data (G_OBJECT (msg), "started", GUINT_TO_POINTER (TRUE)); +} + +static void +msg1_got_headers (SoupMessage *msg, gpointer user_data) +{ + GMainLoop *loop = user_data; + + g_main_loop_quit (loop); +} + +static void +multi_msg_finished (SoupSession *session, SoupMessage *msg, gpointer user_data) +{ + GMainLoop *loop = user_data; + + g_object_set_data (G_OBJECT (msg), "finished", GUINT_TO_POINTER (TRUE)); + g_main_loop_quit (loop); +} + +static void +do_multicontext_test (void) +{ + SoupSession *session; + SoupMessage *msg1, *msg2; + GMainContext *context1, *context2; + GMainLoop *loop1, *loop2; + + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, + SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, + NULL); + g_signal_connect (session, "request-started", + G_CALLBACK (multi_request_started), NULL); + + context1 = g_main_context_new (); + loop1 = g_main_loop_new (context1, FALSE); + context2 = g_main_context_new (); + loop2 = g_main_loop_new (context2, FALSE); + + g_main_context_push_thread_default (context1); + msg1 = soup_message_new ("GET", base_uri); + g_object_ref (msg1); + soup_session_queue_message (session, msg1, multi_msg_finished, loop1); + g_signal_connect (msg1, "got-headers", + G_CALLBACK (msg1_got_headers), loop1); + g_object_set_data (G_OBJECT (msg1), "session", session); + g_main_context_pop_thread_default (context1); + + g_main_context_push_thread_default (context2); + msg2 = soup_message_new ("GET", base_uri); + g_object_ref (msg2); + soup_session_queue_message (session, msg2, multi_msg_finished, loop2); + g_main_context_pop_thread_default (context2); + + g_main_context_push_thread_default (context1); + g_main_loop_run (loop1); + g_main_context_pop_thread_default (context1); + + if (!g_object_get_data (G_OBJECT (msg1), "started")) + soup_test_assert (FALSE, "msg1 not started"); + if (g_object_get_data (G_OBJECT (msg2), "started")) + soup_test_assert (FALSE, "msg2 started while loop1 was running"); + + g_main_context_push_thread_default (context2); + g_main_loop_run (loop2); + g_main_context_pop_thread_default (context2); + + if (g_object_get_data (G_OBJECT (msg1), "finished")) + soup_test_assert (FALSE, "msg1 finished while loop2 was running"); + if (!g_object_get_data (G_OBJECT (msg2), "finished")) + soup_test_assert (FALSE, "msg2 not finished"); + + g_main_context_push_thread_default (context1); + g_main_loop_run (loop1); + g_main_context_pop_thread_default (context1); + + if (!g_object_get_data (G_OBJECT (msg1), "finished")) + soup_test_assert (FALSE, "msg1 not finished"); + + g_object_unref (msg1); + g_object_unref (msg2); + + soup_test_session_abort_unref (session); + + g_main_loop_unref (loop1); + g_main_loop_unref (loop2); + g_main_context_unref (context1); + g_main_context_unref (context2); +} + +int +main (int argc, char **argv) +{ + SoupServer *server; + SoupURI *uri; + int ret; + + test_init (argc, argv, NULL); + + server = soup_test_server_new (SOUP_TEST_SERVER_IN_THREAD); + soup_server_add_handler (server, NULL, server_callback, NULL, NULL); + uri = soup_test_server_get_uri (server, "http", NULL); + base_uri = soup_uri_to_string (uri, FALSE); + soup_uri_free (uri); + + g_test_add_data_func ("/context/blocking/explicit", GINT_TO_POINTER (FALSE), do_test1); + g_test_add_data_func ("/context/blocking/thread-default", GINT_TO_POINTER (TRUE), do_test1); + g_test_add_data_func ("/context/nested/explicit", GINT_TO_POINTER (FALSE), do_test2); + g_test_add_data_func ("/context/nested/thread-default", GINT_TO_POINTER (TRUE), do_test2); + g_test_add_func ("/context/multiple", do_multicontext_test); + + ret = g_test_run (); + + g_free (base_uri); + soup_test_server_quit_unref (server); + + test_cleanup (); + return ret; +} diff --git a/tests/continue-test.c b/tests/continue-test.c new file mode 100644 index 0000000..5e0c660 --- /dev/null +++ b/tests/continue-test.c @@ -0,0 +1,510 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2007 Novell, Inc. + */ + +#include "test-utils.h" + +#define SHORT_BODY "This is a test.\r\n" +#define LONG_BODY (SHORT_BODY SHORT_BODY) + +#define MAX_POST_LENGTH (sizeof (SHORT_BODY)) + +static SoupURI *base_uri; +static GSList *events; + +static void +event (SoupMessage *msg, const char *side, const char *message) +{ + char *data = g_strdup_printf ("%s-%s", side, message); + gboolean record_status = + (!strcmp (data, "server-wrote_headers") || + !strcmp (data, "server-wrote_informational")); + + debug_printf (2, " %s", data); + if (record_status) + debug_printf (2, " (%s)", msg->reason_phrase); + debug_printf (2, "\n"); + + events = g_slist_append (events, data); + if (record_status) + events = g_slist_append (events, GUINT_TO_POINTER (msg->status_code)); +} + +#define EVENT_HANDLER(name) \ +static void \ +name (SoupMessage *msg, gpointer side) \ +{ \ + event (msg, side, #name); \ +} + +EVENT_HANDLER (got_informational) +EVENT_HANDLER (got_headers) +EVENT_HANDLER (got_body) +EVENT_HANDLER (wrote_informational) +EVENT_HANDLER (wrote_headers) +EVENT_HANDLER (wrote_body) +EVENT_HANDLER (finished) + +static void +do_message (const char *path, gboolean long_body, + gboolean expect_continue, gboolean auth, + ...) +{ + SoupSession *session; + SoupMessage *msg; + const char *body; + SoupURI *uri; + va_list ap; + const char *expected_event; + char *actual_event; + int expected_status, actual_status; + + uri = soup_uri_copy (base_uri); + if (auth) { + soup_uri_set_user (uri, "user"); + soup_uri_set_password (uri, "pass"); + } + soup_uri_set_path (uri, path); + msg = soup_message_new_from_uri ("POST", uri); + soup_uri_free (uri); + + body = long_body ? LONG_BODY : SHORT_BODY; + soup_message_set_request (msg, "text/plain", SOUP_MEMORY_STATIC, + body, strlen (body)); + soup_message_headers_append (msg->request_headers, "Connection", "close"); + if (expect_continue) { + soup_message_headers_set_expectations (msg->request_headers, + SOUP_EXPECTATION_CONTINUE); + } + + g_signal_connect (msg, "got_informational", + G_CALLBACK (got_informational), "client"); + g_signal_connect (msg, "got_headers", + G_CALLBACK (got_headers), "client"); + g_signal_connect (msg, "got_body", + G_CALLBACK (got_body), "client"); + g_signal_connect (msg, "wrote_informational", + G_CALLBACK (wrote_informational), "client"); + g_signal_connect (msg, "wrote_headers", + G_CALLBACK (wrote_headers), "client"); + g_signal_connect (msg, "wrote_body", + G_CALLBACK (wrote_body), "client"); + g_signal_connect (msg, "finished", + G_CALLBACK (finished), "client"); + + events = NULL; + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + soup_session_send_message (session, msg); + soup_test_session_abort_unref (session); + + va_start (ap, auth); + while ((expected_event = va_arg (ap, const char *))) { + + if (!events) { + soup_test_assert (events != NULL, + "Expected '%s', got end of list", + expected_event); + continue; + } else { + actual_event = events->data; + g_assert_cmpstr (expected_event, ==, actual_event); + events = g_slist_delete_link (events, events); + } + + if (!strcmp (expected_event, "server-wrote_headers") || + !strcmp (expected_event, "server-wrote_informational")) + expected_status = va_arg (ap, int); + else + expected_status = -1; + if (!strcmp (actual_event, "server-wrote_headers") || + !strcmp (actual_event, "server-wrote_informational")) { + actual_status = GPOINTER_TO_INT (events->data); + events = g_slist_delete_link (events, events); + } else + expected_status = -1; + + if (expected_status != -1 && actual_status != -1 && + expected_status != actual_status) { + soup_test_assert (expected_status == actual_status, + "Expected status '%s', got '%s'", + soup_status_get_phrase (expected_status), + soup_status_get_phrase (actual_status)); + } + + g_free (actual_event); + } + va_end (ap); + while (events) { + actual_event = events->data; + soup_test_assert (events == NULL, + "Expected to be done, got '%s'", actual_event); + events = g_slist_delete_link (events, events); + + if (!strcmp (actual_event, "server-wrote_headers") || + !strcmp (actual_event, "server-wrote_informational")) + events = g_slist_delete_link (events, events); + } + g_object_unref (msg); +} + +static void +do_test_unauth_short_noexpect_nopass (void) +{ + do_message ("/unauth", FALSE, FALSE, FALSE, + "client-wrote_headers", + "client-wrote_body", + "server-got_headers", + "server-got_body", + "server-wrote_headers", SOUP_STATUS_CREATED, + "server-wrote_body", + "server-finished", + "client-got_headers", + "client-got_body", + "client-finished", + NULL); +} + +static void +do_test_unauth_long_noexpect_nopass (void) +{ + do_message ("/unauth", TRUE, FALSE, FALSE, + "client-wrote_headers", + "client-wrote_body", + "server-got_headers", + "server-got_body", + "server-wrote_headers", SOUP_STATUS_REQUEST_ENTITY_TOO_LARGE, + "server-wrote_body", + "server-finished", + "client-got_headers", + "client-got_body", + "client-finished", + NULL); +} + +static void +do_test_unauth_short_expect_nopass (void) +{ + do_message ("/unauth", FALSE, TRUE, FALSE, + "client-wrote_headers", + "server-got_headers", + "server-wrote_informational", SOUP_STATUS_CONTINUE, + "client-got_informational", + "client-wrote_body", + "server-got_body", + "server-wrote_headers", SOUP_STATUS_CREATED, + "server-wrote_body", + "server-finished", + "client-got_headers", + "client-got_body", + "client-finished", + NULL); +} + +static void +do_test_unauth_long_expect_nopass (void) +{ + do_message ("/unauth", TRUE, TRUE, FALSE, + "client-wrote_headers", + "server-got_headers", + "server-wrote_headers", SOUP_STATUS_REQUEST_ENTITY_TOO_LARGE, + "server-wrote_body", + "server-finished", + "client-got_headers", + "client-got_body", + "client-finished", + NULL); +} + +static void +do_test_auth_short_noexpect_nopass (void) +{ + do_message ("/auth", FALSE, FALSE, FALSE, + "client-wrote_headers", + "client-wrote_body", + "server-got_headers", + "server-got_body", + "server-wrote_headers", SOUP_STATUS_UNAUTHORIZED, + "server-wrote_body", + "server-finished", + "client-got_headers", + "client-got_body", + "client-finished", + NULL); +} + +static void +do_test_auth_long_noexpect_nopass (void) +{ + do_message ("/auth", TRUE, FALSE, FALSE, + "client-wrote_headers", + "client-wrote_body", + "server-got_headers", + "server-got_body", + "server-wrote_headers", SOUP_STATUS_UNAUTHORIZED, + "server-wrote_body", + "server-finished", + "client-got_headers", + "client-got_body", + "client-finished", + NULL); +} + +static void +do_test_auth_short_expect_nopass (void) +{ + do_message ("/auth", FALSE, TRUE, FALSE, + "client-wrote_headers", + "server-got_headers", + "server-wrote_headers", SOUP_STATUS_UNAUTHORIZED, + "server-wrote_body", + "server-finished", + "client-got_headers", + "client-got_body", + "client-finished", + NULL); +} + +static void +do_test_auth_long_expect_nopass (void) +{ + do_message ("/auth", TRUE, TRUE, FALSE, + "client-wrote_headers", + "server-got_headers", + "server-wrote_headers", SOUP_STATUS_UNAUTHORIZED, + "server-wrote_body", + "server-finished", + "client-got_headers", + "client-got_body", + "client-finished", + NULL); +} + +static void +do_test_auth_short_noexpect_pass (void) +{ + do_message ("/auth", FALSE, FALSE, TRUE, + "client-wrote_headers", + "client-wrote_body", + "server-got_headers", + "server-got_body", + "server-wrote_headers", SOUP_STATUS_UNAUTHORIZED, + "server-wrote_body", + "server-finished", + "client-got_headers", + "client-got_body", + "client-wrote_headers", + "client-wrote_body", + "server-got_headers", + "server-got_body", + "server-wrote_headers", SOUP_STATUS_CREATED, + "server-wrote_body", + "server-finished", + "client-got_headers", + "client-got_body", + "client-finished", + NULL); +} + +static void +do_test_auth_long_noexpect_pass (void) +{ + do_message ("/auth", TRUE, FALSE, TRUE, + "client-wrote_headers", + "client-wrote_body", + "server-got_headers", + "server-got_body", + "server-wrote_headers", SOUP_STATUS_UNAUTHORIZED, + "server-wrote_body", + "server-finished", + "client-got_headers", + "client-got_body", + "client-wrote_headers", + "client-wrote_body", + "server-got_headers", + "server-got_body", + "server-wrote_headers", SOUP_STATUS_REQUEST_ENTITY_TOO_LARGE, + "server-wrote_body", + "server-finished", + "client-got_headers", + "client-got_body", + "client-finished", + NULL); +} + +static void +do_test_auth_short_expect_pass (void) +{ + do_message ("/auth", FALSE, TRUE, TRUE, + "client-wrote_headers", + "server-got_headers", + "server-wrote_headers", SOUP_STATUS_UNAUTHORIZED, + "server-wrote_body", + "server-finished", + "client-got_headers", + "client-got_body", + "client-wrote_headers", + "server-got_headers", + "server-wrote_informational", SOUP_STATUS_CONTINUE, + "client-got_informational", + "client-wrote_body", + "server-got_body", + "server-wrote_headers", SOUP_STATUS_CREATED, + "server-wrote_body", + "server-finished", + "client-got_headers", + "client-got_body", + "client-finished", + NULL); +} + +static void +do_test_auth_long_expect_pass (void) +{ + do_message ("/auth", TRUE, TRUE, TRUE, + "client-wrote_headers", + "server-got_headers", + "server-wrote_headers", SOUP_STATUS_UNAUTHORIZED, + "server-wrote_body", + "server-finished", + "client-got_headers", + "client-got_body", + "client-wrote_headers", + "server-got_headers", + "server-wrote_headers", SOUP_STATUS_REQUEST_ENTITY_TOO_LARGE, + "server-wrote_body", + "server-finished", + "client-got_headers", + "client-got_body", + "client-finished", + NULL); +} + + +/* SERVER */ + +static void +server_got_headers (SoupMessage *msg, gpointer server) +{ + /* FIXME */ + if (msg->status_code != SOUP_STATUS_CONTINUE && + msg->status_code != 0) + return; + + if (soup_message_headers_get_expectations (msg->request_headers) & + SOUP_EXPECTATION_CONTINUE) { + const char *length; + + length = soup_message_headers_get_one (msg->request_headers, + "Content-Length"); + if (length && atoi (length) > MAX_POST_LENGTH) { + soup_message_set_status (msg, SOUP_STATUS_REQUEST_ENTITY_TOO_LARGE); + soup_message_headers_append (msg->response_headers, "Connection", "close"); + } + } +} + +static void +request_started (SoupServer *server, SoupMessage *msg, + SoupClientContext *client, gpointer user_data) +{ + g_signal_connect (msg, "got_headers", + G_CALLBACK (server_got_headers), server); + + g_signal_connect (msg, "got_informational", + G_CALLBACK (got_informational), "server"); + g_signal_connect (msg, "got_headers", + G_CALLBACK (got_headers), "server"); + g_signal_connect (msg, "got_body", + G_CALLBACK (got_body), "server"); + g_signal_connect (msg, "wrote_informational", + G_CALLBACK (wrote_informational), "server"); + g_signal_connect (msg, "wrote_headers", + G_CALLBACK (wrote_headers), "server"); + g_signal_connect (msg, "wrote_body", + G_CALLBACK (wrote_body), "server"); + g_signal_connect (msg, "finished", + G_CALLBACK (finished), "server"); +} + +static gboolean +auth_callback (SoupAuthDomain *auth_domain, SoupMessage *msg, + const char *username, const char *password, gpointer user_data) +{ + return !strcmp (username, "user") && !strcmp (password, "pass"); +} + +static void +server_callback (SoupServer *server, SoupMessage *msg, + const char *path, GHashTable *query, + SoupClientContext *context, gpointer data) +{ + if (msg->method != SOUP_METHOD_POST) { + soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED); + soup_message_headers_append (msg->response_headers, "Connection", "close"); + } else if (msg->request_body->length > MAX_POST_LENGTH) { + soup_message_set_status (msg, SOUP_STATUS_REQUEST_ENTITY_TOO_LARGE); + soup_message_headers_append (msg->response_headers, "Connection", "close"); + } else + soup_message_set_status (msg, SOUP_STATUS_CREATED); +} + +static SoupServer * +setup_server (void) +{ + SoupServer *server; + SoupAuthDomain *auth_domain; + + server = soup_test_server_new (SOUP_TEST_SERVER_DEFAULT); + + g_signal_connect (server, "request-started", + G_CALLBACK (request_started), NULL); + + soup_server_add_handler (server, NULL, server_callback, NULL, NULL); + + auth_domain = soup_auth_domain_basic_new ( + SOUP_AUTH_DOMAIN_REALM, "continue-test", + SOUP_AUTH_DOMAIN_ADD_PATH, "/auth", + SOUP_AUTH_DOMAIN_BASIC_AUTH_CALLBACK, auth_callback, + NULL); + soup_server_add_auth_domain (server, auth_domain); + g_object_unref (auth_domain); + + return server; +} + +/* MAIN */ + +int +main (int argc, char **argv) +{ + SoupServer *server; + int ret; + + test_init (argc, argv, NULL); + + server = setup_server (); + base_uri = soup_test_server_get_uri (server, "http", NULL); + + g_test_add_func ("/continue/unauth_short_noexpect_nopass", do_test_unauth_short_noexpect_nopass); + g_test_add_func ("/continue/unauth_long_noexpect_nopass", do_test_unauth_long_noexpect_nopass); + g_test_add_func ("/continue/unauth_short_expect_nopass", do_test_unauth_short_expect_nopass); + g_test_add_func ("/continue/unauth_long_expect_nopass", do_test_unauth_long_expect_nopass); + g_test_add_func ("/continue/auth_short_noexpect_nopass", do_test_auth_short_noexpect_nopass); + g_test_add_func ("/continue/auth_long_noexpect_nopass", do_test_auth_long_noexpect_nopass); + g_test_add_func ("/continue/auth_short_expect_nopass", do_test_auth_short_expect_nopass); + g_test_add_func ("/continue/auth_long_expect_nopass", do_test_auth_long_expect_nopass); + g_test_add_func ("/continue/auth_short_noexpect_pass", do_test_auth_short_noexpect_pass); + g_test_add_func ("/continue/auth_long_noexpect_pass", do_test_auth_long_noexpect_pass); + g_test_add_func ("/continue/auth_short_expect_pass", do_test_auth_short_expect_pass); + g_test_add_func ("/continue/auth_long_expect_pass", do_test_auth_long_expect_pass); + + ret = g_test_run (); + + soup_test_server_quit_unref (server); + soup_uri_free (base_uri); + + test_cleanup (); + + return ret; +} diff --git a/tests/cookies-test.c b/tests/cookies-test.c new file mode 100644 index 0000000..17b77f2 --- /dev/null +++ b/tests/cookies-test.c @@ -0,0 +1,322 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2010 Igalia S.L. + */ + +#include "test-utils.h" + +SoupServer *server; +SoupURI *first_party_uri, *third_party_uri; +const char *first_party = "http://127.0.0.1/"; +const char *third_party = "http://localhost/"; + +static void +server_callback (SoupServer *server, SoupMessage *msg, + const char *path, GHashTable *query, + SoupClientContext *context, gpointer data) +{ + if (g_str_equal (path, "/index.html")) { + soup_message_headers_replace (msg->response_headers, + "Set-Cookie", + "foo=bar"); + } else if (g_str_equal (path, "/foo.jpg")) { + soup_message_headers_replace (msg->response_headers, + "Set-Cookie", + "baz=qux"); + } else if (soup_message_headers_get_one (msg->request_headers, + "Echo-Set-Cookie")) { + soup_message_headers_replace (msg->response_headers, + "Set-Cookie", + soup_message_headers_get_one (msg->request_headers, + "Echo-Set-Cookie")); + } + + soup_message_set_status (msg, SOUP_STATUS_OK); +} + +typedef struct { + SoupCookieJarAcceptPolicy policy; + int n_cookies; +} CookiesForPolicy; + +static const CookiesForPolicy validResults[] = { + { SOUP_COOKIE_JAR_ACCEPT_ALWAYS, 2 }, + { SOUP_COOKIE_JAR_ACCEPT_NEVER, 0 }, + { SOUP_COOKIE_JAR_ACCEPT_NO_THIRD_PARTY, 1 } +}; + +static void +do_cookies_accept_policy_test (void) +{ + SoupSession *session; + SoupMessage *msg; + SoupURI *uri; + SoupCookieJar *jar; + GSList *l, *p; + int i; + + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + soup_session_add_feature_by_type (session, SOUP_TYPE_COOKIE_JAR); + jar = SOUP_COOKIE_JAR (soup_session_get_feature (session, SOUP_TYPE_COOKIE_JAR)); + + for (i = 0; i < G_N_ELEMENTS (validResults); i++) { + soup_cookie_jar_set_accept_policy (jar, validResults[i].policy); + + uri = soup_uri_new_with_base (first_party_uri, "/index.html"); + msg = soup_message_new_from_uri ("GET", uri); + soup_message_set_first_party (msg, first_party_uri); + soup_session_send_message (session, msg); + soup_uri_free (uri); + g_object_unref (msg); + + /* We can't use two servers due to limitations in + * test_server, so let's swap first and third party here + * to simulate a cookie coming from a third party. + */ + uri = soup_uri_new_with_base (first_party_uri, "/foo.jpg"); + msg = soup_message_new_from_uri ("GET", uri); + soup_message_set_first_party (msg, third_party_uri); + soup_session_send_message (session, msg); + soup_uri_free (uri); + g_object_unref (msg); + + l = soup_cookie_jar_all_cookies (jar); + g_assert_cmpint (g_slist_length (l), ==, validResults[i].n_cookies); + + for (p = l; p; p = p->next) { + soup_cookie_jar_delete_cookie (jar, p->data); + soup_cookie_free (p->data); + } + + g_slist_free (l); + } + + soup_test_session_abort_unref (session); +} + +static void +do_cookies_subdomain_policy_test (void) +{ + SoupCookieJar *jar; + GSList *cookies; + SoupURI *uri1; + SoupURI *uri2; + SoupURI *uri3; + + g_test_bug ("792130"); + + /* Only the base domain should be considered when deciding + * whether a cookie is a third-party cookie. + */ + uri1 = soup_uri_new ("https://www.gnome.org"); + uri2 = soup_uri_new ("https://foundation.gnome.org"); + uri3 = soup_uri_new ("https://www.gnome.org."); + + /* We can't check subdomains with a test server running on + * localhost, so we'll just check the cookie jar API itself. + */ + + /* Cookie should be accepted. One cookie in the jar. */ + jar = soup_cookie_jar_new (); + soup_cookie_jar_set_accept_policy (jar, SOUP_COOKIE_JAR_ACCEPT_NO_THIRD_PARTY); + soup_cookie_jar_set_cookie_with_first_party (jar, uri1, uri2, "1=foo"); + cookies = soup_cookie_jar_all_cookies (jar); + g_assert_cmpint (g_slist_length (cookies), ==, 1); + g_slist_free_full (cookies, (GDestroyNotify)soup_cookie_free); + + /* Cookie should be accepted. Two cookies in the jar. */ + soup_cookie_jar_set_cookie_with_first_party (jar, uri2, uri1, "2=foo"); + cookies = soup_cookie_jar_all_cookies (jar); + g_assert_cmpint (g_slist_length (cookies), ==, 2); + g_slist_free_full (cookies, (GDestroyNotify)soup_cookie_free); + + /* Third-party cookie should be rejected, so there are still + * only two cookies in the jar. + */ + soup_cookie_jar_set_cookie_with_first_party (jar, third_party_uri, uri1, "3=foo"); + cookies = soup_cookie_jar_all_cookies (jar); + g_assert_cmpint (g_slist_length (cookies), ==, 2); + g_slist_free_full (cookies, (GDestroyNotify)soup_cookie_free); + + /* Now some Domain attribute tests.*/ + soup_cookie_jar_set_accept_policy (jar, SOUP_COOKIE_JAR_ACCEPT_ALWAYS); + + /* The cookie must be rejected if the Domain is not an appropriate + * match for the URI. Still two cookies in the jar. + */ + soup_cookie_jar_set_cookie (jar, uri1, "4=foo; Domain=gitlab.gnome.org"); + cookies = soup_cookie_jar_all_cookies (jar); + g_assert_cmpint (g_slist_length (cookies), ==, 2); + g_slist_free_full (cookies, (GDestroyNotify)soup_cookie_free); + + /* Now the Domain is an appropriate match. Three cookies in the jar. */ + soup_cookie_jar_set_cookie (jar, uri1, "5=foo; Domain=gnome.org"); + cookies = soup_cookie_jar_all_cookies (jar); + g_assert_cmpint (g_slist_length (cookies), ==, 3); + g_slist_free_full (cookies, (GDestroyNotify)soup_cookie_free); + + /* A leading dot in the domain property should not affect things. + * This cookie should be accepted. Four cookies in the jar. + */ + soup_cookie_jar_set_cookie (jar, uri1, "6=foo; Domain=.www.gnome.org"); + cookies = soup_cookie_jar_all_cookies (jar); + g_assert_cmpint (g_slist_length (cookies), ==, 4); + g_slist_free_full (cookies, (GDestroyNotify)soup_cookie_free); + + /* The cookie must be rejected if the Domain ends in a trailing dot + * but the uri doesn't. + */ + soup_cookie_jar_set_cookie (jar, uri1, "7=foo; Domain=www.gnome.org."); + cookies = soup_cookie_jar_all_cookies (jar); + g_assert_cmpint (g_slist_length (cookies), ==, 4); + g_slist_free_full (cookies, (GDestroyNotify)soup_cookie_free); + + /* The cookie should be accepted if both Domain and URI end with a trailing + * dot and they are a match. Five cookies in the jar. + */ + soup_cookie_jar_set_cookie (jar, uri3, "8=foo; Domain=gnome.org."); + cookies = soup_cookie_jar_all_cookies (jar); + g_assert_cmpint (g_slist_length (cookies), ==, 5); + g_slist_free_full (cookies, (GDestroyNotify)soup_cookie_free); + + /* The cookie should be rejected if URI has trailing dot but Domain doesn't. + * Five cookies in the jar. + */ + soup_cookie_jar_set_cookie (jar, uri3, "9=foo; Domain=gnome.org"); + cookies = soup_cookie_jar_all_cookies (jar); + g_assert_cmpint (g_slist_length (cookies), ==, 5); + g_slist_free_full (cookies, (GDestroyNotify)soup_cookie_free); + + /* It should not be possible to set a cookie for a TLD. Still five + * cookies in the jar. + */ + soup_cookie_jar_set_cookie (jar, uri1, "10=foo; Domain=.org"); + cookies = soup_cookie_jar_all_cookies (jar); + g_assert_cmpint (g_slist_length (cookies), ==, 5); + g_slist_free_full (cookies, (GDestroyNotify)soup_cookie_free); + + /* It should still not be possible to set a cookie for a TLD, even if + * we are tricksy and have a trailing dot. Still only five cookies. + */ + soup_cookie_jar_set_cookie (jar, uri3, "11=foo; Domain=.org."); + cookies = soup_cookie_jar_all_cookies (jar); + g_assert_cmpint (g_slist_length (cookies), ==, 5); + g_slist_free_full (cookies, (GDestroyNotify)soup_cookie_free); + + soup_uri_free (uri1); + soup_uri_free (uri2); + soup_uri_free (uri3); + g_object_unref (jar); +} + +/* FIXME: moar tests! */ +static void +do_cookies_parsing_test (void) +{ + SoupSession *session; + SoupMessage *msg; + SoupCookieJar *jar; + GSList *cookies, *iter; + SoupCookie *cookie; + gboolean got1, got2, got3; + + g_test_bug ("678753"); + + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + soup_session_add_feature_by_type (session, SOUP_TYPE_COOKIE_JAR); + jar = SOUP_COOKIE_JAR (soup_session_get_feature (session, SOUP_TYPE_COOKIE_JAR)); + + /* "httponly" is case-insensitive, and its value (if any) is ignored */ + msg = soup_message_new_from_uri ("GET", first_party_uri); + soup_message_headers_append (msg->request_headers, "Echo-Set-Cookie", + "one=1; httponly; max-age=100"); + soup_session_send_message (session, msg); + g_object_unref (msg); + + msg = soup_message_new_from_uri ("GET", first_party_uri); + soup_message_headers_append (msg->request_headers, "Echo-Set-Cookie", + "two=2; HttpOnly; max-age=100"); + soup_session_send_message (session, msg); + g_object_unref (msg); + + msg = soup_message_new_from_uri ("GET", first_party_uri); + soup_message_headers_append (msg->request_headers, "Echo-Set-Cookie", + "three=3; httpONLY=Wednesday; max-age=100"); + soup_session_send_message (session, msg); + g_object_unref (msg); + + cookies = soup_cookie_jar_get_cookie_list (jar, first_party_uri, TRUE); + got1 = got2 = got3 = FALSE; + + for (iter = cookies; iter; iter = iter->next) { + cookie = iter->data; + + if (!strcmp (soup_cookie_get_name (cookie), "one")) { + got1 = TRUE; + g_assert_true (soup_cookie_get_http_only (cookie)); + g_assert_true (soup_cookie_get_expires (cookie) != NULL); + } else if (!strcmp (soup_cookie_get_name (cookie), "two")) { + got2 = TRUE; + g_assert_true (soup_cookie_get_http_only (cookie)); + g_assert_true (soup_cookie_get_expires (cookie) != NULL); + } else if (!strcmp (soup_cookie_get_name (cookie), "three")) { + got3 = TRUE; + g_assert_true (soup_cookie_get_http_only (cookie)); + g_assert_true (soup_cookie_get_expires (cookie) != NULL); + } else { + soup_test_assert (FALSE, "got unexpected cookie '%s'", + soup_cookie_get_name (cookie)); + } + + soup_cookie_free (cookie); + } + g_slist_free (cookies); + + g_assert_true (got1); + g_assert_true (got2); + g_assert_true (got3); + + soup_test_session_abort_unref (session); +} + +static void +do_cookies_parsing_nopath_nullorigin (void) +{ + SoupCookie *cookie = soup_cookie_parse ("NAME=Value", NULL); + g_assert_nonnull (cookie); + g_assert_cmpstr ("/", ==, soup_cookie_get_path (cookie)); + soup_cookie_free (cookie); +} + +int +main (int argc, char **argv) +{ + SoupURI *server_uri; + int ret; + + test_init (argc, argv, NULL); + + server = soup_test_server_new (SOUP_TEST_SERVER_IN_THREAD); + soup_server_add_handler (server, NULL, server_callback, NULL, NULL); + server_uri = soup_test_server_get_uri (server, "http", NULL); + + first_party_uri = soup_uri_new (first_party); + third_party_uri = soup_uri_new (third_party); + soup_uri_set_port (first_party_uri, server_uri->port); + soup_uri_set_port (third_party_uri, server_uri->port); + + g_test_add_func ("/cookies/accept-policy", do_cookies_accept_policy_test); + g_test_add_func ("/cookies/accept-policy-subdomains", do_cookies_subdomain_policy_test); + g_test_add_func ("/cookies/parsing", do_cookies_parsing_test); + g_test_add_func ("/cookies/parsing/no-path-null-origin", do_cookies_parsing_nopath_nullorigin); + + ret = g_test_run (); + + soup_uri_free (first_party_uri); + soup_uri_free (third_party_uri); + soup_uri_free (server_uri); + soup_test_server_quit_unref (server); + + test_cleanup (); + return ret; +} diff --git a/tests/date.c b/tests/date.c new file mode 100644 index 0000000..f623061 --- /dev/null +++ b/tests/date.c @@ -0,0 +1,410 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2005 Novell, Inc. + */ + +#include "test-utils.h" + +static void check_ok (gconstpointer data); + +static SoupDate * +make_date (const char *strdate) +{ + char *dup; + SoupDate *date; + + /* We do it this way so that if soup_date_new_from_string() + * reads off the end of the string, it will trigger an error + * when valgrinding, rather than just reading the start of the + * next const string. + */ + dup = g_strdup (strdate); + date = soup_date_new_from_string (dup); + g_free (dup); + return date; +} + +static SoupDate * +check_correct_date (const char *strdate) +{ + SoupDate *date; + + date = make_date (strdate); + if (!date) { + g_assert_nonnull (date); + return NULL; + } + + g_assert_cmpint (date->year, ==, 2004); + g_assert_cmpint (date->month, ==, 11); + g_assert_cmpint (date->day, ==, 6); + g_assert_cmpint (date->hour, ==, 8); + g_assert_cmpint (date->minute, ==, 9); + g_assert_cmpint (date->second, ==, 7); + + return date; +} + +typedef struct { + SoupDateFormat format; + const char *date; + const char *bugref; +} GoodDate; + +static const GoodDate good_dates[] = { + { SOUP_DATE_HTTP, "Sat, 06 Nov 2004 08:09:07 GMT", NULL }, + { SOUP_DATE_COOKIE, "Sat, 06-Nov-2004 08:09:07 GMT", NULL }, + { SOUP_DATE_RFC2822, "Sat, 6 Nov 2004 08:09:07 -0430", "579055" }, + { SOUP_DATE_ISO8601_COMPACT, "20041106T080907", NULL }, + { SOUP_DATE_ISO8601_FULL, "2004-11-06T08:09:07", NULL }, + { SOUP_DATE_ISO8601_XMLRPC, "20041106T08:09:07", NULL } +}; + +static void +check_good (gconstpointer data) +{ + GoodDate *good = (GoodDate *)data; + SoupDate *date; + char *strdate2; + + if (good->bugref) + g_test_bug (good->bugref); + + date = check_correct_date (good->date); + if (!date) + return; + + strdate2 = soup_date_to_string (date, good->format); + soup_date_free (date); + + soup_test_assert (strcmp (good->date, strdate2) == 0, + "restringification failed: '%s' -> '%s'\n", + good->date, strdate2); + g_free (strdate2); +} + +typedef struct { + const char *date; + const char *bugref; +} OkDate; + +static const OkDate ok_dates[] = { + /* rfc1123-date, and broken variants */ + { "Sat, 06 Nov 2004 08:09:07 GMT", NULL }, + { "Sat, 6 Nov 2004 08:09:07 GMT", NULL }, + { "Sat, 6 Nov 2004 08:09:07 GMT", NULL }, + { "Sat, 06 Nov 2004 08:09:07", NULL }, + { "06 Nov 2004 08:09:07 GMT", NULL }, + { "SAT, 06 NOV 2004 08:09:07 +1000", "644048" }, + + /* rfc850-date, and broken variants */ + { "Saturday, 06-Nov-04 08:09:07 GMT", NULL }, + { "Saturday, 6-Nov-04 08:09:07 GMT", NULL }, + { "Saturday, 6-Nov-04 08:09:07 GMT", NULL }, + { "Saturday, 06-Nov-104 08:09:07 GMT", NULL }, + { "Saturday, 06-Nov-2004 08:09:07 GMT", NULL }, + { "Saturday, 6-Nov-2004 08:09:07 GMT", NULL }, + { "Saturday, 6-Nov-2004 08:09:07 GMT", NULL }, + { "Saturday, 06-Nov-04 08:09:07", NULL }, + { "06-Nov-04 08:09:07 GMT", NULL }, + + /* asctime-date, and broken variants */ + { "Sat Nov 6 08:09:07 2004", NULL }, + { "Sat Nov 06 08:09:07 2004", NULL }, + { "Sat Nov 6 08:09:07 2004", NULL }, + { "Sat Nov 6 08:09:07 2004 GMT", NULL }, + + /* ISO 8601 */ + { "2004-11-06T08:09:07Z", NULL }, + { "20041106T08:09:07Z", NULL }, + { "20041106T08:09:07+00:00", NULL }, + { "20041106T080907+00:00", NULL }, + + /* Netscape cookie spec date, and broken variants */ + { "Sat, 06-Nov-2004 08:09:07 GMT", NULL }, + { "Sat, 6-Nov-2004 08:09:07 GMT", NULL }, + { "Sat, 6-Nov-2004 08:09:07 GMT", NULL }, + { "Sat, 06-Nov-2004 08:09:07", NULL }, + + /* Original version of Netscape cookie spec, and broken variants */ + { "Sat, 06-Nov-04 08:09:07 GMT", NULL }, + { "Sat, 6-Nov-04 08:09:07 GMT", NULL }, + { "Sat, 6-Nov-04 08:09:07 GMT", NULL }, + { "Sat, 06-Nov-104 08:09:07 GMT", NULL }, + { "Sat, 06-Nov-04 08:09:07", NULL }, + + /* Miscellaneous broken formats seen on the web */ + { "Sat 06-Nov-2004 08:9:07", NULL }, + { "Saturday, 06-Nov-04 8:9:07 GMT", NULL }, + { "Sat, 06 Nov 2004 08:09:7 GMT", NULL } +}; + +static void +check_ok (gconstpointer data) +{ + OkDate *ok = (OkDate *)data; + SoupDate *date; + + if (ok->bugref) + g_test_bug (ok->bugref); + + date = check_correct_date (ok->date); + if (!date) + return; + soup_date_free (date); +} + +#define TIME_T 1099728547L +#define TIME_T_STRING "1099728547" + +static void +check_ok_time_t (void) +{ + SoupDate *date; + + date = soup_date_new_from_time_t (TIME_T); + + g_assert_cmpint (date->year, ==, 2004); + g_assert_cmpint (date->month, ==, 11); + g_assert_cmpint (date->day, ==, 6); + g_assert_cmpint (date->hour, ==, 8); + g_assert_cmpint (date->minute, ==, 9); + g_assert_cmpint (date->second, ==, 7); + + soup_date_free (date); +} + +typedef struct { + const char *date; + const char *bugref; +} BadDate; + +static const BadDate bad_dates[] = { + /* broken rfc1123-date */ + { ", 06 Nov 2004 08:09:07 GMT", NULL }, + { "Sat, Nov 2004 08:09:07 GMT", NULL }, + { "Sat, 06 2004 08:09:07 GMT", NULL }, + { "Sat, 06 Nov 08:09:07 GMT", NULL }, + { "Sat, 06 Nov 2004 :09:07 GMT", NULL }, + { "Sat, 06 Nov 2004 09:07 GMT", NULL }, + { "Sat, 06 Nov 2004 08::07 GMT", NULL }, + { "Sat, 06 Nov 2004 08:09: GMT", NULL }, + + /* broken rfc850-date */ + { ", 06-Nov-04 08:09:07 GMT", NULL }, + { "Saturday, -Nov-04 08:09:07 GMT", NULL }, + { "Saturday, Nov-04 08:09:07 GMT", NULL }, + { "Saturday, 06-04 08:09:07 GMT", NULL }, + { "Saturday, 06--04 08:09:07 GMT", NULL }, + { "Saturday, 06-Nov- 08:09:07 GMT", NULL }, + { "Saturday, 06-Nov 08:09:07 GMT", NULL }, + { "Saturday, 06-Nov-04 :09:07 GMT", NULL }, + { "Saturday, 06-Nov-04 09:07 GMT", NULL }, + { "Saturday, 06-Nov-04 08::07 GMT", NULL }, + { "Saturday, 06-Nov-04 08:09: GMT", NULL }, + + /* broken asctime-date */ + { "Nov 6 08:09:07 2004", NULL }, + { "Sat 6 08:09:07 2004", NULL }, + { "Sat Nov 08:09:07 2004", NULL }, + { "Sat Nov 6 :09:07 2004", NULL }, + { "Sat Nov 6 09:07 2004", NULL }, + { "Sat Nov 6 08::07 2004", NULL }, + { "Sat Nov 6 08:09: 2004", NULL }, + { "Sat Nov 6 08:09:07", NULL }, + { "Sat Nov 6 08:09:07 GMT 2004", NULL } +}; + +static void +check_bad (gconstpointer data) +{ + BadDate *bad = (BadDate *)data; + SoupDate *date; + + if (bad->bugref) + g_test_bug (bad->bugref); + + date = make_date (bad->date); + soup_test_assert (date == NULL, + "date parsing succeeded for '%s': %d %d %d - %d %d %d", + bad->date, + date->year, date->month, date->day, + date->hour, date->minute, date->second); + g_clear_pointer (&date, soup_date_free); +} + +typedef struct { + const char *source; + const char *http, *cookie, *rfc2822, *compact, *full, *xmlrpc; +} DateConversion; + +static const DateConversion conversions[] = { + /* SOUP_DATE_HTTP */ + { "Sat, 06 Nov 2004 08:09:07 GMT", + + "Sat, 06 Nov 2004 08:09:07 GMT", + "Sat, 06-Nov-2004 08:09:07 GMT", + "Sat, 6 Nov 2004 08:09:07 +0000", + "20041106T080907Z", + "2004-11-06T08:09:07Z", + "20041106T08:09:07" }, + + /* RFC2822 GMT */ + { "Sat, 6 Nov 2004 08:09:07 +0000", + + "Sat, 06 Nov 2004 08:09:07 GMT", + "Sat, 06-Nov-2004 08:09:07 GMT", + "Sat, 6 Nov 2004 08:09:07 +0000", + "20041106T080907Z", + "2004-11-06T08:09:07Z", + "20041106T08:09:07" }, + + /* RFC2822 with positive offset */ + { "Sat, 6 Nov 2004 08:09:07 +0430", + + "Sat, 06 Nov 2004 04:39:07 GMT", + "Sat, 06-Nov-2004 04:39:07 GMT", + "Sat, 6 Nov 2004 08:09:07 +0430", + "20041106T080907+0430", + "2004-11-06T08:09:07+04:30", + "20041106T08:09:07" }, + + /* RFC2822 with negative offset */ + { "Sat, 6 Nov 2004 08:09:07 -0430", + + "Sat, 06 Nov 2004 12:39:07 GMT", + "Sat, 06-Nov-2004 12:39:07 GMT", + "Sat, 6 Nov 2004 08:09:07 -0430", + "20041106T080907-0430", + "2004-11-06T08:09:07-04:30", + "20041106T08:09:07" }, + + /* RFC2822 floating */ + { "Sat, 6 Nov 2004 08:09:07 -0000", + + "Sat, 06 Nov 2004 08:09:07 GMT", + "Sat, 06-Nov-2004 08:09:07 GMT", + "Sat, 6 Nov 2004 08:09:07 -0000", + "20041106T080907", + "2004-11-06T08:09:07", + "20041106T08:09:07" }, + + /* ISO GMT */ + { "2004-11-06T08:09:07Z", + + "Sat, 06 Nov 2004 08:09:07 GMT", + "Sat, 06-Nov-2004 08:09:07 GMT", + "Sat, 6 Nov 2004 08:09:07 +0000", + "20041106T080907Z", + "2004-11-06T08:09:07Z", + "20041106T08:09:07" }, + + /* ISO with positive offset */ + { "2004-11-06T08:09:07+04:30", + + "Sat, 06 Nov 2004 04:39:07 GMT", + "Sat, 06-Nov-2004 04:39:07 GMT", + "Sat, 6 Nov 2004 08:09:07 +0430", + "20041106T080907+0430", + "2004-11-06T08:09:07+04:30", + "20041106T08:09:07" }, + + /* ISO with negative offset */ + { "2004-11-06T08:09:07-04:30", + + "Sat, 06 Nov 2004 12:39:07 GMT", + "Sat, 06-Nov-2004 12:39:07 GMT", + "Sat, 6 Nov 2004 08:09:07 -0430", + "20041106T080907-0430", + "2004-11-06T08:09:07-04:30", + "20041106T08:09:07" }, + + /* ISO floating */ + { "2004-11-06T08:09:07", + + "Sat, 06 Nov 2004 08:09:07 GMT", + "Sat, 06-Nov-2004 08:09:07 GMT", + "Sat, 6 Nov 2004 08:09:07 -0000", + "20041106T080907", + "2004-11-06T08:09:07", + "20041106T08:09:07" } +}; + +static void +check_conversion (gconstpointer data) +{ + const DateConversion *conv = data; + SoupDate *date; + char *str; + + date = make_date (conv->source); + if (!date) { + soup_test_assert (FALSE, "date parsing failed for '%s'.", conv->source); + return; + } + + str = soup_date_to_string (date, SOUP_DATE_HTTP); + g_assert_cmpstr (str, ==, conv->http); + g_free (str); + + str = soup_date_to_string (date, SOUP_DATE_COOKIE); + g_assert_cmpstr (str, ==, conv->cookie); + g_free (str); + + str = soup_date_to_string (date, SOUP_DATE_RFC2822); + g_assert_cmpstr (str, ==, conv->rfc2822); + g_free (str); + + str = soup_date_to_string (date, SOUP_DATE_ISO8601_COMPACT); + g_assert_cmpstr (str, ==, conv->compact); + g_free (str); + + str = soup_date_to_string (date, SOUP_DATE_ISO8601_FULL); + g_assert_cmpstr (str, ==, conv->full); + g_free (str); + + str = soup_date_to_string (date, SOUP_DATE_ISO8601_XMLRPC); + g_assert_cmpstr (str, ==, conv->xmlrpc); + g_free (str); + + soup_date_free (date); +} + +int +main (int argc, char **argv) +{ + int i, ret; + char *path; + + test_init (argc, argv, NULL); + + for (i = 0; i < G_N_ELEMENTS (good_dates); i++) { + path = g_strdup_printf ("/date/good/%s", good_dates[i].date); + g_test_add_data_func (path, &good_dates[i], check_good); + g_free (path); + } + + for (i = 0; i < G_N_ELEMENTS (ok_dates); i++) { + path = g_strdup_printf ("/date/ok/%s", ok_dates[i].date); + g_test_add_data_func (path, &ok_dates[i], check_ok); + g_free (path); + } + g_test_add_func ("/date/ok/" TIME_T_STRING, check_ok_time_t); + + for (i = 0; i < G_N_ELEMENTS (bad_dates); i++) { + path = g_strdup_printf ("/date/bad/%s", bad_dates[i].date); + g_test_add_data_func (path, &bad_dates[i], check_bad); + g_free (path); + } + + for (i = 0; i < G_N_ELEMENTS (conversions); i++) { + path = g_strdup_printf ("/date/conversions/%s", conversions[i].source); + g_test_add_data_func (path, &conversions[i], check_conversion); + g_free (path); + } + + ret = g_test_run (); + + test_cleanup (); + return ret; +} diff --git a/tests/forms-test.c b/tests/forms-test.c new file mode 100644 index 0000000..349932b --- /dev/null +++ b/tests/forms-test.c @@ -0,0 +1,463 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2007, 2008 Red Hat, Inc. + */ + +#include "test-utils.h" + +static struct { + const char *title, *name; + const char *result; +} tests[] = { + /* Both fields must be filled in */ + { NULL, "Name", "" }, + { "Mr.", NULL, "" }, + + /* Filled-in but empty is OK */ + { "", "", "Hello, " }, + { "", "Name", "Hello, Name" }, + { "Mr.", "", "Hello, MR. " }, + + /* Simple */ + { "Mr.", "Name", "Hello, MR. Name" }, + + /* Encoding of spaces */ + { "Mr.", "Full Name", "Hello, MR. Full Name" }, + { "Mr. and Mrs.", "Full Name", "Hello, MR. AND MRS. Full Name" }, + + /* Encoding of "+" */ + { "Mr.+Mrs.", "Full Name", "Hello, MR.+MRS. Full Name" }, + + /* Encoding of non-ASCII. */ + { "Se\xC3\xB1or", "Nombre", "Hello, SE\xC3\xB1OR Nombre" }, + + /* Encoding of '%' */ + { "Mr.", "Foo %2f Bar", "Hello, MR. Foo %2f Bar" }, +}; + +static void +do_hello_test (int n, gboolean extra, const char *uri) +{ + GPtrArray *args; + char *title_arg = NULL, *name_arg = NULL; + char *str_stdout = NULL; + GError *error = NULL; + + debug_printf (1, "%2d. '%s' '%s'%s: ", n * 2 + (extra ? 2 : 1), + tests[n].title ? tests[n].title : "(null)", + tests[n].name ? tests[n].name : "(null)", + extra ? " + extra" : ""); + + args = g_ptr_array_new (); + g_ptr_array_add (args, "curl"); + g_ptr_array_add (args, "--noproxy"); + g_ptr_array_add (args, "*"); + g_ptr_array_add (args, "-G"); + if (tests[n].title) { + title_arg = soup_form_encode ("title", tests[n].title, NULL); + g_ptr_array_add (args, "-d"); + g_ptr_array_add (args, title_arg); + } + if (tests[n].name) { + name_arg = soup_form_encode ("n@me", tests[n].name, NULL); + g_ptr_array_add (args, "-d"); + g_ptr_array_add (args, name_arg); + } + if (extra) { + g_ptr_array_add (args, "-d"); + g_ptr_array_add (args, "extra=something"); + } + g_ptr_array_add (args, (char *)uri); + g_ptr_array_add (args, NULL); + + if (g_spawn_sync (NULL, (char **)args->pdata, NULL, + G_SPAWN_SEARCH_PATH | G_SPAWN_STDERR_TO_DEV_NULL, + NULL, NULL, + &str_stdout, NULL, NULL, &error)) { + g_assert_cmpstr (str_stdout, ==, tests[n].result); + g_free (str_stdout); + } else { + g_assert_no_error (error); + g_error_free (error); + } + g_ptr_array_free (args, TRUE); + g_free (title_arg); + g_free (name_arg); +} + +static void +do_hello_tests (gconstpointer uri) +{ + int n; + +#ifndef HAVE_CURL + g_test_skip ("/usr/bin/curl is not available"); + return; +#endif + + for (n = 0; n < G_N_ELEMENTS (tests); n++) { + do_hello_test (n, FALSE, uri); + do_hello_test (n, TRUE, uri); + } +} + +#define MD5_TEST_FILE (g_test_get_filename (G_TEST_DIST, "index.txt", NULL)) +#define MD5_TEST_FILE_BASENAME "index.txt" +#define MD5_TEST_FILE_MIME_TYPE "text/plain" + +static char * +get_md5_data (char **contents, gsize *length) +{ + char *my_contents, *md5; + gsize my_length; + GError *error = NULL; + + if (!g_file_get_contents (MD5_TEST_FILE, &my_contents, &my_length, &error)) { + g_assert_no_error (error); + g_error_free (error); + return NULL; + } + + md5 = g_compute_checksum_for_string (G_CHECKSUM_MD5, my_contents, my_length); + + if (contents) + *contents = my_contents; + else + g_free (my_contents); + if (length) + *length = my_length; + + return md5; +} + +static void +do_md5_test_curl (gconstpointer data) +{ + const char *uri = data; + char *md5; + GPtrArray *args; + char *file_arg, *str_stdout; + GError *error = NULL; + +#ifndef HAVE_CURL + g_test_skip ("/usr/bin/curl is not available"); + return; +#endif + + md5 = get_md5_data (NULL, NULL); + if (!md5) + return; + + args = g_ptr_array_new (); + g_ptr_array_add (args, "curl"); + g_ptr_array_add (args, "--noproxy"); + g_ptr_array_add (args, "*"); + g_ptr_array_add (args, "-L"); + g_ptr_array_add (args, "-F"); + file_arg = g_strdup_printf ("file=@%s", MD5_TEST_FILE); + g_ptr_array_add (args, file_arg); + g_ptr_array_add (args, "-F"); + g_ptr_array_add (args, "fmt=txt"); + g_ptr_array_add (args, (char *)uri); + g_ptr_array_add (args, NULL); + + if (g_spawn_sync (NULL, (char **)args->pdata, NULL, + G_SPAWN_SEARCH_PATH | G_SPAWN_STDERR_TO_DEV_NULL, + NULL, NULL, + &str_stdout, NULL, NULL, NULL)) { + g_assert_cmpstr (str_stdout, ==, md5); + g_free (str_stdout); + } else { + g_assert_no_error (error); + g_error_free (error); + } + g_ptr_array_free (args, TRUE); + g_free (file_arg); + + g_free (md5); +} + +static void +do_md5_test_libsoup (gconstpointer data) +{ + const char *uri = data; + char *contents, *md5; + gsize length; + SoupMultipart *multipart; + SoupBuffer *buffer; + SoupMessage *msg; + SoupSession *session; + + g_test_bug ("601640"); + + md5 = get_md5_data (&contents, &length); + if (!md5) + return; + + multipart = soup_multipart_new (SOUP_FORM_MIME_TYPE_MULTIPART); + buffer = soup_buffer_new (SOUP_MEMORY_COPY, contents, length); + soup_multipart_append_form_file (multipart, "file", + MD5_TEST_FILE_BASENAME, + MD5_TEST_FILE_MIME_TYPE, + buffer); + soup_buffer_free (buffer); + soup_multipart_append_form_string (multipart, "fmt", "text"); + + msg = soup_form_request_new_from_multipart (uri, multipart); + soup_multipart_free (multipart); + + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + soup_session_send_message (session, msg); + + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + g_assert_cmpstr (msg->response_body->data, ==, md5); + + g_object_unref (msg); + soup_test_session_abort_unref (session); + + g_free (contents); + g_free (md5); +} + +static void +do_form_decode_test (void) +{ + GHashTable *table; + const gchar *value; + gchar *tmp; + +#ifndef HAVE_CURL + g_test_skip ("/usr/bin/curl is not available"); + return; +#endif + + /* Test that the code handles multiple values with the same key. */ + table = soup_form_decode ("foo=first&foo=second&foo=third"); + + /* Allocate some memory. We do this to test for a bug in + * soup_form_decode() that resulted in values from the hash + * table pointing to memory that is already released. + */ + tmp = g_strdup ("other"); + + value = g_hash_table_lookup (table, "foo"); + g_assert_cmpstr (value, ==, "third"); + + g_free (tmp); + g_hash_table_destroy (table); +} + +static void +hello_callback (SoupServer *server, SoupMessage *msg, + const char *path, GHashTable *query, + SoupClientContext *context, gpointer data) +{ + char *title, *name, *fmt; + const char *content_type; + GString *buf; + + if (msg->method != SOUP_METHOD_GET && msg->method != SOUP_METHOD_HEAD) { + soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED); + return; + } + + if (query) { + title = g_hash_table_lookup (query, "title"); + name = g_hash_table_lookup (query, "n@me"); + fmt = g_hash_table_lookup (query, "fmt"); + } else + title = name = fmt = NULL; + + buf = g_string_new (NULL); + if (!query || (fmt && !strcmp (fmt, "html"))) { + content_type = "text/html"; + g_string_append (buf, "forms-test: hello\r\n"); + if (title && name) { + /* mumble mumble html-escape... */ + g_string_append_printf (buf, "

Hello, %s %s

\r\n", + title, name); + } + g_string_append (buf, "
" + "

Title:

" + "

Name:

" + "

" + "

" + "
\r\n"); + g_string_append (buf, "\r\n"); + } else { + content_type = "text/plain"; + if (title && name) { + char *uptitle = g_ascii_strup (title, -1); + g_string_append_printf (buf, "Hello, %s %s", + uptitle, name); + g_free (uptitle); + } + } + + soup_message_set_response (msg, content_type, + SOUP_MEMORY_TAKE, + buf->str, buf->len); + g_string_free (buf, FALSE); + soup_message_set_status (msg, SOUP_STATUS_OK); +} + +static void +md5_get_callback (SoupServer *server, SoupMessage *msg, + const char *path, GHashTable *query, + SoupClientContext *context, gpointer data) +{ + const char *file = NULL, *md5sum = NULL, *fmt; + const char *content_type; + GString *buf; + + if (query) { + file = g_hash_table_lookup (query, "file"); + md5sum = g_hash_table_lookup (query, "md5sum"); + fmt = g_hash_table_lookup (query, "fmt"); + } else + fmt = "html"; + + buf = g_string_new (NULL); + if (!strcmp (fmt, "html")) { + content_type = "text/html"; + g_string_append (buf, "forms-test: md5\r\n"); + if (file && md5sum) { + /* mumble mumble html-escape... */ + g_string_append_printf (buf, "

File: %s
MD5: %s

\r\n", + file, md5sum); + } + g_string_append (buf, "
" + "

File:

" + "

" + "

" + "
\r\n"); + g_string_append (buf, "\r\n"); + } else { + content_type = "text/plain"; + if (md5sum) + g_string_append_printf (buf, "%s", md5sum); + } + + soup_message_set_response (msg, content_type, + SOUP_MEMORY_TAKE, + buf->str, buf->len); + g_string_free (buf, FALSE); + soup_message_set_status (msg, SOUP_STATUS_OK); +} + +static void +md5_post_callback (SoupServer *server, SoupMessage *msg, + const char *path, GHashTable *query, + SoupClientContext *context, gpointer data) +{ + const char *content_type; + GHashTable *params; + const char *fmt; + char *filename, *md5sum, *redirect_uri; + SoupBuffer *file; + SoupURI *uri; + + content_type = soup_message_headers_get_content_type (msg->request_headers, NULL); + if (!content_type || strcmp (content_type, "multipart/form-data") != 0) { + soup_message_set_status (msg, SOUP_STATUS_BAD_REQUEST); + return; + } + + params = soup_form_decode_multipart (msg, "file", + &filename, NULL, &file); + if (!params) { + soup_message_set_status (msg, SOUP_STATUS_BAD_REQUEST); + return; + } + fmt = g_hash_table_lookup (params, "fmt"); + + md5sum = g_compute_checksum_for_data (G_CHECKSUM_MD5, + (gpointer)file->data, + file->length); + soup_buffer_free (file); + + uri = soup_uri_copy (soup_message_get_uri (msg)); + soup_uri_set_query_from_fields (uri, + "file", filename ? filename : "", + "md5sum", md5sum, + "fmt", fmt ? fmt : "html", + NULL); + redirect_uri = soup_uri_to_string (uri, FALSE); + + soup_message_set_redirect (msg, SOUP_STATUS_SEE_OTHER, redirect_uri); + + g_free (redirect_uri); + soup_uri_free (uri); + g_free (md5sum); + g_free (filename); + g_hash_table_destroy (params); +} + +static void +md5_callback (SoupServer *server, SoupMessage *msg, + const char *path, GHashTable *query, + SoupClientContext *context, gpointer data) +{ + if (msg->method == SOUP_METHOD_GET || msg->method == SOUP_METHOD_HEAD) + md5_get_callback (server, msg, path, query, context, data); + else if (msg->method == SOUP_METHOD_POST) + md5_post_callback (server, msg, path, query, context, data); + else + soup_message_set_status (msg, SOUP_STATUS_METHOD_NOT_ALLOWED); +} + +static gboolean run_tests = TRUE; + +static GOptionEntry no_test_entry[] = { + { "no-tests", 'n', G_OPTION_FLAG_REVERSE, + G_OPTION_ARG_NONE, &run_tests, + "Don't run tests, just run the test server", NULL }, + { NULL } +}; + +int +main (int argc, char **argv) +{ + GMainLoop *loop; + SoupServer *server; + SoupURI *base_uri, *uri; + int ret = 0; + + test_init (argc, argv, no_test_entry); + + server = soup_test_server_new (SOUP_TEST_SERVER_IN_THREAD); + soup_server_add_handler (server, "/hello", + hello_callback, NULL, NULL); + soup_server_add_handler (server, "/md5", + md5_callback, NULL, NULL); + base_uri = soup_test_server_get_uri (server, "http", NULL); + + loop = g_main_loop_new (NULL, TRUE); + + if (run_tests) { + uri = soup_uri_new_with_base (base_uri, "/hello"); + g_test_add_data_func_full ("/forms/hello", soup_uri_to_string (uri, FALSE), do_hello_tests, g_free); + soup_uri_free (uri); + + uri = soup_uri_new_with_base (base_uri, "/md5"); + g_test_add_data_func_full ("/forms/md5/curl", soup_uri_to_string (uri, FALSE), do_md5_test_curl, g_free); + g_test_add_data_func_full ("/forms/md5/libsoup", soup_uri_to_string (uri, FALSE), do_md5_test_libsoup, g_free); + soup_uri_free (uri); + + g_test_add_func ("/forms/decode", do_form_decode_test); + + ret = g_test_run (); + } else { + g_print ("Listening on port %d\n", base_uri->port); + g_main_loop_run (loop); + } + + g_main_loop_unref (loop); + + soup_test_server_quit_unref (server); + soup_uri_free (base_uri); + + if (run_tests) + test_cleanup (); + return ret; +} diff --git a/tests/header-parsing.c b/tests/header-parsing.c new file mode 100644 index 0000000..9cf06ce --- /dev/null +++ b/tests/header-parsing.c @@ -0,0 +1,1187 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ + +#include "test-utils.h" + +typedef struct { + const char *name, *value; +} Header; + +static struct RequestTest { + const char *description; + const char *bugref; + const char *request; + int length; + guint status; + const char *method, *path; + SoupHTTPVersion version; + Header headers[10]; +} reqtests[] = { + /**********************/ + /*** VALID REQUESTS ***/ + /**********************/ + + { "HTTP 1.0 request with no headers", NULL, + "GET / HTTP/1.0\r\n", -1, + SOUP_STATUS_OK, + "GET", "/", SOUP_HTTP_1_0, + { { NULL } } + }, + + { "Req w/ 1 header", NULL, + "GET / HTTP/1.1\r\nHost: example.com\r\n", -1, + SOUP_STATUS_OK, + "GET", "/", SOUP_HTTP_1_1, + { { "Host", "example.com" }, + { NULL } + } + }, + + { "Req w/ 1 header, no leading whitespace", NULL, + "GET / HTTP/1.1\r\nHost:example.com\r\n", -1, + SOUP_STATUS_OK, + "GET", "/", SOUP_HTTP_1_1, + { { "Host", "example.com" }, + { NULL } + } + }, + + { "Req w/ 1 header including trailing whitespace", NULL, + "GET / HTTP/1.1\r\nHost: example.com \r\n", -1, + SOUP_STATUS_OK, + "GET", "/", SOUP_HTTP_1_1, + { { "Host", "example.com" }, + { NULL } + } + }, + + { "Req w/ 1 header, wrapped", NULL, + "GET / HTTP/1.1\r\nFoo: bar\r\n baz\r\n", -1, + SOUP_STATUS_OK, + "GET", "/", SOUP_HTTP_1_1, + { { "Foo", "bar baz" }, + { NULL } + } + }, + + { "Req w/ 1 header, wrapped with additional whitespace", NULL, + "GET / HTTP/1.1\r\nFoo: bar \r\n baz\r\n", -1, + SOUP_STATUS_OK, + "GET", "/", SOUP_HTTP_1_1, + { { "Foo", "bar baz" }, + { NULL } + } + }, + + { "Req w/ 1 header, wrapped with tab", NULL, + "GET / HTTP/1.1\r\nFoo: bar\r\n\tbaz\r\n", -1, + SOUP_STATUS_OK, + "GET", "/", SOUP_HTTP_1_1, + { { "Foo", "bar baz" }, + { NULL } + } + }, + + { "Req w/ 1 header, wrapped before value", NULL, + "GET / HTTP/1.1\r\nFoo:\r\n bar baz\r\n", -1, + SOUP_STATUS_OK, + "GET", "/", SOUP_HTTP_1_1, + { { "Foo", "bar baz" }, + { NULL } + } + }, + + { "Req w/ 1 header with empty value", NULL, + "GET / HTTP/1.1\r\nHost:\r\n", -1, + SOUP_STATUS_OK, + "GET", "/", SOUP_HTTP_1_1, + { { "Host", "" }, + { NULL } + } + }, + + { "Req w/ 2 headers", NULL, + "GET / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\n", -1, + SOUP_STATUS_OK, + "GET", "/", SOUP_HTTP_1_1, + { { "Host", "example.com" }, + { "Connection", "close" }, + { NULL } + } + }, + + { "Req w/ 3 headers", NULL, + "GET / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\nBlah: blah\r\n", -1, + SOUP_STATUS_OK, + "GET", "/", SOUP_HTTP_1_1, + { { "Host", "example.com" }, + { "Connection", "close" }, + { "Blah", "blah" }, + { NULL } + } + }, + + { "Req w/ 3 headers, 1st wrapped", NULL, + "GET / HTTP/1.1\r\nFoo: bar\r\n baz\r\nConnection: close\r\nBlah: blah\r\n", -1, + SOUP_STATUS_OK, + "GET", "/", SOUP_HTTP_1_1, + { { "Foo", "bar baz" }, + { "Connection", "close" }, + { "Blah", "blah" }, + { NULL } + } + }, + + { "Req w/ 3 headers, 2nd wrapped", NULL, + "GET / HTTP/1.1\r\nConnection: close\r\nBlah: blah\r\nFoo: bar\r\n baz\r\n", -1, + SOUP_STATUS_OK, + "GET", "/", SOUP_HTTP_1_1, + { { "Connection", "close" }, + { "Blah", "blah" }, + { "Foo", "bar baz" }, + { NULL } + } + }, + + { "Req w/ 3 headers, 3rd wrapped", NULL, + "GET / HTTP/1.1\r\nConnection: close\r\nBlah: blah\r\nFoo: bar\r\n baz\r\n", -1, + SOUP_STATUS_OK, + "GET", "/", SOUP_HTTP_1_1, + { { "Connection", "close" }, + { "Blah", "blah" }, + { "Foo", "bar baz" }, + { NULL } + } + }, + + { "Req w/ same header multiple times", NULL, + "GET / HTTP/1.1\r\nFoo: bar\r\nFoo: baz\r\nFoo: quux\r\n", -1, + SOUP_STATUS_OK, + "GET", "/", SOUP_HTTP_1_1, + { { "Foo", "bar, baz, quux" }, + { NULL } + } + }, + + { "Connection header on HTTP/1.0 message", NULL, + "GET / HTTP/1.0\r\nFoo: bar\r\nConnection: Bar, Quux\r\nBar: baz\r\nQuux: foo\r\n", -1, + SOUP_STATUS_OK, + "GET", "/", SOUP_HTTP_1_0, + { { "Foo", "bar" }, + { "Connection", "Bar, Quux" }, + { NULL } + } + }, + + { "GET with full URI", "667637", + "GET http://example.com HTTP/1.1\r\n", -1, + SOUP_STATUS_OK, + "GET", "http://example.com", SOUP_HTTP_1_1, + { { NULL } } + }, + + { "GET with full URI in upper-case", "667637", + "GET HTTP://example.com HTTP/1.1\r\n", -1, + SOUP_STATUS_OK, + "GET", "HTTP://example.com", SOUP_HTTP_1_1, + { { NULL } } + }, + + /* It's better for this to be passed through: this means a SoupServer + * could implement ftp-over-http proxying, for instance + */ + { "GET with full URI of unrecognised scheme", "667637", + "GET AbOuT: HTTP/1.1\r\n", -1, + SOUP_STATUS_OK, + "GET", "AbOuT:", SOUP_HTTP_1_1, + { { NULL } } + }, + + /****************************/ + /*** RECOVERABLE REQUESTS ***/ + /****************************/ + + /* RFC 2616 section 4.1 says we SHOULD accept this */ + + { "Spurious leading CRLF", NULL, + "\r\nGET / HTTP/1.1\r\nHost: example.com\r\n", -1, + SOUP_STATUS_OK, + "GET", "/", SOUP_HTTP_1_1, + { { "Host", "example.com" }, + { NULL } + } + }, + + /* RFC 2616 section 3.1 says we MUST accept this */ + + { "HTTP/01.01 request", NULL, + "GET / HTTP/01.01\r\nHost: example.com\r\n", -1, + SOUP_STATUS_OK, + "GET", "/", SOUP_HTTP_1_1, + { { "Host", "example.com" }, + { NULL } + } + }, + + /* RFC 2616 section 19.3 says we SHOULD accept these */ + + { "LF instead of CRLF after header", NULL, + "GET / HTTP/1.1\r\nHost: example.com\nConnection: close\n", -1, + SOUP_STATUS_OK, + "GET", "/", SOUP_HTTP_1_1, + { { "Host", "example.com" }, + { "Connection", "close" }, + { NULL } + } + }, + + { "LF instead of CRLF after Request-Line", NULL, + "GET / HTTP/1.1\nHost: example.com\r\n", -1, + SOUP_STATUS_OK, + "GET", "/", SOUP_HTTP_1_1, + { { "Host", "example.com" }, + { NULL } + } + }, + + { "Mixed CRLF/LF", "666316", + "GET / HTTP/1.1\r\na: b\r\nc: d\ne: f\r\ng: h\n", -1, + SOUP_STATUS_OK, + "GET", "/", SOUP_HTTP_1_1, + { { "a", "b" }, + { "c", "d" }, + { "e", "f" }, + { "g", "h" }, + { NULL } + } + }, + + { "Req w/ incorrect whitespace in Request-Line", NULL, + "GET /\tHTTP/1.1\r\nHost: example.com\r\n", -1, + SOUP_STATUS_OK, + "GET", "/", SOUP_HTTP_1_1, + { { "Host", "example.com" }, + { NULL } + } + }, + + { "Req w/ incorrect whitespace after Request-Line", "475169", + "GET / HTTP/1.1 \r\nHost: example.com\r\n", -1, + SOUP_STATUS_OK, + "GET", "/", SOUP_HTTP_1_1, + { { "Host", "example.com" }, + { NULL } + } + }, + + /* If the request/status line is parseable, then we + * just ignore any invalid-looking headers after that. + */ + + { "Req w/ mangled header", "579318", + "GET / HTTP/1.1\r\nHost: example.com\r\nFoo one\r\nBar: two\r\n", -1, + SOUP_STATUS_OK, + "GET", "/", SOUP_HTTP_1_1, + { { "Host", "example.com" }, + { "Bar", "two" }, + { NULL } + } + }, + + { "First header line is continuation", "666316", + "GET / HTTP/1.1\r\n b\r\nHost: example.com\r\nc: d\r\n", -1, + SOUP_STATUS_OK, + "GET", "/", SOUP_HTTP_1_1, + { { "Host", "example.com" }, + { "c", "d" }, + { NULL } + } + }, + + { "Zero-length header name", "666316", + "GET / HTTP/1.1\r\na: b\r\n: example.com\r\nc: d\r\n", -1, + SOUP_STATUS_OK, + "GET", "/", SOUP_HTTP_1_1, + { { "a", "b" }, + { "c", "d" }, + { NULL } + } + }, + + { "CR in header name", "666316", + "GET / HTTP/1.1\r\na: b\r\na\rb: cd\r\nx\r: y\r\n\rz: w\r\nc: d\r\n", -1, + SOUP_STATUS_OK, + "GET", "/", SOUP_HTTP_1_1, + { { "a", "b" }, + { "c", "d" }, + { NULL } + } + }, + + { "CR in header value", "666316", + "GET / HTTP/1.1\r\na: b\r\nHost: example\rcom\r\np: \rq\r\ns: t\r\r\nc: d\r\n", -1, + SOUP_STATUS_OK, + "GET", "/", SOUP_HTTP_1_1, + { { "a", "b" }, + { "Host", "example com" }, /* CR in the middle turns to space */ + { "p", "q" }, /* CR at beginning is ignored */ + { "s", "t" }, /* CR at end is ignored */ + { "c", "d" }, + { NULL } + } + }, + + { "Tab in header name", "666316", + "GET / HTTP/1.1\r\na: b\r\na\tb: cd\r\nx\t: y\r\np: q\r\n\tz: w\r\nc: d\r\n", -1, + SOUP_STATUS_OK, + "GET", "/", SOUP_HTTP_1_1, + { { "a", "b" }, + /* Tab anywhere in the header name causes it to be + * ignored... except at beginning of line where it's a + * continuation line + */ + { "p", "q z: w" }, + { "c", "d" }, + { NULL } + } + }, + + { "Tab in header value", "666316", + "GET / HTTP/1.1\r\na: b\r\nab: c\td\r\nx: \ty\r\nz: w\t\r\nc: d\r\n", -1, + SOUP_STATUS_OK, + "GET", "/", SOUP_HTTP_1_1, + { { "a", "b" }, + { "ab", "c\td" }, /* internal tab preserved */ + { "x", "y" }, /* leading tab ignored */ + { "z", "w" }, /* trailing tab ignored */ + { "c", "d" }, + { NULL } + } + }, + + { "NUL in header name", "760832", + "GET / HTTP/1.1\r\nHost\x00: example.com\r\n", 36, + SOUP_STATUS_OK, + "GET", "/", SOUP_HTTP_1_1, + { { "Host", "example.com" }, + { NULL } + } + }, + + { "NUL in header value", "760832", + "GET / HTTP/1.1\r\nHost: example\x00" "com\r\n", 35, + SOUP_STATUS_OK, + "GET", "/", SOUP_HTTP_1_1, + { { "Host", "examplecom" }, + { NULL } + } + }, + + /************************/ + /*** INVALID REQUESTS ***/ + /************************/ + + { "HTTP 0.9 request; not supported", NULL, + "GET /\r\n", -1, + SOUP_STATUS_BAD_REQUEST, + NULL, NULL, -1, + { { NULL } } + }, + + { "HTTP 1.2 request (no such thing)", NULL, + "GET / HTTP/1.2\r\n", -1, + SOUP_STATUS_HTTP_VERSION_NOT_SUPPORTED, + NULL, NULL, -1, + { { NULL } } + }, + + { "HTTP 2000 request (no such thing)", NULL, + "GET / HTTP/2000.0\r\n", -1, + SOUP_STATUS_HTTP_VERSION_NOT_SUPPORTED, + NULL, NULL, -1, + { { NULL } } + }, + + { "Non-HTTP request", NULL, + "GET / SOUP/1.1\r\nHost: example.com\r\n", -1, + SOUP_STATUS_BAD_REQUEST, + NULL, NULL, -1, + { { NULL } } + }, + + { "Junk after Request-Line", NULL, + "GET / HTTP/1.1 blah\r\nHost: example.com\r\n", -1, + SOUP_STATUS_BAD_REQUEST, + NULL, NULL, -1, + { { NULL } } + }, + + { "NUL in Method", NULL, + "G\x00T / HTTP/1.1\r\nHost: example.com\r\n", 37, + SOUP_STATUS_BAD_REQUEST, + NULL, NULL, -1, + { { NULL } } + }, + + { "NUL at beginning of Method", "666316", + "\x00 / HTTP/1.1\r\nHost: example.com\r\n", 35, + SOUP_STATUS_BAD_REQUEST, + NULL, NULL, -1, + { { NULL } } + }, + + { "NUL in Path", NULL, + "GET /\x00 HTTP/1.1\r\nHost: example.com\r\n", 38, + SOUP_STATUS_BAD_REQUEST, + NULL, NULL, -1, + { { NULL } } + }, + + { "No terminating CRLF", NULL, + "GET / HTTP/1.1\r\nHost: example.com", -1, + SOUP_STATUS_BAD_REQUEST, + NULL, NULL, -1, + { { NULL } } + }, + + { "Unrecognized expectation", NULL, + "GET / HTTP/1.1\r\nHost: example.com\r\nExpect: the-impossible\r\n", -1, + SOUP_STATUS_EXPECTATION_FAILED, + NULL, NULL, -1, + { { NULL } } + } +}; +static const int num_reqtests = G_N_ELEMENTS (reqtests); + +static struct ResponseTest { + const char *description; + const char *bugref; + const char *response; + int length; + SoupHTTPVersion version; + guint status_code; + const char *reason_phrase; + Header headers[10]; +} resptests[] = { + /***********************/ + /*** VALID RESPONSES ***/ + /***********************/ + + { "HTTP 1.0 response w/ no headers", NULL, + "HTTP/1.0 200 ok\r\n", -1, + SOUP_HTTP_1_0, SOUP_STATUS_OK, "ok", + { { NULL } } + }, + + { "HTTP 1.1 response w/ no headers", NULL, + "HTTP/1.1 200 ok\r\n", -1, + SOUP_HTTP_1_1, SOUP_STATUS_OK, "ok", + { { NULL } } + }, + + { "Response w/ multi-word Reason-Phrase", NULL, + "HTTP/1.1 400 bad request\r\n", -1, + SOUP_HTTP_1_1, SOUP_STATUS_BAD_REQUEST, "bad request", + { { NULL } } + }, + + { "Response w/ 1 header", NULL, + "HTTP/1.1 200 ok\r\nFoo: bar\r\n", -1, + SOUP_HTTP_1_1, SOUP_STATUS_OK, "ok", + { { "Foo", "bar" }, + { NULL } + } + }, + + { "Response w/ 2 headers", NULL, + "HTTP/1.1 200 ok\r\nFoo: bar\r\nBaz: quux\r\n", -1, + SOUP_HTTP_1_1, SOUP_STATUS_OK, "ok", + { { "Foo", "bar" }, + { "Baz", "quux" }, + { NULL } + } + }, + + { "Response w/ same header multiple times", NULL, + "HTTP/1.1 200 ok\r\nFoo: bar\r\nFoo: baz\r\nFoo: quux\r\n", -1, + SOUP_HTTP_1_1, SOUP_STATUS_OK, "ok", + { { "Foo", "bar, baz, quux" }, + { NULL } + } + }, + + { "Response w/ no reason phrase", NULL, + "HTTP/1.1 200 \r\nFoo: bar\r\n", -1, + SOUP_HTTP_1_1, SOUP_STATUS_OK, "", + { { "Foo", "bar" }, + { NULL } + } + }, + + { "Response w/ unknown status code", NULL, + "HTTP/1.1 999 Request denied\r\nFoo: bar\r\n", -1, + SOUP_HTTP_1_1, 999, "Request denied", + { { "Foo", "bar" }, + { NULL } + } + }, + + { "Connection header on HTTP/1.0 message", NULL, + "HTTP/1.0 200 ok\r\nFoo: bar\r\nConnection: Bar\r\nBar: quux\r\n", -1, + SOUP_HTTP_1_0, SOUP_STATUS_OK, "ok", + { { "Foo", "bar" }, + { "Connection", "Bar" }, + { NULL } + } + }, + + /* Tests from Cockpit */ + + { "Response w/ 3 headers, check case-insensitivity", "722341", + "HTTP/1.0 200 ok\r\nHeader1: value3\r\nHeader2: field\r\nHead3: Another \r\n", -1, + SOUP_HTTP_1_0, SOUP_STATUS_OK, "ok", + { { "header1", "value3" }, + { "Header2", "field" }, + { "hEAD3", "Another" }, + { "Something else", NULL }, + { NULL } + } + }, + + /*****************************/ + /*** RECOVERABLE RESPONSES ***/ + /*****************************/ + + /* RFC 2616 section 3.1 says we MUST accept this */ + + { "HTTP/01.01 response", NULL, + "HTTP/01.01 200 ok\r\nFoo: bar\r\n", -1, + SOUP_HTTP_1_1, SOUP_STATUS_OK, "ok", + { { "Foo", "bar" }, + { NULL } + } + }, + + /* RFC 2616 section 19.3 says we SHOULD accept these */ + + { "Response w/ LF instead of CRLF after Status-Line", NULL, + "HTTP/1.1 200 ok\nFoo: bar\r\n", -1, + SOUP_HTTP_1_1, SOUP_STATUS_OK, "ok", + { { "Foo", "bar" }, + { NULL } + } + }, + + { "Response w/ incorrect spacing in Status-Line", NULL, + "HTTP/1.1 200\tok\r\nFoo: bar\r\n", -1, + SOUP_HTTP_1_1, SOUP_STATUS_OK, "ok", + { { "Foo", "bar" }, + { NULL } + } + }, + + { "Response w/ no reason phrase or preceding SP", NULL, + "HTTP/1.1 200\r\nFoo: bar\r\n", -1, + SOUP_HTTP_1_1, SOUP_STATUS_OK, "", + { { "Foo", "bar" }, + { NULL } + } + }, + + { "Response w/ no whitespace after status code", NULL, + "HTTP/1.1 200ok\r\nFoo: bar\r\n", -1, + SOUP_HTTP_1_1, SOUP_STATUS_OK, "ok", + { { "Foo", "bar" }, + { NULL } + } + }, + + /* Shoutcast support */ + { "Shoutcast server not-quite-HTTP", "502325", + "ICY 200 OK\r\nFoo: bar\r\n", -1, + SOUP_HTTP_1_0, SOUP_STATUS_OK, "OK", + { { "Foo", "bar" }, + { NULL } + } + }, + + { "Response w/ mangled header", "579318", + "HTTP/1.1 200 ok\r\nFoo: one\r\nBar two:2\r\nBaz: three\r\n", -1, + SOUP_HTTP_1_1, SOUP_STATUS_OK, "ok", + { { "Foo", "one" }, + { "Baz", "three" }, + { NULL } + } + }, + + { "HTTP 1.1 response with leading line break", "602863", + "\nHTTP/1.1 200 ok\r\nFoo: bar\r\n", -1, + SOUP_HTTP_1_1, SOUP_STATUS_OK, "ok", + { { "Foo", "bar" }, + { NULL } } + }, + + { "NUL in header name", "760832", + "HTTP/1.1 200 OK\r\nF\x00oo: bar\r\n", 28, + SOUP_HTTP_1_1, SOUP_STATUS_OK, "OK", + { { "Foo", "bar" }, + { NULL } + } + }, + + { "NUL in header value", "760832", + "HTTP/1.1 200 OK\r\nFoo: b\x00" "ar\r\n", 28, + SOUP_HTTP_1_1, SOUP_STATUS_OK, "OK", + { { "Foo", "bar" }, + { NULL } + } + }, + + /********************************/ + /*** VALID CONTINUE RESPONSES ***/ + /********************************/ + + /* Tests from Cockpit project */ + + { "Response w/ 101 Switching Protocols + spaces after new line", NULL, + "HTTP/1.0 101 Switching Protocols\r\n \r\n", 38, + SOUP_HTTP_1_0, SOUP_STATUS_SWITCHING_PROTOCOLS, "Switching Protocols", + { { NULL } } + }, + + { "Response w/ 101 Switching Protocols missing \\r + spaces", NULL, + "HTTP/1.0 101 Switching Protocols\r\n \r\n", 40, + SOUP_HTTP_1_0, SOUP_STATUS_SWITCHING_PROTOCOLS, "Switching Protocols", + { { NULL } } + }, + + { "Response w/ 101 Switching Protocols + spaces after & before new line", NULL, + "HTTP/1.1 101 Switching Protocols \r\n \r\n", 42, + SOUP_HTTP_1_1, SOUP_STATUS_SWITCHING_PROTOCOLS, "Switching Protocols", + { { NULL } } + }, + + /*************************/ + /*** INVALID RESPONSES ***/ + /*************************/ + + { "Invalid HTTP version", NULL, + "HTTP/1.2 200 OK\r\nFoo: bar\r\n", -1, + -1, 0, NULL, + { { NULL } } + }, + + { "Non-HTTP response", NULL, + "SOUP/1.1 200 OK\r\nFoo: bar\r\n", -1, + -1, 0, NULL, + { { NULL } } + }, + + { "Non-numeric status code", NULL, + "HTTP/1.1 XXX OK\r\nFoo: bar\r\n", -1, + -1, 0, NULL, + { { NULL } } + }, + + { "No status code", NULL, + "HTTP/1.1 OK\r\nFoo: bar\r\n", -1, + -1, 0, NULL, + { { NULL } } + }, + + { "One-digit status code", NULL, + "HTTP/1.1 2 OK\r\nFoo: bar\r\n", -1, + -1, 0, NULL, + { { NULL } } + }, + + { "Two-digit status code", NULL, + "HTTP/1.1 20 OK\r\nFoo: bar\r\n", -1, + -1, 0, NULL, + { { NULL } } + }, + + { "Four-digit status code", NULL, + "HTTP/1.1 2000 OK\r\nFoo: bar\r\n", -1, + -1, 0, NULL, + { { NULL } } + }, + + { "Status code < 100", NULL, + "HTTP/1.1 001 OK\r\nFoo: bar\r\n", -1, + -1, 0, NULL, + { { NULL } } + }, + + { "Status code > 999", NULL, + "HTTP/1.1 1000 OK\r\nFoo: bar\r\n", -1, + -1, 0, NULL, + { { NULL } } + }, + + { "NUL at start", "666316", + "\x00HTTP/1.1 200 OK\r\nFoo: bar\r\n", 28, + -1, 0, NULL, + { { NULL } } + }, + + { "NUL in Reason Phrase", NULL, + "HTTP/1.1 200 O\x00K\r\nFoo: bar\r\n", 28, + -1, 0, NULL, + { { NULL } } + }, + + /* Failing test from Cockpit */ + + { "Partial response stops after HTTP/", NULL, + "HTTP/", -1, + -1, 0, NULL, + { { NULL } } + }, + + { "Space before HTTP/", NULL, + " HTTP/1.0 101 Switching Protocols\r\n ", -1, + -1, 0, NULL, + { { NULL } } + }, + + { "Missing reason", NULL, + "HTTP/1.0 101\r\n ", -1, + -1, 0, NULL, + { { NULL } } + }, + + { "Response code containing alphabetic character", NULL, + "HTTP/1.1 1A01 Switching Protocols \r\n ", -1, + -1, 0, NULL, + { { NULL } } + }, + + { "TESTONE\\r\\n", NULL, + "TESTONE\r\n ", -1, + -1, 0, NULL, + { { NULL } } + }, + + { "Response w/ 3 headers truncated", NULL, + "HTTP/1.0 200 ok\r\nHeader1: value3\r\nHeader2: field\r\nHead3: Anothe", -1, + -1, 0, NULL, + { { NULL } + } + }, +}; +static const int num_resptests = G_N_ELEMENTS (resptests); + +static struct QValueTest { + const char *header_value; + const char *acceptable[7]; + const char *unacceptable[2]; +} qvaluetests[] = { + { "text/plain; q=0.5, text/html,\t text/x-dvi; q=0.8, text/x-c", + { "text/html", "text/x-c", "text/x-dvi", "text/plain", NULL }, + { NULL }, + }, + + { "text/*;q=0.3, text/html;q=0.7, text/html;level=1, text/html;level=2;q=0.4, */*;q=0.5", + { "text/html;level=1", "text/html", "*/*", "text/html;level=2", + "text/*", NULL }, + { NULL } + }, + + { "gzip;q=1.0, identity; q=0.5, *;q=0", + { "gzip", "identity", NULL }, + { "*", NULL }, + } +}; +static const int num_qvaluetests = G_N_ELEMENTS (qvaluetests); + +static void +check_headers (Header *headers, SoupMessageHeaders *hdrs) +{ + GSList *header_names, *h; + SoupMessageHeadersIter iter; + const char *name, *value; + int i; + + header_names = NULL; + soup_message_headers_iter_init (&iter, hdrs); + while (soup_message_headers_iter_next (&iter, &name, &value)) { + if (!g_slist_find_custom (header_names, name, + (GCompareFunc)strcmp)) + header_names = g_slist_append (header_names, (char *)name); + } + + for (i = 0, h = header_names; headers[i].name && h; i++, h = h->next) { + g_assert (g_ascii_strcasecmp (h->data, headers[i].name) == 0); + + value = soup_message_headers_get_list (hdrs, headers[i].name); + g_assert_cmpstr (value, ==, headers[i].value); + } + /* If we have remaining fields to check, they should return NULL */ + for (; headers[i].name; i++) { + value = soup_message_headers_get_list (hdrs, headers[i].name); + g_assert_null (value); + } + g_assert_null (headers[i].name); + g_assert_null (h); + + g_slist_free (header_names); +} + +static void +do_request_tests (void) +{ + int i, len; + char *method, *path; + SoupHTTPVersion version; + SoupMessageHeaders *headers; + guint status; + + for (i = 0; i < num_reqtests; i++) { + debug_printf (1, "%2d. %s (%s)\n", i + 1, reqtests[i].description, + soup_status_get_phrase (reqtests[i].status)); + + headers = soup_message_headers_new (SOUP_MESSAGE_HEADERS_REQUEST); + method = path = NULL; + + if (reqtests[i].length == -1) + len = strlen (reqtests[i].request); + else + len = reqtests[i].length; + status = soup_headers_parse_request (reqtests[i].request, len, + headers, &method, &path, + &version); + g_assert_cmpint (status, ==, reqtests[i].status); + if (SOUP_STATUS_IS_SUCCESSFUL (status)) { + g_assert_cmpstr (method, ==, reqtests[i].method); + g_assert_cmpstr (path, ==, reqtests[i].path); + g_assert_cmpint (version, ==, reqtests[i].version); + + check_headers (reqtests[i].headers, headers); + } + + g_free (method); + g_free (path); + soup_message_headers_free (headers); + } +} + +static void +do_response_tests (void) +{ + int i, len; + guint status_code; + char *reason_phrase; + SoupHTTPVersion version; + SoupMessageHeaders *headers; + + for (i = 0; i < num_resptests; i++) { + debug_printf (1, "%2d. %s (%s)\n", i + 1, resptests[i].description, + resptests[i].reason_phrase ? "should parse" : "should NOT parse"); + + headers = soup_message_headers_new (SOUP_MESSAGE_HEADERS_RESPONSE); + reason_phrase = NULL; + + if (resptests[i].length == -1) + len = strlen (resptests[i].response); + else + len = resptests[i].length; + if (soup_headers_parse_response (resptests[i].response, len, + headers, &version, + &status_code, &reason_phrase)) { + g_assert_cmpint (version, ==, resptests[i].version); + g_assert_cmpint (status_code, ==, resptests[i].status_code); + g_assert_cmpstr (reason_phrase, ==, resptests[i].reason_phrase); + + check_headers (resptests[i].headers, headers); + } else + g_assert_null (resptests[i].reason_phrase); + + g_free (reason_phrase); + soup_message_headers_free (headers); + } +} + +static void +do_qvalue_tests (void) +{ + int i, j; + GSList *acceptable, *unacceptable, *iter; + + for (i = 0; i < num_qvaluetests; i++) { + debug_printf (1, "%2d. %s:\n", i + 1, qvaluetests[i].header_value); + + unacceptable = NULL; + acceptable = soup_header_parse_quality_list (qvaluetests[i].header_value, + &unacceptable); + + debug_printf (1, " acceptable: "); + if (acceptable) { + /* Kludge to deal with the fact that the sort order of the first + * test is not fully specified. + */ + if (i == 0 && acceptable->next && + !g_str_equal (acceptable->data, qvaluetests[i].acceptable[0]) && + g_str_equal (acceptable->data, qvaluetests[i].acceptable[1])) { + gpointer tmp = acceptable->data; + acceptable->data = acceptable->next->data; + acceptable->next->data = tmp; + } + + for (iter = acceptable, j = 0; iter; iter = iter->next, j++) { + debug_printf (1, "%s ", (char *)iter->data); + g_assert_cmpstr (iter->data, ==, qvaluetests[i].acceptable[j]); + } + debug_printf (1, "\n"); + soup_header_free_list (acceptable); + } else + debug_printf (1, "(none)\n"); + + debug_printf (1, " unacceptable: "); + if (unacceptable) { + for (iter = unacceptable, j = 0; iter; iter = iter->next, j++) { + debug_printf (1, "%s ", (char *)iter->data); + g_assert_cmpstr (iter->data, ==, qvaluetests[i].unacceptable[j]); + } + debug_printf (1, "\n"); + soup_header_free_list (unacceptable); + } else + debug_printf (1, "(none)\n"); + } +} + +#define RFC5987_TEST_FILENAME "t\xC3\xA9st.txt" +#define RFC5987_TEST_FALLBACK_FILENAME "test.txt" + +#define RFC5987_TEST_HEADER_ENCODED "attachment; filename*=UTF-8''t%C3%A9st.txt" + +#define RFC5987_TEST_HEADER_UTF8 "attachment; filename*=UTF-8''t%C3%A9st.txt; filename=\"test.txt\"" +#define RFC5987_TEST_HEADER_ISO "attachment; filename=\"test.txt\"; filename*=iso-8859-1''t%E9st.txt" +#define RFC5987_TEST_HEADER_FALLBACK "attachment; filename*=Unknown''t%FF%FF%FFst.txt; filename=\"test.txt\"" + +static void +do_content_disposition_tests (void) +{ + SoupMessageHeaders *hdrs; + GHashTable *params; + const char *header, *filename; + char *disposition; + SoupBuffer *buffer; + SoupMultipart *multipart; + SoupMessageBody *body; + + hdrs = soup_message_headers_new (SOUP_MESSAGE_HEADERS_MULTIPART); + params = g_hash_table_new (g_str_hash, g_str_equal); + g_hash_table_insert (params, "filename", RFC5987_TEST_FILENAME); + soup_message_headers_set_content_disposition (hdrs, "attachment", params); + g_hash_table_destroy (params); + + header = soup_message_headers_get_one (hdrs, "Content-Disposition"); + g_assert_cmpstr (header, ==, RFC5987_TEST_HEADER_ENCODED); + + /* UTF-8 decoding */ + soup_message_headers_clear (hdrs); + soup_message_headers_append (hdrs, "Content-Disposition", + RFC5987_TEST_HEADER_UTF8); + if (!soup_message_headers_get_content_disposition (hdrs, + &disposition, + ¶ms)) { + soup_test_assert (FALSE, "UTF-8 decoding FAILED"); + return; + } + g_free (disposition); + + filename = g_hash_table_lookup (params, "filename"); + g_assert_cmpstr (filename, ==, RFC5987_TEST_FILENAME); + g_hash_table_destroy (params); + + /* ISO-8859-1 decoding */ + soup_message_headers_clear (hdrs); + soup_message_headers_append (hdrs, "Content-Disposition", + RFC5987_TEST_HEADER_ISO); + if (!soup_message_headers_get_content_disposition (hdrs, + &disposition, + ¶ms)) { + soup_test_assert (FALSE, "iso-8859-1 decoding FAILED"); + return; + } + g_free (disposition); + + filename = g_hash_table_lookup (params, "filename"); + g_assert_cmpstr (filename, ==, RFC5987_TEST_FILENAME); + g_hash_table_destroy (params); + + /* Fallback */ + soup_message_headers_clear (hdrs); + soup_message_headers_append (hdrs, "Content-Disposition", + RFC5987_TEST_HEADER_FALLBACK); + if (!soup_message_headers_get_content_disposition (hdrs, + &disposition, + ¶ms)) { + soup_test_assert (FALSE, "fallback decoding FAILED"); + return; + } + g_free (disposition); + + filename = g_hash_table_lookup (params, "filename"); + g_assert_cmpstr (filename, ==, RFC5987_TEST_FALLBACK_FILENAME); + g_hash_table_destroy (params); + + soup_message_headers_free (hdrs); + + /* Ensure that soup-multipart always quotes filename */ + g_test_bug ("641280"); + multipart = soup_multipart_new (SOUP_FORM_MIME_TYPE_MULTIPART); + buffer = soup_buffer_new (SOUP_MEMORY_STATIC, "foo", 3); + soup_multipart_append_form_file (multipart, "test", "token", + "text/plain", buffer); + soup_buffer_free (buffer); + + hdrs = soup_message_headers_new (SOUP_MESSAGE_HEADERS_MULTIPART); + body = soup_message_body_new (); + soup_multipart_to_message (multipart, hdrs, body); + soup_message_headers_free (hdrs); + soup_multipart_free (multipart); + + buffer = soup_message_body_flatten (body); + soup_message_body_free (body); + + g_assert_true (strstr (buffer->data, "filename=\"token\"")); + + soup_buffer_free (buffer); +} + +#define CONTENT_TYPE_TEST_MIME_TYPE "text/plain" +#define CONTENT_TYPE_TEST_ATTRIBUTE "charset" +#define CONTENT_TYPE_TEST_VALUE "US-ASCII" +#define CONTENT_TYPE_TEST_HEADER "text/plain; charset=US-ASCII" + +#define CONTENT_TYPE_BAD_HEADER "plain text, not text/html" + +static void +do_content_type_tests (void) +{ + SoupMessageHeaders *hdrs; + GHashTable *params; + const char *header, *mime_type; + + g_test_bug ("576760"); + + hdrs = soup_message_headers_new (SOUP_MESSAGE_HEADERS_MULTIPART); + params = g_hash_table_new (g_str_hash, g_str_equal); + g_hash_table_insert (params, CONTENT_TYPE_TEST_ATTRIBUTE, + CONTENT_TYPE_TEST_VALUE); + soup_message_headers_set_content_type (hdrs, CONTENT_TYPE_TEST_MIME_TYPE, params); + g_hash_table_destroy (params); + + header = soup_message_headers_get_one (hdrs, "Content-Type"); + g_assert_cmpstr (header, ==, CONTENT_TYPE_TEST_HEADER); + + soup_message_headers_clear (hdrs); + soup_message_headers_append (hdrs, "Content-Type", + CONTENT_TYPE_TEST_MIME_TYPE); + /* Add a second Content-Type header: should be ignored */ + soup_message_headers_append (hdrs, "Content-Type", + CONTENT_TYPE_TEST_MIME_TYPE); + + mime_type = soup_message_headers_get_content_type (hdrs, ¶ms); + g_assert_cmpstr (mime_type, ==, CONTENT_TYPE_TEST_MIME_TYPE); + g_assert_cmpint (g_hash_table_size (params), ==, 0); + if (params) + g_hash_table_destroy (params); + + g_test_bug ("577630"); + + soup_message_headers_clear (hdrs); + soup_message_headers_append (hdrs, "Content-Type", + CONTENT_TYPE_BAD_HEADER); + mime_type = soup_message_headers_get_content_type (hdrs, ¶ms); + g_assert_null (mime_type); + + soup_message_headers_free (hdrs); +} + +struct { + const char *name, *value; +} test_params[] = { + { "one", "foo" }, + { "two", "test with spaces" }, + { "three", "test with \"quotes\" and \\s" }, + { "four", NULL }, + { "five", "test with \xC3\xA1\xC3\xA7\xC4\x89\xC3\xA8\xC3\xB1\xC5\xA3\xC5\xA1" } +}; + +#define TEST_PARAMS_RESULT "one=foo, two=\"test with spaces\", three=\"test with \\\"quotes\\\" and \\\\s\", four, five*=UTF-8''test%20with%20%C3%A1%C3%A7%C4%89%C3%A8%C3%B1%C5%A3%C5%A1" + +static void +do_append_param_tests (void) +{ + GString *params; + int i; + + g_test_bug ("577728"); + + params = g_string_new (NULL); + for (i = 0; i < G_N_ELEMENTS (test_params); i++) { + if (i > 0) + g_string_append (params, ", "); + soup_header_g_string_append_param (params, + test_params[i].name, + test_params[i].value); + } + g_assert_cmpstr (params->str, ==, TEST_PARAMS_RESULT); + g_string_free (params, TRUE); +} + +static const struct { + const char *description, *name, *value; +} bad_headers[] = { + { "Empty name", "", "value" }, + { "Name with spaces", "na me", "value" }, + { "Name with colon", "na:me", "value" }, + { "Name with CR", "na\rme", "value" }, + { "Name with LF", "na\nme", "value" }, + { "Name with tab", "na\tme", "value" }, + { "Value with CR", "name", "val\rue" }, + { "Value with LF", "name", "val\nue" }, + { "Value with LWS", "name", "val\r\n ue" } +}; + +static void +do_bad_header_tests (void) +{ + SoupMessageHeaders *hdrs; + int i; + + hdrs = soup_message_headers_new (SOUP_MESSAGE_HEADERS_MULTIPART); + for (i = 0; i < G_N_ELEMENTS (bad_headers); i++) { + debug_printf (1, " %s\n", bad_headers[i].description); + + g_test_expect_message ("libsoup", G_LOG_LEVEL_CRITICAL, + "*soup_message_headers_append*assertion*failed*"); + soup_message_headers_append (hdrs, bad_headers[i].name, + bad_headers[i].value); + g_test_assert_expected_messages (); + } + soup_message_headers_free (hdrs); +} + +int +main (int argc, char **argv) +{ + int ret; + + test_init (argc, argv, NULL); + + g_test_add_func ("/header-parsing/request", do_request_tests); + g_test_add_func ("/header-parsing/response", do_response_tests); + g_test_add_func ("/header-parsing/qvalue", do_qvalue_tests); + g_test_add_func ("/header-parsing/content-disposition", do_content_disposition_tests); + g_test_add_func ("/header-parsing/content-type", do_content_type_tests); + g_test_add_func ("/header-parsing/append-param", do_append_param_tests); + g_test_add_func ("/header-parsing/bad", do_bad_header_tests); + + ret = g_test_run (); + + test_cleanup (); + return ret; +} diff --git a/tests/htdigest b/tests/htdigest new file mode 100644 index 0000000..352520f --- /dev/null +++ b/tests/htdigest @@ -0,0 +1,3 @@ +user1:realm1:69cb1fa0285304a71f8975aecd027008 +user2:realm2:b67d8ee3c2e271abba78f71d12fe472e +user3:realm3:601c319693279abbc07d332bd7637239 diff --git a/tests/htpasswd b/tests/htpasswd new file mode 100644 index 0000000..04e9ce2 --- /dev/null +++ b/tests/htpasswd @@ -0,0 +1,3 @@ +user1:sTFk2g6n8RsWY +user2:N.Dlbd.xU4K1w +user3:c2vSU/3eQHy.w diff --git a/tests/httpd.conf.in b/tests/httpd.conf.in new file mode 100644 index 0000000..b818c12 --- /dev/null +++ b/tests/httpd.conf.in @@ -0,0 +1,284 @@ +# http.conf used for testing auth-test + +ServerName 127.0.0.1 +Listen 127.0.0.1:47524 + +DocumentRoot . + +# The tests shut down apache with "graceful-stop", because that makes +# it close its listening socket right away. But it seems to sometimes +# result in apache never fully exiting. This fixes that. +GracefulShutdownTimeout 1 + +# Change this to "./error.log" if it's failing and you don't know why +ErrorLog /dev/null + +LoadModule mpm_prefork_module @APACHE_MODULE_DIR@/mod_mpm_prefork.so +LoadModule alias_module @APACHE_MODULE_DIR@/mod_alias.so +LoadModule auth_basic_module @APACHE_MODULE_DIR@/mod_auth_basic.so +LoadModule auth_digest_module @APACHE_MODULE_DIR@/mod_auth_digest.so +LoadModule authn_core_module @APACHE_MODULE_DIR@/mod_authn_core.so +LoadModule authn_file_module @APACHE_MODULE_DIR@/mod_authn_file.so +LoadModule authz_core_module @APACHE_MODULE_DIR@/mod_authz_core.so +LoadModule authz_host_module @APACHE_MODULE_DIR@/mod_authz_host.so +LoadModule authz_user_module @APACHE_MODULE_DIR@/mod_authz_user.so +LoadModule dir_module @APACHE_MODULE_DIR@/mod_dir.so +LoadModule mime_module @APACHE_MODULE_DIR@/mod_mime.so +@IF_HAVE_PHP@LoadModule php7_module @APACHE_PHP_MODULE_DIR@/libphp7.so +LoadModule proxy_module @APACHE_MODULE_DIR@/mod_proxy.so +LoadModule proxy_http_module @APACHE_MODULE_DIR@/mod_proxy_http.so +LoadModule proxy_connect_module @APACHE_MODULE_DIR@/mod_proxy_connect.so +LoadModule ssl_module @APACHE_SSL_MODULE_DIR@/mod_ssl.so +@IF_HAVE_MOD_UNIXD@LoadModule unixd_module @APACHE_SSL_MODULE_DIR@/mod_unixd.so + +DirectoryIndex index.txt +TypesConfig /dev/null +AddType application/x-httpd-php .php +Redirect permanent /redirected /index.txt + +# Proxy #1: unauthenticated +Listen 127.0.0.1:47526 + + ProxyRequests On + AllowCONNECT 47525 + + # Deny proxying by default + + Require all denied + + + # Allow local http connections + + Require all granted + + + # Allow CONNECT to local https port + + Require all granted + + + # Deny non-proxy requests + + Require all denied + + + +# Proxy #2: authenticated +Listen 127.0.0.1:47527 + + ProxyRequests On + AllowCONNECT 47525 + + # Deny proxying by default + + Require all denied + + + # Allow local http connections with authentication + + AuthType Basic + AuthName realm1 + AuthUserFile ./htpasswd + Require valid-user + + + # Allow CONNECT to local https port with authentication + + AuthType Basic + AuthName realm1 + AuthUserFile ./htpasswd + Require valid-user + + + # Fail non-proxy requests + + Require all denied + + + +# Proxy #3: unauthenticatable-to +Listen 127.0.0.1:47528 + + ProxyRequests On + AllowCONNECT 47525 + + # Deny proxying by default + + Require all denied + + + # Allow local http connections with authentication + + AuthType Basic + AuthName realm1 + AuthUserFile ./htpasswd + Require user no-such-user + + + # Allow CONNECT to local https port with authentication + + AuthType Basic + AuthName realm1 + AuthUserFile ./htpasswd + Require user no-such-user + + + # Fail non-proxy requests + + Require all denied + + + + +# SSL setup + + Listen 127.0.0.1:47525 + + + SSLEngine on + + SSLCertificateFile ./test-cert.pem + SSLCertificateKeyFile ./test-key.pem + + + + + +# Basic auth tests +Alias /Basic/realm1/realm2/realm1 . +Alias /Basic/realm1/realm2 . +Alias /Basic/realm1/subdir . +Alias /Basic/realm1/not . +Alias /Basic/realm1 . +Alias /Basic/realm12/subdir . +Alias /Basic/realm12 . +Alias /Basic/realm2 . +Alias /Basic/realm3 . +Alias /Basic . +Alias /BasicRoot . + + + AuthType Basic + AuthName realm1 + AuthUserFile ./htpasswd + Require user user1 + + + + AuthType Basic + AuthName realm1 + AuthUserFile ./htpasswd + Require user user2 + + + + AuthType Basic + AuthName realm12 + AuthUserFile ./htpasswd + Require user user1 user2 + + + + AuthType Basic + AuthName realm2 + AuthUserFile ./htpasswd + Require user user2 + + + + AuthType Basic + AuthName realm1 + AuthUserFile ./htpasswd + Require user user1 + + + + AuthType Basic + AuthName realm2 + AuthUserFile ./htpasswd + Require user user2 + + + + AuthType Basic + AuthName realm3 + AuthUserFile ./htpasswd + Require user user3 + + + + AuthType Basic + AuthName realm1 + AuthUserFile ./htpasswd + Require user user1 + + +# Digest auth tests +Alias /Digest/realm1/realm2/realm1 . +Alias /Digest/realm1/realm2 . +Alias /Digest/realm1/subdir . +Alias /Digest/realm1/expire . +Alias /Digest/realm1/not . +Alias /Digest/realm1 . +Alias /Digest/realm2 . +Alias /Digest/realm3 . +Alias /Digest . + + + AuthType Digest + AuthName realm1 + AuthUserFile ./htdigest + AuthDigestDomain /Digest/realm1 /Digest/realm1/realm2/realm1 + Require valid-user + + + + AuthType Digest + AuthName realm1 + AuthUserFile ./htdigest + AuthDigestDomain /Digest/realm1 /Digest/realm1/realm2/realm1 + AuthDigestNonceLifetime 2 + Require valid-user + + + + AuthType Digest + AuthName realm1 + AuthUserFile ./htdigest + AuthDigestDomain /Digest/realm1 /Digest/realm1/realm2/realm1 + Require user user2 + + + + AuthType Digest + AuthName realm2 + AuthUserFile ./htdigest + AuthDigestDomain /Digest/realm2 /Digest/realm1/realm2 + Require valid-user + + + + AuthType Digest + AuthName realm1 + AuthUserFile ./htdigest + AuthDigestDomain /Digest/realm1 /Digest/realm1/realm2/realm1 + Require valid-user + + + + AuthType Digest + AuthName realm2 + AuthUserFile ./htdigest + AuthDigestDomain /Digest/realm2 /Digest/realm1/realm2 + Require valid-user + + + + AuthType Digest + AuthName realm3 + AuthUserFile ./htdigest + AuthDigestDomain /Digest/realm3 + Require valid-user + # test RFC2069-style Digest + AuthDigestQop none + diff --git a/tests/index.txt b/tests/index.txt new file mode 100644 index 0000000..931a6aa --- /dev/null +++ b/tests/index.txt @@ -0,0 +1,430 @@ +Directory index file for test httpd. + +pull-api wants this file to be larger than 3 times +soup-message-io.c:RESPONSE_BUFFER_SIZE. Also, the contents of the file +should not repeat themselves. (There are no duplicated lines here +other than the two blank lines.) + + !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdef +g hijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMN +OP QRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456 +789 :;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{| +}~!" #$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcd +efghi jklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKL +MNOPQR STUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./01234 +56789:; <=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz +{|}~!"#$ %&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`ab +cdefghijk lmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJ +KLMNOPQRST UVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./012 +3456789:;<= >?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwx +yz{|}~!"#$%& '()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_` +abcdefghijklm nopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGH +IJKLMNOPQRSTUV WXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0 +123456789:;<=>? @ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuv +wxyz{|}~!"#$%&'( )*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^ +_`abcdefghijklmno pqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEF +GHIJKLMNOPQRSTUVWX YZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-. +/0123456789:;<=>?@A BCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrst +uvwxyz{|}~!"#$%&'()* +,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\ +]^_`abcdefghijklmnopq rstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCD +EFGHIJKLMNOPQRSTUVWXYZ [\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+, +-./0123456789:;<=>?@ABC DEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqr +stuvwxyz{|}~!"#$%&'()*+, -./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ +[\]^_`abcdefghijklmnopqrs tuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@AB +CDEFGHIJKLMNOPQRSTUVWXYZ[\ ]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()* ++,-./0123456789:;<=>?@ABCDE FGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnop +qrstuvwxyz{|}~!"#$%&'()*+,-. /0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWX +YZ[\]^_`abcdefghijklmnopqrstu vwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ +ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^ _`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'( +)*+,-./0123456789:;<=>?@ABCDEFG HIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmn +opqrstuvwxyz{|}~!"#$%&'()*+,-./0 123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUV +WXYZ[\]^_`abcdefghijklmnopqrstuvw xyz{|}~!"#$%&'()*+,-./0123456789:;<=> +?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_` abcdefghijklmnopqrstuvwxyz{|}~!"#$%& +'()*+,-./0123456789:;<=>?@ABCDEFGHI JKLMNOPQRSTUVWXYZ[\]^_`abcdefghijkl +mnopqrstuvwxyz{|}~!"#$%&'()*+,-./012 3456789:;<=>?@ABCDEFGHIJKLMNOPQRST +UVWXYZ[\]^_`abcdefghijklmnopqrstuvwxy z{|}~!"#$%&'()*+,-./0123456789:;< +=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`ab cdefghijklmnopqrstuvwxyz{|}~!"#$ +%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJK LMNOPQRSTUVWXYZ[\]^_`abcdefghij +klmnopqrstuvwxyz{|}~!"#$%&'()*+,-./01234 56789:;<=>?@ABCDEFGHIJKLMNOPQR +STUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{ |}~!"#$%&'()*+,-./0123456789: +;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcd efghijklmnopqrstuvwxyz{|}~!" +#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLM NOPQRSTUVWXYZ[\]^_`abcdefgh +ijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456 789:;<=>?@ABCDEFGHIJKLMNOP +QRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|} ~!"#$%&'()*+,-./012345678 +9:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdef ghijklmnopqrstuvwxyz{|}~ +!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNO PQRSTUVWXYZ[\]^_`abcdef +ghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./012345678 9:;<=>?@ABCDEFGHIJKLMN +OPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~! "#$%&'()*+,-./0123456 +789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefgh ijklmnopqrstuvwxyz{| +}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQ RSTUVWXYZ[\]^_`abcd +efghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789: ;<=>?@ABCDEFGHIJKL +MNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"# $%&'()*+,-./01234 +56789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghij klmnopqrstuvwxyz +{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRS TUVWXYZ[\]^_`ab +cdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;< =>?@ABCDEFGHIJ +KLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$% &'()*+,-./012 +3456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijkl mnopqrstuvwx +yz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTU VWXYZ[\]^_` +abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=> ?@ABCDEFGH +IJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&' ()*+,-./0 +123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmn opqrstuv +wxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVW XYZ[\]^ +_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ ABCDEF +GHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'() *+,-. +/0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnop qrst +uvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXY Z[\ +]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@AB CD +EFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+ , +-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqr + stuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ +[ \]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@AB +CD EFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()* ++,- ./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnop +qrst uvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWX +YZ[\] ^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ +ABCDEF GHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'( +)*+,-./ 0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmn +opqrstuv wxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUV +WXYZ[\]^_ `abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=> +?@ABCDEFGH IJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%& +'()*+,-./01 23456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijkl +mnopqrstuvwx yz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRST +UVWXYZ[\]^_`a bcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;< +=>?@ABCDEFGHIJ KLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$ +%&'()*+,-./0123 456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghij +klmnopqrstuvwxyz {|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQR +STUVWXYZ[\]^_`abc defghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789: +;<=>?@ABCDEFGHIJKL MNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!" +#$%&'()*+,-./012345 6789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefgh +ijklmnopqrstuvwxyz{| }~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOP +QRSTUVWXYZ[\]^_`abcde fghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./012345678 +9:;<=>?@ABCDEFGHIJKLMN OPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ +!"#$%&'()*+,-./01234567 89:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdef +ghijklmnopqrstuvwxyz{|}~ !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMN +OPQRSTUVWXYZ[\]^_`abcdefg hijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456 +789:;<=>?@ABCDEFGHIJKLMNOP QRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{| +}~!"#$%&'()*+,-./0123456789 :;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcd +efghijklmnopqrstuvwxyz{|}~!" #$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKL +MNOPQRSTUVWXYZ[\]^_`abcdefghi jklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./01234 +56789:;<=>?@ABCDEFGHIJKLMNOPQR STUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz +{|}~!"#$%&'()*+,-./0123456789:; <=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`ab +cdefghijklmnopqrstuvwxyz{|}~!"#$ %&'()*+,-./0123456789:;<=>?@ABCDEFGHIJ +KLMNOPQRSTUVWXYZ[\]^_`abcdefghijk lmnopqrstuvwxyz{|}~!"#$%&'()*+,-./012 +3456789:;<=>?@ABCDEFGHIJKLMNOPQRST UVWXYZ[\]^_`abcdefghijklmnopqrstuvwx +yz{|}~!"#$%&'()*+,-./0123456789:;<= >?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_` +abcdefghijklmnopqrstuvwxyz{|}~!"#$%& '()*+,-./0123456789:;<=>?@ABCDEFGH +IJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklm nopqrstuvwxyz{|}~!"#$%&'()*+,-./0 +123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUV WXYZ[\]^_`abcdefghijklmnopqrstuv +wxyz{|}~!"#$%&'()*+,-./0123456789:;<=>? @ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^ +_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'( )*+,-./0123456789:;<=>?@ABCDEF +GHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmno pqrstuvwxyz{|}~!"#$%&'()*+,-. +/0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWX YZ[\]^_`abcdefghijklmnopqrst +uvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@A BCDEFGHIJKLMNOPQRSTUVWXYZ[\ +]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()* +,-./0123456789:;<=>?@ABCD +EFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopq rstuvwxyz{|}~!"#$%&'()*+, +-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ [\]^_`abcdefghijklmnopqr +stuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABC DEFGHIJKLMNOPQRSTUVWXYZ +[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+, -./0123456789:;<=>?@AB +CDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrs tuvwxyz{|}~!"#$%&'()* ++,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\ ]^_`abcdefghijklmnop +qrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDE FGHIJKLMNOPQRSTUVWX +YZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-. /0123456789:;<=>?@ +ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstu vwxyz{|}~!"#$%&'( +)*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^ _`abcdefghijklmn +opqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFG HIJKLMNOPQRSTUV +WXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0 123456789:;<=> +?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvw xyz{|}~!"#$%& +'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_` abcdefghijkl +mnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHI JKLMNOPQRST +UVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./012 3456789:;< +=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxy z{|}~!"#$ +%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`ab cdefghij +klmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJK LMNOPQR +STUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./01234 56789: +;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{ |}~!" +#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcd efgh +ijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLM NOP +QRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456 78 +9:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|} ~ +!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdef + ghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMN +O PQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456 +78 9:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{| +}~! "#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcd +efgh ijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKL +MNOPQ RSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./01234 +56789: ;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz +{|}~!"# $%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`ab +cdefghij klmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJ +KLMNOPQRS TUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./012 +3456789:;< =>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwx +yz{|}~!"#$% &'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_` +abcdefghijkl mnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGH +IJKLMNOPQRSTU VWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0 +123456789:;<=> ?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuv +wxyz{|}~!"#$%&' ()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^ +_`abcdefghijklmn opqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEF +GHIJKLMNOPQRSTUVW XYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-. +/0123456789:;<=>?@ ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrst +uvwxyz{|}~!"#$%&'() *+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\ +]^_`abcdefghijklmnop qrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCD +EFGHIJKLMNOPQRSTUVWXY Z[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+, +-./0123456789:;<=>?@AB CDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqr +stuvwxyz{|}~!"#$%&'()*+ ,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ +[\]^_`abcdefghijklmnopqr stuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@AB +CDEFGHIJKLMNOPQRSTUVWXYZ[ \]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()* ++,-./0123456789:;<=>?@ABCD EFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnop +qrstuvwxyz{|}~!"#$%&'()*+,- ./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWX +YZ[\]^_`abcdefghijklmnopqrst uvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ +ABCDEFGHIJKLMNOPQRSTUVWXYZ[\] ^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'( +)*+,-./0123456789:;<=>?@ABCDEF GHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmn +opqrstuvwxyz{|}~!"#$%&'()*+,-./ 0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUV +WXYZ[\]^_`abcdefghijklmnopqrstuv wxyz{|}~!"#$%&'()*+,-./0123456789:;<=> +?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_ `abcdefghijklmnopqrstuvwxyz{|}~!"#$%& +'()*+,-./0123456789:;<=>?@ABCDEFGH IJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijkl +mnopqrstuvwxyz{|}~!"#$%&'()*+,-./01 23456789:;<=>?@ABCDEFGHIJKLMNOPQRST +UVWXYZ[\]^_`abcdefghijklmnopqrstuvwx yz{|}~!"#$%&'()*+,-./0123456789:;< +=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`a bcdefghijklmnopqrstuvwxyz{|}~!"#$ +%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJ KLMNOPQRSTUVWXYZ[\]^_`abcdefghij +klmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123 456789:;<=>?@ABCDEFGHIJKLMNOPQR +STUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz {|}~!"#$%&'()*+,-./0123456789: +;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abc defghijklmnopqrstuvwxyz{|}~!" +#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKL MNOPQRSTUVWXYZ[\]^_`abcdefgh +ijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./012345 6789:;<=>?@ABCDEFGHIJKLMNOP +QRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{| }~!"#$%&'()*+,-./012345678 +9:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcde fghijklmnopqrstuvwxyz{|}~ +!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMN OPQRSTUVWXYZ[\]^_`abcdef +ghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./01234567 89:;<=>?@ABCDEFGHIJKLMN +OPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ !"#$%&'()*+,-./0123456 +789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefg hijklmnopqrstuvwxyz{| +}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOP QRSTUVWXYZ[\]^_`abcd +efghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789 :;<=>?@ABCDEFGHIJKL +MNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!" #$%&'()*+,-./01234 +56789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghi jklmnopqrstuvwxyz +{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQR STUVWXYZ[\]^_`ab +cdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:; <=>?@ABCDEFGHIJ +KLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$ %&'()*+,-./012 +3456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijk lmnopqrstuvwx +yz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRST UVWXYZ[\]^_` +abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<= >?@ABCDEFGH +IJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%& '()*+,-./0 +123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklm nopqrstuv +wxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUV WXYZ[\]^ +_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>? @ABCDEF +GHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'( )*+,-. +/0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmno pqrst +uvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWX YZ[\ +]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@A BCD +EFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()* +, +-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopq r +stuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ + [\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@AB +C DEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()* ++, -./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnop +qrs tuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWX +YZ[\ ]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ +ABCDE FGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'( +)*+,-. /0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmn +opqrstu vwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUV +WXYZ[\]^ _`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=> +?@ABCDEFG HIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%& +'()*+,-./0 123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijkl +mnopqrstuvw xyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRST +UVWXYZ[\]^_` abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;< +=>?@ABCDEFGHI JKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$ +%&'()*+,-./012 3456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghij +klmnopqrstuvwxy z{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQR +STUVWXYZ[\]^_`ab cdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789: +;<=>?@ABCDEFGHIJK LMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!" +#$%&'()*+,-./01234 56789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefgh +ijklmnopqrstuvwxyz{ |}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOP +QRSTUVWXYZ[\]^_`abcd efghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./012345678 +9:;<=>?@ABCDEFGHIJKLM NOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ +!"#$%&'()*+,-./0123456 789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdef +ghijklmnopqrstuvwxyz{|} ~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMN +OPQRSTUVWXYZ[\]^_`abcdef ghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456 +789:;<=>?@ABCDEFGHIJKLMNO PQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{| +}~!"#$%&'()*+,-./012345678 9:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcd +efghijklmnopqrstuvwxyz{|}~! "#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKL +MNOPQRSTUVWXYZ[\]^_`abcdefgh ijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./01234 +56789:;<=>?@ABCDEFGHIJKLMNOPQ RSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz +{|}~!"#$%&'()*+,-./0123456789: ;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`ab +cdefghijklmnopqrstuvwxyz{|}~!"# $%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJ +KLMNOPQRSTUVWXYZ[\]^_`abcdefghij klmnopqrstuvwxyz{|}~!"#$%&'()*+,-./012 +3456789:;<=>?@ABCDEFGHIJKLMNOPQRS TUVWXYZ[\]^_`abcdefghijklmnopqrstuvwx +yz{|}~!"#$%&'()*+,-./0123456789:;< =>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_` +abcdefghijklmnopqrstuvwxyz{|}~!"#$% &'()*+,-./0123456789:;<=>?@ABCDEFGH +IJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijkl mnopqrstuvwxyz{|}~!"#$%&'()*+,-./0 +123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTU VWXYZ[\]^_`abcdefghijklmnopqrstuv +wxyz{|}~!"#$%&'()*+,-./0123456789:;<=> ?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^ +_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&' ()*+,-./0123456789:;<=>?@ABCDEF +GHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmn opqrstuvwxyz{|}~!"#$%&'()*+,-. +/0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVW XYZ[\]^_`abcdefghijklmnopqrst +uvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ ABCDEFGHIJKLMNOPQRSTUVWXYZ[\ +]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'() *+,-./0123456789:;<=>?@ABCD +EFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnop qrstuvwxyz{|}~!"#$%&'()*+, +-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXY Z[\]^_`abcdefghijklmnopqr +stuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@AB CDEFGHIJKLMNOPQRSTUVWXYZ +[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+ ,-./0123456789:;<=>?@AB +CDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqr stuvwxyz{|}~!"#$%&'()* ++,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[ \]^_`abcdefghijklmnop +qrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCD EFGHIJKLMNOPQRSTUVWX +YZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,- ./0123456789:;<=>?@ +ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrst uvwxyz{|}~!"#$%&'( +)*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\] ^_`abcdefghijklmn +opqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEF GHIJKLMNOPQRSTUV +WXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./ 0123456789:;<=> +?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuv wxyz{|}~!"#$%& +'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_ `abcdefghijkl +mnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGH IJKLMNOPQRST +UVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./01 23456789:;< +=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwx yz{|}~!"#$ +%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`a bcdefghij +klmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJ KLMNOPQR +STUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123 456789: +;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz {|}~!" +#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abc defgh +ijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKL MNOP +QRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./012345 678 +9:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{| }~ +!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcde f +ghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMN + OPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456 +7 89:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{| +}~ !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcd +efg hijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKL +MNOP QRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./01234 +56789 :;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz +{|}~!" #$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`ab +cdefghi jklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJ +KLMNOPQR STUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./012 +3456789:; <=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwx +yz{|}~!"#$ %&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_` +abcdefghijk lmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGH +IJKLMNOPQRST UVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0 +123456789:;<= >?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuv +wxyz{|}~!"#$%& '()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^ +_`abcdefghijklm nopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEF +GHIJKLMNOPQRSTUV WXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-. +/0123456789:;<=>? @ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrst +uvwxyz{|}~!"#$%&'( )*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\ +]^_`abcdefghijklmno pqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCD +EFGHIJKLMNOPQRSTUVWX YZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+, +-./0123456789:;<=>?@A BCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqr +stuvwxyz{|}~!"#$%&'()* +,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ +[\]^_`abcdefghijklmnopq rstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@AB +CDEFGHIJKLMNOPQRSTUVWXYZ [\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()* ++,-./0123456789:;<=>?@ABC DEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnop +qrstuvwxyz{|}~!"#$%&'()*+, -./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWX +YZ[\]^_`abcdefghijklmnopqrs tuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ +ABCDEFGHIJKLMNOPQRSTUVWXYZ[\ ]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'( +)*+,-./0123456789:;<=>?@ABCDE FGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmn +opqrstuvwxyz{|}~!"#$%&'()*+,-. /0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUV +WXYZ[\]^_`abcdefghijklmnopqrstu vwxyz{|}~!"#$%&'()*+,-./0123456789:;<=> +?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^ _`abcdefghijklmnopqrstuvwxyz{|}~!"#$%& +'()*+,-./0123456789:;<=>?@ABCDEFG HIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijkl +mnopqrstuvwxyz{|}~!"#$%&'()*+,-./0 123456789:;<=>?@ABCDEFGHIJKLMNOPQRST +UVWXYZ[\]^_`abcdefghijklmnopqrstuvw xyz{|}~!"#$%&'()*+,-./0123456789:;< +=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_` abcdefghijklmnopqrstuvwxyz{|}~!"#$ +%&'()*+,-./0123456789:;<=>?@ABCDEFGHI JKLMNOPQRSTUVWXYZ[\]^_`abcdefghij +klmnopqrstuvwxyz{|}~!"#$%&'()*+,-./012 3456789:;<=>?@ABCDEFGHIJKLMNOPQR +STUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxy z{|}~!"#$%&'()*+,-./0123456789: +;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`ab cdefghijklmnopqrstuvwxyz{|}~!" +#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJK LMNOPQRSTUVWXYZ[\]^_`abcdefgh +ijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./01234 56789:;<=>?@ABCDEFGHIJKLMNOP +QRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{ |}~!"#$%&'()*+,-./012345678 +9:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcd efghijklmnopqrstuvwxyz{|}~ +!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLM NOPQRSTUVWXYZ[\]^_`abcdef +ghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456 789:;<=>?@ABCDEFGHIJKLMN +OPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|} ~!"#$%&'()*+,-./0123456 +789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdef ghijklmnopqrstuvwxyz{| +}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNO PQRSTUVWXYZ[\]^_`abcd +efghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./012345678 9:;<=>?@ABCDEFGHIJKL +MNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~! "#$%&'()*+,-./01234 +56789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefgh ijklmnopqrstuvwxyz +{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQ RSTUVWXYZ[\]^_`ab +cdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789: ;<=>?@ABCDEFGHIJ +KLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"# $%&'()*+,-./012 +3456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghij klmnopqrstuvwx +yz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRS TUVWXYZ[\]^_` +abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;< =>?@ABCDEFGH +IJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$% &'()*+,-./0 +123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijkl mnopqrstuv +wxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTU VWXYZ[\]^ +_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=> ?@ABCDEF +GHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&' ()*+,-. +/0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmn opqrst +uvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVW XYZ[\ +]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ ABCD +EFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'() *+, +-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnop qr +stuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXY Z +[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@AB + CDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()* ++ ,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnop +qr stuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWX +YZ[ \]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ +ABCD EFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'( +)*+,- ./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmn +opqrst uvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUV +WXYZ[\] ^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=> +?@ABCDEF GHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%& +'()*+,-./ 0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijkl +mnopqrstuv wxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRST +UVWXYZ[\]^_ `abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;< +=>?@ABCDEFGH IJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$ +%&'()*+,-./01 23456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghij +klmnopqrstuvwx yz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQR +STUVWXYZ[\]^_`a bcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789: +;<=>?@ABCDEFGHIJ KLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!" +#$%&'()*+,-./0123 456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefgh +ijklmnopqrstuvwxyz {|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOP +QRSTUVWXYZ[\]^_`abc defghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./012345678 +9:;<=>?@ABCDEFGHIJKL MNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ +!"#$%&'()*+,-./012345 6789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdef +ghijklmnopqrstuvwxyz{| }~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMN +OPQRSTUVWXYZ[\]^_`abcde fghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456 +789:;<=>?@ABCDEFGHIJKLMN OPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{| +}~!"#$%&'()*+,-./01234567 89:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcd +efghijklmnopqrstuvwxyz{|}~ !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKL +MNOPQRSTUVWXYZ[\]^_`abcdefg hijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./01234 +56789:;<=>?@ABCDEFGHIJKLMNOP QRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz +{|}~!"#$%&'()*+,-./0123456789 :;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`ab +cdefghijklmnopqrstuvwxyz{|}~!" #$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJ +KLMNOPQRSTUVWXYZ[\]^_`abcdefghi jklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./012 +3456789:;<=>?@ABCDEFGHIJKLMNOPQR STUVWXYZ[\]^_`abcdefghijklmnopqrstuvwx +yz{|}~!"#$%&'()*+,-./0123456789:; <=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_` +abcdefghijklmnopqrstuvwxyz{|}~!"#$ %&'()*+,-./0123456789:;<=>?@ABCDEFGH +IJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijk lmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0 +123456789:;<=>?@ABCDEFGHIJKLMNOPQRST UVWXYZ[\]^_`abcdefghijklmnopqrstuv +wxyz{|}~!"#$%&'()*+,-./0123456789:;<= >?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^ +_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%& '()*+,-./0123456789:;<=>?@ABCDEF +GHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklm nopqrstuvwxyz{|}~!"#$%&'()*+,-. +/0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUV WXYZ[\]^_`abcdefghijklmnopqrst +uvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>? @ABCDEFGHIJKLMNOPQRSTUVWXYZ[\ +]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'( )*+,-./0123456789:;<=>?@ABCD +EFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmno pqrstuvwxyz{|}~!"#$%&'()*+, +-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWX YZ[\]^_`abcdefghijklmnopqr +stuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@A BCDEFGHIJKLMNOPQRSTUVWXYZ +[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()* +,-./0123456789:;<=>?@AB +CDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopq rstuvwxyz{|}~!"#$%&'()* ++,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ [\]^_`abcdefghijklmnop +qrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABC DEFGHIJKLMNOPQRSTUVWX +YZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+, -./0123456789:;<=>?@ +ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrs tuvwxyz{|}~!"#$%&'( +)*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\ ]^_`abcdefghijklmn +opqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDE FGHIJKLMNOPQRSTUV +WXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-. /0123456789:;<=> +?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstu vwxyz{|}~!"#$%& +'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^ _`abcdefghijkl +mnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFG HIJKLMNOPQRST +UVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0 123456789:;< +=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvw xyz{|}~!"#$ +%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_` abcdefghij +klmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHI JKLMNOPQR +STUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./012 3456789: +;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxy z{|}~!" +#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`ab cdefgh +ijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJK LMNOP +QRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./01234 5678 +9:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{ |}~ diff --git a/tests/libsoup.supp b/tests/libsoup.supp new file mode 100644 index 0000000..2c7ba9b --- /dev/null +++ b/tests/libsoup.supp @@ -0,0 +1,595 @@ +# valgrind suppressions file + +{ + ld.so/map + Memcheck:Cond + fun:index + fun:expand_dynamic_string_token + fun:_dl_map_object +} +{ + ld.so/relocate + Memcheck:Cond + fun:_dl_relocate_object + fun:dl_main + fun:_dl_sysdep_start + fun:_dl_start +} + +{ + glib/g_type_init + Memcheck:Leak + ... + fun:g_type_init +} +{ + glib/g_type_init_with_debug_flags + Memcheck:Leak + ... + fun:g_type_init_with_debug_flags +} +{ + glib/g_thread_init + Memcheck:Leak + ... + fun:g_thread_init +} +{ + glib/g_thread_init_glib + Memcheck:Leak + ... + fun:g_thread_init_glib +} +{ + glib/g_thread_self + Memcheck:Leak + ... + fun:g_slice_alloc0 + fun:g_thread_self +} +{ + glib/g_type_register_static + Memcheck:Leak + ... + fun:g_type_register_static +} +{ + glib/g_boxed_type_register_static + Memcheck:Leak + ... + fun:g_boxed_type_register_static +} +{ + glib/g_type_add_interface_static + Memcheck:Leak + ... + fun:g_type_add_interface_static +} +{ + glib/g_type_interface_add_prerequisite + Memcheck:Leak + ... + fun:g_type_interface_add_prerequisite +} +{ + glib/g_type_class_ref + Memcheck:Leak + ... + fun:g_type_class_ref +} +{ + glib/g_set_prgname + Memcheck:Leak + ... + fun:g_set_prgname +} +{ + glib/g_intern_string + Memcheck:Leak + ... + fun:g_intern_string +} +{ + glib/g_intern_static_string + Memcheck:Leak + ... + fun:g_intern_static_string +} +{ + glib/g_quark_from_string + Memcheck:Leak + ... + fun:g_quark_from_string +} +{ + glib/g_quark_from_static_string + Memcheck:Leak + ... + fun:g_quark_from_static_string +} +{ + glib/get_dispatch + Memcheck:Leak + ... + fun:get_dispatch +} +{ + glib/g_signal_connect + Memcheck:Leak + ... + fun:handler_list_ensure +} +{ + glib/g_signal_handlers_destroy + Memcheck:Leak + ... + fun:g_signal_handlers_destroy +} +{ + glib/g_data_initialize + Memcheck:Leak + ... + fun:g_data_initialize +} +{ + glib/g_static_private_set + Memcheck:Leak + ... + fun:g_static_private_set +} +{ + glib/g_child_watch_source_init_multi_threaded + Memcheck:Leak + ... + fun:g_child_watch_source_init_multi_threaded +} +{ + glib/xdg_mime_init + Memcheck:Leak + ... + fun:xdg_mime_init +} +{ + glib/GResolver + Memcheck:Leak + ... + fun:g_resolver_get_default +} +{ + glib/g_main_context_push_thread_default + Memcheck:Leak + ... + fun:g_main_context_push_thread_default +} +{ + glib/g_socket_connection_factory + Memcheck:Leak + ... + fun:g_socket_connection_factory_register_type +} +{ + glib/g_get_language_names + Memcheck:Leak + ... + fun:g_get_language_names +} +{ + glib/giomodules + Memcheck:Leak + ... + fun:_g_io_modules_ensure_loaded +} +{ + glib/giomodules2 + Memcheck:Leak + ... + fun:_g_io_module_get_default +} +{ + glib/proxydefault + Memcheck:Leak + ... + fun:get_default_proxy_resolver +} +{ + glib/proxysettings + Memcheck:Leak + ... + fun:update_settings + fun:g_proxy_resolver_gnome_lookup +} +{ + glib/tlsdefault + Memcheck:Leak + ... + fun:get_default_tls_backend +} +{ + glib/tlsdb + Memcheck:Leak + ... + fun:g_tls_backend_gnutls_get_default_database +} +{ + glib/tlsdb_dummy + Memcheck:Leak + ... + fun:g_dummy_tls_backend_get_default_database +} +{ + glib/tlscache + Memcheck:Leak + ... + fun:g_bytes_new_with_free_func + fun:g_tls_client_connection_gnutls_constructed +} +{ + glib/tlspriority + Memcheck:Leak + ... + fun:g_tls_connection_gnutls_init_priorities +} +{ + glib/gfileinfo + Memcheck:Leak + ... + fun:ensure_attribute_hash + fun:lookup_attribute +} +{ + glib/gfileinfo2 + Memcheck:Leak + ... + fun:_lookup_namespace +} +{ + glib/unixsignalthread + Memcheck:Leak + ... + fun:ensure_unix_signal_handler_installed_unlocked +} +{ + glib/gioscheduler + Memcheck:Leak + ... + fun:init_scheduler +} +{ + glib/gtestinit + Memcheck:Leak + ... + fun:g_test_init +} +{ + glib/gtestroot + Memcheck:Leak + ... + fun:g_test_get_root +} +{ + glib/gtestseed + Memcheck:Leak + ... + fun:test_run_seed +} +{ + glib/gtestcase + Memcheck:Leak + ... + fun:g_test_create_case +} +{ + glib/gtestsuite + Memcheck:Leak + ... + fun:g_test_create_suite +} +{ + glib/gtestsuiteadd + Memcheck:Leak + ... + fun:g_test_suite_add +} +{ + glib/gtestsuiteaddsuite + Memcheck:Leak + ... + fun:g_test_suite_add_suite +} +{ + glib/gtestsuiterun + Memcheck:Leak + ... + fun:g_slist_copy + fun:g_test_run_suite_internal +} +{ + glib/gthreadpool + Memcheck:Leak + ... + fun:g_thread_pool_start_thread +} +{ + glib/gthreadpool1 + Memcheck:Leak + ... + fun:g_thread_pool_wait_for_new_pool +} +{ + glib/gthreadpool2 + Memcheck:Leak + ... + fun:g_thread_pool_wait_for_new_task +} +{ + glib/unused_thread_queue + Memcheck:Leak + ... + fun:g_async_queue_new_full + fun:g_thread_pool_new +} +{ + glib/gthreadtls + Memcheck:Leak + ... + fun:_dl_allocate_tls + ... + fun:g_system_thread_new +} +{ + glib/filenamecharsets + Memcheck:Leak + ... + fun:g_get_filename_charsets +} +{ + glib/charset + Memcheck:Leak + ... + fun:g_get_charset +} +{ + glib/tmpdir + Memcheck:Leak + ... + fun:g_get_tmp_dir +} +{ + glib/g_get_user_name + Memcheck:Leak + ... + fun:g_get_user_name +} +{ + glib/gtlssessioncache + Memcheck:Leak + ... + fun:g_tls_backend_gnutls_store_session +} +{ + glib/gtlssessioncache_client + Memcheck:Leak + ... + fun:gnutls_session_get_data2 + fun:g_tls_client_connection_gnutls_finish_handshake +} +{ + glib/gtlssessioncache_client2 + Memcheck:Leak + ... + fun:g_bytes_new_with_free_func + fun:g_tls_client_connection_gnutls_finish_handshake +} +{ + glib/gtlssessioncache_client3 + Memcheck:Leak + ... + fun:g_bytes_new_take + fun:g_tls_client_connection_gnutls_constructed +} +{ + glib/gtlssessioncache_client4 + Memcheck:Leak + ... + fun:g_strdup_printf + fun:g_tls_client_connection_gnutls_constructed +} +{ + glib/gtlssessioncache_server + Memcheck:Leak + ... + fun:g_tls_server_connection_gnutls_db_store +} +{ + glib/cached_poll_array + Memcheck:Leak + ... + fun:g_malloc_n + fun:g_main_context_iterate +} +{ + glib/rand + Memcheck:Leak + ... + fun:g_rand_new + fun:g_random_int_range +} +{ + glib/g_cancellable_push_current + Memcheck:Leak + ... + fun:g_cancellable_push_current +} +{ + glib/slice_thread_local + Memcheck:Leak + ... + fun:thread_memory_from_self +} +{ + glib/gobjectinit + Memcheck:Leak + ... + fun:gobject_init_ctor +} +{ + glib/gtask threadpool + Memcheck:Leak + ... + fun:g_thread_pool_new + fun:g_task_thread_pool_init +} +{ + glib/resources + Memcheck:Leak + ... + fun:g_resource_load +} +{ + glib/resources2 + Memcheck:Leak + ... + fun:g_resources_register +} +{ + glib/worker + Memcheck:Leak + ... + fun:g_get_worker_context +} +{ + glib/worker2 + Memcheck:Leak + ... + fun:glib_worker_main +} + +# probably inlines the aggressive memcpy/memcmp +{ + gnutls/der + Memcheck:Addr4 + ... + fun:asn1_der_coding +} +# probably using uninitialized memory as padding or something +{ + gnutls/handshake + Memcheck:Cond + ... + fun:gnutls_handshake +} +{ + gnutls/init + Memcheck:Leak + ... + fun:gnutls_global_init +} +# known leak in gnutls 2.12, fixed in 3.0 +{ + gnutls/server_key_leak + Memcheck:Leak + ... + fun:call_get_cert_callback +} + +{ + libxml2/xmlInitGlobals + Memcheck:Leak + ... + fun:xmlInitGlobals +} +{ + libxml2/xmlInitMemory + Memcheck:Leak + ... + fun:xmlInitMemory +} +{ + libxml2/xmlInitParserCtxt + Memcheck:Leak + ... + fun:xmlInitParserCtxt +} +{ + libxml2/xmlInitializeDict + Memcheck:Leak + ... + fun:__xmlInitializeDict +} +{ + libxml2/xmlInitCharEncodingHandlers + Memcheck:Leak + ... + fun:xmlInitCharEncodingHandlers +} +{ + libxml2/xmlNewCharEncodingHandler + Memcheck:Leak + ... + fun:xmlNewCharEncodingHandler +} + +{ + libsoup/interned_uri_schemes + Memcheck:Leak + ... + fun:g_ascii_strdown + fun:soup_uri_parse_scheme +} +{ + libsoup/interned_headers + Memcheck:Leak + ... + fun:intern_header_name +} +{ + libsoup/tlds + Memcheck:Leak + ... + fun:soup_tld_ensure_rules_hash_table +} + + +# fixme? +{ + glib/gmuteximpl + Memcheck:Leak + ... + fun:g_mutex_impl_new + fun:g_mutex_get_impl +} +{ + glib/grecmuteximpl + Memcheck:Leak + ... + fun:g_rec_mutex_impl_new + fun:g_rec_mutex_get_impl +} +{ + glib/grwlockimpl + Memcheck:Leak + ... + fun:g_rw_lock_impl_new + fun:g_rw_lock_get_impl +} +{ + glib/gcondimpl + Memcheck:Leak + ... + fun:g_cond_impl_new + fun:g_cond_get_impl +} +{ + glib/gprivateimpl + Memcheck:Leak + ... + fun:g_private_impl_new + fun:g_private_get_impl +} +{ + glib/test_uri_base + Memcheck:Leak + ... + fun:g_strdup + fun:test_case_run +} \ No newline at end of file diff --git a/tests/misc-test.c b/tests/misc-test.c new file mode 100644 index 0000000..8cbda80 --- /dev/null +++ b/tests/misc-test.c @@ -0,0 +1,1248 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright 2007-2012 Red Hat, Inc. + */ + +#include "test-utils.h" + +SoupServer *server, *ssl_server; +SoupURI *base_uri, *ssl_base_uri; + +static gboolean +auth_callback (SoupAuthDomain *auth_domain, SoupMessage *msg, + const char *username, const char *password, gpointer data) +{ + return !strcmp (username, "user") && !strcmp (password, "password"); +} + +static gboolean +timeout_finish_message (gpointer msg) +{ + SoupServer *server = g_object_get_data (G_OBJECT (msg), "server"); + + soup_server_unpause_message (server, msg); + return FALSE; +} + +static void +server_callback (SoupServer *server, SoupMessage *msg, + const char *path, GHashTable *query, + SoupClientContext *context, gpointer data) +{ + SoupURI *uri = soup_message_get_uri (msg); + const char *server_protocol = data; + + if (msg->method != SOUP_METHOD_GET && msg->method != SOUP_METHOD_POST) { + soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED); + return; + } + + if (!strcmp (path, "/redirect")) { + soup_message_set_redirect (msg, SOUP_STATUS_FOUND, "/"); + return; + } + + if (!strcmp (path, "/alias-redirect")) { + SoupURI *redirect_uri; + char *redirect_string; + const char *redirect_protocol; + + redirect_protocol = soup_message_headers_get_one (msg->request_headers, "X-Redirect-Protocol"); + + redirect_uri = soup_uri_copy (uri); + soup_uri_set_scheme (redirect_uri, "foo"); + if (!g_strcmp0 (redirect_protocol, "https")) + soup_uri_set_port (redirect_uri, ssl_base_uri->port); + else + soup_uri_set_port (redirect_uri, base_uri->port); + soup_uri_set_path (redirect_uri, "/alias-redirected"); + redirect_string = soup_uri_to_string (redirect_uri, FALSE); + + soup_message_set_redirect (msg, SOUP_STATUS_FOUND, redirect_string); + g_free (redirect_string); + soup_uri_free (redirect_uri); + return; + } else if (!strcmp (path, "/alias-redirected")) { + soup_message_set_status (msg, SOUP_STATUS_OK); + soup_message_headers_append (msg->response_headers, + "X-Redirected-Protocol", + server_protocol); + return; + } + + if (!strcmp (path, "/slow")) { + soup_server_pause_message (server, msg); + g_object_set_data (G_OBJECT (msg), "server", server); + soup_add_timeout (g_main_context_get_thread_default (), + 1000, timeout_finish_message, msg); + } + + soup_message_set_status (msg, SOUP_STATUS_OK); + if (!strcmp (uri->host, "foo")) { + soup_message_set_response (msg, "text/plain", + SOUP_MEMORY_STATIC, "foo-index", 9); + return; + } else { + soup_message_set_response (msg, "text/plain", + SOUP_MEMORY_STATIC, "index", 5); + return; + } +} + +/* Host header handling: client must be able to override the default + * value, server must be able to recognize different Host values. + */ +static void +do_host_test (void) +{ + SoupSession *session; + SoupMessage *one, *two; + + g_test_bug ("539803"); + + session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL); + + one = soup_message_new_from_uri ("GET", base_uri); + two = soup_message_new_from_uri ("GET", base_uri); + soup_message_headers_replace (two->request_headers, "Host", "foo"); + + soup_session_send_message (session, one); + soup_session_send_message (session, two); + + soup_test_session_abort_unref (session); + + soup_test_assert_message_status (one, SOUP_STATUS_OK); + g_assert_cmpstr (one->response_body->data, ==, "index"); + g_object_unref (one); + + soup_test_assert_message_status (two, SOUP_STATUS_OK); + g_assert_cmpstr (two->response_body->data, ==, "foo-index"); + g_object_unref (two); +} + +/* request with too big header should be discarded with a IO error to + * prevent DOS attacks. + */ +static void +do_host_big_header (void) +{ + SoupMessage *msg; + SoupSession *session; + int i; + + g_test_bug ("792173"); + + session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL); + + msg = soup_message_new_from_uri ("GET", base_uri); + for (i = 0; i < 2048; i++) { + char *key = g_strdup_printf ("test-long-header-key%d", i); + char *value = g_strdup_printf ("test-long-header-key%d", i); + soup_message_headers_append (msg->request_headers, key, value); + g_free (value); + g_free (key); + } + + soup_session_send_message (session, msg); + + soup_test_session_abort_unref (session); + + soup_test_assert_message_status (msg, SOUP_STATUS_IO_ERROR); + + g_object_unref (msg); +} + +/* Dropping the application's ref on the session from a callback + * should not cause the session to be freed at an incorrect time. + * (This test will crash if it fails.) + */ +static void +cu_one_completed (SoupSession *session, SoupMessage *msg, gpointer loop) +{ + debug_printf (2, " Message 1 completed\n"); + soup_test_assert_message_status (msg, SOUP_STATUS_CANT_CONNECT); + g_object_unref (session); +} + +static gboolean +cu_idle_quit (gpointer loop) +{ + g_main_loop_quit (loop); + return FALSE; +} + +static void +cu_two_completed (SoupSession *session, SoupMessage *msg, gpointer loop) +{ + debug_printf (2, " Message 2 completed\n"); + soup_test_assert_message_status (msg, SOUP_STATUS_CANT_CONNECT); + g_idle_add (cu_idle_quit, loop); +} + +static void +do_callback_unref_test (void) +{ + SoupServer *bad_server; + SoupSession *session; + SoupMessage *one, *two; + GMainLoop *loop; + SoupURI *bad_uri; + + g_test_bug ("533473"); + + /* Get a guaranteed-bad URI */ + bad_server = soup_test_server_new (SOUP_TEST_SERVER_DEFAULT); + bad_uri = soup_test_server_get_uri (bad_server, "http", NULL); + soup_test_server_quit_unref (bad_server); + + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + g_object_add_weak_pointer (G_OBJECT (session), (gpointer *)&session); + + loop = g_main_loop_new (NULL, TRUE); + + one = soup_message_new_from_uri ("GET", bad_uri); + g_object_add_weak_pointer (G_OBJECT (one), (gpointer *)&one); + two = soup_message_new_from_uri ("GET", bad_uri); + g_object_add_weak_pointer (G_OBJECT (two), (gpointer *)&two); + soup_uri_free (bad_uri); + + soup_session_queue_message (session, one, cu_one_completed, loop); + soup_session_queue_message (session, two, cu_two_completed, loop); + + g_main_loop_run (loop); + g_main_loop_unref (loop); + + g_assert_null (session); + if (session) { + g_object_remove_weak_pointer (G_OBJECT (session), (gpointer *)&session); + g_object_unref (session); + } + g_assert_null (one); + if (one) { + g_object_remove_weak_pointer (G_OBJECT (one), (gpointer *)&one); + g_object_unref (one); + } + g_assert_null (two); + if (two) { + g_object_remove_weak_pointer (G_OBJECT (two), (gpointer *)&two); + g_object_unref (two); + } + + /* Otherwise, if we haven't crashed, we're ok. */ +} + +static void +cur_one_completed (GObject *source, GAsyncResult *result, gpointer session) +{ + SoupRequest *one = SOUP_REQUEST (source); + GError *error = NULL; + + debug_printf (2, " Request 1 completed\n"); + soup_request_send_finish (one, result, &error); + g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CONNECTION_REFUSED); + g_clear_error (&error); + + g_object_unref (session); +} + +static gboolean +cur_idle_quit (gpointer loop) +{ + g_main_loop_quit (loop); + return FALSE; +} + +static void +cur_two_completed (GObject *source, GAsyncResult *result, gpointer loop) +{ + SoupRequest *two = SOUP_REQUEST (source); + GError *error = NULL; + + debug_printf (2, " Request 2 completed\n"); + soup_request_send_finish (two, result, &error); + g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CONNECTION_REFUSED); + g_clear_error (&error); + + g_idle_add (cur_idle_quit, loop); +} + +static void +do_callback_unref_req_test (void) +{ + SoupServer *bad_server; + SoupSession *session; + SoupRequest *one, *two; + GMainLoop *loop; + SoupURI *bad_uri; + + /* Get a guaranteed-bad URI */ + bad_server = soup_test_server_new (SOUP_TEST_SERVER_DEFAULT); + bad_uri = soup_test_server_get_uri (bad_server, "http", NULL); + soup_test_server_quit_unref (bad_server); + + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, + SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, + NULL); + g_object_add_weak_pointer (G_OBJECT (session), (gpointer *)&session); + + loop = g_main_loop_new (NULL, TRUE); + + one = soup_session_request_uri (session, bad_uri, NULL); + g_object_add_weak_pointer (G_OBJECT (one), (gpointer *)&one); + two = soup_session_request_uri (session, bad_uri, NULL); + g_object_add_weak_pointer (G_OBJECT (two), (gpointer *)&two); + soup_uri_free (bad_uri); + + soup_request_send_async (one, NULL, cur_one_completed, session); + g_object_unref (one); + soup_request_send_async (two, NULL, cur_two_completed, loop); + g_object_unref (two); + + g_main_loop_run (loop); + g_main_loop_unref (loop); + + g_assert_null (session); + if (session) { + g_object_remove_weak_pointer (G_OBJECT (session), (gpointer *)&session); + g_object_unref (session); + } + g_assert_null (one); + if (one) { + g_object_remove_weak_pointer (G_OBJECT (one), (gpointer *)&one); + g_object_unref (one); + } + g_assert_null (two); + if (two) { + g_object_remove_weak_pointer (G_OBJECT (two), (gpointer *)&two); + g_object_unref (two); + } + + /* Otherwise, if we haven't crashed, we're ok. */ +} + +/* SoupSession should clean up all signal handlers on a message after + * it is finished, allowing the message to be reused if desired. + */ +static void +ensure_no_signal_handlers (SoupMessage *msg, guint *signal_ids, guint n_signal_ids) +{ + int i; + guint id; + + for (i = 0; i < n_signal_ids; i++) { + id = g_signal_handler_find (msg, G_SIGNAL_MATCH_ID, signal_ids[i], + 0, NULL, NULL, NULL); + soup_test_assert (id == 0, + "message has handler for '%s'", + g_signal_name (signal_ids[i])); + } +} + +static void +reuse_test_authenticate (SoupSession *session, SoupMessage *msg, + SoupAuth *auth, gboolean retrying) +{ + /* Get it wrong the first time, then succeed */ + if (!retrying) + soup_auth_authenticate (auth, "user", "wrong password"); + else + soup_auth_authenticate (auth, "user", "password"); +} + +static void +do_msg_reuse_test (void) +{ + SoupSession *session; + SoupMessage *msg; + SoupURI *uri; + guint *signal_ids, n_signal_ids; + + g_test_bug ("559054"); + + signal_ids = g_signal_list_ids (SOUP_TYPE_MESSAGE, &n_signal_ids); + + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + g_signal_connect (session, "authenticate", + G_CALLBACK (reuse_test_authenticate), NULL); + + debug_printf (1, " First message\n"); + msg = soup_message_new_from_uri ("GET", base_uri); + soup_session_send_message (session, msg); + ensure_no_signal_handlers (msg, signal_ids, n_signal_ids); + + debug_printf (1, " Redirect message\n"); + uri = soup_uri_new_with_base (base_uri, "/redirect"); + soup_message_set_uri (msg, uri); + soup_uri_free (uri); + soup_session_send_message (session, msg); + g_assert_true (soup_uri_equal (soup_message_get_uri (msg), base_uri)); + ensure_no_signal_handlers (msg, signal_ids, n_signal_ids); + + debug_printf (1, " Auth message\n"); + uri = soup_uri_new_with_base (base_uri, "/auth"); + soup_message_set_uri (msg, uri); + soup_uri_free (uri); + soup_session_send_message (session, msg); + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + ensure_no_signal_handlers (msg, signal_ids, n_signal_ids); + + /* One last try to make sure the auth stuff got cleaned up */ + debug_printf (1, " Last message\n"); + soup_message_set_uri (msg, base_uri); + soup_session_send_message (session, msg); + ensure_no_signal_handlers (msg, signal_ids, n_signal_ids); + + soup_test_session_abort_unref (session); + g_object_unref (msg); + g_free (signal_ids); +} + +/* Handle unexpectedly-early aborts. */ +static void +ea_msg_completed_one (SoupSession *session, SoupMessage *msg, gpointer loop) +{ + debug_printf (2, " Message 1 completed\n"); + soup_test_assert_message_status (msg, SOUP_STATUS_CANCELLED); + g_main_loop_quit (loop); +} + +static gboolean +ea_abort_session (gpointer session) +{ + soup_session_abort (session); + return FALSE; +} + +static void +ea_connection_state_changed (GObject *conn, GParamSpec *pspec, gpointer session) +{ + SoupConnectionState state; + + g_object_get (conn, "state", &state, NULL); + if (state == SOUP_CONNECTION_CONNECTING) { + g_idle_add_full (G_PRIORITY_HIGH, + ea_abort_session, + session, NULL); + g_signal_handlers_disconnect_by_func (conn, ea_connection_state_changed, session); + } +} + +static void +ea_connection_created (SoupSession *session, GObject *conn, gpointer user_data) +{ + g_signal_connect (conn, "notify::state", + G_CALLBACK (ea_connection_state_changed), session); + g_signal_handlers_disconnect_by_func (session, ea_connection_created, user_data); +} + +static void +ea_message_starting (SoupMessage *msg, SoupSession *session) +{ + soup_session_cancel_message (session, msg, SOUP_STATUS_CANCELLED); +} + +static void +do_early_abort_test (void) +{ + SoupSession *session; + SoupMessage *msg; + GMainContext *context; + GMainLoop *loop; + + g_test_bug ("596074"); + g_test_bug ("618641"); + + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + msg = soup_message_new_from_uri ("GET", base_uri); + + context = g_main_context_default (); + loop = g_main_loop_new (context, TRUE); + soup_session_queue_message (session, msg, ea_msg_completed_one, loop); + g_main_context_iteration (context, FALSE); + + soup_session_abort (session); + while (g_main_context_pending (context)) + g_main_context_iteration (context, FALSE); + g_main_loop_unref (loop); + soup_test_session_abort_unref (session); + + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + msg = soup_message_new_from_uri ("GET", base_uri); + + g_signal_connect (session, "connection-created", + G_CALLBACK (ea_connection_created), NULL); + soup_session_send_message (session, msg); + debug_printf (2, " Message 2 completed\n"); + + soup_test_assert_message_status (msg, SOUP_STATUS_CANCELLED); + g_object_unref (msg); + + while (g_main_context_pending (context)) + g_main_context_iteration (context, FALSE); + + soup_test_session_abort_unref (session); + + g_test_bug ("668098"); + + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + msg = soup_message_new_from_uri ("GET", base_uri); + + g_signal_connect (msg, "starting", + G_CALLBACK (ea_message_starting), session); + soup_session_send_message (session, msg); + debug_printf (2, " Message 3 completed\n"); + + soup_test_assert_message_status (msg, SOUP_STATUS_CANCELLED); + g_object_unref (msg); + + while (g_main_context_pending (context)) + g_main_context_iteration (context, FALSE); + + soup_test_session_abort_unref (session); +} + +static void +ear_one_completed (GObject *source, GAsyncResult *result, gpointer user_data) +{ + GError *error = NULL; + + debug_printf (2, " Request 1 completed\n"); + soup_request_send_finish (SOUP_REQUEST (source), result, &error); + g_assert_error (error, SOUP_HTTP_ERROR, SOUP_STATUS_CANCELLED); + g_clear_error (&error); +} + +static void +ear_two_completed (GObject *source, GAsyncResult *result, gpointer loop) +{ + GError *error = NULL; + + debug_printf (2, " Request 2 completed\n"); + soup_request_send_finish (SOUP_REQUEST (source), result, &error); + g_assert_error (error, SOUP_HTTP_ERROR, SOUP_STATUS_CANCELLED); + g_clear_error (&error); + + g_main_loop_quit (loop); +} + +static void +ear_three_completed (GObject *source, GAsyncResult *result, gpointer loop) +{ + GError *error = NULL; + + debug_printf (2, " Request 3 completed\n"); + soup_request_send_finish (SOUP_REQUEST (source), result, &error); + g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED); + g_clear_error (&error); + + g_main_loop_quit (loop); +} + +static void +ear_message_starting (SoupMessage *msg, gpointer cancellable) +{ + g_cancellable_cancel (cancellable); +} + +static void +ear_request_queued (SoupSession *session, SoupMessage *msg, + gpointer cancellable) +{ + g_signal_connect (msg, "starting", + G_CALLBACK (ear_message_starting), + cancellable); +} + +static void +do_early_abort_req_test (void) +{ + SoupSession *session; + SoupRequest *req; + GMainContext *context; + GMainLoop *loop; + GCancellable *cancellable; + + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, + SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, + NULL); + req = soup_session_request_uri (session, base_uri, NULL); + + context = g_main_context_default (); + loop = g_main_loop_new (context, TRUE); + soup_request_send_async (req, NULL, ear_one_completed, NULL); + g_object_unref (req); + g_main_context_iteration (context, FALSE); + + soup_session_abort (session); + while (g_main_context_pending (context)) + g_main_context_iteration (context, FALSE); + soup_test_session_abort_unref (session); + + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, + SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, + NULL); + req = soup_session_request_uri (session, base_uri, NULL); + + g_signal_connect (session, "connection-created", + G_CALLBACK (ea_connection_created), NULL); + soup_request_send_async (req, NULL, ear_two_completed, loop); + g_main_loop_run (loop); + g_object_unref (req); + + while (g_main_context_pending (context)) + g_main_context_iteration (context, FALSE); + + soup_test_session_abort_unref (session); + + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, + SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, + NULL); + req = soup_session_request_uri (session, base_uri, NULL); + + cancellable = g_cancellable_new (); + g_signal_connect (session, "request-queued", + G_CALLBACK (ear_request_queued), cancellable); + soup_request_send_async (req, cancellable, ear_three_completed, loop); + g_main_loop_run (loop); + g_object_unref (req); + g_object_unref (cancellable); + + while (g_main_context_pending (context)) + g_main_context_iteration (context, FALSE); + + soup_test_session_abort_unref (session); + g_main_loop_unref (loop); +} + +static void +do_one_accept_language_test (const char *language, const char *expected_header) +{ + SoupSession *session; + SoupMessage *msg; + const char *val; + + debug_printf (1, " LANGUAGE=%s\n", language); + g_setenv ("LANGUAGE", language, TRUE); + session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, + SOUP_SESSION_ACCEPT_LANGUAGE_AUTO, TRUE, + NULL); + msg = soup_message_new_from_uri ("GET", base_uri); + soup_session_send_message (session, msg); + soup_test_session_abort_unref (session); + + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + val = soup_message_headers_get_list (msg->request_headers, + "Accept-Language"); + g_assert_cmpstr (val, ==, expected_header); + + g_object_unref (msg); +} + +static void +do_accept_language_test (void) +{ + const char *orig_language; + + g_test_bug ("602547"); + + orig_language = g_getenv ("LANGUAGE"); + do_one_accept_language_test ("C", "en"); + do_one_accept_language_test ("fr_FR", "fr-fr, fr;q=0.9"); + do_one_accept_language_test ("fr_FR:de:en_US", "fr-fr, fr;q=0.9, de;q=0.8, en-us;q=0.7, en;q=0.6"); + + if (orig_language) + g_setenv ("LANGUAGE", orig_language, TRUE); + else + g_unsetenv ("LANGUAGE"); +} + +static gboolean +cancel_message_timeout (gpointer msg) +{ + SoupSession *session = g_object_get_data (G_OBJECT (msg), "session"); + + soup_session_cancel_message (session, msg, SOUP_STATUS_CANCELLED); + g_object_unref (msg); + g_object_unref (session); + return FALSE; +} + +static gpointer +cancel_message_thread (gpointer msg) +{ + SoupSession *session = g_object_get_data (G_OBJECT (msg), "session"); + + g_usleep (100000); /* .1s */ + soup_session_cancel_message (session, msg, SOUP_STATUS_CANCELLED); + g_object_unref (msg); + g_object_unref (session); + return NULL; +} + +static void +set_done (SoupSession *session, SoupMessage *msg, gpointer user_data) +{ + gboolean *done = user_data; + + *done = TRUE; +} + +static void +do_cancel_while_reading_test_for_session (SoupSession *session) +{ + SoupMessage *msg; + GThread *thread = NULL; + SoupURI *uri; + gboolean done = FALSE; + + uri = soup_uri_new_with_base (base_uri, "/slow"); + msg = soup_message_new_from_uri ("GET", uri); + soup_uri_free (uri); + + g_object_set_data (G_OBJECT (msg), "session", session); + g_object_ref (msg); + g_object_ref (session); + if (SOUP_IS_SESSION_ASYNC (session)) + g_timeout_add (100, cancel_message_timeout, msg); + else + thread = g_thread_new ("cancel_message_thread", cancel_message_thread, msg); + + /* We intentionally don't use soup_session_send_message() here, + * because it holds an extra ref on the SoupMessageQueueItem + * relative to soup_session_queue_message(). + */ + g_object_ref (msg); + soup_session_queue_message (session, msg, set_done, &done); + while (!done) + g_main_context_iteration (NULL, TRUE); + + soup_test_assert_message_status (msg, SOUP_STATUS_CANCELLED); + g_object_unref (msg); + + if (thread) + g_thread_join (thread); +} + +static void +do_cancel_while_reading_test (void) +{ + SoupSession *session; + + g_test_bug ("637741"); + g_test_bug ("676038"); + + debug_printf (1, " Async session\n"); + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + do_cancel_while_reading_test_for_session (session); + soup_test_session_abort_unref (session); + + debug_printf (1, " Sync session\n"); + session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL); + do_cancel_while_reading_test_for_session (session); + soup_test_session_abort_unref (session); +} + +static void +do_cancel_while_reading_req_test_for_session (SoupSession *session, + guint flags) +{ + SoupRequest *req; + SoupURI *uri; + GCancellable *cancellable; + GError *error = NULL; + + uri = soup_uri_new_with_base (base_uri, "/slow"); + req = soup_session_request_uri (session, uri, NULL); + soup_uri_free (uri); + + cancellable = g_cancellable_new (); + soup_test_request_send (req, cancellable, flags, &error); + g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED); + g_clear_error (&error); + + g_object_unref (req); + g_object_unref (cancellable); +} + +static void +do_cancel_while_reading_immediate_req_test (void) +{ + SoupSession *session; + guint flags; + + g_test_bug ("692310"); + + flags = SOUP_TEST_REQUEST_CANCEL_CANCELLABLE | SOUP_TEST_REQUEST_CANCEL_IMMEDIATE; + + debug_printf (1, " Async session\n"); + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, + SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, + NULL); + do_cancel_while_reading_req_test_for_session (session, flags); + soup_test_session_abort_unref (session); + + debug_printf (1, " Sync session\n"); + session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, + NULL); + do_cancel_while_reading_req_test_for_session (session, flags); + soup_test_session_abort_unref (session); +} + +static void +do_cancel_while_reading_delayed_req_test (void) +{ + SoupSession *session; + guint flags; + + flags = SOUP_TEST_REQUEST_CANCEL_CANCELLABLE | SOUP_TEST_REQUEST_CANCEL_SOON; + + debug_printf (1, " Async session\n"); + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, + SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, + NULL); + do_cancel_while_reading_req_test_for_session (session, flags); + soup_test_session_abort_unref (session); + + debug_printf (1, " Sync session\n"); + session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, + NULL); + do_cancel_while_reading_req_test_for_session (session, flags); + soup_test_session_abort_unref (session); +} + +static void +do_cancel_while_reading_preemptive_req_test (void) +{ + SoupSession *session; + guint flags; + + g_test_bug ("637039"); + + flags = SOUP_TEST_REQUEST_CANCEL_CANCELLABLE | SOUP_TEST_REQUEST_CANCEL_PREEMPTIVE; + + debug_printf (1, " Async session\n"); + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, + SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, + NULL); + do_cancel_while_reading_req_test_for_session (session, flags); + soup_test_session_abort_unref (session); + + debug_printf (1, " Sync session\n"); + session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, + NULL); + do_cancel_while_reading_req_test_for_session (session, flags); + soup_test_session_abort_unref (session); +} + +static void +do_aliases_test_for_session (SoupSession *session, + const char *redirect_protocol) +{ + SoupMessage *msg; + SoupURI *uri; + const char *redirected_protocol; + + uri = soup_uri_new_with_base (base_uri, "/alias-redirect"); + msg = soup_message_new_from_uri ("GET", uri); + if (redirect_protocol) + soup_message_headers_append (msg->request_headers, "X-Redirect-Protocol", redirect_protocol); + soup_uri_free (uri); + soup_session_send_message (session, msg); + + redirected_protocol = soup_message_headers_get_one (msg->response_headers, "X-Redirected-Protocol"); + + g_assert_cmpstr (redirect_protocol, ==, redirected_protocol); + if (redirect_protocol) + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + else + soup_test_assert_message_status (msg, SOUP_STATUS_FOUND); + + g_object_unref (msg); +} + +static void +do_aliases_test (void) +{ + SoupSession *session; + char *aliases[] = { "foo", NULL }; + + debug_printf (1, " Default behavior\n"); + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + do_aliases_test_for_session (session, "http"); + soup_test_session_abort_unref (session); + + if (tls_available) { + debug_printf (1, " foo-means-https\n"); + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, + SOUP_SESSION_HTTPS_ALIASES, aliases, + NULL); + do_aliases_test_for_session (session, "https"); + soup_test_session_abort_unref (session); + } else + debug_printf (1, " foo-means-https -- SKIPPING\n"); + + debug_printf (1, " foo-means-nothing\n"); + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, + SOUP_SESSION_HTTP_ALIASES, NULL, + NULL); + do_aliases_test_for_session (session, NULL); + soup_test_session_abort_unref (session); +} + +static void +do_idle_on_dispose_test (void) +{ + SoupSession *session; + SoupMessage *msg; + GMainContext *async_context; + + g_test_bug ("667364"); + + async_context = g_main_context_new (); + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, + SOUP_SESSION_ASYNC_CONTEXT, async_context, + NULL); + + msg = soup_message_new_from_uri ("GET", base_uri); + soup_session_send_message (session, msg); + g_object_unref (msg); + + while (g_main_context_iteration (async_context, FALSE)) + ; + + g_object_run_dispose (G_OBJECT (session)); + + if (g_main_context_iteration (async_context, FALSE)) + soup_test_assert (FALSE, "idle was queued"); + + g_object_unref (session); + g_main_context_unref (async_context); +} + +static void +do_pause_abort_test (void) +{ + SoupSession *session; + SoupMessage *msg; + gpointer ptr; + + g_test_bug ("673905"); + + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + + msg = soup_message_new_from_uri ("GET", base_uri); + soup_session_queue_message (session, msg, NULL, NULL); + soup_session_pause_message (session, msg); + + g_object_add_weak_pointer (G_OBJECT (msg), &ptr); + soup_test_session_abort_unref (session); + + g_assert_null (ptr); +} + +static GMainLoop *pause_cancel_loop; + +static void +pause_cancel_got_headers (SoupMessage *msg, gpointer user_data) +{ + SoupSession *session = user_data; + + soup_session_pause_message (session, msg); + g_main_loop_quit (pause_cancel_loop); +} + +static void +pause_cancel_finished (SoupSession *session, SoupMessage *msg, gpointer user_data) +{ + gboolean *finished = user_data; + + *finished = TRUE; + g_main_loop_quit (pause_cancel_loop); +} + +static gboolean +pause_cancel_timeout (gpointer user_data) +{ + gboolean *timed_out = user_data; + + *timed_out = TRUE; + g_main_loop_quit (pause_cancel_loop); + return FALSE; +} + +static void +do_pause_cancel_test (void) +{ + SoupSession *session; + SoupMessage *msg; + gboolean finished = FALSE, timed_out = FALSE; + guint timeout_id; + + g_test_bug ("745094"); + + session = soup_test_session_new (SOUP_TYPE_SESSION, NULL); + pause_cancel_loop = g_main_loop_new (NULL, FALSE); + + timeout_id = g_timeout_add_seconds (5, pause_cancel_timeout, &timed_out); + + msg = soup_message_new_from_uri ("GET", base_uri); + g_object_ref (msg); + g_signal_connect (msg, "got-headers", + G_CALLBACK (pause_cancel_got_headers), session); + + soup_session_queue_message (session, msg, pause_cancel_finished, &finished); + g_main_loop_run (pause_cancel_loop); + g_assert_false (finished); + + soup_session_cancel_message (session, msg, SOUP_STATUS_CANCELLED); + g_main_loop_run (pause_cancel_loop); + g_assert_true (finished); + g_assert_false (timed_out); + + soup_test_assert_message_status (msg, SOUP_STATUS_CANCELLED); + g_object_unref (msg); + + soup_test_session_abort_unref (session); + g_main_loop_unref (pause_cancel_loop); + if (!timed_out) + g_source_remove (timeout_id); +} + +static gboolean +run_echo_server (gpointer user_data) +{ + GIOStream *stream = user_data; + GInputStream *istream; + GDataInputStream *distream; + GOutputStream *ostream; + char *str, *caps; + gssize n; + GError *error = NULL; + + istream = g_io_stream_get_input_stream (stream); + distream = G_DATA_INPUT_STREAM (g_data_input_stream_new (istream)); + ostream = g_io_stream_get_output_stream (stream); + + /* Echo until the client disconnects */ + while (TRUE) { + str = g_data_input_stream_read_line (distream, NULL, NULL, &error); + g_assert_no_error (error); + if (!str) + break; + + caps = g_ascii_strup (str, -1); + n = g_output_stream_write (ostream, caps, strlen (caps), NULL, &error); + g_assert_no_error (error); + g_assert_cmpint (n, ==, strlen (caps)); + n = g_output_stream_write (ostream, "\n", 1, NULL, &error); + g_assert_no_error (error); + g_assert_cmpint (n, ==, 1); + g_free (caps); + g_free (str); + } + + g_object_unref (distream); + + g_io_stream_close (stream, NULL, &error); + g_assert_no_error (error); + g_object_unref (stream); + + return FALSE; +} + +static void +steal_after_upgrade (SoupMessage *msg, gpointer user_data) +{ + SoupClientContext *context = user_data; + GIOStream *stream; + GSource *source; + + /* This should not ever be seen. */ + soup_message_set_status (msg, SOUP_STATUS_INTERNAL_SERVER_ERROR); + + stream = soup_client_context_steal_connection (context); + + source = g_idle_source_new (); + g_source_set_callback (source, run_echo_server, stream, NULL); + g_source_attach (source, g_main_context_get_thread_default ()); + g_source_unref (source); +} + +static void +upgrade_server_callback (SoupServer *server, SoupMessage *msg, + const char *path, GHashTable *query, + SoupClientContext *context, gpointer data) +{ + if (msg->method != SOUP_METHOD_GET) { + soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED); + return; + } + + soup_message_set_status (msg, SOUP_STATUS_SWITCHING_PROTOCOLS); + soup_message_headers_append (msg->request_headers, "Upgrade", "ECHO"); + soup_message_headers_append (msg->request_headers, "Connection", "upgrade"); + + g_signal_connect (msg, "wrote-informational", + G_CALLBACK (steal_after_upgrade), context); +} + +static void +callback_not_reached (SoupSession *session, SoupMessage *msg, gpointer user_data) +{ + g_assert_not_reached (); +} + +static void +switching_protocols (SoupMessage *msg, gpointer user_data) +{ + GIOStream **out_iostream = user_data; + SoupSession *session = g_object_get_data (G_OBJECT (msg), "SoupSession"); + + *out_iostream = soup_session_steal_connection (session, msg); +} + +static void +do_stealing_test (gconstpointer data) +{ + gboolean sync = GPOINTER_TO_INT (data); + SoupServer *server; + SoupURI *uri; + SoupSession *session; + SoupMessage *msg; + GIOStream *iostream; + GInputStream *istream; + GDataInputStream *distream; + GOutputStream *ostream; + int i; + gssize n; + char *str, *caps; + GError *error = NULL; + static const char *strings[] = { "one", "two", "three", "four", "five" }; + + server = soup_test_server_new (SOUP_TEST_SERVER_IN_THREAD); + uri = soup_test_server_get_uri (server, SOUP_URI_SCHEME_HTTP, "127.0.0.1"); + soup_server_add_handler (server, NULL, upgrade_server_callback, NULL, NULL); + + session = soup_test_session_new (SOUP_TYPE_SESSION, NULL); + msg = soup_message_new_from_uri ("GET", uri); + soup_message_headers_append (msg->request_headers, "Upgrade", "echo"); + soup_message_headers_append (msg->request_headers, "Connection", "upgrade"); + g_object_set_data (G_OBJECT (msg), "SoupSession", session); + + soup_message_add_status_code_handler (msg, "got-informational", + SOUP_STATUS_SWITCHING_PROTOCOLS, + G_CALLBACK (switching_protocols), &iostream); + + iostream = NULL; + + if (sync) { + soup_session_send_message (session, msg); + soup_test_assert_message_status (msg, SOUP_STATUS_SWITCHING_PROTOCOLS); + } else { + g_object_ref (msg); + soup_session_queue_message (session, msg, callback_not_reached, NULL); + while (iostream == NULL) + g_main_context_iteration (NULL, TRUE); + } + + g_assert (iostream != NULL); + + g_object_unref (msg); + soup_test_session_abort_unref (session); + soup_uri_free (uri); + + /* Now iostream connects to a (capitalizing) echo server */ + + istream = g_io_stream_get_input_stream (iostream); + distream = G_DATA_INPUT_STREAM (g_data_input_stream_new (istream)); + ostream = g_io_stream_get_output_stream (iostream); + + for (i = 0; i < G_N_ELEMENTS (strings); i++) { + n = g_output_stream_write (ostream, strings[i], strlen (strings[i]), + NULL, &error); + g_assert_no_error (error); + g_assert_cmpint (n, ==, strlen (strings[i])); + n = g_output_stream_write (ostream, "\n", 1, NULL, &error); + g_assert_no_error (error); + g_assert_cmpint (n, ==, 1); + } + + for (i = 0; i < G_N_ELEMENTS (strings); i++) { + str = g_data_input_stream_read_line (distream, NULL, NULL, &error); + g_assert_no_error (error); + caps = g_ascii_strup (strings[i], -1); + g_assert_cmpstr (caps, ==, str); + g_free (caps); + g_free (str); + } + + g_object_unref (distream); + + g_io_stream_close (iostream, NULL, &error); + g_assert_no_error (error); + g_object_unref (iostream); + + /* We can't do this until the end because it's in another thread, and + * soup_test_server_quit_unref() will wait for that thread to exit. + */ + soup_test_server_quit_unref (server); +} + +int +main (int argc, char **argv) +{ + SoupAuthDomain *auth_domain; + int ret; + + test_init (argc, argv, NULL); + + server = soup_test_server_new (SOUP_TEST_SERVER_IN_THREAD); + soup_server_add_handler (server, NULL, server_callback, "http", NULL); + base_uri = soup_test_server_get_uri (server, "http", NULL); + + auth_domain = soup_auth_domain_basic_new ( + SOUP_AUTH_DOMAIN_REALM, "misc-test", + SOUP_AUTH_DOMAIN_ADD_PATH, "/auth", + SOUP_AUTH_DOMAIN_BASIC_AUTH_CALLBACK, auth_callback, + NULL); + soup_server_add_auth_domain (server, auth_domain); + g_object_unref (auth_domain); + + if (tls_available) { + ssl_server = soup_test_server_new (SOUP_TEST_SERVER_IN_THREAD); + soup_server_add_handler (ssl_server, NULL, server_callback, "https", NULL); + ssl_base_uri = soup_test_server_get_uri (ssl_server, "https", "127.0.0.1"); + } + + g_test_add_func ("/misc/bigheader", do_host_big_header); + g_test_add_func ("/misc/host", do_host_test); + g_test_add_func ("/misc/callback-unref/msg", do_callback_unref_test); + g_test_add_func ("/misc/callback-unref/req", do_callback_unref_req_test); + g_test_add_func ("/misc/msg-reuse", do_msg_reuse_test); + g_test_add_func ("/misc/early-abort/msg", do_early_abort_test); + g_test_add_func ("/misc/early-abort/req", do_early_abort_req_test); + g_test_add_func ("/misc/accept-language", do_accept_language_test); + g_test_add_func ("/misc/cancel-while-reading/msg", do_cancel_while_reading_test); + g_test_add_func ("/misc/cancel-while-reading/req/immediate", do_cancel_while_reading_immediate_req_test); + g_test_add_func ("/misc/cancel-while-reading/req/delayed", do_cancel_while_reading_delayed_req_test); + g_test_add_func ("/misc/cancel-while-reading/req/preemptive", do_cancel_while_reading_preemptive_req_test); + g_test_add_func ("/misc/aliases", do_aliases_test); + g_test_add_func ("/misc/idle-on-dispose", do_idle_on_dispose_test); + g_test_add_func ("/misc/pause-abort", do_pause_abort_test); + g_test_add_func ("/misc/pause-cancel", do_pause_cancel_test); + g_test_add_data_func ("/misc/stealing/async", GINT_TO_POINTER (FALSE), do_stealing_test); + g_test_add_data_func ("/misc/stealing/sync", GINT_TO_POINTER (TRUE), do_stealing_test); + + ret = g_test_run (); + + soup_uri_free (base_uri); + soup_test_server_quit_unref (server); + + if (tls_available) { + soup_uri_free (ssl_base_uri); + soup_test_server_quit_unref (ssl_server); + } + + test_cleanup (); + return ret; +} diff --git a/tests/multipart-test.c b/tests/multipart-test.c new file mode 100644 index 0000000..488865a --- /dev/null +++ b/tests/multipart-test.c @@ -0,0 +1,520 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2011 Collabora Ltd. + */ + +#include +#include +#include +#include + +#include "test-utils.h" + +#define READ_BUFFER_SIZE 8192 + +typedef enum { + NO_MULTIPART, + SYNC_MULTIPART, + ASYNC_MULTIPART, + ASYNC_MULTIPART_SMALL_READS +} MultipartMode; + +char *buffer; +SoupSession *session; +char *base_uri_string; +SoupURI *base_uri; +SoupMultipartInputStream *multipart; +unsigned passes; + + +/* This payload contains 4 different responses. + * + * First, a text/html response with a Content-Length (31); + * Second, a response lacking Content-Type with Content-Length (11); + * Third, a text/css response with no Content-Length; + * Fourth, same as the third, but with different content; + */ +const char *payload = \ + "--cut-here\r\n" \ + "Content-Type: text/html\n" + "Content-Length: 30\r\n" \ + "\r\n" \ + "Hey!" \ + "\r\n--cut-here\r\n" \ + "Content-Length: 10\r\n" \ + "\r\n" \ + "soup rocks" \ + "\r\n--cut-here\r\n" \ + "Content-Type: text/css\r\n" \ + "\r\n" \ + ".soup { before: rocks; }" \ + "\r\n--cut-here\n" /* Tests boundary ending in a single \n. */ \ + "Content-Type: text/css\r\n" \ + "\r\n" \ + "#soup { background-color: black; }" \ + "\r\n--cut-here--"; + +static void +server_callback (SoupServer *server, SoupMessage *msg, + const char *path, GHashTable *query, + SoupClientContext *context, gpointer data) +{ + if (msg->method != SOUP_METHOD_GET) { + soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED); + return; + } + + soup_message_set_status (msg, SOUP_STATUS_OK); + + soup_message_headers_append (msg->response_headers, + "Content-Type", "multipart/x-mixed-replace; boundary=cut-here"); + + soup_message_body_append (msg->response_body, + SOUP_MEMORY_STATIC, + payload, + strlen (payload)); + + soup_message_body_complete (msg->response_body); +} + +static void +content_sniffed (SoupMessage *msg, char *content_type, GHashTable *params, int *sniffed_count) +{ + *sniffed_count = *sniffed_count + 1; + debug_printf (2, " content-sniffed -> %s\n", content_type); +} + +static void +check_is_next (gboolean is_next) +{ + soup_test_assert (is_next, + "expected a header, but there are no more headers"); +} + +static void +got_headers (SoupMessage *msg, int *headers_count) +{ + SoupMessageHeadersIter iter; + gboolean is_next; + const char* name, *value; + + *headers_count = *headers_count + 1; + + soup_message_headers_iter_init (&iter, msg->response_headers); + + is_next = soup_message_headers_iter_next (&iter, &name, &value); + check_is_next (is_next); + + if (g_str_equal (name, "Date")) { + is_next = soup_message_headers_iter_next (&iter, &name, &value); + check_is_next (is_next); + } + + g_assert_cmpstr (name, ==, "Content-Type"); + g_assert_cmpstr (value, ==, "multipart/x-mixed-replace; boundary=cut-here"); +} + +static void +read_cb (GObject *source, GAsyncResult *asyncResult, gpointer data) +{ + GMainLoop *loop = (GMainLoop*)data; + GInputStream *stream = G_INPUT_STREAM (source); + GError *error = NULL; + gssize bytes_read; + + bytes_read = g_input_stream_read_finish (stream, asyncResult, &error); + g_assert_no_error (error); + if (error) { + g_object_unref (stream); + g_main_loop_quit (loop); + return; + } + + if (!bytes_read) { + g_input_stream_close (stream, NULL, &error); + g_assert_no_error (error); + g_object_unref (stream); + g_main_loop_quit (loop); + return; + } + + g_input_stream_read_async (stream, buffer, READ_BUFFER_SIZE, + G_PRIORITY_DEFAULT, NULL, + read_cb, data); +} + +static void +no_multipart_handling_cb (GObject *source, GAsyncResult *res, gpointer data) +{ + GMainLoop *loop = (GMainLoop*)data; + SoupRequest *request = SOUP_REQUEST (source); + GError *error = NULL; + GInputStream* in; + + in = soup_request_send_finish (request, res, &error); + g_assert_no_error (error); + if (error) { + g_main_loop_quit (loop); + return; + } + + g_input_stream_read_async (in, buffer, READ_BUFFER_SIZE, + G_PRIORITY_DEFAULT, NULL, + read_cb, data); +} + +static void +multipart_close_part_cb (GObject *source, GAsyncResult *res, gpointer data) +{ + GInputStream *in = G_INPUT_STREAM (source); + GError *error = NULL; + + g_input_stream_close_finish (in, res, &error); + g_assert_no_error (error); +} + +static void multipart_next_part_cb (GObject *source, + GAsyncResult *res, + gpointer data); + +static void +check_read (gsize nread, unsigned passes) +{ + switch (passes) { + case 0: + g_assert_cmpint (nread, ==, 30); + break; + case 1: + g_assert_cmpint (nread, ==, 10); + break; + case 2: + g_assert_cmpint (nread, ==, 24); + break; + case 3: + g_assert_cmpint (nread, ==, 34); + break; + default: + soup_test_assert (FALSE, "unexpected read of size: %d", (int)nread); + break; + } +} + +static void +multipart_read_cb (GObject *source, GAsyncResult *asyncResult, gpointer data) +{ + GMainLoop *loop = (GMainLoop*)data; + GInputStream *in = G_INPUT_STREAM (source); + GError *error = NULL; + static gssize bytes_read_for_part = 0; + gssize bytes_read; + + bytes_read = g_input_stream_read_finish (in, asyncResult, &error); + g_assert_no_error (error); + if (error) { + g_input_stream_close_async (in, G_PRIORITY_DEFAULT, NULL, + multipart_close_part_cb, NULL); + g_object_unref (in); + + g_main_loop_quit (loop); + return; + } + + /* Read 0 bytes - try to start reading another part. */ + if (!bytes_read) { + check_read (bytes_read_for_part, passes); + bytes_read_for_part = 0; + passes++; + + g_input_stream_close_async (in, G_PRIORITY_DEFAULT, NULL, + multipart_close_part_cb, NULL); + g_object_unref (in); + + soup_multipart_input_stream_next_part_async (multipart, G_PRIORITY_DEFAULT, NULL, + multipart_next_part_cb, data); + return; + } + + bytes_read_for_part += bytes_read; + g_input_stream_read_async (in, buffer, READ_BUFFER_SIZE, + G_PRIORITY_DEFAULT, NULL, + multipart_read_cb, data); +} + +static void +check_headers (SoupMultipartInputStream* multipart, unsigned passes) +{ + SoupMessageHeaders *headers; + SoupMessageHeadersIter iter; + gboolean is_next; + const char *name, *value; + + headers = soup_multipart_input_stream_get_headers (multipart); + soup_message_headers_iter_init (&iter, headers); + + switch (passes) { + case 0: + is_next = soup_message_headers_iter_next (&iter, &name, &value); + check_is_next (is_next); + + g_assert_cmpstr (name, ==, "Content-Type"); + g_assert_cmpstr (value, ==, "text/html"); + + is_next = soup_message_headers_iter_next (&iter, &name, &value); + check_is_next (is_next); + + g_assert_cmpstr (name, ==, "Content-Length"); + g_assert_cmpstr (value, ==, "30"); + + break; + case 1: + is_next = soup_message_headers_iter_next (&iter, &name, &value); + check_is_next (is_next); + + g_assert_cmpstr (name, ==, "Content-Length"); + g_assert_cmpstr (value, ==, "10"); + + break; + case 2: + case 3: + is_next = soup_message_headers_iter_next (&iter, &name, &value); + check_is_next (is_next); + + g_assert_cmpstr (name, ==, "Content-Type"); + g_assert_cmpstr (value, ==, "text/css"); + + break; + default: + soup_test_assert (FALSE, "unexpected part received"); + break; + } +} + +static void +multipart_next_part_cb (GObject *source, GAsyncResult *res, gpointer data) +{ + GMainLoop *loop = (GMainLoop*)data; + GError *error = NULL; + GInputStream *in; + gsize read_size = READ_BUFFER_SIZE; + + g_assert (SOUP_MULTIPART_INPUT_STREAM (source) == multipart); + + in = soup_multipart_input_stream_next_part_finish (multipart, res, &error); + g_assert_no_error (error); + if (error) { + g_clear_error (&error); + g_object_unref (multipart); + g_main_loop_quit (loop); + return; + } + + if (!in) { + g_assert_cmpint (passes, ==, 4); + g_object_unref (multipart); + g_main_loop_quit (loop); + return; + } + + check_headers (multipart, passes); + + if (g_object_get_data (G_OBJECT (multipart), "multipart-small-reads")) + read_size = 4; + + g_input_stream_read_async (in, buffer, read_size, + G_PRIORITY_DEFAULT, NULL, + multipart_read_cb, data); +} + +static void +multipart_handling_cb (GObject *source, GAsyncResult *res, gpointer data) +{ + GMainLoop *loop = (GMainLoop*)data; + SoupRequest *request = SOUP_REQUEST (source); + GError *error = NULL; + GInputStream *in; + SoupMessage *message; + + in = soup_request_send_finish (request, res, &error); + g_assert_no_error (error); + if (error) { + g_main_loop_quit (loop); + return; + } + + message = soup_request_http_get_message (SOUP_REQUEST_HTTP (request)); + multipart = soup_multipart_input_stream_new (message, in); + g_object_unref (message); + g_object_unref (in); + + if (g_object_get_data (source, "multipart-small-reads")) + g_object_set_data (G_OBJECT (multipart), "multipart-small-reads", GINT_TO_POINTER(1)); + + soup_multipart_input_stream_next_part_async (multipart, G_PRIORITY_DEFAULT, NULL, + multipart_next_part_cb, data); +} + +static void +sync_multipart_handling_cb (GObject *source, GAsyncResult *res, gpointer data) +{ + GMainLoop *loop = (GMainLoop*)data; + SoupRequest *request = SOUP_REQUEST (source); + GError *error = NULL; + GInputStream *in; + SoupMessage *message; + char buffer[READ_BUFFER_SIZE]; + gsize bytes_read; + + in = soup_request_send_finish (request, res, &error); + g_assert_no_error (error); + if (error) { + g_main_loop_quit (loop); + return; + } + + message = soup_request_http_get_message (SOUP_REQUEST_HTTP (request)); + multipart = soup_multipart_input_stream_new (message, in); + g_object_unref (message); + g_object_unref (in); + + while (TRUE) { + in = soup_multipart_input_stream_next_part (multipart, NULL, &error); + g_assert_no_error (error); + if (error) { + g_clear_error (&error); + break; + } + + if (!in) + break; + + check_headers (multipart, passes); + + g_input_stream_read_all (in, (void*)buffer, sizeof (buffer), &bytes_read, NULL, &error); + g_assert_no_error (error); + if (error) { + g_clear_error (&error); + g_object_unref (in); + break; + } + + check_read (bytes_read, passes); + + passes++; + g_object_unref (in); + } + + g_assert_cmpint (passes, ==, 4); + + g_main_loop_quit (loop); + g_object_unref (multipart); +} + +static void +test_multipart (gconstpointer data) +{ + int headers_expected = 1, sniffed_expected = 1; + MultipartMode multipart_mode = GPOINTER_TO_INT (data); + SoupRequest* request; + SoupMessage *msg; + GMainLoop *loop; + int headers_count = 0; + int sniffed_count = 0; + GHashTable *params; + const char *content_type; + gboolean message_is_multipart = FALSE; + GError* error = NULL; + + request = soup_session_request (session, base_uri_string, &error); + g_assert_no_error (error); + if (error) + return; + + msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (request)); + + /* This is used to track the number of parts. */ + passes = 0; + + /* Force the server to close the connection. */ + soup_message_headers_append (msg->request_headers, + "Connection", "close"); + + g_signal_connect (msg, "got_headers", + G_CALLBACK (got_headers), &headers_count); + + g_signal_connect (msg, "content-sniffed", + G_CALLBACK (content_sniffed), &sniffed_count); + + loop = g_main_loop_new (NULL, TRUE); + + if (multipart_mode == ASYNC_MULTIPART) + soup_request_send_async (request, NULL, multipart_handling_cb, loop); + else if (multipart_mode == ASYNC_MULTIPART_SMALL_READS) { + g_object_set_data (G_OBJECT (request), "multipart-small-reads", GINT_TO_POINTER(1)); + soup_request_send_async (request, NULL, multipart_handling_cb, loop); + } else if (multipart_mode == SYNC_MULTIPART) + soup_request_send_async (request, NULL, sync_multipart_handling_cb, loop); + else + soup_request_send_async (request, NULL, no_multipart_handling_cb, loop); + + g_main_loop_run (loop); + + content_type = soup_message_headers_get_content_type (msg->response_headers, ¶ms); + + if (content_type && + g_str_has_prefix (content_type, "multipart/") && + g_hash_table_lookup (params, "boundary")) { + message_is_multipart = TRUE; + } + g_clear_pointer (¶ms, g_hash_table_unref); + + g_assert_true (message_is_multipart); + g_assert_cmpint (headers_count, ==, headers_expected); + g_assert_cmpint (sniffed_count, ==, sniffed_expected); + + g_object_unref (msg); + g_object_unref (request); + g_main_loop_unref (loop); +} + +int +main (int argc, char **argv) +{ + SoupServer *server; + int ret; + + test_init (argc, argv, NULL); + + buffer = g_malloc (READ_BUFFER_SIZE); + + server = soup_test_server_new (SOUP_TEST_SERVER_DEFAULT); + soup_server_add_handler (server, NULL, server_callback, NULL, NULL); + base_uri = soup_test_server_get_uri (server, "http", NULL); + base_uri_string = soup_uri_to_string (base_uri, FALSE); + + /* FIXME: I had to raise the number of connections allowed here, otherwise I + * was hitting the limit, which indicates some connections are not dying. + */ + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, + "use-thread-context", TRUE, + "max-conns", 20, + "max-conns-per-host", 20, + NULL); + soup_session_add_feature_by_type (session, SOUP_TYPE_CONTENT_SNIFFER); + + g_test_add_data_func ("/multipart/no", GINT_TO_POINTER (NO_MULTIPART), test_multipart); + g_test_add_data_func ("/multipart/sync", GINT_TO_POINTER (SYNC_MULTIPART), test_multipart); + g_test_add_data_func ("/multipart/async", GINT_TO_POINTER (ASYNC_MULTIPART), test_multipart); + g_test_add_data_func ("/multipart/async-small-reads", GINT_TO_POINTER (ASYNC_MULTIPART_SMALL_READS), test_multipart); + + ret = g_test_run (); + + soup_uri_free (base_uri); + g_free (base_uri_string); + g_free (buffer); + + soup_test_session_abort_unref (session); + soup_test_server_quit_unref (server); + + test_cleanup (); + return ret; +} diff --git a/tests/no-ssl-test.c b/tests/no-ssl-test.c new file mode 100644 index 0000000..c9d9bca --- /dev/null +++ b/tests/no-ssl-test.c @@ -0,0 +1,166 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ + +#include "test-utils.h" + +static void +do_ssl_test_for_session (SoupSession *session, SoupURI *uri) +{ + SoupMessage *msg; + GTlsCertificate *cert = NULL; + GTlsCertificateFlags flags; + gboolean is_https; + + msg = soup_message_new_from_uri ("GET", uri); + soup_session_send_message (session, msg); + soup_test_assert_message_status (msg, SOUP_STATUS_SSL_FAILED); + + is_https = soup_message_get_https_status (msg, &cert, &flags); + soup_test_assert (!is_https, "get_http_status() returned TRUE? (flags %x)", flags); + + g_assert_null (cert); + g_assert_false (soup_message_get_flags (msg) & SOUP_MESSAGE_CERTIFICATE_TRUSTED); + + g_object_unref (msg); +} + +static void +do_ssl_tests (gconstpointer data) +{ + SoupURI *uri = (SoupURI *)data; + SoupSession *session; + + g_test_bug ("700518"); + + debug_printf (1, " plain\n"); + session = soup_test_session_new (SOUP_TYPE_SESSION, NULL); + do_ssl_test_for_session (session, uri); + soup_test_session_abort_unref (session); + + debug_printf (1, " async\n"); + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + do_ssl_test_for_session (session, uri); + soup_test_session_abort_unref (session); + + debug_printf (1, " sync\n"); + session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL); + do_ssl_test_for_session (session, uri); + soup_test_session_abort_unref (session); +} + +static void +do_session_property_tests (void) +{ + gboolean use_system; + GTlsDatabase *tlsdb; + char *ca_file; + SoupSession *session; + GParamSpec *pspec; + + g_test_bug ("700518"); + + G_GNUC_BEGIN_IGNORE_DEPRECATIONS; + session = soup_session_async_new (); + G_GNUC_END_IGNORE_DEPRECATIONS; + + /* Temporarily undeprecate SOUP_SESSION_SSL_CA_FILE to avoid warnings. */ + pspec = g_object_class_find_property (g_type_class_peek (SOUP_TYPE_SESSION), + SOUP_SESSION_SSL_CA_FILE); + pspec->flags &= ~G_PARAM_DEPRECATED; + + g_object_get (G_OBJECT (session), + "ssl-use-system-ca-file", &use_system, + "tls-database", &tlsdb, + "ssl-ca-file", &ca_file, + NULL); + soup_test_assert (!use_system, "ssl-use-system-ca-file defaults to TRUE"); + soup_test_assert (tlsdb == NULL, "tls-database set by default"); + soup_test_assert (ca_file == NULL, "ca-file set by default"); + + g_object_set (G_OBJECT (session), + "ssl-use-system-ca-file", TRUE, + NULL); + g_object_get (G_OBJECT (session), + "ssl-ca-file", &ca_file, + NULL); + soup_test_assert (ca_file == NULL, "setting ssl-use-system-ca-file set ssl-ca-file"); + + g_object_set (G_OBJECT (session), + "ssl-ca-file", + g_test_get_filename (G_TEST_DIST, "test-cert.pem", NULL), + NULL); + g_object_get (G_OBJECT (session), + "ssl-use-system-ca-file", &use_system, + "tls-database", &tlsdb, + "ssl-ca-file", &ca_file, + NULL); + soup_test_assert (ca_file == NULL, "setting ssl-ca-file did not fail"); + soup_test_assert (!use_system, "setting ssl-ca-file set ssl-use-system-ca-file"); + soup_test_assert (tlsdb == NULL, "setting ssl-ca-file set tls-database"); + + g_object_set (G_OBJECT (session), + "tls-database", NULL, + NULL); + g_object_get (G_OBJECT (session), + "ssl-use-system-ca-file", &use_system, + "tls-database", &tlsdb, + "ssl-ca-file", &ca_file, + NULL); + soup_test_assert (tlsdb == NULL, "setting tls-database NULL failed"); + soup_test_assert (!use_system, "setting tls-database NULL set ssl-use-system-ca-file"); + soup_test_assert (ca_file == NULL, "setting tls-database NULL set ssl-ca-file"); + + soup_test_session_abort_unref (session); + + /* Re-deprecate SOUP_SESSION_SSL_CA_FILE */ + pspec->flags |= G_PARAM_DEPRECATED; +} + +static void +server_handler (SoupServer *server, + SoupMessage *msg, + const char *path, + GHashTable *query, + SoupClientContext *client, + gpointer user_data) +{ + soup_message_set_status (msg, SOUP_STATUS_OK); + soup_message_set_response (msg, "text/plain", + SOUP_MEMORY_STATIC, + "ok\r\n", 4); +} + +int +main (int argc, char **argv) +{ + SoupServer *server; + SoupURI *uri; + guint port; + int ret; + + /* Force this test to use the dummy TLS backend */ + g_setenv ("GIO_USE_TLS", "dummy", TRUE); + + test_init (argc, argv, NULL); + + /* Make a non-SSL server and pretend that it's ssl, which is fine + * since we won't ever actually talk to it anyway. We don't + * currently test that failing to construct an SSL server works. + */ + server = soup_test_server_new (TRUE); + soup_server_add_handler (server, NULL, server_handler, NULL, NULL); + uri = soup_test_server_get_uri (server, "http", NULL); + port = uri->port; + soup_uri_set_scheme (uri, SOUP_URI_SCHEME_HTTPS); + soup_uri_set_port (uri, port); + + g_test_add_func ("/no-ssl/session-properties", do_session_property_tests); + g_test_add_data_func ("/no-ssl/request-error", uri, do_ssl_tests); + + ret = g_test_run (); + + soup_uri_free (uri); + soup_test_server_quit_unref (server); + + test_cleanup (); + return ret; +} diff --git a/tests/ntlm-test-helper.c b/tests/ntlm-test-helper.c new file mode 100644 index 0000000..f2450ca --- /dev/null +++ b/tests/ntlm-test-helper.c @@ -0,0 +1,103 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright 2012 Red Hat, Inc. + */ + +#include +#include +#include +#include + +#include +#include "libsoup/soup.h" + +const char *helper_protocol, *username, *domain; +gboolean use_cached_creds; + +static GOptionEntry entries[] = { + { "helper-protocol", 0, 0, + G_OPTION_ARG_STRING, &helper_protocol, + NULL, NULL }, + { "use-cached-creds", 0, 0, + G_OPTION_ARG_NONE, &use_cached_creds, + NULL, NULL }, + { "username", 0, 0, + G_OPTION_ARG_STRING, &username, + NULL, NULL }, + { "domain", 0, 0, + G_OPTION_ARG_STRING, &domain, + NULL, NULL }, + { NULL } +}; + +int +main (int argc, char **argv) +{ + GOptionContext *opts; + char buf[256], *header; + SoupMessage *msg; + SoupAuth *auth; + + /* Don't recurse */ + g_setenv ("SOUP_NTLM_AUTH_DEBUG", "", TRUE); + + setlocale (LC_ALL, ""); + + opts = g_option_context_new (NULL); + g_option_context_add_main_entries (opts, entries, NULL); + if (!g_option_context_parse (opts, &argc, &argv, NULL)) { + g_printerr ("Bad arguments\n"); + exit (1); + } + g_option_context_free (opts); + + if (!username || !use_cached_creds || !helper_protocol || + !g_str_equal (helper_protocol, "ntlmssp-client-1")) { + g_printerr ("Wrong arguments; this program is only intended for use by ntlm-test\n"); + exit (1); + } + + msg = soup_message_new ("GET", "http://localhost/"); + auth = NULL; + + while (fgets (buf, sizeof (buf), stdin)) { + if (strchr (buf, '\n')) + *strchr (buf, '\n') = '\0'; + if (!strcmp (buf, "YR")) { + if (g_getenv ("SOUP_NTLM_AUTH_DEBUG_NOCREDS")) { + g_print ("PW\n"); + continue; + } + + g_clear_object (&auth); + auth = g_object_new (SOUP_TYPE_AUTH_NTLM, NULL); + header = soup_auth_get_authorization (auth, msg); + g_print ("YR %s\n", header + 5); + g_free (header); + } else if (g_str_has_prefix (buf, "TT ")) { + header = g_strdup_printf ("NTLM %s\n", buf + 3); + if (!soup_auth_update (auth, msg, header)) { + g_printerr ("Bad challenge\n"); + exit (1); + } + g_free (header); + + soup_auth_authenticate (auth, username, "password"); + header = soup_auth_get_authorization (auth, msg); + if (!header) { + g_printerr ("Internal authentication failure\n"); + exit (1); + } + g_print ("KK %s\n", header + 5); + g_free (header); + } else { + g_printerr ("Unexpected command\n"); + exit (1); + } + } + + g_object_unref (msg); + g_clear_object (&auth); + + return 0; +} diff --git a/tests/ntlm-test.c b/tests/ntlm-test.c new file mode 100644 index 0000000..0cc41a7 --- /dev/null +++ b/tests/ntlm-test.c @@ -0,0 +1,660 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2007 Red Hat, Inc. + */ + +/* This doesn't implement full server-side NTLM, and it mostly doesn't + * even test that the client is doing the crypto/encoding/etc parts of + * NTLM correctly. It only tests that the right message headers get + * set in the right messages. + */ + +#include "test-utils.h" + +typedef enum { + NTLM_UNAUTHENTICATED, + NTLM_RECEIVED_REQUEST, + NTLM_SENT_CHALLENGE, + NTLM_AUTHENTICATED_ALICE, + NTLM_AUTHENTICATED_BOB +} NTLMServerState; + +static const char *state_name[] = { + "unauth", "recv", "sent", "alice", "bob" +}; + +#define NTLM_REQUEST_START "TlRMTVNTUAABAAAA" +#define NTLM_RESPONSE_START "TlRMTVNTUAADAAAA" + +#define NTLM_CHALLENGE "TlRMTVNTUAACAAAADAAMADAAAAABAoEAASNFZ4mrze8AAAAAAAAAAGIAYgA8AAAARABPAE0AQQBJAE4AAgAMAEQATwBNAEEASQBOAAEADABTAEUAUgBWAEUAUgAEABQAZABvAG0AYQBpAG4ALgBjAG8AbQADACIAcwBlAHIAdgBlAHIALgBkAG8AbQBhAGkAbgAuAGMAbwBtAAAAAAA=" +#define NTLMSSP_CHALLENGE "TlRMTVNTUAACAAAADAAMADAAAAABAokAASNFZ4mrze8AAAAAAAAAAGIAYgA8AAAARABPAE0AQQBJAE4AAgAMAEQATwBNAEEASQBOAAEADABTAEUAUgBWAEUAUgAEABQAZABvAG0AYQBpAG4ALgBjAG8AbQADACIAcwBlAHIAdgBlAHIALgBkAG8AbQBhAGkAbgAuAGMAbwBtAAAAAAA=" + +#define NTLM_RESPONSE_USER(response) ((response)[86] == 'E' ? NTLM_AUTHENTICATED_ALICE : ((response)[86] == 'I' ? NTLM_AUTHENTICATED_BOB : NTLM_UNAUTHENTICATED)) + +typedef struct { + SoupServer *server; + GHashTable *connections; + SoupURI *uri; + gboolean ntlmssp; +} TestServer; + +static void +clear_state (gpointer connections, GObject *ex_connection) +{ + g_hash_table_remove (connections, ex_connection); +} + +static void +server_callback (SoupServer *server, SoupMessage *msg, + const char *path, GHashTable *query, + SoupClientContext *client, gpointer data) +{ + TestServer *ts = data; + GSocket *socket; + const char *auth; + NTLMServerState state, required_user = 0; + gboolean auth_required, not_found = FALSE; + gboolean basic_allowed = TRUE, ntlm_allowed = TRUE; + + if (msg->method != SOUP_METHOD_GET) { + soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED); + return; + } + + if (!strncmp (path, "/alice", 6)) + required_user = NTLM_AUTHENTICATED_ALICE; + else if (!strncmp (path, "/bob", 4)) + required_user = NTLM_AUTHENTICATED_BOB; + else if (!strncmp (path, "/either", 7)) + ; + else if (!strncmp (path, "/basic", 6)) + ntlm_allowed = FALSE; + else if (!strncmp (path, "/noauth", 7)) + basic_allowed = ntlm_allowed = FALSE; + auth_required = ntlm_allowed || basic_allowed; + + if (strstr (path, "/404")) + not_found = TRUE; + + socket = soup_client_context_get_gsocket (client); + state = GPOINTER_TO_INT (g_hash_table_lookup (ts->connections, socket)); + auth = soup_message_headers_get_one (msg->request_headers, + "Authorization"); + + if (auth) { + if (!strncmp (auth, "NTLM ", 5)) { + if (!strncmp (auth + 5, NTLM_REQUEST_START, + strlen (NTLM_REQUEST_START))) { + state = NTLM_RECEIVED_REQUEST; + /* If they start, they must finish, even if + * it was unnecessary. + */ + auth_required = ntlm_allowed = TRUE; + basic_allowed = FALSE; + } else if (state == NTLM_SENT_CHALLENGE && + !strncmp (auth + 5, NTLM_RESPONSE_START, + strlen (NTLM_RESPONSE_START))) { + state = NTLM_RESPONSE_USER (auth + 5); + } else + state = NTLM_UNAUTHENTICATED; + } else if (basic_allowed && !strncmp (auth, "Basic ", 6)) { + gsize len; + char *decoded = (char *)g_base64_decode (auth + 6, &len); + + if (!strncmp (decoded, "alice:password", len) && + required_user != NTLM_AUTHENTICATED_BOB) + auth_required = FALSE; + else if (!strncmp (decoded, "bob:password", len) && + required_user != NTLM_AUTHENTICATED_ALICE) + auth_required = FALSE; + g_free (decoded); + } + } + + if (ntlm_allowed && state > NTLM_SENT_CHALLENGE && + (!required_user || required_user == state)) + auth_required = FALSE; + + if (auth_required) { + soup_message_set_status (msg, SOUP_STATUS_UNAUTHORIZED); + + if (basic_allowed && state != NTLM_RECEIVED_REQUEST) { + soup_message_headers_append (msg->response_headers, + "WWW-Authenticate", + "Basic realm=\"ntlm-test\""); + } + + if (ntlm_allowed && state == NTLM_RECEIVED_REQUEST) { + soup_message_headers_append (msg->response_headers, + "WWW-Authenticate", + ts->ntlmssp ? ("NTLM " NTLMSSP_CHALLENGE) : ("NTLM " NTLM_CHALLENGE)); + state = NTLM_SENT_CHALLENGE; + } else if (ntlm_allowed) { + soup_message_headers_append (msg->response_headers, + "WWW-Authenticate", "NTLM"); + soup_message_headers_append (msg->response_headers, + "Connection", "close"); + } + } else { + if (not_found) + soup_message_set_status (msg, SOUP_STATUS_NOT_FOUND); + else { + soup_message_set_response (msg, "text/plain", + SOUP_MEMORY_STATIC, + "OK\r\n", 4); + soup_message_set_status (msg, SOUP_STATUS_OK); + } + } + + debug_printf (2, " (S:%s)", state_name[state]); + g_hash_table_insert (ts->connections, socket, GINT_TO_POINTER (state)); + g_object_weak_ref (G_OBJECT (socket), clear_state, ts->connections); +} + +static void +setup_server (TestServer *ts, + gconstpointer test_data) +{ + ts->server = soup_test_server_new (SOUP_TEST_SERVER_IN_THREAD); + ts->connections = g_hash_table_new (NULL, NULL); + ts->ntlmssp = FALSE; + soup_server_add_handler (ts->server, NULL, server_callback, ts, NULL); + + ts->uri = soup_test_server_get_uri (ts->server, "http", NULL); +} + +static void +setup_ntlmssp_server (TestServer *ts, + gconstpointer test_data) +{ + setup_server (ts, test_data); + ts->ntlmssp = TRUE; +} + +static void +teardown_server (TestServer *ts, + gconstpointer test_data) +{ + soup_uri_free (ts->uri); + soup_test_server_quit_unref (ts->server); + g_hash_table_destroy (ts->connections); +} + +static gboolean authenticated_ntlm = FALSE; + +static void +authenticate (SoupSession *session, SoupMessage *msg, + SoupAuth *auth, gboolean retrying, gpointer user) +{ + if (!retrying) { + soup_auth_authenticate (auth, user, "password"); + if (g_str_equal (soup_auth_get_scheme_name (auth), "NTLM")) + authenticated_ntlm = TRUE; + } +} + +typedef struct { + gboolean got_ntlm_prompt; + gboolean got_basic_prompt; + gboolean sent_ntlm_request; + gboolean got_ntlm_challenge; + gboolean sent_ntlm_response; + gboolean sent_basic_response; +} NTLMState; + +static void +prompt_check (SoupMessage *msg, gpointer user_data) +{ + NTLMState *state = user_data; + const char *header; + + header = soup_message_headers_get_list (msg->response_headers, + "WWW-Authenticate"); + if (header && strstr (header, "Basic ")) + state->got_basic_prompt = TRUE; + if (header && strstr (header, "NTLM") && + (!strstr (header, NTLM_CHALLENGE) && + !strstr (header, NTLMSSP_CHALLENGE))) { + state->got_ntlm_prompt = TRUE; + } +} + +static void +challenge_check (SoupMessage *msg, gpointer user_data) +{ + NTLMState *state = user_data; + const char *header; + + header = soup_message_headers_get_list (msg->response_headers, + "WWW-Authenticate"); + if (header && !strncmp (header, "NTLM ", 5)) + state->got_ntlm_challenge = TRUE; +} + +static void +request_check (SoupMessage *msg, gpointer user_data) +{ + NTLMState *state = user_data; + const char *header; + + header = soup_message_headers_get_one (msg->request_headers, + "Authorization"); + if (header && !strncmp (header, "NTLM " NTLM_REQUEST_START, + strlen ("NTLM " NTLM_REQUEST_START))) + state->sent_ntlm_request = TRUE; +} + +static void +response_check (SoupMessage *msg, gpointer user_data) +{ + NTLMState *state = user_data; + const char *header; + + header = soup_message_headers_get_one (msg->request_headers, + "Authorization"); + if (header && !strncmp (header, "NTLM " NTLM_RESPONSE_START, + strlen ("NTLM " NTLM_RESPONSE_START))) + state->sent_ntlm_response = TRUE; + if (header && !strncmp (header, "Basic ", 6)) + state->sent_basic_response = TRUE; +} + +static void +do_message (SoupSession *session, SoupURI *base_uri, const char *path, + gboolean get_ntlm_prompt, gboolean do_ntlm, + gboolean get_basic_prompt, gboolean do_basic, + guint status_code) +{ + SoupURI *uri; + SoupMessage *msg; + NTLMState state = { FALSE, FALSE, FALSE, FALSE }; + + uri = soup_uri_new_with_base (base_uri, path); + msg = soup_message_new_from_uri ("GET", uri); + soup_uri_free (uri); + + g_signal_connect (msg, "got_headers", + G_CALLBACK (prompt_check), &state); + g_signal_connect (msg, "got_headers", + G_CALLBACK (challenge_check), &state); + g_signal_connect (msg, "wrote-headers", + G_CALLBACK (request_check), &state); + g_signal_connect (msg, "wrote-headers", + G_CALLBACK (response_check), &state); + + soup_session_send_message (session, msg); + debug_printf (1, " %-10s -> ", path); + + if (state.got_ntlm_prompt) { + debug_printf (1, " NTLM_PROMPT"); + if (!get_ntlm_prompt) + debug_printf (1, "???"); + } else if (get_ntlm_prompt) + debug_printf (1, " no-ntlm-prompt???"); + + if (state.got_basic_prompt) { + debug_printf (1, " BASIC_PROMPT"); + if (!get_basic_prompt) + debug_printf (1, "???"); + } else if (get_basic_prompt) + debug_printf (1, " no-basic-prompt???"); + + if (state.sent_ntlm_request) { + debug_printf (1, " REQUEST"); + if (!do_ntlm) + debug_printf (1, "???"); + } else if (do_ntlm) + debug_printf (1, " no-request???"); + + if (state.got_ntlm_challenge) { + debug_printf (1, " CHALLENGE"); + if (!do_ntlm) + debug_printf (1, "???"); + } else if (do_ntlm) + debug_printf (1, " no-challenge???"); + + if (state.sent_ntlm_response) { + debug_printf (1, " NTLM_RESPONSE"); + if (!do_ntlm) + debug_printf (1, "???"); + } else if (do_ntlm) + debug_printf (1, " no-ntlm-response???"); + + if (state.sent_basic_response) { + debug_printf (1, " BASIC_RESPONSE"); + if (!do_basic) + debug_printf (1, "???"); + } else if (do_basic) + debug_printf (1, " no-basic-response???"); + + debug_printf (1, " -> %s", msg->reason_phrase); + if (msg->status_code != status_code) + debug_printf (1, "???"); + debug_printf (1, "\n"); + + g_assert_true (state.got_ntlm_prompt == get_ntlm_prompt); + g_assert_true (state.got_basic_prompt == get_basic_prompt); + g_assert_true (state.sent_ntlm_request == do_ntlm); + g_assert_true (state.got_ntlm_challenge == do_ntlm); + g_assert_true (state.sent_ntlm_response == do_ntlm); + g_assert_true (state.sent_basic_response == do_basic); + soup_test_assert_message_status (msg, status_code); + + g_object_unref (msg); +} + +static void +do_ntlm_round (SoupURI *base_uri, gboolean use_ntlm, + const char *user, gboolean use_builtin_ntlm) +{ + SoupSession *session; + gboolean alice = !g_strcmp0 (user, "alice"); + gboolean bob = !g_strcmp0 (user, "bob"); + gboolean alice_via_ntlm = use_ntlm && alice; + gboolean bob_via_ntlm = use_ntlm && bob; + gboolean alice_via_basic = !use_ntlm && alice; + + session = soup_test_session_new (SOUP_TYPE_SESSION, NULL); + + if (user) { + g_signal_connect (session, "authenticate", + G_CALLBACK (authenticate), (char *)user); + if (use_ntlm && !use_builtin_ntlm) + g_setenv ("NTLMUSER", user, TRUE); + } + if (use_ntlm) { + SoupAuthManager *auth_manager; + SoupAuth *ntlm; + + soup_session_add_feature_by_type (session, SOUP_TYPE_AUTH_NTLM); + auth_manager = SOUP_AUTH_MANAGER (soup_session_get_feature (session, SOUP_TYPE_AUTH_MANAGER)); + ntlm = g_object_new (SOUP_TYPE_AUTH_NTLM, NULL); + soup_auth_manager_use_auth (auth_manager, base_uri, ntlm); + g_object_unref (ntlm); + } + + /* 1. Server doesn't request auth, so both get_ntlm_prompt and + * get_basic_prompt are both FALSE, and likewise do_basic. But + * if we're using NTLM we'll try that even without the server + * asking. + */ + authenticated_ntlm = FALSE; + do_message (session, base_uri, "/noauth/", + FALSE, use_ntlm, + FALSE, FALSE, + SOUP_STATUS_OK); + + soup_test_assert (authenticated_ntlm == (use_ntlm && use_builtin_ntlm), + "%s built-in NTLM support, but authenticate signal %s emitted\n", + use_builtin_ntlm ? "Using" : "Not using", + authenticated_ntlm ? "was" : "wasn't"); + + /* 2. Server requires auth as Alice, so it will request that + * if we didn't already authenticate the connection to her in + * the previous step. If we authenticated as Bob in the + * previous step, then we'll just immediately get a 401 here. + * So in no case will we see the client try to do_ntlm. + */ + do_message (session, base_uri, "/alice/", + !alice_via_ntlm, FALSE, + !alice_via_ntlm, alice_via_basic, + alice ? SOUP_STATUS_OK : + SOUP_STATUS_UNAUTHORIZED); + + /* 3. Server still requires auth as Alice, but this URI + * doesn't exist, so Alice should get a 404, but others still + * get 401. Alice-via-NTLM is still authenticated, and so + * won't get prompts, and Alice-via-Basic knows at this point + * to send auth without it being requested, so also won't get + * prompts. But Bob/nobody will. + */ + do_message (session, base_uri, "/alice/404", + !alice, bob_via_ntlm, + !alice, alice_via_basic, + alice ? SOUP_STATUS_NOT_FOUND : + SOUP_STATUS_UNAUTHORIZED); + + /* 4. Should be exactly the same as #3, except the status code */ + do_message (session, base_uri, "/alice/", + !alice, bob_via_ntlm, + !alice, alice_via_basic, + alice ? SOUP_STATUS_OK : + SOUP_STATUS_UNAUTHORIZED); + + /* 5. This path requires auth as Bob; Alice-via-NTLM will get + * an immediate 401 and not try to reauthenticate. + * Alice-via-Basic will get a 401 and then try to do Basic + * (and fail). Bob-via-NTLM will try to do NTLM right away and + * succeed. + */ + do_message (session, base_uri, "/bob/", + !bob_via_ntlm, bob_via_ntlm, + !bob_via_ntlm, alice_via_basic, + bob ? SOUP_STATUS_OK : + SOUP_STATUS_UNAUTHORIZED); + + /* 6. Back to /alice. Somewhat the inverse of #5; Bob-via-NTLM + * will get an immediate 401 and not try again, Alice-via-NTLM + * will try to do NTLM right away and succeed. Alice-via-Basic + * still knows about this path, so will try Basic right away + * and succeed. + */ + do_message (session, base_uri, "/alice/", + !alice_via_ntlm, alice_via_ntlm, + !alice_via_ntlm, alice_via_basic, + alice ? SOUP_STATUS_OK : + SOUP_STATUS_UNAUTHORIZED); + + /* 7. Server accepts Basic auth from either user, but not NTLM. + * Since Bob-via-NTLM is unauthenticated at this point, he'll try + * NTLM before realizing that the server doesn't support it. + */ + do_message (session, base_uri, "/basic/", + FALSE, bob_via_ntlm, + TRUE, user != NULL, + user != NULL ? SOUP_STATUS_OK : + SOUP_STATUS_UNAUTHORIZED); + + /* 8. Server accepts Basic or NTLM from either user. + * NTLM users will try NTLM without getting a prompt (their + * previous NTLM connections will have been closed by the 401 + * from /basic). Non-NTLM users will be prompted for either. + */ + do_message (session, base_uri, "/either/", + !use_ntlm, use_ntlm, + !use_ntlm, !use_ntlm && user != NULL, + user != NULL ? SOUP_STATUS_OK : + SOUP_STATUS_UNAUTHORIZED); + + soup_test_session_abort_unref (session); +} + +typedef enum { + BUILTIN, + WINBIND, + FALLBACK +} NtlmType; + +typedef struct { + const char *name, *user; + gboolean conn_uses_ntlm; + NtlmType ntlm_type; +} NtlmTest; + +static const NtlmTest ntlm_tests[] = { + { "/ntlm/builtin/none", NULL, FALSE, BUILTIN }, + { "/ntlm/builtin/alice", "alice", TRUE, BUILTIN }, + { "/ntlm/builtin/bob", "bob", TRUE, BUILTIN }, + { "/ntlm/builtin/basic", "alice", FALSE, BUILTIN }, + + { "/ntlm/winbind/none", NULL, FALSE, WINBIND }, + { "/ntlm/winbind/alice", "alice", TRUE, WINBIND }, + { "/ntlm/winbind/bob", "bob", TRUE, WINBIND }, + { "/ntlm/winbind/basic", "alice", FALSE, WINBIND }, + + { "/ntlm/fallback/none", NULL, FALSE, FALLBACK }, + { "/ntlm/fallback/alice", "alice", TRUE, FALLBACK }, + { "/ntlm/fallback/bob", "bob", TRUE, FALLBACK }, + { "/ntlm/fallback/basic", "alice", FALSE, FALLBACK } +}; + +static const NtlmTest ntlmssp_tests[] = { + { "/ntlm/ssp/none", NULL, FALSE, BUILTIN }, + { "/ntlm/ssp/alice", "alice", TRUE, BUILTIN }, + { "/ntlm/ssp/bob", "bob", TRUE, BUILTIN }, + { "/ntlm/ssp/basic", "alice", FALSE, BUILTIN } +}; + +static void +do_ntlm_test (TestServer *ts, + gconstpointer data) +{ + const NtlmTest *test = data; + gboolean use_builtin_ntlm = TRUE; + + switch (test->ntlm_type) { + case BUILTIN: + /* Built-in NTLM auth support. (We set SOUP_NTLM_AUTH_DEBUG to + * an empty string to ensure that the built-in support is + * being used, even if /usr/bin/ntlm_auth is available.) + */ + g_setenv ("SOUP_NTLM_AUTH_DEBUG", "", TRUE); + break; + + case WINBIND: +#ifndef USE_NTLM_AUTH + g_test_skip ("/usr/bin/ntlm_auth is not available"); + return; +#endif + + /* Samba winbind /usr/bin/ntlm_auth helper support (via a + * helper program that emulates its interface). + */ + g_setenv ("SOUP_NTLM_AUTH_DEBUG", + g_test_get_filename (G_TEST_BUILT, "ntlm-test-helper", NULL), + TRUE); + g_unsetenv ("SOUP_NTLM_AUTH_DEBUG_NOCREDS"); + use_builtin_ntlm = FALSE; + break; + + case FALLBACK: +#ifndef USE_NTLM_AUTH + g_test_skip ("/usr/bin/ntlm_auth is not available"); + return; +#endif + + /* Support for when ntlm_auth is installed, but the user has + * no cached credentials (and thus we have to fall back to + * libsoup's built-in NTLM support). + */ + g_setenv ("SOUP_NTLM_AUTH_DEBUG", + g_test_get_filename (G_TEST_BUILT, "ntlm-test-helper", NULL), + TRUE); + g_setenv ("SOUP_NTLM_AUTH_DEBUG_NOCREDS", "1", TRUE); + break; + } + + do_ntlm_round (ts->uri, test->conn_uses_ntlm, test->user, use_builtin_ntlm); +} + +static void +retry_test_authenticate (SoupSession *session, SoupMessage *msg, + SoupAuth *auth, gboolean retrying, + gpointer user_data) +{ + gboolean *retried = user_data; + + if (!retrying) { + /* server_callback doesn't actually verify the password, + * only the username. So we pass an incorrect username + * rather than an incorrect password. + */ + soup_auth_authenticate (auth, "wrong", "password"); + } else if (!*retried) { + soup_auth_authenticate (auth, "alice", "password"); + *retried = TRUE; + } +} + +static void +do_retrying_test (TestServer *ts, + gconstpointer data) +{ + SoupSession *session; + SoupMessage *msg; + SoupURI *uri; + gboolean retried = FALSE; + + g_test_bug ("693222"); + + g_setenv ("SOUP_NTLM_AUTH_DEBUG", "", TRUE); + + debug_printf (1, " /alice\n"); + + session = soup_test_session_new (SOUP_TYPE_SESSION, + SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_AUTH_NTLM, + NULL); + g_signal_connect (session, "authenticate", + G_CALLBACK (retry_test_authenticate), &retried); + + uri = soup_uri_new_with_base (ts->uri, "/alice"); + msg = soup_message_new_from_uri ("GET", uri); + soup_uri_free (uri); + + soup_session_send_message (session, msg); + + g_assert_true (retried); + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + + g_object_unref (msg); + + soup_test_session_abort_unref (session); + + debug_printf (1, " /bob\n"); + + session = soup_test_session_new (SOUP_TYPE_SESSION, + SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_AUTH_NTLM, + NULL); + g_signal_connect (session, "authenticate", + G_CALLBACK (retry_test_authenticate), &retried); + retried = FALSE; + + uri = soup_uri_new_with_base (ts->uri, "/bob"); + msg = soup_message_new_from_uri ("GET", uri); + soup_uri_free (uri); + + soup_session_send_message (session, msg); + + g_assert_true (retried); + soup_test_assert_message_status (msg, SOUP_STATUS_UNAUTHORIZED); + + g_object_unref (msg); + + soup_test_session_abort_unref (session); +} + +int +main (int argc, char **argv) +{ + int i, ret; + + test_init (argc, argv, NULL); + + for (i = 0; i < G_N_ELEMENTS (ntlm_tests); i++) { + g_test_add (ntlm_tests[i].name, TestServer, &ntlm_tests[i], + setup_server, do_ntlm_test, teardown_server); + } + for (i = 0; i < G_N_ELEMENTS (ntlmssp_tests); i++) { + g_test_add (ntlmssp_tests[i].name, TestServer, &ntlmssp_tests[i], + setup_ntlmssp_server, do_ntlm_test, teardown_server); + } + + g_test_add ("/ntlm/retry", TestServer, NULL, + setup_server, do_retrying_test, teardown_server); + + ret = g_test_run (); + + test_cleanup (); + + return ret; +} diff --git a/tests/proxy-test.c b/tests/proxy-test.c new file mode 100644 index 0000000..1d68aa0 --- /dev/null +++ b/tests/proxy-test.c @@ -0,0 +1,447 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ + +#include "test-utils.h" + +typedef struct { + const char *explanation; + const char *url; + const guint final_status; + const char *bugref; +} SoupProxyTest; + +static SoupProxyTest tests[] = { + { "GET -> 200", "", SOUP_STATUS_OK, NULL }, + { "GET -> 404", "/not-found", SOUP_STATUS_NOT_FOUND, NULL }, + { "GET -> 401 -> 200", "/Basic/realm1/", SOUP_STATUS_OK, NULL }, + { "GET -> 401 -> 401", "/Basic/realm2/", SOUP_STATUS_UNAUTHORIZED, NULL }, + { "GET -> 403", "http://no-such-hostname.xx/", SOUP_STATUS_FORBIDDEN, "577532" }, + { "GET -> 200 (unproxied)", "http://localhost:47524/", SOUP_STATUS_OK, "700472" }, +}; +static const int ntests = sizeof (tests) / sizeof (tests[0]); + +#define HTTP_SERVER "http://127.0.0.1:47524" +#define HTTPS_SERVER "https://127.0.0.1:47525" + +enum { + SIMPLE_PROXY, + AUTH_PROXY, + UNAUTH_PROXY +}; +static const char *proxies[] = { + "http://127.0.0.1:47526", + "http://127.0.0.1:47527", + "http://127.0.0.1:47528" +}; +static const char *proxy_names[] = { + "simple proxy", + "authenticated proxy", + "unauthenticatable-to proxy" +}; +static GProxyResolver *proxy_resolvers[3]; +static const char *ignore_hosts[] = { "localhost", NULL }; + +static void +authenticate (SoupSession *session, SoupMessage *msg, + SoupAuth *auth, gboolean retrying, gpointer data) +{ + if (msg->status_code == SOUP_STATUS_UNAUTHORIZED) { + soup_test_assert (!soup_auth_is_for_proxy (auth), + "got proxy auth object for 401"); + } else if (msg->status_code == SOUP_STATUS_PROXY_UNAUTHORIZED) { + soup_test_assert (soup_auth_is_for_proxy (auth), + "got regular auth object for 407"); + } else { + soup_test_assert (FALSE, + "got authenticate signal with status %d\n", + msg->status_code); + } + + if (!retrying) + soup_auth_authenticate (auth, "user1", "realm1"); +} + +static void +set_close_on_connect (SoupSession *session, SoupMessage *msg, + SoupSocket *sock, gpointer user_data) +{ + /* This is used to test that we can handle the server closing + * the connection when returning a 407 in response to a + * CONNECT. (Rude!) + */ + if (msg->method == SOUP_METHOD_CONNECT) { + soup_message_headers_append (msg->request_headers, + "Connection", "close"); + } +} + + +static void +test_url (const char *url, int proxy, guint expected, + gboolean sync, gboolean close) +{ + SoupSession *session; + SoupMessage *msg; + gboolean noproxy = !!strstr (url, "localhost"); + + if (!tls_available && g_str_has_prefix (url, "https:")) + return; + + debug_printf (1, " GET %s via %s%s\n", url, proxy_names[proxy], + close ? " (with Connection: close)" : ""); + if (proxy == UNAUTH_PROXY && expected != SOUP_STATUS_FORBIDDEN && !noproxy) + expected = SOUP_STATUS_PROXY_UNAUTHORIZED; + + /* We create a new session for each request to ensure that + * connections/auth aren't cached between tests. + */ + session = soup_test_session_new (sync ? SOUP_TYPE_SESSION_SYNC : SOUP_TYPE_SESSION_ASYNC, + SOUP_SESSION_PROXY_RESOLVER, proxy_resolvers[proxy], + SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, + SOUP_SESSION_SSL_STRICT, FALSE, + NULL); + g_signal_connect (session, "authenticate", + G_CALLBACK (authenticate), NULL); + if (close) { + /* FIXME g_test_bug ("611663") */ + g_signal_connect (session, "request-started", + G_CALLBACK (set_close_on_connect), NULL); + } + + msg = soup_message_new (SOUP_METHOD_GET, url); + if (!msg) { + g_printerr ("proxy-test: Could not parse URI\n"); + exit (1); + } + + soup_session_send_message (session, msg); + + debug_printf (1, " %d %s\n", msg->status_code, msg->reason_phrase); + soup_test_assert_message_status (msg, expected); + + g_object_unref (msg); + soup_test_session_abort_unref (session); +} + +static void +test_url_new_api (const char *url, int proxy, guint expected, + gboolean sync, gboolean close) +{ + SoupSession *session; + SoupMessage *msg; + SoupRequest *request; + GInputStream *stream; + GError *error = NULL; + gboolean noproxy = !!strstr (url, "localhost"); + + /* FIXME g_test_skip() FIXME g_test_bug ("675865") */ + if (!tls_available && g_str_has_prefix (url, "https:")) + return; + + debug_printf (1, " GET (request API) %s via %s%s\n", url, proxy_names[proxy], + close ? " (with Connection: close)" : ""); + if (proxy == UNAUTH_PROXY && expected != SOUP_STATUS_FORBIDDEN && !noproxy) + expected = SOUP_STATUS_PROXY_UNAUTHORIZED; + + /* We create a new session for each request to ensure that + * connections/auth aren't cached between tests. + */ + session = soup_test_session_new (sync ? SOUP_TYPE_SESSION_SYNC : SOUP_TYPE_SESSION_ASYNC, + SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, + SOUP_SESSION_PROXY_RESOLVER, proxy_resolvers[proxy], + SOUP_SESSION_SSL_STRICT, FALSE, + NULL); + + g_signal_connect (session, "authenticate", + G_CALLBACK (authenticate), NULL); + if (close) { + /* FIXME g_test_bug ("611663") */ + g_signal_connect (session, "request-started", + G_CALLBACK (set_close_on_connect), NULL); + } + + request = soup_session_request (session, url, NULL); + msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (request)); + + stream = soup_test_request_send (request, NULL, 0, &error); + g_assert_no_error (error); + g_clear_error (&error); + + if (stream) { + soup_test_request_close_stream (request, stream, NULL, &error); + g_assert_no_error (error); + g_clear_error (&error); + g_object_unref (stream); + } + + debug_printf (1, " %d %s\n", msg->status_code, msg->reason_phrase); + soup_test_assert_message_status (msg, expected); + + g_object_unref (msg); + g_object_unref (request); + + soup_test_session_abort_unref (session); +} + +static void +do_proxy_test (SoupProxyTest *test, gboolean sync) +{ + char *http_url, *https_url; + + if (test->bugref) + g_test_bug (test->bugref); + + if (!strncmp (test->url, "http", 4)) { + SoupURI *uri; + guint port; + + http_url = g_strdup (test->url); + + uri = soup_uri_new (test->url); + port = uri->port; + soup_uri_set_scheme (uri, "https"); + if (port) + soup_uri_set_port (uri, port + 1); + https_url = soup_uri_to_string (uri, FALSE); + soup_uri_free (uri); + } else { + http_url = g_strconcat (HTTP_SERVER, test->url, NULL); + https_url = g_strconcat (HTTPS_SERVER, test->url, NULL); + } + + test_url (http_url, SIMPLE_PROXY, test->final_status, sync, FALSE); + test_url_new_api (http_url, SIMPLE_PROXY, test->final_status, sync, FALSE); + test_url (https_url, SIMPLE_PROXY, test->final_status, sync, FALSE); + test_url_new_api (https_url, SIMPLE_PROXY, test->final_status, sync, FALSE); + + test_url (http_url, AUTH_PROXY, test->final_status, sync, FALSE); + test_url_new_api (http_url, AUTH_PROXY, test->final_status, sync, FALSE); + test_url (https_url, AUTH_PROXY, test->final_status, sync, FALSE); + test_url_new_api (https_url, AUTH_PROXY, test->final_status, sync, FALSE); + test_url (https_url, AUTH_PROXY, test->final_status, sync, TRUE); + test_url_new_api (https_url, AUTH_PROXY, test->final_status, sync, TRUE); + + test_url (http_url, UNAUTH_PROXY, test->final_status, sync, FALSE); + test_url_new_api (http_url, UNAUTH_PROXY, test->final_status, sync, FALSE); + test_url (https_url, UNAUTH_PROXY, test->final_status, sync, FALSE); + test_url_new_api (https_url, UNAUTH_PROXY, test->final_status, sync, FALSE); + + g_free (http_url); + g_free (https_url); +} + +static void +do_async_proxy_test (gconstpointer data) +{ + SoupProxyTest *test = (SoupProxyTest *)data; + + SOUP_TEST_SKIP_IF_NO_APACHE; + + do_proxy_test (test, FALSE); +} + +static void +do_sync_proxy_test (gconstpointer data) +{ + SoupProxyTest *test = (SoupProxyTest *)data; + + SOUP_TEST_SKIP_IF_NO_APACHE; + + do_proxy_test (test, TRUE); +} + +static void +server_callback (SoupServer *server, SoupMessage *msg, + const char *path, GHashTable *query, + SoupClientContext *context, gpointer data) +{ + SoupURI *uri = soup_message_get_uri (msg); + + soup_message_set_status (msg, uri->fragment ? SOUP_STATUS_BAD_REQUEST : SOUP_STATUS_OK); +} + +static void +do_proxy_fragment_test (gconstpointer data) +{ + SoupURI *base_uri = (SoupURI *)data; + SoupSession *session; + SoupURI *proxy_uri, *req_uri; + SoupMessage *msg; + + SOUP_TEST_SKIP_IF_NO_APACHE; + + proxy_uri = soup_uri_new (proxies[SIMPLE_PROXY]); + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, + SOUP_SESSION_PROXY_URI, proxy_uri, + NULL); + soup_uri_free (proxy_uri); + + req_uri = soup_uri_new_with_base (base_uri, "/#foo"); + msg = soup_message_new_from_uri (SOUP_METHOD_GET, req_uri); + soup_uri_free (req_uri); + soup_session_send_message (session, msg); + + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + + g_object_unref (msg); + soup_test_session_abort_unref (session); +} + +static void +do_proxy_redirect_test (void) +{ + SoupSession *session; + SoupURI *proxy_uri, *req_uri, *new_uri; + SoupMessage *msg; + + g_test_bug ("631368"); + + SOUP_TEST_SKIP_IF_NO_APACHE; + SOUP_TEST_SKIP_IF_NO_TLS; + + proxy_uri = soup_uri_new (proxies[SIMPLE_PROXY]); + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, + SOUP_SESSION_PROXY_URI, proxy_uri, + NULL); + soup_uri_free (proxy_uri); + + req_uri = soup_uri_new (HTTPS_SERVER); + soup_uri_set_path (req_uri, "/redirected"); + msg = soup_message_new_from_uri (SOUP_METHOD_GET, req_uri); + soup_message_headers_append (msg->request_headers, + "Connection", "close"); + soup_session_send_message (session, msg); + + new_uri = soup_message_get_uri (msg); + soup_test_assert (strcmp (req_uri->path, new_uri->path) != 0, + "message was not redirected"); + soup_uri_free (req_uri); + + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + + g_object_unref (msg); + soup_test_session_abort_unref (session); +} + +static void +do_proxy_auth_request (const char *url, SoupSession *session, gboolean do_read) +{ + SoupRequest *request; + SoupMessage *msg; + GInputStream *stream; + GError *error = NULL; + + request = soup_session_request (session, url, NULL); + msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (request)); + + stream = soup_test_request_send (request, NULL, 0, &error); + g_assert_no_error (error); + g_clear_error (&error); + + if (do_read) { + char buffer[256]; + gsize nread; + + do { + g_input_stream_read_all (stream, buffer, sizeof (buffer), &nread, + NULL, &error); + g_assert_no_error (error); + g_clear_error (&error); + } while (nread > 0); + } + + soup_test_request_close_stream (request, stream, NULL, &error); + g_assert_no_error (error); + g_clear_error (&error); + g_object_unref (stream); + + debug_printf (1, " %d %s\n", msg->status_code, msg->reason_phrase); + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + + g_object_unref (msg); + g_object_unref (request); +} + +static void +do_proxy_auth_cache_test (void) +{ + SoupSession *session; + char *cache_dir; + SoupCache *cache; + char *url; + + g_test_bug ("756076"); + + SOUP_TEST_SKIP_IF_NO_APACHE; + + cache_dir = g_dir_make_tmp ("cache-test-XXXXXX", NULL); + debug_printf (2, " Caching to %s\n", cache_dir); + cache = soup_cache_new (cache_dir, SOUP_CACHE_SINGLE_USER); + g_free (cache_dir); + + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, + SOUP_SESSION_PROXY_RESOLVER, proxy_resolvers[AUTH_PROXY], + SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, + SOUP_SESSION_ADD_FEATURE, cache, + NULL); + g_signal_connect (session, "authenticate", + G_CALLBACK (authenticate), NULL); + + url = g_strconcat (HTTP_SERVER, "/Basic/realm1/", NULL); + + debug_printf (1, " GET %s via %s (from network)\n", url, proxy_names[AUTH_PROXY]); + do_proxy_auth_request (url, session, TRUE); + soup_cache_flush (cache); + + debug_printf (1, " GET %s via %s (from cache)\n", url, proxy_names[AUTH_PROXY]); + do_proxy_auth_request (url, session, FALSE); + + g_free (url); + soup_test_session_abort_unref (session); + g_object_unref (cache); +} + +int +main (int argc, char **argv) +{ + SoupServer *server; + SoupURI *base_uri; + char *path; + int i, ret; + + test_init (argc, argv, NULL); + apache_init (); + + for (i = 0; i < 3; i++) { + proxy_resolvers[i] = + g_simple_proxy_resolver_new (proxies[i], (char **) ignore_hosts); + } + + server = soup_test_server_new (SOUP_TEST_SERVER_IN_THREAD); + soup_server_add_handler (server, NULL, server_callback, NULL, NULL); + base_uri = soup_test_server_get_uri (server, "http", NULL); + + for (i = 0; i < ntests; i++) { + path = g_strdup_printf ("/proxy/async/%s", tests[i].explanation); + g_test_add_data_func (path, &tests[i], do_async_proxy_test); + g_free (path); + } + for (i = 0; i < ntests; i++) { + path = g_strdup_printf ("/proxy/sync/%s", tests[i].explanation); + g_test_add_data_func (path, &tests[i], do_sync_proxy_test); + g_free (path); + } + + g_test_add_data_func ("/proxy/fragment", base_uri, do_proxy_fragment_test); + g_test_add_func ("/proxy/redirect", do_proxy_redirect_test); + g_test_add_func ("/proxy/auth-cache", do_proxy_auth_cache_test); + + ret = g_test_run (); + + soup_uri_free (base_uri); + soup_test_server_quit_unref (server); + for (i = 0; i < 3; i++) + g_object_unref (proxy_resolvers[i]); + + test_cleanup (); + return ret; +} diff --git a/tests/pull-api.c b/tests/pull-api.c new file mode 100644 index 0000000..2915b9e --- /dev/null +++ b/tests/pull-api.c @@ -0,0 +1,533 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ + +#include "test-utils.h" + +static SoupBuffer *correct_response; + +static void +authenticate (SoupSession *session, SoupMessage *msg, + SoupAuth *auth, gboolean retrying, gpointer data) +{ + if (!retrying) + soup_auth_authenticate (auth, "user2", "realm2"); +} + +#if HAVE_APACHE +static void +get_correct_response (const char *uri) +{ + SoupSession *session; + SoupMessage *msg; + + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + msg = soup_message_new (SOUP_METHOD_GET, uri); + soup_session_send_message (session, msg); + if (msg->status_code != SOUP_STATUS_OK) { + g_printerr ("Could not fetch %s: %d %s\n", uri, + msg->status_code, msg->reason_phrase); + exit (1); + } + + correct_response = soup_message_body_flatten (msg->response_body); + + g_object_unref (msg); + soup_test_session_abort_unref (session); +} +#endif + +/* Pull API version 1: fully-async. More like a "poke" API. Rather + * than having SoupMessage emit "got_chunk" signals whenever it wants, + * we stop it after it finishes reading the message headers, and then + * tell it when we want to hear about new chunks. + */ + +typedef struct { + GMainLoop *loop; + SoupSession *session; + SoupMessage *msg; + guint timeout; + gboolean chunks_ready; + gboolean chunk_wanted; + gboolean did_first_timeout; + gsize read_so_far; + guint expected_status; +} FullyAsyncData; + +static void fully_async_got_headers (SoupMessage *msg, gpointer user_data); +static void fully_async_got_chunk (SoupMessage *msg, SoupBuffer *chunk, + gpointer user_data); +static void fully_async_finished (SoupSession *session, SoupMessage *msg, + gpointer user_data); +static gboolean fully_async_request_chunk (gpointer user_data); + +static void +do_fully_async_test (SoupSession *session, + const char *base_uri, const char *sub_uri, + gboolean fast_request, guint expected_status) +{ + GMainLoop *loop; + FullyAsyncData ad; + SoupMessage *msg; + char *uri; + + loop = g_main_loop_new (NULL, FALSE); + + uri = g_build_filename (base_uri, sub_uri, NULL); + debug_printf (1, "GET %s\n", uri); + + msg = soup_message_new (SOUP_METHOD_GET, uri); + g_free (uri); + + ad.loop = loop; + ad.session = session; + ad.msg = msg; + ad.chunks_ready = FALSE; + ad.chunk_wanted = FALSE; + ad.did_first_timeout = FALSE; + ad.read_so_far = 0; + ad.expected_status = expected_status; + + /* Since we aren't going to look at the final value of + * msg->response_body, we tell libsoup to not even bother + * generating it. + */ + soup_message_body_set_accumulate (msg->response_body, FALSE); + + /* Connect to "got_headers", from which we'll decide where to + * go next. + */ + g_signal_connect (msg, "got_headers", + G_CALLBACK (fully_async_got_headers), &ad); + + /* Queue the request */ + soup_session_queue_message (session, msg, fully_async_finished, &ad); + + /* In a real program, we'd probably just return at this point. + * Eventually the caller would return all the way to the main + * loop, and then eventually, some event would cause the + * application to request a chunk of data from the message + * response. + * + * In our test program, there is no "real" main loop, so we + * had to create our own. We use a timeout to represent the + * event that causes the app to decide to request another body + * chunk. We use short timeouts in one set of tests, and long + * ones in another, to test both the + * chunk-requested-before-its-been-read and + * chunk-read-before-its-been-requested cases. + */ + ad.timeout = g_timeout_add (fast_request ? 0 : 100, + fully_async_request_chunk, &ad); + g_main_loop_run (ad.loop); + g_main_loop_unref (ad.loop); +} + +static gboolean +fully_async_request_chunk (gpointer user_data) +{ + FullyAsyncData *ad = user_data; + + if (!ad->did_first_timeout) { + debug_printf (1, " first timeout\n"); + ad->did_first_timeout = TRUE; + } else + debug_printf (2, " timeout\n"); + ad->timeout = 0; + + /* ad->chunks_ready and ad->chunk_wanted are used because + * there's a race condition between the application requesting + * the first chunk, and the message reaching a point where + * it's actually ready to read chunks. If chunks_ready has + * been set, we can just call soup_session_unpause_message() to + * cause the first chunk to be read. But if it's not, we just + * set chunk_wanted, to let the got_headers handler below know + * that a chunk has already been requested. + */ + if (ad->chunks_ready) + soup_session_unpause_message (ad->session, ad->msg); + else + ad->chunk_wanted = TRUE; + + return FALSE; +} + +static void +fully_async_got_headers (SoupMessage *msg, gpointer user_data) +{ + FullyAsyncData *ad = user_data; + + debug_printf (1, " %d %s\n", msg->status_code, msg->reason_phrase); + if (msg->status_code == SOUP_STATUS_UNAUTHORIZED) { + /* Let soup handle this one; this got_headers handler + * will get called again next time around. + */ + return; + } else if (msg->status_code != SOUP_STATUS_OK) { + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + return; + } + + /* OK, we're happy with the response. So, we connect to + * "got_chunk". If there has already been a chunk requested, + * we let I/O continue; but if there hasn't, we pause now + * until one is requested. + */ + ad->chunks_ready = TRUE; + g_signal_connect (msg, "got_chunk", + G_CALLBACK (fully_async_got_chunk), ad); + if (!ad->chunk_wanted) + soup_session_pause_message (ad->session, msg); +} + +static void +fully_async_got_chunk (SoupMessage *msg, SoupBuffer *chunk, gpointer user_data) +{ + FullyAsyncData *ad = user_data; + + debug_printf (2, " got chunk from %lu - %lu\n", + (unsigned long) ad->read_so_far, + (unsigned long) ad->read_so_far + chunk->length); + + /* We've got a chunk, let's process it. In the case of the + * test program, that means comparing it against + * correct_response to make sure that we got the right data. + */ + g_assert_cmpint (ad->read_so_far + chunk->length, <=, correct_response->length); + soup_assert_cmpmem (chunk->data, chunk->length, + correct_response->data + ad->read_so_far, + chunk->length); + ad->read_so_far += chunk->length; + + /* Now pause I/O, and prepare to read another chunk later. + * (Again, the timeout just abstractly represents the idea of + * the application requesting another chunk at some random + * point in the future. You wouldn't be using a timeout in a + * real program.) + */ + soup_session_pause_message (ad->session, msg); + ad->chunk_wanted = FALSE; + + ad->timeout = g_timeout_add (10, fully_async_request_chunk, ad); +} + +static void +fully_async_finished (SoupSession *session, SoupMessage *msg, + gpointer user_data) +{ + FullyAsyncData *ad = user_data; + + soup_test_assert_message_status (msg, ad->expected_status); + + if (ad->timeout != 0) + g_source_remove (ad->timeout); + + /* Since our test program is only running the loop for the + * purpose of this one test, we quit the loop once the + * test is done. + */ + g_main_loop_quit (ad->loop); +} + +static void +do_fast_async_test (gconstpointer data) +{ + const char *base_uri = data; + SoupSession *session; + + SOUP_TEST_SKIP_IF_NO_APACHE; + + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + g_signal_connect (session, "authenticate", + G_CALLBACK (authenticate), NULL); + do_fully_async_test (session, base_uri, "/", + TRUE, SOUP_STATUS_OK); + do_fully_async_test (session, base_uri, "/Basic/realm1/", + TRUE, SOUP_STATUS_UNAUTHORIZED); + do_fully_async_test (session, base_uri, "/Basic/realm2/", + TRUE, SOUP_STATUS_OK); + soup_test_session_abort_unref (session); +} + +static void +do_slow_async_test (gconstpointer data) +{ + const char *base_uri = data; + SoupSession *session; + + SOUP_TEST_SKIP_IF_NO_APACHE; + + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + g_signal_connect (session, "authenticate", + G_CALLBACK (authenticate), NULL); + do_fully_async_test (session, base_uri, "/", + FALSE, SOUP_STATUS_OK); + do_fully_async_test (session, base_uri, "/Basic/realm1/", + FALSE, SOUP_STATUS_UNAUTHORIZED); + do_fully_async_test (session, base_uri, "/Basic/realm2/", + FALSE, SOUP_STATUS_OK); + soup_test_session_abort_unref (session); +} + +/* Pull API version 2: synchronous pull API via async I/O. */ + +typedef struct { + GMainLoop *loop; + SoupSession *session; + SoupBuffer *chunk; +} SyncAsyncData; + +static void sync_async_send (SoupSession *session, + SoupMessage *msg); +static gboolean sync_async_is_finished(SoupMessage *msg); +static SoupBuffer *sync_async_read_chunk (SoupMessage *msg); +static void sync_async_cleanup (SoupMessage *msg); + +static void sync_async_got_headers (SoupMessage *msg, gpointer user_data); +static void sync_async_copy_chunk (SoupMessage *msg, SoupBuffer *chunk, + gpointer user_data); +static void sync_async_finished (SoupSession *session, SoupMessage *msg, + gpointer user_data); + +static void +do_synchronously_async_test (SoupSession *session, + const char *base_uri, const char *sub_uri, + guint expected_status) +{ + SoupMessage *msg; + char *uri; + gsize read_so_far; + SoupBuffer *chunk; + + uri = g_build_filename (base_uri, sub_uri, NULL); + debug_printf (1, "GET %s\n", uri); + + msg = soup_message_new (SOUP_METHOD_GET, uri); + g_free (uri); + + /* As in the fully-async case, we turn off accumulate, as an + * optimization. + */ + soup_message_body_set_accumulate (msg->response_body, FALSE); + + /* Send the message, get back headers */ + sync_async_send (session, msg); + if (expected_status == SOUP_STATUS_OK) { + soup_test_assert (!sync_async_is_finished (msg), + "finished without reading response"); + } else { + soup_test_assert (sync_async_is_finished (msg), + "request failed to fail"); + } + + /* Now we're ready to read the response body (though we could + * put that off until later if we really wanted). + */ + read_so_far = 0; + while ((chunk = sync_async_read_chunk (msg))) { + debug_printf (2, " read chunk from %lu - %lu\n", + (unsigned long) read_so_far, + (unsigned long) read_so_far + chunk->length); + + g_assert_cmpint (read_so_far + chunk->length, <=, correct_response->length); + soup_assert_cmpmem (chunk->data, chunk->length, + correct_response->data + read_so_far, + chunk->length); + + read_so_far += chunk->length; + soup_buffer_free (chunk); + } + + g_assert_true (sync_async_is_finished (msg)); + soup_test_assert_message_status (msg, expected_status); + if (msg->status_code == SOUP_STATUS_OK) + g_assert_cmpint (read_so_far, ==, correct_response->length); + + sync_async_cleanup (msg); + g_object_unref (msg); +} + +/* Sends @msg on async session @session and returns after the headers + * of a successful response (or the complete body of a failed + * response) have been read. + */ +static void +sync_async_send (SoupSession *session, SoupMessage *msg) +{ + SyncAsyncData *ad; + + ad = g_new0 (SyncAsyncData, 1); + g_object_set_data (G_OBJECT (msg), "SyncAsyncData", ad); + + /* In this case, unlike the fully-async case, the loop + * actually belongs to us, not the application; it will only + * be run when we're waiting for chunks, not at other times. + * + * If session has an async_context associated with it, we'd + * want to pass that, rather than NULL, here. + */ + ad->loop = g_main_loop_new (NULL, FALSE); + ad->session = session; + + g_signal_connect (msg, "got_headers", + G_CALLBACK (sync_async_got_headers), ad); + + /* Start the request by queuing it and then running our main + * loop. Note: we have to use soup_session_queue_message() + * here; soup_session_send_message() won't work, for several + * reasons. Also, since soup_session_queue_message() steals a + * ref to the message and then unrefs it after invoking the + * callback, we have to add an extra ref before calling it. + */ + g_object_ref (msg); + soup_session_queue_message (session, msg, sync_async_finished, ad); + g_main_loop_run (ad->loop); + + /* At this point, one of two things has happened; either the + * got_headers handler got headers it liked, and so stopped + * the loop, or else the message was fully processed without + * the got_headers handler interrupting it, and so the final + * callback (sync_async_finished) was invoked, and stopped the + * loop. + * + * Either way, we're done, so we return to the caller. + */ +} + +static void +sync_async_got_headers (SoupMessage *msg, gpointer user_data) +{ + SyncAsyncData *ad = user_data; + + debug_printf (1, " %d %s\n", msg->status_code, msg->reason_phrase); + if (msg->status_code == SOUP_STATUS_UNAUTHORIZED) { + /* Let soup handle this one; this got_headers handler + * will get called again next time around. + */ + return; + } else if (msg->status_code != SOUP_STATUS_OK) { + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + return; + } + + /* Stop I/O and return to the caller */ + soup_session_pause_message (ad->session, msg); + g_main_loop_quit (ad->loop); +} + +static gboolean +sync_async_is_finished (SoupMessage *msg) +{ + SyncAsyncData *ad = g_object_get_data (G_OBJECT (msg), "SyncAsyncData"); + + /* sync_async_finished clears ad->loop */ + return ad->loop == NULL; +} + +/* Tries to read a chunk. Returns %NULL on error/end-of-response. */ +static SoupBuffer * +sync_async_read_chunk (SoupMessage *msg) +{ + SyncAsyncData *ad = g_object_get_data (G_OBJECT (msg), "SyncAsyncData"); + guint handler; + + if (sync_async_is_finished (msg)) + return NULL; + + ad->chunk = NULL; + handler = g_signal_connect (msg, "got_chunk", + G_CALLBACK (sync_async_copy_chunk), + ad); + soup_session_unpause_message (ad->session, msg); + g_main_loop_run (ad->loop); + g_signal_handler_disconnect (msg, handler); + + return ad->chunk; +} + +static void +sync_async_copy_chunk (SoupMessage *msg, SoupBuffer *chunk, gpointer user_data) +{ + SyncAsyncData *ad = user_data; + + ad->chunk = soup_buffer_copy (chunk); + + /* Now pause and return from the g_main_loop_run() call in + * sync_async_read_chunk(). + */ + soup_session_pause_message (ad->session, msg); + g_main_loop_quit (ad->loop); +} + +static void +sync_async_finished (SoupSession *session, SoupMessage *msg, gpointer user_data) +{ + SyncAsyncData *ad = user_data; + + /* Unlike in the fully_async_case, we don't need to do much + * here, because control will return to + * do_synchronously_async_test() when we're done, and we do + * the final tests there. + */ + g_main_loop_quit (ad->loop); + g_main_loop_unref (ad->loop); + ad->loop = NULL; +} + +static void +sync_async_cleanup (SoupMessage *msg) +{ + SyncAsyncData *ad = g_object_get_data (G_OBJECT (msg), "SyncAsyncData"); + + if (ad->loop) + g_main_loop_unref (ad->loop); + g_free (ad); +} + +static void +do_sync_async_test (gconstpointer data) +{ + const char *base_uri = data; + SoupSession *session; + + SOUP_TEST_SKIP_IF_NO_APACHE; + + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + g_signal_connect (session, "authenticate", + G_CALLBACK (authenticate), NULL); + do_synchronously_async_test (session, base_uri, "/", + SOUP_STATUS_OK); + do_synchronously_async_test (session, base_uri, "/Basic/realm1/", + SOUP_STATUS_UNAUTHORIZED); + do_synchronously_async_test (session, base_uri, "/Basic/realm2/", + SOUP_STATUS_OK); + soup_test_session_abort_unref (session); +} + + +int +main (int argc, char **argv) +{ + const char *base_uri; + int ret; + + test_init (argc, argv, NULL); + apache_init (); + + base_uri = "http://127.0.0.1:47524/"; +#if HAVE_APACHE + get_correct_response (base_uri); +#endif + + g_test_add_data_func ("/pull-api/async/fast", base_uri, do_fast_async_test); + g_test_add_data_func ("/pull-api/async/slow", base_uri, do_slow_async_test); + g_test_add_data_func ("/pull-api/sync-async", base_uri, do_sync_async_test); + + ret = g_test_run (); + +#if HAVE_APACHE + soup_buffer_free (correct_response); +#endif + + test_cleanup (); + return ret; +} diff --git a/tests/range-test.c b/tests/range-test.c new file mode 100644 index 0000000..d3c4996 --- /dev/null +++ b/tests/range-test.c @@ -0,0 +1,397 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ + +#include "test-utils.h" + +SoupBuffer *full_response; +int total_length; +char *test_response; + +static void +check_part (SoupMessageHeaders *headers, const char *body, gsize body_len, + gboolean check_start_end, int expected_start, int expected_end) +{ + goffset start, end, total_length; + + debug_printf (1, " Content-Range: %s\n", + soup_message_headers_get_one (headers, "Content-Range")); + + if (!soup_message_headers_get_content_range (headers, &start, &end, &total_length)) { + soup_test_assert (FALSE, "Could not find/parse Content-Range"); + return; + } + + if (total_length != full_response->length && total_length != -1) { + soup_test_assert (FALSE, + "Unexpected total length %" G_GINT64_FORMAT " in response\n", + total_length); + return; + } + + if (check_start_end) { + if ((expected_start >= 0 && start != expected_start) || + (expected_start < 0 && start != full_response->length + expected_start)) { + soup_test_assert (FALSE, + "Unexpected range start %" G_GINT64_FORMAT " in response\n", + start); + return; + } + + if ((expected_end >= 0 && end != expected_end) || + (expected_end < 0 && end != full_response->length - 1)) { + soup_test_assert (FALSE, + "Unexpected range end %" G_GINT64_FORMAT " in response\n", + end); + return; + } + } + + if (end - start + 1 != body_len) { + soup_test_assert (FALSE, "Range length (%d) does not match body length (%d)\n", + (int)(end - start) + 1, + (int)body_len); + return; + } + + memcpy (test_response + start, body, body_len); +} + +static void +do_single_range (SoupSession *session, SoupMessage *msg, + int start, int end, gboolean succeed) +{ + const char *content_type; + + debug_printf (1, " Range: %s\n", + soup_message_headers_get_one (msg->request_headers, "Range")); + + soup_session_send_message (session, msg); + + if (!succeed) { + soup_test_assert_message_status (msg, SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE); + if (msg->status_code != SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE) { + const char *content_range; + + content_range = soup_message_headers_get_one (msg->response_headers, + "Content-Range"); + if (content_range) + debug_printf (1, " Content-Range: %s\n", content_range); + } + + g_object_unref (msg); + return; + } + + soup_test_assert_message_status (msg, SOUP_STATUS_PARTIAL_CONTENT); + + content_type = soup_message_headers_get_content_type ( + msg->response_headers, NULL); + g_assert_cmpstr (content_type, !=, "multipart/byteranges"); + + check_part (msg->response_headers, msg->response_body->data, + msg->response_body->length, TRUE, start, end); + g_object_unref (msg); +} + +static void +request_single_range (SoupSession *session, const char *uri, + int start, int end, gboolean succeed) +{ + SoupMessage *msg; + + msg = soup_message_new ("GET", uri); + soup_message_headers_set_range (msg->request_headers, start, end); + do_single_range (session, msg, start, end, succeed); +} + +static void +do_multi_range (SoupSession *session, SoupMessage *msg, + int expected_return_ranges) +{ + SoupMultipart *multipart; + const char *content_type; + int i, length; + + debug_printf (1, " Range: %s\n", + soup_message_headers_get_one (msg->request_headers, "Range")); + + soup_session_send_message (session, msg); + + soup_test_assert_message_status (msg, SOUP_STATUS_PARTIAL_CONTENT); + + content_type = soup_message_headers_get_content_type (msg->response_headers, NULL); + g_assert_cmpstr (content_type, ==, "multipart/byteranges"); + + multipart = soup_multipart_new_from_message (msg->response_headers, + msg->response_body); + if (!multipart) { + soup_test_assert (FALSE, "Could not parse multipart"); + g_object_unref (msg); + return; + } + + length = soup_multipart_get_length (multipart); + g_assert_cmpint (length, ==, expected_return_ranges); + + for (i = 0; i < length; i++) { + SoupMessageHeaders *headers; + SoupBuffer *body; + + debug_printf (1, " Part %d\n", i + 1); + soup_multipart_get_part (multipart, i, &headers, &body); + check_part (headers, body->data, body->length, FALSE, 0, 0); + } + + soup_multipart_free (multipart); + g_object_unref (msg); +} + +static void +request_double_range (SoupSession *session, const char *uri, + int first_start, int first_end, + int second_start, int second_end, + int expected_return_ranges) +{ + SoupMessage *msg; + SoupRange ranges[2]; + + msg = soup_message_new ("GET", uri); + ranges[0].start = first_start; + ranges[0].end = first_end; + ranges[1].start = second_start; + ranges[1].end = second_end; + soup_message_headers_set_ranges (msg->request_headers, ranges, 2); + + if (expected_return_ranges == 1) { + do_single_range (session, msg, + MIN (first_start, second_start), + MAX (first_end, second_end), + TRUE); + } else + do_multi_range (session, msg, expected_return_ranges); +} + +static void +request_triple_range (SoupSession *session, const char *uri, + int first_start, int first_end, + int second_start, int second_end, + int third_start, int third_end, + int expected_return_ranges) +{ + SoupMessage *msg; + SoupRange ranges[3]; + + msg = soup_message_new ("GET", uri); + ranges[0].start = first_start; + ranges[0].end = first_end; + ranges[1].start = second_start; + ranges[1].end = second_end; + ranges[2].start = third_start; + ranges[2].end = third_end; + soup_message_headers_set_ranges (msg->request_headers, ranges, 3); + + if (expected_return_ranges == 1) { + do_single_range (session, msg, + MIN (first_start, MIN (second_start, third_start)), + MAX (first_end, MAX (second_end, third_end)), + TRUE); + } else + do_multi_range (session, msg, expected_return_ranges); +} + +static void +request_semi_invalid_range (SoupSession *session, const char *uri, + int first_good_start, int first_good_end, + int bad_start, int bad_end, + int second_good_start, int second_good_end) +{ + SoupMessage *msg; + SoupRange ranges[3]; + + msg = soup_message_new ("GET", uri); + ranges[0].start = first_good_start; + ranges[0].end = first_good_end; + ranges[1].start = bad_start; + ranges[1].end = bad_end; + ranges[2].start = second_good_start; + ranges[2].end = second_good_end; + soup_message_headers_set_ranges (msg->request_headers, ranges, 3); + + do_multi_range (session, msg, 2); +} + +static void +do_range_test (SoupSession *session, const char *uri, + gboolean expect_coalesce, gboolean expect_partial_coalesce) +{ + int twelfths = full_response->length / 12; + + memset (test_response, 0, full_response->length); + + /* We divide the response into 12 ranges and request them + * as follows: + * + * 0: A (first single request) + * 1: D (2nd part of triple request) + * 2: C (1st part of double request) + * 3: D (1st part of triple request) + * 4: F (trickier overlapping request) + * 5: C (2nd part of double request) + * 6: D (3rd part of triple request) + * 7: E (overlapping request) + * 8: E (overlapping request) + * 9: F (trickier overlapping request) + * 10: F (trickier overlapping request) + * 11: B (second and third single requests) + */ + + /* A: 0, simple request */ + debug_printf (1, "Requesting %d-%d\n", 0 * twelfths, 1 * twelfths); + request_single_range (session, uri, + 0 * twelfths, 1 * twelfths, + TRUE); + + /* B: 11, end-relative request. These two are mostly redundant + * in terms of data coverage, but they may still catch + * Range-header-generating bugs. + */ + debug_printf (1, "Requesting %d-\n", 11 * twelfths); + request_single_range (session, uri, + 11 * twelfths, -1, + TRUE); + debug_printf (1, "Requesting -%d\n", 1 * twelfths); + request_single_range (session, uri, + -1 * twelfths, -1, + TRUE); + + /* C: 2 and 5 */ + debug_printf (1, "Requesting %d-%d,%d-%d\n", + 2 * twelfths, 3 * twelfths, + 5 * twelfths, 6 * twelfths); + request_double_range (session, uri, + 2 * twelfths, 3 * twelfths, + 5 * twelfths, 6 * twelfths, + 2); + + /* D: 1, 3, 6 */ + debug_printf (1, "Requesting %d-%d,%d-%d,%d-%d\n", + 3 * twelfths, 4 * twelfths, + 1 * twelfths, 2 * twelfths, + 6 * twelfths, 7 * twelfths); + request_triple_range (session, uri, + 3 * twelfths, 4 * twelfths, + 1 * twelfths, 2 * twelfths, + 6 * twelfths, 7 * twelfths, + 3); + + /* E: 7 and 8: should coalesce into a single response */ + debug_printf (1, "Requesting %d-%d,%d-%d (can coalesce)\n", + 7 * twelfths, 8 * twelfths, + 8 * twelfths, 9 * twelfths); + request_double_range (session, uri, + 7 * twelfths, 8 * twelfths, + 8 * twelfths, 9 * twelfths, + expect_coalesce ? 1 : 2); + + /* F: 4, 9, 10: 9 and 10 should coalesce even though 4 was + * requested between them. (Also, they actually overlap in + * this case, as opposed to just touching.) + */ + debug_printf (1, "Requesting %d-%d,%d-%d,%d-%d (can partially coalesce)\n", + 9 * twelfths, 10 * twelfths + 5, + 4 * twelfths, 5 * twelfths, + 10 * twelfths - 5, 11 * twelfths); + request_triple_range (session, uri, + 9 * twelfths, 10 * twelfths + 5, + 4 * twelfths, 5 * twelfths, + 10 * twelfths - 5, 11 * twelfths, + expect_partial_coalesce ? 2 : 3); + + soup_assert_cmpmem (full_response->data, full_response->length, + test_response, full_response->length); + + debug_printf (1, "Requesting (invalid) %d-%d\n", + (int) full_response->length + 1, + (int) full_response->length + 100); + request_single_range (session, uri, + full_response->length + 1, full_response->length + 100, + FALSE); + + debug_printf (1, "Requesting (semi-invalid) 1-10,%d-%d,20-30\n", + (int) full_response->length + 1, + (int) full_response->length + 100); + request_semi_invalid_range (session, uri, + 1, 10, + full_response->length + 1, full_response->length + 100, + 20, 30); +} + +static void +do_apache_range_test (void) +{ + SoupSession *session; + + SOUP_TEST_SKIP_IF_NO_APACHE; + + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + + do_range_test (session, "http://127.0.0.1:47524/", TRUE, FALSE); + + soup_test_session_abort_unref (session); +} + +static void +server_handler (SoupServer *server, + SoupMessage *msg, + const char *path, + GHashTable *query, + SoupClientContext *client, + gpointer user_data) +{ + soup_message_set_status (msg, SOUP_STATUS_OK); + soup_message_body_append_buffer (msg->response_body, + full_response); +} + +static void +do_libsoup_range_test (void) +{ + SoupSession *session; + SoupServer *server; + SoupURI *base_uri; + char *base_uri_str; + + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + + server = soup_test_server_new (SOUP_TEST_SERVER_DEFAULT); + soup_server_add_handler (server, NULL, server_handler, NULL, NULL); + base_uri = soup_test_server_get_uri (server, "http", NULL); + base_uri_str = soup_uri_to_string (base_uri, FALSE); + do_range_test (session, base_uri_str, TRUE, TRUE); + soup_uri_free (base_uri); + g_free (base_uri_str); + soup_test_server_quit_unref (server); + + soup_test_session_abort_unref (session); +} + +int +main (int argc, char **argv) +{ + int ret; + + test_init (argc, argv, NULL); + apache_init (); + + full_response = soup_test_get_index (); + test_response = g_malloc0 (full_response->length); + + g_test_add_func ("/ranges/apache", do_apache_range_test); + g_test_add_func ("/ranges/libsoup", do_libsoup_range_test); + + ret = g_test_run (); + + g_free (test_response); + + test_cleanup (); + return ret; +} diff --git a/tests/redirect-test.c b/tests/redirect-test.c new file mode 100644 index 0000000..ccdd4c2 --- /dev/null +++ b/tests/redirect-test.c @@ -0,0 +1,463 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2008 Red Hat, Inc. + */ + +#include "test-utils.h" + +SoupURI *base_uri; +char *server2_uri; +SoupSession *async_session, *sync_session; + +typedef struct { + const char *method; + const char *path; + guint status_code; + gboolean repeat; +} TestRequest; + +typedef struct { + TestRequest requests[3]; + guint final_status; + const char *bugref; +} TestCase; + +static TestCase tests[] = { + /* A redirecty response to a GET or HEAD should cause a redirect */ + + { { { "GET", "/301", 301 }, + { "GET", "/", 200 }, + { NULL } }, 200, NULL }, + { { { "GET", "/302", 302 }, + { "GET", "/", 200 }, + { NULL } }, 200, NULL }, + { { { "GET", "/303", 303 }, + { "GET", "/", 200 }, + { NULL } }, 200, NULL }, + { { { "GET", "/307", 307 }, + { "GET", "/", 200 }, + { NULL } }, 200, NULL }, + { { { "HEAD", "/301", 301 }, + { "HEAD", "/", 200 }, + { NULL } }, 200, "551190" }, + { { { "HEAD", "/302", 302 }, + { "HEAD", "/", 200 }, + { NULL } }, 200, "551190" }, + /* 303 is a nonsensical response to HEAD, but some sites do + * it anyway. :-/ + */ + { { { "HEAD", "/303", 303 }, + { "HEAD", "/", 200 }, + { NULL } }, 200, "600830" }, + { { { "HEAD", "/307", 307 }, + { "HEAD", "/", 200 }, + { NULL } }, 200, "551190" }, + + /* A non-redirecty response to a GET or HEAD should not */ + + { { { "GET", "/300", 300 }, + { NULL } }, 300, NULL }, + { { { "GET", "/304", 304 }, + { NULL } }, 304, NULL }, + { { { "GET", "/305", 305 }, + { NULL } }, 305, NULL }, + { { { "GET", "/306", 306 }, + { NULL } }, 306, NULL }, + { { { "GET", "/308", 308 }, + { NULL } }, 308, NULL }, + { { { "HEAD", "/300", 300 }, + { NULL } }, 300, "551190" }, + { { { "HEAD", "/304", 304 }, + { NULL } }, 304, "551190" }, + { { { "HEAD", "/305", 305 }, + { NULL } }, 305, "551190" }, + { { { "HEAD", "/306", 306 }, + { NULL } }, 306, "551190" }, + { { { "HEAD", "/308", 308 }, + { NULL } }, 308, "551190" }, + + /* Test double-redirect */ + + { { { "GET", "/301/302", 301 }, + { "GET", "/302", 302 }, + { "GET", "/", 200 } }, 200, NULL }, + { { { "HEAD", "/301/302", 301 }, + { "HEAD", "/302", 302 }, + { "HEAD", "/", 200 } }, 200, "551190" }, + + /* POST should only automatically redirect on 301, 302 and 303 */ + + { { { "POST", "/301", 301 }, + { "GET", "/", 200 }, + { NULL } }, 200, "586692" }, + { { { "POST", "/302", 302 }, + { "GET", "/", 200 }, + { NULL } }, 200, NULL }, + { { { "POST", "/303", 303 }, + { "GET", "/", 200 }, + { NULL } }, 200, NULL }, + { { { "POST", "/307", 307 }, + { NULL } }, 307, NULL }, + + /* Test behavior with recoverably-bad Location header */ + { { { "GET", "/bad", 302 }, + { "GET", "/bad%20with%20spaces", 200 }, + { NULL } }, 200, "566530" }, + + /* Test behavior with irrecoverably-bad Location header */ + { { { "GET", "/bad-no-host", 302 }, + { NULL } }, SOUP_STATUS_MALFORMED, "528882" }, + + /* Test infinite redirection */ + { { { "GET", "/bad-recursive", 302, TRUE }, + { NULL } }, SOUP_STATUS_TOO_MANY_REDIRECTS, "604383" }, + + /* Test redirection to a different server */ + { { { "GET", "/server2", 302 }, + { "GET", "/on-server2", 200 }, + { NULL } }, 200, NULL }, +}; +static const int n_tests = G_N_ELEMENTS (tests); + +static void +got_headers (SoupMessage *msg, gpointer user_data) +{ + TestRequest **treq = user_data; + const char *location; + + debug_printf (2, " -> %d %s\n", msg->status_code, + msg->reason_phrase); + location = soup_message_headers_get_one (msg->response_headers, + "Location"); + if (location) + debug_printf (2, " Location: %s\n", location); + + if (!(*treq)->method) + return; + + soup_test_assert_message_status (msg, (*treq)->status_code); +} + +static void +restarted (SoupMessage *msg, gpointer user_data) +{ + TestRequest **treq = user_data; + SoupURI *uri = soup_message_get_uri (msg); + + debug_printf (2, " %s %s\n", msg->method, uri->path); + + if ((*treq)->method && !(*treq)->repeat) + (*treq)++; + + soup_test_assert ((*treq)->method, + "Expected to be done"); + + g_assert_cmpstr (msg->method, ==, (*treq)->method); + g_assert_cmpstr (uri->path, ==, (*treq)->path); +} + +static void +do_message_api_test (SoupSession *session, TestCase *test) +{ + SoupURI *uri; + SoupMessage *msg; + TestRequest *treq; + + if (test->bugref) + g_test_bug (test->bugref); + + uri = soup_uri_new_with_base (base_uri, test->requests[0].path); + msg = soup_message_new_from_uri (test->requests[0].method, uri); + soup_uri_free (uri); + + if (msg->method == SOUP_METHOD_POST) { + soup_message_set_request (msg, "text/plain", + SOUP_MEMORY_STATIC, + "post body", + strlen ("post body")); + } + + treq = &test->requests[0]; + g_signal_connect (msg, "got_headers", + G_CALLBACK (got_headers), &treq); + g_signal_connect (msg, "restarted", + G_CALLBACK (restarted), &treq); + + soup_session_send_message (session, msg); + + soup_test_assert_message_status (msg, test->final_status); + + g_object_unref (msg); +} + +static void +do_request_api_test (SoupSession *session, TestCase *test) +{ + SoupURI *uri; + SoupRequestHTTP *reqh; + SoupMessage *msg; + TestRequest *treq; + GInputStream *stream; + GError *error = NULL; + + if (test->bugref) + g_test_bug (test->bugref); + + uri = soup_uri_new_with_base (base_uri, test->requests[0].path); + reqh = soup_session_request_http_uri (session, + test->requests[0].method, + uri, &error); + soup_uri_free (uri); + g_assert_no_error (error); + if (error) { + g_error_free (error); + return; + } + + msg = soup_request_http_get_message (reqh); + if (msg->method == SOUP_METHOD_POST) { + soup_message_set_request (msg, "text/plain", + SOUP_MEMORY_STATIC, + "post body", + strlen ("post body")); + } + + treq = &test->requests[0]; + g_signal_connect (msg, "got_headers", + G_CALLBACK (got_headers), &treq); + g_signal_connect (msg, "restarted", + G_CALLBACK (restarted), &treq); + + stream = soup_test_request_send (SOUP_REQUEST (reqh), NULL, 0, &error); + + if (SOUP_STATUS_IS_TRANSPORT_ERROR (test->final_status) && + test->final_status != SOUP_STATUS_MALFORMED) { + g_assert_error (error, SOUP_HTTP_ERROR, test->final_status); + g_clear_error (&error); + + g_assert_null (stream); + g_clear_object (&stream); + + g_object_unref (msg); + g_object_unref (reqh); + return; + } + + g_assert_no_error (error); + if (error) { + g_error_free (error); + g_object_unref (msg); + g_object_unref (reqh); + return; + } + + soup_test_request_read_all (SOUP_REQUEST (reqh), stream, NULL, &error); + g_assert_no_error (error); + g_clear_error (&error); + + soup_test_request_close_stream (SOUP_REQUEST (reqh), stream, NULL, &error); + g_assert_no_error (error); + g_clear_error (&error); + g_object_unref (stream); + + if (test->final_status == SOUP_STATUS_MALFORMED) + g_assert_cmpint (msg->status_code, ==, test->requests[0].status_code); + else + g_assert_cmpint (msg->status_code, ==, test->final_status); + + g_object_unref (msg); + g_object_unref (reqh); +} + +static void +do_async_msg_api_test (gconstpointer test) +{ + do_message_api_test (async_session, (TestCase *)test); +} + +static void +do_async_req_api_test (gconstpointer test) +{ + do_request_api_test (async_session, (TestCase *)test); +} + +static void +do_sync_msg_api_test (gconstpointer test) +{ + do_message_api_test (sync_session, (TestCase *)test); +} + +static void +do_sync_req_api_test (gconstpointer test) +{ + do_request_api_test (sync_session, (TestCase *)test); +} + +static void +server_callback (SoupServer *server, SoupMessage *msg, + const char *path, GHashTable *query, + SoupClientContext *context, gpointer data) +{ + char *remainder; + guint status_code; + + /* Make sure that a HTTP/1.0 redirect doesn't cause an + * HTTP/1.0 re-request. (#521848) + */ + if (soup_message_get_http_version (msg) == SOUP_HTTP_1_0) { + soup_message_set_status (msg, SOUP_STATUS_BAD_REQUEST); + return; + } + + if (g_str_has_prefix (path, "/bad")) { + if (!strcmp (path, "/bad")) { + soup_message_set_status (msg, SOUP_STATUS_FOUND); + soup_message_headers_replace (msg->response_headers, + "Location", + "/bad with spaces"); + } else if (!strcmp (path, "/bad-recursive")) { + soup_message_set_status (msg, SOUP_STATUS_FOUND); + soup_message_headers_replace (msg->response_headers, + "Location", + "/bad-recursive"); + } else if (!strcmp (path, "/bad-no-host")) { + soup_message_set_status (msg, SOUP_STATUS_FOUND); + soup_message_headers_replace (msg->response_headers, + "Location", + "about:blank"); + } else if (!strcmp (path, "/bad with spaces")) + soup_message_set_status (msg, SOUP_STATUS_OK); + else + soup_message_set_status (msg, SOUP_STATUS_NOT_FOUND); + return; + } else if (!strcmp (path, "/server2")) { + soup_message_set_status (msg, SOUP_STATUS_FOUND); + soup_message_headers_replace (msg->response_headers, + "Location", + server2_uri); + return; + } else if (!strcmp (path, "/")) { + if (msg->method != SOUP_METHOD_GET && + msg->method != SOUP_METHOD_HEAD) { + soup_message_set_status (msg, SOUP_STATUS_METHOD_NOT_ALLOWED); + return; + } + + /* Make sure that redirecting a POST clears the body */ + if (msg->request_body->length) { + soup_message_set_status (msg, SOUP_STATUS_BAD_REQUEST); + return; + } + + soup_message_set_status (msg, SOUP_STATUS_OK); + + /* FIXME: this is wrong, though it doesn't matter for + * the purposes of this test, and to do the right + * thing currently we'd have to set Content-Length by + * hand. + */ + if (msg->method != SOUP_METHOD_HEAD) { + soup_message_set_response (msg, "text/plain", + SOUP_MEMORY_STATIC, + "OK\r\n", 4); + } + return; + } + + status_code = strtoul (path + 1, &remainder, 10); + if (!SOUP_STATUS_IS_REDIRECTION (status_code) || + (*remainder && *remainder != '/')) { + soup_message_set_status (msg, SOUP_STATUS_NOT_FOUND); + return; + } + + /* See above comment re bug 521848. We only test this on the + * double-redirects so that we get connection-reuse testing + * the rest of the time. + */ + if (*remainder == '/') + soup_message_set_http_version (msg, SOUP_HTTP_1_0); + + soup_message_set_redirect (msg, status_code, + *remainder ? remainder : "/"); +} + +static void +server2_callback (SoupServer *server, SoupMessage *msg, + const char *path, GHashTable *query, + SoupClientContext *context, gpointer data) +{ + soup_message_set_status (msg, SOUP_STATUS_OK); +} + +int +main (int argc, char **argv) +{ + GMainLoop *loop; + SoupServer *server, *server2; + SoupURI *uri2; + char *path; + int n, ret; + + test_init (argc, argv, NULL); + + server = soup_test_server_new (SOUP_TEST_SERVER_IN_THREAD); + soup_server_add_handler (server, NULL, + server_callback, NULL, NULL); + base_uri = soup_test_server_get_uri (server, "http", NULL); + + server2 = soup_test_server_new (SOUP_TEST_SERVER_IN_THREAD); + soup_server_add_handler (server2, NULL, + server2_callback, NULL, NULL); + uri2 = soup_test_server_get_uri (server2, "http", NULL); + soup_uri_set_path (uri2, "/on-server2"); + server2_uri = soup_uri_to_string (uri2, FALSE); + soup_uri_free (uri2); + + loop = g_main_loop_new (NULL, TRUE); + + async_session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, + SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, + NULL); + sync_session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL); + + for (n = 0; n < n_tests; n++) { + path = g_strdup_printf ("/redirect/async/msg/%d-%s-%d", n, + tests[n].requests[0].method, + tests[n].requests[0].status_code); + g_test_add_data_func (path, &tests[n], do_async_msg_api_test); + g_free (path); + + path = g_strdup_printf ("/redirect/async/req/%d-%s-%d", n, + tests[n].requests[0].method, + tests[n].requests[0].status_code); + g_test_add_data_func (path, &tests[n], do_async_req_api_test); + g_free (path); + + path = g_strdup_printf ("/redirect/sync/msg/%d-%s-%d", n, + tests[n].requests[0].method, + tests[n].requests[0].status_code); + g_test_add_data_func (path, &tests[n], do_sync_msg_api_test); + g_free (path); + + path = g_strdup_printf ("/redirect/sync/req/%d-%s-%d", n, + tests[n].requests[0].method, + tests[n].requests[0].status_code); + g_test_add_data_func (path, &tests[n], do_sync_req_api_test); + g_free (path); + } + + ret = g_test_run (); + + g_main_loop_unref (loop); + soup_uri_free (base_uri); + soup_test_server_quit_unref (server); + g_free (server2_uri); + soup_test_server_quit_unref (server2); + + soup_test_session_abort_unref (async_session); + soup_test_session_abort_unref (sync_session); + + test_cleanup (); + return ret; +} diff --git a/tests/requester-test.c b/tests/requester-test.c new file mode 100644 index 0000000..6d6d572 --- /dev/null +++ b/tests/requester-test.c @@ -0,0 +1,887 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2011 Red Hat, Inc. + */ + +/* Kill SoupRequester-related deprecation warnings */ +#define SOUP_VERSION_MIN_REQUIRED SOUP_VERSION_2_40 + +#include "test-utils.h" + +SoupServer *server; +GMainLoop *loop; +char buf[1024]; + +SoupBuffer *response, *auth_response; + +#define REDIRECT_HTML_BODY "Try again\r\n" +#define AUTH_HTML_BODY "Unauthorized\r\n" + +typedef enum { + NO_CANCEL, + SYNC_CANCEL, + PAUSE_AND_CANCEL_ON_IDLE +} CancelPolicy; + +static gboolean +slow_finish_message (gpointer msg) +{ + SoupServer *server = g_object_get_data (G_OBJECT (msg), "server"); + + soup_server_unpause_message (server, msg); + return FALSE; +} + +static void +slow_pause_message (SoupMessage *msg, gpointer server) +{ + soup_server_pause_message (server, msg); + soup_add_timeout (soup_server_get_async_context (server), + 1000, slow_finish_message, msg); +} + +static void +server_callback (SoupServer *server, SoupMessage *msg, + const char *path, GHashTable *query, + SoupClientContext *context, gpointer data) +{ + gboolean chunked = FALSE; + int i; + + if (strcmp (path, "/auth") == 0) { + soup_message_set_status (msg, SOUP_STATUS_UNAUTHORIZED); + soup_message_set_response (msg, "text/html", + SOUP_MEMORY_STATIC, + AUTH_HTML_BODY, + strlen (AUTH_HTML_BODY)); + soup_message_headers_append (msg->response_headers, + "WWW-Authenticate", + "Basic: realm=\"requester-test\""); + return; + } else if (strcmp (path, "/foo") == 0) { + soup_message_set_redirect (msg, SOUP_STATUS_FOUND, "/"); + /* Make the response HTML so if we sniff that instead of the + * real body, we'll notice. + */ + soup_message_set_response (msg, "text/html", + SOUP_MEMORY_STATIC, + REDIRECT_HTML_BODY, + strlen (REDIRECT_HTML_BODY)); + return; + } else if (strcmp (path, "/chunked") == 0) { + chunked = TRUE; + } else if (strcmp (path, "/non-persistent") == 0) { + soup_message_headers_append (msg->response_headers, + "Connection", "close"); + } else if (!strcmp (path, "/slow")) { + g_object_set_data (G_OBJECT (msg), "server", server); + g_signal_connect (msg, "wrote-headers", + G_CALLBACK (slow_pause_message), server); + } + + soup_message_set_status (msg, SOUP_STATUS_OK); + + if (chunked) { + soup_message_headers_set_encoding (msg->response_headers, + SOUP_ENCODING_CHUNKED); + + for (i = 0; i < response->length; i += 8192) { + SoupBuffer *tmp; + + tmp = soup_buffer_new_subbuffer (response, i, + MIN (8192, response->length - i)); + soup_message_body_append_buffer (msg->response_body, tmp); + soup_buffer_free (tmp); + } + soup_message_body_complete (msg->response_body); + } else + soup_message_body_append_buffer (msg->response_body, response); +} + +typedef struct { + GString *body; + gboolean cancel; +} RequestData; + +static void +stream_closed (GObject *source, GAsyncResult *res, gpointer user_data) +{ + GInputStream *stream = G_INPUT_STREAM (source); + GError *error = NULL; + + g_input_stream_close_finish (stream, res, &error); + g_assert_no_error (error); + g_main_loop_quit (loop); + g_object_unref (stream); +} + +static void +test_read_ready (GObject *source, GAsyncResult *res, gpointer user_data) +{ + GInputStream *stream = G_INPUT_STREAM (source); + RequestData *data = user_data; + GString *body = data->body; + GError *error = NULL; + gsize nread; + + nread = g_input_stream_read_finish (stream, res, &error); + if (nread == -1) { + g_assert_no_error (error); + g_error_free (error); + g_input_stream_close (stream, NULL, NULL); + g_object_unref (stream); + g_main_loop_quit (loop); + return; + } else if (nread == 0) { + g_input_stream_close_async (stream, + G_PRIORITY_DEFAULT, NULL, + stream_closed, NULL); + return; + } + + g_string_append_len (body, buf, nread); + g_input_stream_read_async (stream, buf, sizeof (buf), + G_PRIORITY_DEFAULT, NULL, + test_read_ready, data); +} + +static void +auth_test_sent (GObject *source, GAsyncResult *res, gpointer user_data) +{ + RequestData *data = user_data; + GInputStream *stream; + GError *error = NULL; + SoupMessage *msg; + const char *content_type; + + stream = soup_request_send_finish (SOUP_REQUEST (source), res, &error); + if (!stream) { + g_assert_no_error (error); + g_clear_error (&error); + g_main_loop_quit (loop); + return; + } + + msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (source)); + soup_test_assert_message_status (msg, SOUP_STATUS_UNAUTHORIZED); + g_object_unref (msg); + + content_type = soup_request_get_content_type (SOUP_REQUEST (source)); + g_assert_cmpstr (content_type, ==, "text/html"); + + g_input_stream_read_async (stream, buf, sizeof (buf), + G_PRIORITY_DEFAULT, NULL, + test_read_ready, data); +} + +static void +test_sent (GObject *source, GAsyncResult *res, gpointer user_data) +{ + RequestData *data = user_data; + GInputStream *stream; + GError *error = NULL; + const char *content_type; + + stream = soup_request_send_finish (SOUP_REQUEST (source), res, &error); + if (data->cancel) { + g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED); + g_clear_error (&error); + g_main_loop_quit (loop); + return; + } else { + g_assert_no_error (error); + if (!stream) { + g_main_loop_quit (loop); + g_clear_error (&error); + return; + } + } + + content_type = soup_request_get_content_type (SOUP_REQUEST (source)); + g_assert_cmpstr (content_type, ==, "text/plain"); + + g_input_stream_read_async (stream, buf, sizeof (buf), + G_PRIORITY_DEFAULT, NULL, + test_read_ready, data); +} + +static void +cancel_message (SoupMessage *msg, gpointer session) +{ + soup_session_cancel_message (session, msg, SOUP_STATUS_FORBIDDEN); +} + +typedef struct { + SoupMessage *msg; + SoupSession *session; +} CancelData; + +static gboolean +cancel_message_idle (CancelData *data) +{ + cancel_message (data->msg, data->session); + return FALSE; +} + +static void +pause_and_cancel_message (SoupMessage *msg, gpointer session) +{ + CancelData *data = g_new (CancelData, 1); + GSource *source = g_idle_source_new (); + + soup_session_pause_message (session, msg); + data->msg = msg; + data->session = session; + g_source_set_callback (source, (GSourceFunc)cancel_message_idle, data, g_free); + g_source_attach (source, soup_session_get_async_context (session)); + g_source_unref (source); +} + +static void +request_started (SoupSession *session, SoupMessage *msg, + SoupSocket *socket, gpointer user_data) +{ + SoupSocket **save_socket = user_data; + + g_clear_object (save_socket); + *save_socket = g_object_ref (socket); +} + +static void +do_async_test (SoupSession *session, SoupURI *uri, + GAsyncReadyCallback callback, guint expected_status, + SoupBuffer *expected_response, + gboolean persistent, CancelPolicy cancel_policy) +{ + SoupRequester *requester; + SoupRequest *request; + guint started_id; + SoupSocket *socket = NULL; + SoupMessage *msg; + RequestData data; + + if (SOUP_IS_SESSION_ASYNC (session)) + requester = SOUP_REQUESTER (soup_session_get_feature (session, SOUP_TYPE_REQUESTER)); + else + requester = NULL; + + data.body = g_string_new (NULL); + data.cancel = cancel_policy != NO_CANCEL; + if (requester) + request = soup_requester_request_uri (requester, uri, NULL); + else + request = soup_session_request_uri (session, uri, NULL); + msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (request)); + + switch (cancel_policy) { + case SYNC_CANCEL: + g_signal_connect (msg, "got-headers", + G_CALLBACK (cancel_message), session); + break; + case PAUSE_AND_CANCEL_ON_IDLE: + g_signal_connect (msg, "got-headers", + G_CALLBACK (pause_and_cancel_message), session); + break; + case NO_CANCEL: + break; + } + + started_id = g_signal_connect (session, "request-started", + G_CALLBACK (request_started), + &socket); + + soup_request_send_async (request, NULL, callback, &data); + g_object_unref (request); + + loop = g_main_loop_new (soup_session_get_async_context (session), TRUE); + g_main_loop_run (loop); + g_main_loop_unref (loop); + + g_signal_handler_disconnect (session, started_id); + + soup_test_assert_message_status (msg, expected_status); + g_object_unref (msg); + + if (expected_response) { + soup_assert_cmpmem (data.body->str, data.body->len, + expected_response->data, expected_response->length); + } else + g_assert_cmpint (data.body->len, ==, 0); + + if (persistent) + g_assert_true (soup_socket_is_connected (socket)); + else + g_assert_false (soup_socket_is_connected (socket)); + + g_object_unref (socket); + + g_string_free (data.body, TRUE); +} + +static void +do_test_for_thread_and_context (SoupSession *session, SoupURI *base_uri) +{ + SoupRequester *requester; + SoupURI *uri; + + if (SOUP_IS_SESSION_ASYNC (session)) { + requester = soup_requester_new (); + soup_session_add_feature (session, SOUP_SESSION_FEATURE (requester)); + g_object_unref (requester); + } + soup_session_add_feature_by_type (session, SOUP_TYPE_CONTENT_SNIFFER); + + debug_printf (1, " basic test\n"); + do_async_test (session, base_uri, test_sent, + SOUP_STATUS_OK, response, + TRUE, NO_CANCEL); + + debug_printf (1, " chunked test\n"); + uri = soup_uri_new_with_base (base_uri, "/chunked"); + do_async_test (session, uri, test_sent, + SOUP_STATUS_OK, response, + TRUE, NO_CANCEL); + soup_uri_free (uri); + + debug_printf (1, " auth test\n"); + uri = soup_uri_new_with_base (base_uri, "/auth"); + do_async_test (session, uri, auth_test_sent, + SOUP_STATUS_UNAUTHORIZED, auth_response, + TRUE, NO_CANCEL); + soup_uri_free (uri); + + debug_printf (1, " non-persistent test\n"); + uri = soup_uri_new_with_base (base_uri, "/non-persistent"); + do_async_test (session, uri, test_sent, + SOUP_STATUS_OK, response, + FALSE, NO_CANCEL); + soup_uri_free (uri); + + debug_printf (1, " cancellation test\n"); + uri = soup_uri_new_with_base (base_uri, "/"); + do_async_test (session, uri, test_sent, + SOUP_STATUS_FORBIDDEN, NULL, + FALSE, SYNC_CANCEL); + soup_uri_free (uri); + + debug_printf (1, " cancellation after paused test\n"); + uri = soup_uri_new_with_base (base_uri, "/"); + do_async_test (session, uri, test_sent, + SOUP_STATUS_FORBIDDEN, NULL, + FALSE, PAUSE_AND_CANCEL_ON_IDLE); + soup_uri_free (uri); +} + +static void +do_simple_plain_test (gconstpointer data) +{ + SoupURI *uri = (SoupURI *)data; + SoupSession *session; + + g_test_bug ("653707"); + + session = soup_test_session_new (SOUP_TYPE_SESSION, NULL); + do_test_for_thread_and_context (session, uri); + soup_test_session_abort_unref (session); +} + +static void +do_simple_async_test (gconstpointer data) +{ + SoupURI *uri = (SoupURI *)data; + SoupSession *session; + + g_test_bug ("653707"); + + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, + SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, + NULL); + do_test_for_thread_and_context (session, uri); + soup_test_session_abort_unref (session); +} + +static void +do_test_with_context_and_type (SoupURI *uri, gboolean plain_session) +{ + GMainContext *async_context; + SoupSession *session; + + g_test_bug ("653707"); + + async_context = g_main_context_new (); + g_main_context_push_thread_default (async_context); + + session = soup_test_session_new (plain_session ? SOUP_TYPE_SESSION : SOUP_TYPE_SESSION_ASYNC, + SOUP_SESSION_ASYNC_CONTEXT, async_context, + SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, + NULL); + + do_test_for_thread_and_context (session, uri); + soup_test_session_abort_unref (session); + + g_main_context_pop_thread_default (async_context); + g_main_context_unref (async_context); +} + +static void +do_async_test_with_context (gconstpointer data) +{ + SoupURI *uri = (SoupURI *)data; + + do_test_with_context_and_type (uri, FALSE); +} + +static void +do_plain_test_with_context (gconstpointer data) +{ + SoupURI *uri = (SoupURI *)data; + + do_test_with_context_and_type (uri, TRUE); +} + +static gpointer +async_test_thread (gpointer uri) +{ + do_test_with_context_and_type (uri, TRUE); + return NULL; +} + +static gpointer +plain_test_thread (gpointer uri) +{ + do_test_with_context_and_type (uri, FALSE); + return NULL; +} + +static void +do_async_test_in_thread (gconstpointer data) +{ + SoupURI *uri = (SoupURI *)data; + GThread *thread; + + thread = g_thread_new ("do_async_test_in_thread", + async_test_thread, + (gpointer)uri); + g_thread_join (thread); +} + +static void +do_plain_test_in_thread (gconstpointer data) +{ + SoupURI *uri = (SoupURI *)data; + GThread *thread; + + thread = g_thread_new ("do_plain_test_in_thread", + plain_test_thread, + (gpointer)uri); + g_thread_join (thread); +} + +static void +do_sync_request (SoupSession *session, SoupRequest *request, + guint expected_status, SoupBuffer *expected_response, + gboolean persistent, CancelPolicy cancel_policy) +{ + GInputStream *in; + SoupMessage *msg; + GError *error = NULL; + GString *body; + char buf[1024]; + gssize nread; + guint started_id; + SoupSocket *socket = NULL; + + msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (request)); + if (cancel_policy == SYNC_CANCEL) { + g_signal_connect (msg, "got-headers", + G_CALLBACK (cancel_message), session); + } + + started_id = g_signal_connect (session, "request-started", + G_CALLBACK (request_started), + &socket); + + in = soup_request_send (request, NULL, &error); + g_signal_handler_disconnect (session, started_id); + if (cancel_policy == SYNC_CANCEL) { + g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED); + g_clear_error (&error); + g_object_unref (msg); + g_object_unref (socket); + return; + } else if (!in) { + g_assert_no_error (error); + g_clear_error (&error); + g_object_unref (msg); + g_object_unref (socket); + return; + } + + soup_test_assert_message_status (msg, expected_status); + g_object_unref (msg); + + body = g_string_new (NULL); + do { + nread = g_input_stream_read (in, buf, sizeof (buf), + NULL, &error); + g_assert_no_error (error); + if (nread == -1) { + g_clear_error (&error); + break; + } + g_string_append_len (body, buf, nread); + } while (nread > 0); + + g_input_stream_close (in, NULL, &error); + g_assert_no_error (error); + g_clear_error (&error); + g_object_unref (in); + + if (expected_response) { + soup_assert_cmpmem (body->str, body->len, + expected_response->data, expected_response->length); + } else + g_assert_cmpint (body->len, ==, 0); + + if (persistent) + g_assert_true (soup_socket_is_connected (socket)); + else + g_assert_false (soup_socket_is_connected (socket)); + g_object_unref (socket); + + g_string_free (body, TRUE); +} + +static void +do_sync_tests_for_session (SoupSession *session, SoupURI *base_uri) +{ + SoupRequester *requester; + SoupRequest *request; + SoupURI *uri; + + requester = SOUP_REQUESTER (soup_session_get_feature (session, SOUP_TYPE_REQUESTER)); + + uri = soup_uri_copy (base_uri); + + debug_printf (1, " basic test\n"); + if (requester) + request = soup_requester_request_uri (requester, uri, NULL); + else + request = soup_session_request_uri (session, uri, NULL); + do_sync_request (session, request, + SOUP_STATUS_OK, response, + TRUE, NO_CANCEL); + g_object_unref (request); + + debug_printf (1, " chunked test\n"); + soup_uri_set_path (uri, "/chunked"); + if (requester) + request = soup_requester_request_uri (requester, uri, NULL); + else + request = soup_session_request_uri (session, uri, NULL); + do_sync_request (session, request, + SOUP_STATUS_OK, response, + TRUE, NO_CANCEL); + g_object_unref (request); + + debug_printf (1, " auth test\n"); + soup_uri_set_path (uri, "/auth"); + if (requester) + request = soup_requester_request_uri (requester, uri, NULL); + else + request = soup_session_request_uri (session, uri, NULL); + do_sync_request (session, request, + SOUP_STATUS_UNAUTHORIZED, auth_response, + TRUE, NO_CANCEL); + g_object_unref (request); + + debug_printf (1, " non-persistent test\n"); + soup_uri_set_path (uri, "/non-persistent"); + if (requester) + request = soup_requester_request_uri (requester, uri, NULL); + else + request = soup_session_request_uri (session, uri, NULL); + do_sync_request (session, request, + SOUP_STATUS_OK, response, + FALSE, NO_CANCEL); + g_object_unref (request); + + debug_printf (1, " cancel test\n"); + soup_uri_set_path (uri, "/"); + if (requester) + request = soup_requester_request_uri (requester, uri, NULL); + else + request = soup_session_request_uri (session, uri, NULL); + do_sync_request (session, request, + SOUP_STATUS_FORBIDDEN, NULL, + TRUE, SYNC_CANCEL); + g_object_unref (request); + + soup_uri_free (uri); +} + +static void +do_plain_sync_test (gconstpointer data) +{ + SoupURI *uri = (SoupURI *)data; + SoupSession *session; + + session = soup_test_session_new (SOUP_TYPE_SESSION, NULL); + do_sync_tests_for_session (session, uri); + soup_test_session_abort_unref (session); +} + +static void +do_sync_sync_test (gconstpointer data) +{ + SoupURI *uri = (SoupURI *)data; + SoupSession *session; + SoupRequester *requester; + + session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL); + requester = soup_requester_new (); + soup_session_add_feature (session, SOUP_SESSION_FEATURE (requester)); + g_object_unref (requester); + do_sync_tests_for_session (session, uri); + soup_test_session_abort_unref (session); +} + +static void +do_null_char_request (SoupSession *session, const char *encoded_data, + const char *expected_data, int expected_len) +{ + GError *error = NULL; + GInputStream *stream; + SoupRequest *request; + SoupURI *uri; + char *uri_string, buf[256]; + gsize nread; + + uri_string = g_strdup_printf ("data:text/html,%s", encoded_data); + uri = soup_uri_new (uri_string); + g_free (uri_string); + + request = soup_session_request_uri (session, uri, NULL); + stream = soup_test_request_send (request, NULL, 0, &error); + g_assert_no_error (error); + if (error) { + g_error_free (error); + g_object_unref (request); + soup_uri_free (uri); + return; + } + + g_input_stream_read_all (stream, buf, sizeof (buf), &nread, NULL, &error); + g_assert_no_error (error); + g_clear_error (&error); + + soup_test_request_close_stream (request, stream, NULL, &error); + g_assert_no_error (error); + g_clear_error (&error); + + soup_assert_cmpmem (buf, nread, expected_data, expected_len); + + g_object_unref (stream); + g_object_unref (request); + soup_uri_free (uri); +} + +static void +do_null_char_test_for_session (SoupSession *session) +{ + static struct { + const char *encoded_data; + const char *expected_data; + int expected_len; + } test_cases[] = { + { "%3Cscript%3Ea%3D'%00'%3C%2Fscript%3E", "", 22 }, + { "%00%3Cscript%3Ea%3D42%3C%2Fscript%3E", "\0", 22 }, + { "%3Cscript%3E%00%3Cbr%2F%3E%3C%2Fscript%3E%00", "\0", 24 }, + }; + static int num_test_cases = G_N_ELEMENTS(test_cases); + int i; + + for (i = 0; i < num_test_cases; i++) { + do_null_char_request (session, test_cases[i].encoded_data, + test_cases[i].expected_data, test_cases[i].expected_len); + } +} + +static void +do_plain_null_char_test (void) +{ + SoupSession *session; + + session = soup_test_session_new (SOUP_TYPE_SESSION, NULL); + do_null_char_test_for_session (session); + soup_test_session_abort_unref (session); +} + +static void +do_async_null_char_test (void) +{ + SoupSession *session; + + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, + SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, + NULL); + do_null_char_test_for_session (session); + soup_test_session_abort_unref (session); +} + +static void +close_test_msg_finished (SoupMessage *msg, + gpointer user_data) +{ + gboolean *finished = user_data; + + *finished = TRUE; +} + +static void +do_close_test_for_session (SoupSession *session, + SoupURI *uri) +{ + GError *error = NULL; + GInputStream *stream; + SoupRequest *request; + guint64 start, end; + GCancellable *cancellable; + SoupMessage *msg; + gboolean finished = FALSE; + + debug_printf (1, " normal close\n"); + + request = soup_session_request_uri (session, uri, NULL); + stream = soup_test_request_send (request, NULL, 0, &error); + g_assert_no_error (error); + if (error) { + g_error_free (error); + g_object_unref (request); + return; + } + + start = g_get_monotonic_time (); + soup_test_request_close_stream (request, stream, NULL, &error); + g_assert_no_error (error); + g_clear_error (&error); + end = g_get_monotonic_time (); + + g_assert_cmpint (end - start, <=, 500000); + + g_object_unref (stream); + g_object_unref (request); + + + debug_printf (1, " error close\n"); + + request = soup_session_request_uri (session, uri, NULL); + msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (request)); + g_signal_connect (msg, "finished", G_CALLBACK (close_test_msg_finished), &finished); + g_object_unref (msg); + + stream = soup_test_request_send (request, NULL, 0, &error); + g_assert_no_error (error); + if (error) { + g_error_free (error); + g_object_unref (request); + return; + } + + cancellable = g_cancellable_new (); + g_cancellable_cancel (cancellable); + soup_test_request_close_stream (request, stream, cancellable, &error); + if (error) + g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED); + g_clear_error (&error); + g_object_unref (cancellable); + + g_assert_true (finished); + + g_object_unref (stream); + g_object_unref (request); +} + +static void +do_async_close_test (gconstpointer data) +{ + SoupURI *uri = (SoupURI *)data; + SoupSession *session; + SoupURI *slow_uri; + + g_test_bug ("695652"); + g_test_bug ("711260"); + + slow_uri = soup_uri_new_with_base ((SoupURI *)uri, "/slow"); + + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, + SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, + NULL); + do_close_test_for_session (session, slow_uri); + soup_test_session_abort_unref (session); + + soup_uri_free (slow_uri); +} + +static void +do_sync_close_test (gconstpointer data) +{ + SoupURI *uri = (SoupURI *)data; + SoupSession *session; + SoupURI *slow_uri; + + g_test_bug ("695652"); + g_test_bug ("711260"); + + slow_uri = soup_uri_new_with_base ((SoupURI *)uri, "/slow"); + + session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, + SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, + NULL); + do_close_test_for_session (session, slow_uri); + soup_test_session_abort_unref (session); + + soup_uri_free (slow_uri); +} + +int +main (int argc, char **argv) +{ + SoupURI *uri; + int ret; + + test_init (argc, argv, NULL); + + response = soup_test_get_index (); + auth_response = soup_buffer_new (SOUP_MEMORY_STATIC, + AUTH_HTML_BODY, + strlen (AUTH_HTML_BODY)); + + server = soup_test_server_new (SOUP_TEST_SERVER_IN_THREAD); + soup_server_add_handler (server, NULL, server_callback, NULL, NULL); + + uri = soup_test_server_get_uri (server, "http", NULL); + soup_uri_set_path (uri, "/foo"); + + g_test_add_data_func ("/requester/simple/SoupSession", uri, do_simple_plain_test); + g_test_add_data_func ("/requester/simple/SoupSessionAsync", uri, do_simple_async_test); + g_test_add_data_func ("/requester/threaded/SoupSession", uri, do_plain_test_in_thread); + g_test_add_data_func ("/requester/threaded/SoupSessionAsync", uri, do_async_test_in_thread); + g_test_add_data_func ("/requester/context/SoupSession", uri, do_plain_test_with_context); + g_test_add_data_func ("/requester/context/SoupSessionAsync", uri, do_async_test_with_context); + g_test_add_data_func ("/requester/sync/SoupSession", uri, do_plain_sync_test); + g_test_add_data_func ("/requester/sync/SoupSessionSync", uri, do_sync_sync_test); + g_test_add_func ("/requester/null-char/SoupSession", do_plain_null_char_test); + g_test_add_func ("/requester/null-char/SoupSessionAsync", do_async_null_char_test); + g_test_add_data_func ("/requester/close/SoupSessionAsync", uri, do_async_close_test); + g_test_add_data_func ("/requester/close/SoupSessionSync", uri, do_sync_close_test); + + ret = g_test_run (); + + soup_uri_free (uri); + soup_buffer_free (auth_response); + soup_test_server_quit_unref (server); + + test_cleanup (); + return ret; +} diff --git a/tests/resource-test.c b/tests/resource-test.c new file mode 100644 index 0000000..6fcb899 --- /dev/null +++ b/tests/resource-test.c @@ -0,0 +1,220 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2012 Igalia S.L. + */ + +#include "test-utils.h" + +SoupBuffer *index_buffer; + +typedef struct { + GString *body; + char buffer[1024]; + GMainLoop *loop; +} AsyncRequestData; + +static void +stream_closed (GObject *source, GAsyncResult *result, gpointer user_data) +{ + GInputStream *in = G_INPUT_STREAM (source); + AsyncRequestData *data = user_data; + GError *error = NULL; + + g_input_stream_close_finish (in, result, &error); + g_assert_no_error (error); + g_main_loop_quit (data->loop); + g_object_unref (in); +} + +static void +test_read_ready (GObject *source, GAsyncResult *result, gpointer user_data) +{ + GInputStream *in = G_INPUT_STREAM (source); + AsyncRequestData *data = user_data; + gssize nread; + GError *error = NULL; + + nread = g_input_stream_read_finish (in, result, &error); + if (nread == -1) { + g_assert_no_error (error); + g_clear_error (&error); + g_input_stream_close (in, NULL, NULL); + g_object_unref (in); + return; + } else if (nread == 0) { + g_input_stream_close_async (in, G_PRIORITY_DEFAULT, NULL, + stream_closed, data); + return; + } + + g_string_append_len (data->body, data->buffer, nread); + g_input_stream_read_async (in, data->buffer, sizeof (data->buffer), + G_PRIORITY_DEFAULT, NULL, + test_read_ready, data); +} + +static void +async_request_sent (GObject *source, GAsyncResult *result, gpointer user_data) +{ + GInputStream *in; + AsyncRequestData *data = user_data; + GError *error = NULL; + + in = soup_request_send_finish (SOUP_REQUEST (source), result, &error); + if (!in) { + g_assert_no_error (error); + g_clear_error (&error); + return; + } + + g_input_stream_read_async (in, data->buffer, sizeof (data->buffer), + G_PRIORITY_DEFAULT, NULL, + test_read_ready, data); +} + +static void +do_async_request (SoupRequest *request) +{ + AsyncRequestData data; + + data.body = g_string_new (NULL); + soup_request_send_async (request, NULL, async_request_sent, &data); + + data.loop = g_main_loop_new (soup_session_get_async_context (soup_request_get_session (request)), TRUE); + g_main_loop_run (data.loop); + g_main_loop_unref (data.loop); + + soup_assert_cmpmem (data.body->str, data.body->len, + index_buffer->data, index_buffer->length); + g_string_free (data.body, TRUE); +} + +static void +do_sync_request (SoupRequest *request) +{ + GInputStream *in; + GString *body; + char buffer[1024]; + gssize nread; + GError *error = NULL; + + in = soup_request_send (request, NULL, &error); + if (!in) { + g_assert_no_error (error); + g_clear_error (&error); + return; + } + + body = g_string_new (NULL); + do { + nread = g_input_stream_read (in, buffer, sizeof (buffer), + NULL, &error); + if (nread == -1) { + g_assert_no_error (error); + g_clear_error (&error); + break; + } + g_string_append_len (body, buffer, nread); + } while (nread > 0); + + g_input_stream_close (in, NULL, &error); + g_assert_no_error (error); + g_clear_error (&error); + g_object_unref (in); + + soup_assert_cmpmem (body->str, body->len, index_buffer->data, index_buffer->length); + g_string_free (body, TRUE); +} + +static void +do_request (const char *uri_string, gconstpointer type) +{ + SoupSession *session; + SoupRequest *request; + GError *error = NULL; + + session = soup_test_session_new (GPOINTER_TO_SIZE (type), + SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, + NULL); + + request = soup_session_request (session, uri_string, &error); + g_assert_no_error (error); + + if (SOUP_IS_SESSION_ASYNC (session)) + do_async_request (request); + else + do_sync_request (request); + + g_object_unref (request); + soup_test_session_abort_unref (session); +} + +static void +do_request_file_test (gconstpointer type) +{ + GFile *index; + char *uri_string; + + index = g_file_new_for_path (g_test_get_filename (G_TEST_DIST, "index.txt", NULL)); + uri_string = g_file_get_uri (index); + g_object_unref (index); + + do_request (uri_string, type); + g_free (uri_string); +} + +static void +do_request_data_test (gconstpointer type) +{ + gchar *base64; + char *uri_string; + + base64 = g_base64_encode ((const guchar *)index_buffer->data, index_buffer->length); + uri_string = g_strdup_printf ("data:text/plain;charset=utf8;base64,%s", base64); + g_free (base64); + + do_request (uri_string, type); + g_free (uri_string); +} + +static void +do_request_gresource_test (gconstpointer type) +{ + do_request ("resource:///org/gnome/libsoup/tests/index.txt", type); +} + +int +main (int argc, char **argv) +{ + int ret; + + test_init (argc, argv, NULL); + + index_buffer = soup_test_get_index (); + soup_test_register_resources (); + + g_test_add_data_func ("/resource/sync/file", + GSIZE_TO_POINTER (SOUP_TYPE_SESSION_SYNC), + do_request_file_test); + g_test_add_data_func ("/resource/sync/data", + GSIZE_TO_POINTER (SOUP_TYPE_SESSION_SYNC), + do_request_data_test); + g_test_add_data_func ("/resource/sync/gresource", + GSIZE_TO_POINTER (SOUP_TYPE_SESSION_SYNC), + do_request_gresource_test); + + g_test_add_data_func ("/resource/async/file", + GSIZE_TO_POINTER (SOUP_TYPE_SESSION_ASYNC), + do_request_file_test); + g_test_add_data_func ("/resource/async/data", + GSIZE_TO_POINTER (SOUP_TYPE_SESSION_ASYNC), + do_request_data_test); + g_test_add_data_func ("/resource/async/gresource", + GSIZE_TO_POINTER (SOUP_TYPE_SESSION_ASYNC), + do_request_gresource_test); + + ret = g_test_run (); + + test_cleanup (); + return ret; +} diff --git a/tests/resources/atom.xml b/tests/resources/atom.xml new file mode 100644 index 0000000..962ecf4 --- /dev/null +++ b/tests/resources/atom.xml @@ -0,0 +1,35 @@ + + + A small ATOM feed + 2009-07-02T10:27:44Z + kov + + Anonymous Coward + + http://libsoup.rocks/atom.xml + + + + + http://libsoup.rocks/so/much/ + + One post too many + woo [...] +

woohoo

+
+ 2009-07-02T10:38:28Z + + + + kov + + + http://libsoup.rocks/blog + + + Just stuff to test libsoup + Random stuff to test libsoup + 2009-07-02T00:38:29Z + +
+
diff --git a/tests/resources/feed.rdf b/tests/resources/feed.rdf new file mode 100644 index 0000000..f3d9e27 --- /dev/null +++ b/tests/resources/feed.rdf @@ -0,0 +1,32 @@ + + + + + + + + XML.com + http://xml.com/pub + + XML.com features a rich mix of information and services + for the XML community. + + + + + + + + + + + + + + + diff --git a/tests/resources/home.gif b/tests/resources/home.gif new file mode 100644 index 0000000..55e1d59 Binary files /dev/null and b/tests/resources/home.gif differ diff --git a/tests/resources/home.jpg b/tests/resources/home.jpg new file mode 100644 index 0000000..ac1f3bb Binary files /dev/null and b/tests/resources/home.jpg differ diff --git a/tests/resources/home.png b/tests/resources/home.png new file mode 100644 index 0000000..0bb82ba Binary files /dev/null and b/tests/resources/home.png differ diff --git a/tests/resources/html_binary.html b/tests/resources/html_binary.html new file mode 100644 index 0000000..d443048 --- /dev/null +++ b/tests/resources/html_binary.html @@ -0,0 +1 @@ + + + + + + + +

GNOME!

+ + diff --git a/tests/resources/mbox b/tests/resources/mbox new file mode 100644 index 0000000..2e96727 --- /dev/null +++ b/tests/resources/mbox @@ -0,0 +1,64 @@ +From email@here Wed Jun 17 21:20:48 2009 +Return-path: +Envelope-to: email@here +Delivery-date: Wed, 17 Jun 2009 21:20:48 -0300 +Received: from email by here.domain with local (Exim 4.69) + (envelope-from ) + id 1MH5N2-0008Lq-7c + for email@here; Wed, 17 Jun 2009 21:20:48 -0300 +To: email@here +Subject: This is just so that I have a mailbox +Message-Id: +From: A Nice User +Date: Wed, 17 Jun 2009 21:20:48 -0300 + +This is a dumb email. + +From email@here Wed Jun 17 21:20:48 2009 +Return-path: +Envelope-to: email@here +Delivery-date: Wed, 17 Jun 2009 21:20:48 -0300 +Received: from email by here.domain with local (Exim 4.69) + (envelope-from ) + id 1MH5N2-0008Lq-7c + for email@here; Wed, 17 Jun 2009 21:20:48 -0300 +To: email@here +Subject: This is just so that I have a mailbox +Message-Id: +From: A Nice User +Date: Wed, 17 Jun 2009 21:20:48 -0300 + +This is a dumb email. + +From email@here Wed Jun 17 21:20:48 2009 +Return-path: +Envelope-to: email@here +Delivery-date: Wed, 17 Jun 2009 21:20:48 -0300 +Received: from email by here.domain with local (Exim 4.69) + (envelope-from ) + id 1MH5N2-0008Lq-7c + for email@here; Wed, 17 Jun 2009 21:20:48 -0300 +To: email@here +Subject: This is just so that I have a mailbox +Message-Id: +From: A Nice User +Date: Wed, 17 Jun 2009 21:20:48 -0300 + +This is a dumb email. + +From email@here Wed Jun 17 21:20:48 2009 +Return-path: +Envelope-to: email@here +Delivery-date: Wed, 17 Jun 2009 21:20:48 -0300 +Received: from email by here.domain with local (Exim 4.69) + (envelope-from ) + id 1MH5N2-0008Lq-7c + for email@here; Wed, 17 Jun 2009 21:20:48 -0300 +To: email@here +Subject: This is just so that I have a mailbox +Message-Id: +From: A Nice User +Date: Wed, 17 Jun 2009 21:20:48 -0300 + +This is a dumb email. + diff --git a/tests/resources/mbox.gz b/tests/resources/mbox.gz new file mode 100644 index 0000000..1a70d06 Binary files /dev/null and b/tests/resources/mbox.gz differ diff --git a/tests/resources/mbox.raw b/tests/resources/mbox.raw new file mode 100644 index 0000000..bd4e262 Binary files /dev/null and b/tests/resources/mbox.raw differ diff --git a/tests/resources/mbox.zlib b/tests/resources/mbox.zlib new file mode 100644 index 0000000..bd24ed4 Binary files /dev/null and b/tests/resources/mbox.zlib differ diff --git a/tests/resources/misc.xml b/tests/resources/misc.xml new file mode 100644 index 0000000..15361e6 --- /dev/null +++ b/tests/resources/misc.xml @@ -0,0 +1,11 @@ + + + + test1.txt + test.gresource.xml + + + test2.txt + test2.txt + + diff --git a/tests/resources/ps_binary.ps b/tests/resources/ps_binary.ps new file mode 100644 index 0000000..3d210ed --- /dev/null +++ b/tests/resources/ps_binary.ps @@ -0,0 +1 @@ +%!PS-Adobe-"  diff --git a/tests/resources/rss20.xml b/tests/resources/rss20.xml new file mode 100644 index 0000000..d64bdda --- /dev/null +++ b/tests/resources/rss20.xml @@ -0,0 +1,26 @@ + + + + + A small RSS + http://libsoup.rocks/ + en + A small RSS to test libsoup + + + One post too many + http://libsoup.rocks/so/much/ + http://libsoup.rocks/so/much/ + <p>woohoo</p> + Wed, 02 Jul 2009 10:26:28 +0000 + + + GCDS will rock + http://libsoup.rocks/so/much/again/ + http://libsoup.rocks/so/much/again/ + <p>I mean, really.</p> + Wed, 02 Jul 2009 10:26:28 +0000 + + + + diff --git a/tests/resources/test.aiff b/tests/resources/test.aiff new file mode 100644 index 0000000..9a1ecbb Binary files /dev/null and b/tests/resources/test.aiff differ diff --git a/tests/resources/test.html b/tests/resources/test.html new file mode 100644 index 0000000..5a6cc0c --- /dev/null +++ b/tests/resources/test.html @@ -0,0 +1,10 @@ + + + + + + + +

GNOME!

+ + diff --git a/tests/resources/test.mp4 b/tests/resources/test.mp4 new file mode 100644 index 0000000..d278c8a Binary files /dev/null and b/tests/resources/test.mp4 differ diff --git a/tests/resources/test.ogg b/tests/resources/test.ogg new file mode 100644 index 0000000..e8f49ac Binary files /dev/null and b/tests/resources/test.ogg differ diff --git a/tests/resources/test.wav b/tests/resources/test.wav new file mode 100644 index 0000000..11660b2 Binary files /dev/null and b/tests/resources/test.wav differ diff --git a/tests/resources/test.webm b/tests/resources/test.webm new file mode 100644 index 0000000..7e53d0b Binary files /dev/null and b/tests/resources/test.webm differ diff --git a/tests/resources/text.txt b/tests/resources/text.txt new file mode 100644 index 0000000..ff7066f --- /dev/null +++ b/tests/resources/text.txt @@ -0,0 +1 @@ +This is just text. diff --git a/tests/resources/text_binary.txt b/tests/resources/text_binary.txt new file mode 100644 index 0000000..113bfdd --- /dev/null +++ b/tests/resources/text_binary.txt @@ -0,0 +1 @@ +abc \ No newline at end of file diff --git a/tests/resources/tux.webp b/tests/resources/tux.webp new file mode 100644 index 0000000..8764f06 Binary files /dev/null and b/tests/resources/tux.webp differ diff --git a/tests/server-auth-test.c b/tests/server-auth-test.c new file mode 100644 index 0000000..34c297b --- /dev/null +++ b/tests/server-auth-test.c @@ -0,0 +1,401 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2001-2003, Ximian, Inc. + */ + +#include "test-utils.h" + +static SoupURI *base_uri; + +static struct { + gboolean client_sent_basic, client_sent_digest; + gboolean server_requested_basic, server_requested_digest; + gboolean succeeded; +} test_data; + +static void +curl_exited (GPid pid, int status, gpointer data) +{ + gboolean *done = data; + + *done = TRUE; + test_data.succeeded = (status == 0); +} + +static void +do_test (SoupURI *base_uri, const char *path, + gboolean good_user, gboolean good_password, + gboolean offer_basic, gboolean offer_digest, + gboolean client_sends_basic, gboolean client_sends_digest, + gboolean server_requests_basic, gboolean server_requests_digest, + gboolean success) +{ + SoupURI *uri; + char *uri_str; + GPtrArray *args; + GPid pid; + gboolean done; + + /* We build the URI this way to avoid having soup_uri_new() + normalize the path, hence losing the encoded characters in + tests 4. and 5. below. */ + uri = soup_uri_copy (base_uri); + soup_uri_set_path (uri, path); + uri_str = soup_uri_to_string (uri, FALSE); + soup_uri_free (uri); + + args = g_ptr_array_new (); + g_ptr_array_add (args, "curl"); + g_ptr_array_add (args, "--noproxy"); + g_ptr_array_add (args, "*"); + g_ptr_array_add (args, "-f"); + g_ptr_array_add (args, "-s"); + if (offer_basic || offer_digest) { + g_ptr_array_add (args, "-u"); + if (good_user) { + if (good_password) + g_ptr_array_add (args, "user:password"); + else + g_ptr_array_add (args, "user:badpassword"); + } else { + if (good_password) + g_ptr_array_add (args, "baduser:password"); + else + g_ptr_array_add (args, "baduser:badpassword"); + } + + if (offer_basic && offer_digest) + g_ptr_array_add (args, "--anyauth"); + else if (offer_basic) + g_ptr_array_add (args, "--basic"); + else + g_ptr_array_add (args, "--digest"); + } + g_ptr_array_add (args, uri_str); + g_ptr_array_add (args, NULL); + + memset (&test_data, 0, sizeof (test_data)); + if (g_spawn_async (NULL, (char **)args->pdata, NULL, + G_SPAWN_SEARCH_PATH | G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL | G_SPAWN_DO_NOT_REAP_CHILD, + NULL, NULL, &pid, NULL)) { + done = FALSE; + g_child_watch_add (pid, curl_exited, &done); + + while (!done) + g_main_context_iteration (NULL, TRUE); + } else + test_data.succeeded = FALSE; + g_ptr_array_free (args, TRUE); + g_free (uri_str); + + g_assert_cmpint (server_requests_basic, ==, test_data.server_requested_basic); + g_assert_cmpint (server_requests_digest, ==, test_data.server_requested_digest); + g_assert_cmpint (client_sends_basic, ==, test_data.client_sent_basic); + g_assert_cmpint (client_sends_digest, ==, test_data.client_sent_digest); + + g_assert_cmpint (success, ==, test_data.succeeded); +} + +#define TEST_USES_BASIC(t) (((t) & 1) == 1) +#define TEST_USES_DIGEST(t) (((t) & 2) == 2) +#define TEST_GOOD_USER(t) (((t) & 4) == 4) +#define TEST_GOOD_PASSWORD(t) (((t) & 8) == 8) + +#define TEST_GOOD_AUTH(t) (TEST_GOOD_USER (t) && TEST_GOOD_PASSWORD (t)) +#define TEST_PREEMPTIVE_BASIC(t) (TEST_USES_BASIC (t) && !TEST_USES_DIGEST (t)) + +static void +do_server_auth_test (gconstpointer data) +{ + int i = GPOINTER_TO_INT (data); + +#ifndef HAVE_CURL + g_test_skip ("/usr/bin/curl is not available"); + return; +#endif + + /* 1. No auth required. The server will ignore the + * Authorization headers completely, and the request + * will always succeed. + */ + do_test (base_uri, "/foo", + TEST_GOOD_USER (i), TEST_GOOD_PASSWORD (i), + /* request */ + TEST_USES_BASIC (i), TEST_USES_DIGEST (i), + /* expected from client */ + TEST_PREEMPTIVE_BASIC (i), FALSE, + /* expected from server */ + FALSE, FALSE, + /* success? */ + TRUE); + + /* 2. Basic auth required. The server will send + * "WWW-Authenticate: Basic" if the client fails to + * send an Authorization: Basic on the first request, + * or if it sends a bad password. + */ + do_test (base_uri, "/Basic/foo", + TEST_GOOD_USER (i), TEST_GOOD_PASSWORD (i), + /* request */ + TEST_USES_BASIC (i), TEST_USES_DIGEST (i), + /* expected from client */ + TEST_USES_BASIC (i), FALSE, + /* expected from server */ + !TEST_PREEMPTIVE_BASIC (i) || !TEST_GOOD_AUTH (i), FALSE, + /* success? */ + TEST_USES_BASIC (i) && TEST_GOOD_AUTH (i)); + + /* 3. Digest auth required. Simpler than the basic + * case because the client can't send Digest auth + * premptively. + */ + do_test (base_uri, "/Digest/foo", + TEST_GOOD_USER (i), TEST_GOOD_PASSWORD (i), + /* request */ + TEST_USES_BASIC (i), TEST_USES_DIGEST (i), + /* expected from client */ + TEST_PREEMPTIVE_BASIC (i), TEST_USES_DIGEST (i), + /* expected from server */ + FALSE, TRUE, + /* success? */ + TEST_USES_DIGEST (i) && TEST_GOOD_AUTH (i)); + + /* 4. Digest auth with encoded URI. See #794208. + */ + do_test (base_uri, "/Digest/A%20B", + TEST_GOOD_USER (i), TEST_GOOD_PASSWORD (i), + /* request */ + TEST_USES_BASIC (i), TEST_USES_DIGEST (i), + /* expected from client */ + TEST_PREEMPTIVE_BASIC (i), TEST_USES_DIGEST (i), + /* expected from server */ + FALSE, TRUE, + /* success? */ + TEST_USES_DIGEST (i) && TEST_GOOD_AUTH (i)); + + /* 5. Digest auth with a mixture of encoded and decoded chars in the URI. See #794208. + */ + do_test (base_uri, "/Digest/A%20|%20B", + TEST_GOOD_USER (i), TEST_GOOD_PASSWORD (i), + /* request */ + TEST_USES_BASIC (i), TEST_USES_DIGEST (i), + /* expected from client */ + TEST_PREEMPTIVE_BASIC (i), TEST_USES_DIGEST (i), + /* expected from server */ + FALSE, TRUE, + /* success? */ + TEST_USES_DIGEST (i) && TEST_GOOD_AUTH (i)); + + /* 6. Digest auth with UTF-8 chars in the URI. See #794208. + */ + do_test (base_uri, "/Digest/A௹B", + TEST_GOOD_USER (i), TEST_GOOD_PASSWORD (i), + /* request */ + TEST_USES_BASIC (i), TEST_USES_DIGEST (i), + /* expected from client */ + TEST_PREEMPTIVE_BASIC (i), TEST_USES_DIGEST (i), + /* expected from server */ + FALSE, TRUE, + /* success? */ + TEST_USES_DIGEST (i) && TEST_GOOD_AUTH (i)); + + /* 7. Any auth required. */ + do_test (base_uri, "/Any/foo", + TEST_GOOD_USER (i), TEST_GOOD_PASSWORD (i), + /* request */ + TEST_USES_BASIC (i), TEST_USES_DIGEST (i), + /* expected from client */ + TEST_PREEMPTIVE_BASIC (i), TEST_USES_DIGEST (i), + /* expected from server */ + !TEST_PREEMPTIVE_BASIC (i) || !TEST_GOOD_AUTH (i), !TEST_PREEMPTIVE_BASIC (i) || !TEST_GOOD_AUTH (i), + /* success? */ + (TEST_USES_BASIC (i) || TEST_USES_DIGEST (i)) && TEST_GOOD_AUTH (i)); + + /* 8. No auth required again. (Makes sure that + * SOUP_AUTH_DOMAIN_REMOVE_PATH works.) + */ + do_test (base_uri, "/Any/Not/foo", + TEST_GOOD_USER (i), TEST_GOOD_PASSWORD (i), + /* request */ + TEST_USES_BASIC (i), TEST_USES_DIGEST (i), + /* expected from client */ + TEST_PREEMPTIVE_BASIC (i), FALSE, + /* expected from server */ + FALSE, FALSE, + /* success? */ + TRUE); +} + +static gboolean +basic_auth_callback (SoupAuthDomain *auth_domain, SoupMessage *msg, + const char *username, const char *password, gpointer data) +{ + return !strcmp (username, "user") && !strcmp (password, "password"); +} + +static char * +digest_auth_callback (SoupAuthDomain *auth_domain, SoupMessage *msg, + const char *username, gpointer data) +{ + if (strcmp (username, "user") != 0) + return NULL; + + /* Note: this is exactly how you *shouldn't* do it in the real + * world; you should have the pre-encoded password stored in a + * database of some sort rather than using the cleartext + * password in the callback. + */ + return soup_auth_domain_digest_encode_password ("user", + "server-auth-test", + "password"); +} + +static void +server_callback (SoupServer *server, SoupMessage *msg, + const char *path, GHashTable *query, + SoupClientContext *context, gpointer data) +{ + if (msg->method != SOUP_METHOD_GET && msg->method != SOUP_METHOD_HEAD) { + soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED); + return; + } + + soup_message_set_response (msg, "text/plain", + SOUP_MEMORY_STATIC, + "OK\r\n", 4); + soup_message_set_status (msg, SOUP_STATUS_OK); +} + +static void +got_headers_callback (SoupMessage *msg, gpointer data) +{ + const char *header; + + header = soup_message_headers_get_one (msg->request_headers, + "Authorization"); + if (header) { + if (strstr (header, "Basic ")) + test_data.client_sent_basic = TRUE; + if (strstr (header, "Digest ")) + test_data.client_sent_digest = TRUE; + } +} + +static void +wrote_headers_callback (SoupMessage *msg, gpointer data) +{ + const char *header; + + header = soup_message_headers_get_list (msg->response_headers, + "WWW-Authenticate"); + if (header) { + if (strstr (header, "Basic ")) + test_data.server_requested_basic = TRUE; + if (strstr (header, "Digest ")) + test_data.server_requested_digest = TRUE; + } +} + +static void +request_started_callback (SoupServer *server, SoupMessage *msg, + SoupClientContext *client, gpointer data) +{ + g_signal_connect (msg, "got_headers", + G_CALLBACK (got_headers_callback), NULL); + g_signal_connect (msg, "wrote_headers", + G_CALLBACK (wrote_headers_callback), NULL); +} + +static gboolean run_tests = TRUE; + +static GOptionEntry no_test_entry[] = { + { "no-tests", 'n', G_OPTION_FLAG_REVERSE, + G_OPTION_ARG_NONE, &run_tests, + "Don't run tests, just run the test server", NULL }, + { NULL } +}; + +int +main (int argc, char **argv) +{ + GMainLoop *loop; + SoupServer *server; + SoupAuthDomain *auth_domain; + int ret; + + test_init (argc, argv, no_test_entry); + + server = soup_test_server_new (SOUP_TEST_SERVER_DEFAULT); + g_signal_connect (server, "request_started", + G_CALLBACK (request_started_callback), NULL); + soup_server_add_handler (server, NULL, + server_callback, NULL, NULL); + + auth_domain = soup_auth_domain_basic_new ( + SOUP_AUTH_DOMAIN_REALM, "server-auth-test", + SOUP_AUTH_DOMAIN_ADD_PATH, "/Basic", + SOUP_AUTH_DOMAIN_ADD_PATH, "/Any", + SOUP_AUTH_DOMAIN_REMOVE_PATH, "/Any/Not", + SOUP_AUTH_DOMAIN_BASIC_AUTH_CALLBACK, basic_auth_callback, + NULL); + soup_server_add_auth_domain (server, auth_domain); + g_object_unref (auth_domain); + + auth_domain = soup_auth_domain_digest_new ( + SOUP_AUTH_DOMAIN_REALM, "server-auth-test", + SOUP_AUTH_DOMAIN_ADD_PATH, "/Digest", + SOUP_AUTH_DOMAIN_ADD_PATH, "/Any", + SOUP_AUTH_DOMAIN_REMOVE_PATH, "/Any/Not", + SOUP_AUTH_DOMAIN_DIGEST_AUTH_CALLBACK, digest_auth_callback, + NULL); + soup_server_add_auth_domain (server, auth_domain); + g_object_unref (auth_domain); + + loop = g_main_loop_new (NULL, TRUE); + + base_uri = soup_test_server_get_uri (server, "http", NULL); + if (run_tests) { + int i; + + for (i = 0; i < 16; i++) { + char *path; + const char *authtypes; + + if (!TEST_GOOD_USER (i) && !TEST_GOOD_PASSWORD (i)) + continue; + if (TEST_USES_BASIC (i)) { + if (TEST_USES_DIGEST (i)) + authtypes = "basic+digest"; + else + authtypes = "basic"; + } else { + if (TEST_USES_DIGEST (i)) + authtypes = "digest"; + else + authtypes = "none"; + } + + path = g_strdup_printf ("/server-auth/%s/%s-user%c%s-password", + authtypes, + TEST_GOOD_USER (i) ? "good" : "bad", + TEST_GOOD_USER (i) ? '/' : '\0', + TEST_GOOD_PASSWORD (i) ? "good" : "bad"); + g_test_add_data_func (path, GINT_TO_POINTER (i), do_server_auth_test); + g_free (path); + } + + ret = g_test_run (); + } else { + g_print ("Listening on port %d\n", base_uri->port); + g_main_loop_run (loop); + ret = 0; + } + soup_uri_free (base_uri); + + g_main_loop_unref (loop); + soup_test_server_quit_unref (server); + + if (run_tests) + test_cleanup (); + return ret; +} diff --git a/tests/server-test.c b/tests/server-test.c new file mode 100644 index 0000000..cf132b3 --- /dev/null +++ b/tests/server-test.c @@ -0,0 +1,1353 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright 2007-2012 Red Hat, Inc. + */ + +#include "test-utils.h" + +#include + +typedef struct { + SoupServer *server; + SoupURI *base_uri, *ssl_base_uri; + GSList *handlers; +} ServerData; + +static void +server_callback (SoupServer *server, SoupMessage *msg, + const char *path, GHashTable *query, + SoupClientContext *context, gpointer data) +{ + soup_message_headers_append (msg->response_headers, + "X-Handled-By", "server_callback"); + + if (!strcmp (path, "*")) { + soup_test_assert (FALSE, "default server_callback got request for '*'"); + soup_message_set_status (msg, SOUP_STATUS_INTERNAL_SERVER_ERROR); + return; + } + + if (msg->method != SOUP_METHOD_GET && msg->method != SOUP_METHOD_POST) { + soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED); + return; + } + + soup_message_set_status (msg, SOUP_STATUS_OK); + soup_message_set_response (msg, "text/plain", + SOUP_MEMORY_STATIC, "index", 5); +} + +static void +server_setup_nohandler (ServerData *sd, gconstpointer test_data) +{ + sd->server = soup_test_server_new (SOUP_TEST_SERVER_IN_THREAD); + sd->base_uri = soup_test_server_get_uri (sd->server, "http", NULL); + if (tls_available) + sd->ssl_base_uri = soup_test_server_get_uri (sd->server, "https", NULL); +} + +static void +server_add_handler (ServerData *sd, + const char *path, + SoupServerCallback callback, + gpointer user_data, + GDestroyNotify destroy) +{ + soup_server_add_handler (sd->server, path, callback, user_data, destroy); + sd->handlers = g_slist_prepend (sd->handlers, g_strdup (path)); +} + +static void +server_add_early_handler (ServerData *sd, + const char *path, + SoupServerCallback callback, + gpointer user_data, + GDestroyNotify destroy) +{ + soup_server_add_early_handler (sd->server, path, callback, user_data, destroy); + sd->handlers = g_slist_prepend (sd->handlers, g_strdup (path)); +} + +static void +server_setup (ServerData *sd, gconstpointer test_data) +{ + server_setup_nohandler (sd, test_data); + server_add_handler (sd, NULL, server_callback, NULL, NULL); +} + +static void +server_teardown (ServerData *sd, gconstpointer test_data) +{ + GSList *iter; + + for (iter = sd->handlers; iter; iter = iter->next) + soup_server_remove_handler (sd->server, iter->data); + g_slist_free_full (sd->handlers, g_free); + + g_clear_pointer (&sd->server, soup_test_server_quit_unref); + g_clear_pointer (&sd->base_uri, soup_uri_free); + g_clear_pointer (&sd->ssl_base_uri, soup_uri_free); +} + +static void +server_star_callback (SoupServer *server, SoupMessage *msg, + const char *path, GHashTable *query, + SoupClientContext *context, gpointer data) +{ + soup_message_headers_append (msg->response_headers, + "X-Handled-By", "star_callback"); + + if (strcmp (path, "*") != 0) { + soup_test_assert (FALSE, "server_star_callback got request for '%s'", path); + soup_message_set_status (msg, SOUP_STATUS_INTERNAL_SERVER_ERROR); + return; + } + + if (msg->method != SOUP_METHOD_OPTIONS) { + soup_message_set_status (msg, SOUP_STATUS_METHOD_NOT_ALLOWED); + return; + } + + soup_message_set_status (msg, SOUP_STATUS_OK); +} + +/* Server handlers for "*" work but are separate from handlers for + * all other URIs. #590751 + */ +static void +do_star_test (ServerData *sd, gconstpointer test_data) +{ + SoupSession *session; + SoupMessage *msg; + SoupURI *star_uri; + const char *handled_by; + + g_test_bug ("590751"); + + session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL); + star_uri = soup_uri_copy (sd->base_uri); + soup_uri_set_path (star_uri, "*"); + + debug_printf (1, " Testing with no handler\n"); + msg = soup_message_new_from_uri ("OPTIONS", star_uri); + soup_session_send_message (session, msg); + + soup_test_assert_message_status (msg, SOUP_STATUS_NOT_FOUND); + handled_by = soup_message_headers_get_one (msg->response_headers, + "X-Handled-By"); + g_assert_cmpstr (handled_by, ==, NULL); + g_object_unref (msg); + + server_add_handler (sd, "*", server_star_callback, NULL, NULL); + + debug_printf (1, " Testing with handler\n"); + msg = soup_message_new_from_uri ("OPTIONS", star_uri); + soup_session_send_message (session, msg); + + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + handled_by = soup_message_headers_get_one (msg->response_headers, + "X-Handled-By"); + g_assert_cmpstr (handled_by, ==, "star_callback"); + g_object_unref (msg); + + soup_test_session_abort_unref (session); + soup_uri_free (star_uri); +} + +static void +do_one_server_aliases_test (SoupURI *uri, + const char *alias, + gboolean succeed) +{ + GSocketClient *client; + GSocketConnectable *addr; + GSocketConnection *conn; + GInputStream *in; + GOutputStream *out; + GError *error = NULL; + GString *req; + static char buf[1024]; + + debug_printf (1, " %s via %s\n", alias, uri->scheme); + + /* There's no way to make libsoup's client side send an absolute + * URI (to a non-proxy server), so we have to fake this. + */ + + client = g_socket_client_new (); + if (uri->scheme == SOUP_URI_SCHEME_HTTPS) { + g_socket_client_set_tls (client, TRUE); + g_socket_client_set_tls_validation_flags (client, 0); + } + addr = g_network_address_new (uri->host, uri->port); + + conn = g_socket_client_connect (client, addr, NULL, &error); + g_object_unref (addr); + g_object_unref (client); + if (!conn) { + g_assert_no_error (error); + g_error_free (error); + return; + } + + in = g_io_stream_get_input_stream (G_IO_STREAM (conn)); + out = g_io_stream_get_output_stream (G_IO_STREAM (conn)); + + req = g_string_new (NULL); + g_string_append_printf (req, "GET %s://%s:%d HTTP/1.1\r\n", + alias, uri->host, uri->port); + g_string_append_printf (req, "Host: %s:%d\r\n", + uri->host, uri->port); + g_string_append (req, "Connection: close\r\n\r\n"); + + if (!g_output_stream_write_all (out, req->str, req->len, NULL, NULL, &error)) { + g_assert_no_error (error); + g_error_free (error); + g_object_unref (conn); + g_string_free (req, TRUE); + return; + } + g_string_free (req, TRUE); + + if (!g_input_stream_read_all (in, buf, sizeof (buf), NULL, NULL, &error)) { + g_assert_no_error (error); + g_error_free (error); + g_object_unref (conn); + return; + } + + if (succeed) + g_assert_true (g_str_has_prefix (buf, "HTTP/1.1 200 ")); + else + g_assert_true (g_str_has_prefix (buf, "HTTP/1.1 400 ")); + + g_io_stream_close (G_IO_STREAM (conn), NULL, NULL); + g_object_unref (conn); +} + +static void +do_server_aliases_test (ServerData *sd, gconstpointer test_data) +{ + char *http_aliases[] = { "dav", NULL }; + char *https_aliases[] = { "davs", NULL }; + char *http_good[] = { "http", "dav", NULL }; + char *http_bad[] = { "https", "davs", "fred", NULL }; + char *https_good[] = { "https", "davs", NULL }; + char *https_bad[] = { "http", "dav", "fred", NULL }; + int i; + + g_test_bug ("703694"); + + g_object_set (G_OBJECT (sd->server), + SOUP_SERVER_HTTP_ALIASES, http_aliases, + SOUP_SERVER_HTTPS_ALIASES, https_aliases, + NULL); + + for (i = 0; http_good[i]; i++) + do_one_server_aliases_test (sd->base_uri, http_good[i], TRUE); + for (i = 0; http_bad[i]; i++) + do_one_server_aliases_test (sd->base_uri, http_bad[i], FALSE); + + if (tls_available) { + for (i = 0; https_good[i]; i++) + do_one_server_aliases_test (sd->ssl_base_uri, https_good[i], TRUE); + for (i = 0; https_bad[i]; i++) + do_one_server_aliases_test (sd->ssl_base_uri, https_bad[i], FALSE); + } +} + +static void +do_dot_dot_test (ServerData *sd, gconstpointer test_data) +{ + SoupSession *session; + SoupMessage *msg; + SoupURI *uri; + + g_test_bug ("667635"); + + session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL); + + uri = soup_uri_new_with_base (sd->base_uri, "/..%2ftest"); + msg = soup_message_new_from_uri ("GET", uri); + soup_uri_free (uri); + + soup_session_send_message (session, msg); + soup_test_assert_message_status (msg, SOUP_STATUS_BAD_REQUEST); + g_object_unref (msg); + + soup_test_session_abort_unref (session); +} + +static void +ipv6_server_callback (SoupServer *server, SoupMessage *msg, + const char *path, GHashTable *query, + SoupClientContext *context, gpointer data) +{ + const char *host; + GSocketAddress *addr; + char expected_host[128]; + + addr = soup_client_context_get_local_address (context); + g_snprintf (expected_host, sizeof (expected_host), + "[::1]:%d", + g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (addr))); + + host = soup_message_headers_get_one (msg->request_headers, "Host"); + g_assert_cmpstr (host, ==, expected_host); + + if (g_test_failed ()) + soup_message_set_status (msg, SOUP_STATUS_BAD_REQUEST); + else + soup_message_set_status (msg, SOUP_STATUS_OK); +} + +static void +do_ipv6_test (ServerData *sd, gconstpointer test_data) +{ + SoupSession *session; + SoupMessage *msg; + GError *error = NULL; + + g_test_bug ("666399"); + + sd->server = soup_test_server_new (SOUP_TEST_SERVER_NO_DEFAULT_LISTENER); + server_add_handler (sd, NULL, ipv6_server_callback, NULL, NULL); + + if (!soup_server_listen_local (sd->server, 0, + SOUP_SERVER_LISTEN_IPV6_ONLY, + &error)) { +#if GLIB_CHECK_VERSION (2, 41, 0) + g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED); +#endif + g_test_skip ("no IPv6 support"); + return; + } + + sd->base_uri = soup_test_server_get_uri (sd->server, "http", "::1"); + + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + + debug_printf (1, " HTTP/1.1\n"); + msg = soup_message_new_from_uri ("GET", sd->base_uri); + soup_session_send_message (session, msg); + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + g_object_unref (msg); + + debug_printf (1, " HTTP/1.0\n"); + msg = soup_message_new_from_uri ("GET", sd->base_uri); + soup_message_set_http_version (msg, SOUP_HTTP_1_0); + soup_session_send_message (session, msg); + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + g_object_unref (msg); + + soup_test_session_abort_unref (session); +} + +static void +multi_server_callback (SoupServer *server, SoupMessage *msg, + const char *path, GHashTable *query, + SoupClientContext *context, gpointer data) +{ + GSocketAddress *addr; + GInetSocketAddress *iaddr; + SoupURI *uri; + char *uristr, *addrstr; + + addr = soup_client_context_get_local_address (context); + iaddr = G_INET_SOCKET_ADDRESS (addr); + + uri = soup_message_get_uri (msg); + uristr = soup_uri_to_string (uri, FALSE); + + addrstr = g_inet_address_to_string (g_inet_socket_address_get_address (iaddr)); + g_assert_cmpstr (addrstr, ==, uri->host); + g_free (addrstr); + + g_assert_cmpint (g_inet_socket_address_get_port (iaddr), ==, uri->port); + + /* FIXME ssl */ + + soup_message_set_response (msg, "text/plain", + SOUP_MEMORY_TAKE, uristr, strlen (uristr)); + soup_message_set_status (msg, SOUP_STATUS_OK); +} + +static void +do_multi_test (ServerData *sd, SoupURI *uri1, SoupURI *uri2) +{ + char *uristr; + SoupSession *session; + SoupMessage *msg; + + server_add_handler (sd, NULL, multi_server_callback, NULL, NULL); + + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + + uristr = soup_uri_to_string (uri1, FALSE); + msg = soup_message_new ("GET", uristr); + soup_session_send_message (session, msg); + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + g_assert_cmpstr (msg->response_body->data, ==, uristr); + g_object_unref (msg); + g_free (uristr); + + uristr = soup_uri_to_string (uri2, FALSE); + msg = soup_message_new ("GET", uristr); + soup_session_send_message (session, msg); + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + g_assert_cmpstr (msg->response_body->data, ==, uristr); + g_object_unref (msg); + g_free (uristr); + + soup_test_session_abort_unref (session); + + soup_uri_free (uri1); + soup_uri_free (uri2); +} + +static void +do_multi_port_test (ServerData *sd, gconstpointer test_data) +{ + GSList *uris; + SoupURI *uri1, *uri2; + GError *error = NULL; + + sd->server = soup_test_server_new (SOUP_TEST_SERVER_NO_DEFAULT_LISTENER); + + if (!soup_server_listen_local (sd->server, 0, SOUP_SERVER_LISTEN_IPV4_ONLY, &error)) { + g_assert_no_error (error); + g_error_free (error); + return; + } + if (!soup_server_listen_local (sd->server, 0, SOUP_SERVER_LISTEN_IPV4_ONLY, &error)) { + g_assert_no_error (error); + g_error_free (error); + return; + } + + uris = soup_server_get_uris (sd->server); + g_assert_cmpint (g_slist_length (uris), ==, 2); + uri1 = uris->data; + uri2 = uris->next->data; + g_slist_free (uris); + + g_assert_cmpint (uri1->port, !=, uri2->port); + + do_multi_test (sd, uri1, uri2); +} + +static void +do_multi_scheme_test (ServerData *sd, gconstpointer test_data) +{ + GSList *uris; + SoupURI *uri1, *uri2; + GError *error = NULL; + + SOUP_TEST_SKIP_IF_NO_TLS; + + sd->server = soup_test_server_new (SOUP_TEST_SERVER_NO_DEFAULT_LISTENER); + + if (!soup_server_listen_local (sd->server, 0, SOUP_SERVER_LISTEN_IPV4_ONLY, &error)) { + g_assert_no_error (error); + g_error_free (error); + return; + } + if (!soup_server_listen_local (sd->server, 0, + SOUP_SERVER_LISTEN_IPV4_ONLY | SOUP_SERVER_LISTEN_HTTPS, + &error)) { + g_assert_no_error (error); + g_error_free (error); + return; + } + + uris = soup_server_get_uris (sd->server); + g_assert_cmpint (g_slist_length (uris), ==, 2); + uri1 = uris->data; + uri2 = uris->next->data; + g_slist_free (uris); + + g_assert_cmpstr (uri1->scheme, !=, uri2->scheme); + + do_multi_test (sd, uri1, uri2); +} + +static void +do_multi_family_test (ServerData *sd, gconstpointer test_data) +{ + GSList *uris; + SoupURI *uri1, *uri2; + GError *error = NULL; + + sd->server = soup_test_server_new (SOUP_TEST_SERVER_NO_DEFAULT_LISTENER); + + if (!soup_server_listen_local (sd->server, 0, 0, &error)) { + g_assert_no_error (error); + g_error_free (error); + return; + } + + uris = soup_server_get_uris (sd->server); + if (g_slist_length (uris) == 1) { + gboolean ipv6_works; + + /* No IPv6? Double-check */ + ipv6_works = soup_server_listen_local (sd->server, 0, + SOUP_SERVER_LISTEN_IPV6_ONLY, + NULL); + if (ipv6_works) + g_assert_false (ipv6_works); + else + g_test_skip ("no IPv6 support"); + return; + } + + g_assert_cmpint (g_slist_length (uris), ==, 2); + uri1 = uris->data; + uri2 = uris->next->data; + g_slist_free (uris); + + g_assert_cmpstr (uri1->host, !=, uri2->host); + g_assert_cmpint (uri1->port, ==, uri2->port); + + do_multi_test (sd, uri1, uri2); +} + +static void +do_gsocket_import_test (void) +{ + GSocket *gsock; + GSocketAddress *gaddr; + SoupServer *server; + GSList *listeners; + SoupURI *uri; + SoupSession *session; + SoupMessage *msg; + GError *error = NULL; + + gsock = g_socket_new (G_SOCKET_FAMILY_IPV4, + G_SOCKET_TYPE_STREAM, + G_SOCKET_PROTOCOL_DEFAULT, + &error); + g_assert_no_error (error); + + gaddr = g_inet_socket_address_new_from_string ("127.0.0.1", 0); + g_socket_bind (gsock, gaddr, TRUE, &error); + g_object_unref (gaddr); + g_assert_no_error (error); + g_socket_listen (gsock, &error); + g_assert_no_error (error); + + gaddr = g_socket_get_local_address (gsock, &error); + g_assert_no_error (error); + g_object_unref (gaddr); + + server = soup_test_server_new (SOUP_TEST_SERVER_NO_DEFAULT_LISTENER); + soup_server_add_handler (server, NULL, server_callback, NULL, NULL); + + listeners = soup_server_get_listeners (server); + g_assert_cmpint (g_slist_length (listeners), ==, 0); + g_slist_free (listeners); + + soup_server_listen_socket (server, gsock, 0, &error); + g_assert_no_error (error); + listeners = soup_server_get_listeners (server); + g_assert_cmpint (g_slist_length (listeners), ==, 1); + g_slist_free (listeners); + + uri = soup_test_server_get_uri (server, "http", "127.0.0.1"); + g_assert_nonnull (uri); + listeners = soup_server_get_listeners (server); + g_assert_cmpint (g_slist_length (listeners), ==, 1); + g_slist_free (listeners); + + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + msg = soup_message_new_from_uri ("GET", uri); + soup_session_send_message (session, msg); + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + g_object_unref (msg); + + soup_test_session_abort_unref (session); + + soup_uri_free (uri); + soup_test_server_quit_unref (server); + + g_assert_false (g_socket_is_connected (gsock)); + g_object_unref (gsock); +} + +static void +do_fd_import_test (void) +{ + GSocket *gsock; + GSocketAddress *gaddr; + SoupServer *server; + GSList *listeners; + SoupURI *uri; + SoupSession *session; + SoupMessage *msg; + int type; + GError *error = NULL; + + gsock = g_socket_new (G_SOCKET_FAMILY_IPV4, + G_SOCKET_TYPE_STREAM, + G_SOCKET_PROTOCOL_DEFAULT, + &error); + g_assert_no_error (error); + + gaddr = g_inet_socket_address_new_from_string ("127.0.0.1", 0); + g_socket_bind (gsock, gaddr, TRUE, &error); + g_object_unref (gaddr); + g_assert_no_error (error); + g_socket_listen (gsock, &error); + g_assert_no_error (error); + + gaddr = g_socket_get_local_address (gsock, &error); + g_assert_no_error (error); + g_object_unref (gaddr); + + server = soup_test_server_new (SOUP_TEST_SERVER_NO_DEFAULT_LISTENER); + soup_server_add_handler (server, NULL, server_callback, NULL, NULL); + + listeners = soup_server_get_listeners (server); + g_assert_cmpint (g_slist_length (listeners), ==, 0); + g_slist_free (listeners); + + soup_server_listen_fd (server, g_socket_get_fd (gsock), 0, &error); + g_assert_no_error (error); + listeners = soup_server_get_listeners (server); + g_assert_cmpint (g_slist_length (listeners), ==, 1); + g_slist_free (listeners); + + uri = soup_test_server_get_uri (server, "http", "127.0.0.1"); + g_assert_nonnull (uri); + listeners = soup_server_get_listeners (server); + g_assert_cmpint (g_slist_length (listeners), ==, 1); + g_slist_free (listeners); + + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + msg = soup_message_new_from_uri ("GET", uri); + soup_session_send_message (session, msg); + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + g_object_unref (msg); + + soup_test_session_abort_unref (session); + + soup_uri_free (uri); + soup_test_server_quit_unref (server); + + /* @server should have closed our socket, although @gsock doesn't + * know this. + */ + g_socket_get_option (gsock, SOL_SOCKET, SO_TYPE, &type, &error); + g_assert_error (error, G_IO_ERROR, G_IO_ERROR_FAILED); + g_clear_error (&error); + g_object_unref (gsock); +} + +typedef struct +{ + GIOStream parent; + GInputStream *input_stream; + GOutputStream *output_stream; +} GTestIOStream; + +typedef struct +{ + GIOStreamClass parent_class; +} GTestIOStreamClass; + +static GType g_test_io_stream_get_type (void); +G_DEFINE_TYPE (GTestIOStream, g_test_io_stream, G_TYPE_IO_STREAM); + + +static GInputStream * +get_input_stream (GIOStream *io_stream) +{ + GTestIOStream *self = (GTestIOStream *) io_stream; + + return self->input_stream; +} + +static GOutputStream * +get_output_stream (GIOStream *io_stream) +{ + GTestIOStream *self = (GTestIOStream *) io_stream; + + return self->output_stream; +} + +static void +finalize (GObject *object) +{ + GTestIOStream *self = (GTestIOStream *) object; + + if (self->input_stream != NULL) + g_object_unref (self->input_stream); + + if (self->output_stream != NULL) + g_object_unref (self->output_stream); + + G_OBJECT_CLASS (g_test_io_stream_parent_class)->finalize (object); +} + +static void +g_test_io_stream_class_init (GTestIOStreamClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GIOStreamClass *io_class = G_IO_STREAM_CLASS (klass); + + object_class->finalize = finalize; + + io_class->get_input_stream = get_input_stream; + io_class->get_output_stream = get_output_stream; +} + +static void +g_test_io_stream_init (GTestIOStream *self) +{ +} + +static GIOStream * +g_test_io_stream_new (GInputStream *input, GOutputStream *output) +{ + GTestIOStream *self; + + self = g_object_new (g_test_io_stream_get_type (), NULL); + self->input_stream = g_object_ref (input); + self->output_stream = g_object_ref (output); + + return G_IO_STREAM (self); +} + +static void +mem_server_callback (SoupServer *server, SoupMessage *msg, + const char *path, GHashTable *query, + SoupClientContext *context, gpointer data) +{ + GSocketAddress *addr; + GSocket *sock; + const char *host; + + addr = soup_client_context_get_local_address (context); + g_assert_nonnull (addr); + + addr = soup_client_context_get_remote_address (context); + g_assert_nonnull (addr); + + sock = soup_client_context_get_gsocket (context); + g_assert_null (sock); + + host = soup_client_context_get_host (context); + g_assert_cmpstr (host, ==, "127.0.0.1"); + + server_callback (server, msg, path, query, context, data); +} + +static void +do_iostream_accept_test (void) +{ + GError *error = NULL; + SoupServer *server; + GInputStream *input; + GOutputStream *output; + GIOStream *stream; + GSocketAddress *addr; + const char req[] = "GET / HTTP/1.0\r\n\r\n"; + gchar *reply; + gsize reply_size; + + server = soup_test_server_new (SOUP_TEST_SERVER_NO_DEFAULT_LISTENER); + soup_server_add_handler (server, NULL, mem_server_callback, NULL, NULL); + + input = g_memory_input_stream_new_from_data (req, sizeof(req), NULL); + output = g_memory_output_stream_new (NULL, 0, g_realloc, g_free); + stream = g_test_io_stream_new (input, output); + + addr = g_inet_socket_address_new_from_string ("127.0.0.1", 0); + + soup_server_accept_iostream (server, stream, addr, addr, &error); + g_assert_no_error (error); + + soup_test_server_quit_unref (server); + + reply = g_memory_output_stream_get_data (G_MEMORY_OUTPUT_STREAM (output)); + reply_size = g_memory_output_stream_get_data_size (G_MEMORY_OUTPUT_STREAM (output)); + g_assert_true (reply_size > 0); + g_assert_true (g_str_has_prefix (reply, "HTTP/1.0 200 OK")); + + g_clear_object (&addr); + g_clear_object (&stream); + g_clear_object (&input); + g_clear_object (&output); + g_clear_error (&error); +} + +typedef struct { + SoupServer *server; + SoupMessage *smsg; + gboolean handler_called; + gboolean paused; +} UnhandledServerData; + +static gboolean +idle_unpause_message (gpointer user_data) +{ + UnhandledServerData *usd = user_data; + + soup_server_unpause_message (usd->server, usd->smsg); + return FALSE; +} + +static void +unhandled_server_callback (SoupServer *server, SoupMessage *msg, + const char *path, GHashTable *query, + SoupClientContext *context, gpointer data) +{ + UnhandledServerData *usd = data; + + usd->handler_called = TRUE; + + if (soup_message_headers_get_one (msg->request_headers, "X-Test-Server-Pause")) { + usd->paused = TRUE; + usd->server = server; + usd->smsg = msg; + soup_server_pause_message (server, msg); + g_idle_add (idle_unpause_message, usd); + } +} + +static void +do_fail_404_test (ServerData *sd, gconstpointer test_data) +{ + SoupSession *session; + SoupMessage *msg; + UnhandledServerData usd; + + usd.handler_called = usd.paused = FALSE; + + server_add_handler (sd, "/not-a-match", unhandled_server_callback, &usd, NULL); + + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + msg = soup_message_new_from_uri ("GET", sd->base_uri); + soup_session_send_message (session, msg); + soup_test_assert_message_status (msg, SOUP_STATUS_NOT_FOUND); + g_object_unref (msg); + + g_assert_false (usd.handler_called); + g_assert_false (usd.paused); + + soup_test_session_abort_unref (session); +} + +static void +do_fail_500_test (ServerData *sd, gconstpointer pause) +{ + SoupSession *session; + SoupMessage *msg; + UnhandledServerData usd; + + usd.handler_called = usd.paused = FALSE; + + server_add_handler (sd, NULL, unhandled_server_callback, &usd, NULL); + + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + msg = soup_message_new_from_uri ("GET", sd->base_uri); + if (pause) + soup_message_headers_append (msg->request_headers, "X-Test-Server-Pause", "true"); + soup_session_send_message (session, msg); + soup_test_assert_message_status (msg, SOUP_STATUS_INTERNAL_SERVER_ERROR); + g_object_unref (msg); + + g_assert_true (usd.handler_called); + if (pause) + g_assert_true (usd.paused); + else + g_assert_false (usd.paused); + + soup_test_session_abort_unref (session); +} + +static void +stream_got_chunk (SoupMessage *msg, SoupBuffer *chunk, gpointer user_data) +{ + GChecksum *checksum = user_data; + + g_checksum_update (checksum, (const guchar *)chunk->data, chunk->length); +} + +static void +stream_got_body (SoupMessage *msg, gpointer user_data) +{ + GChecksum *checksum = user_data; + const char *md5 = g_checksum_get_string (checksum); + + soup_message_set_status (msg, SOUP_STATUS_OK); + soup_message_set_response (msg, "text/plain", SOUP_MEMORY_COPY, + md5, strlen (md5)); + g_checksum_free (checksum); +} + +static void +early_stream_callback (SoupServer *server, SoupMessage *msg, + const char *path, GHashTable *query, + SoupClientContext *context, gpointer data) +{ + GChecksum *checksum; + + if (msg->method != SOUP_METHOD_POST) { + soup_message_set_status (msg, SOUP_STATUS_METHOD_NOT_ALLOWED); + return; + } + + checksum = g_checksum_new (G_CHECKSUM_MD5); + g_signal_connect (msg, "got-chunk", + G_CALLBACK (stream_got_chunk), checksum); + g_signal_connect (msg, "got-body", + G_CALLBACK (stream_got_body), checksum); + + soup_message_body_set_accumulate (msg->request_body, TRUE); +} + +static void +do_early_stream_test (ServerData *sd, gconstpointer test_data) +{ + SoupSession *session; + SoupMessage *msg; + SoupBuffer *index; + char *md5; + + server_add_early_handler (sd, NULL, early_stream_callback, NULL, NULL); + + session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL); + + msg = soup_message_new_from_uri ("POST", sd->base_uri); + + index = soup_test_get_index (); + soup_message_body_append (msg->request_body, SOUP_MEMORY_COPY, + index->data, index->length); + soup_session_send_message (session, msg); + + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + + md5 = g_compute_checksum_for_data (G_CHECKSUM_MD5, + (guchar *) index->data, index->length); + g_assert_cmpstr (md5, ==, msg->response_body->data); + g_free (md5); + + g_object_unref (msg); + soup_test_session_abort_unref (session); +} + +static void +early_respond_callback (SoupServer *server, SoupMessage *msg, + const char *path, GHashTable *query, + SoupClientContext *context, gpointer data) +{ + if (!strcmp (path, "/")) + soup_message_set_status (msg, SOUP_STATUS_FORBIDDEN); +} + +static void +do_early_respond_test (ServerData *sd, gconstpointer test_data) +{ + SoupSession *session; + SoupMessage *msg; + SoupURI *uri2; + + server_add_early_handler (sd, NULL, early_respond_callback, NULL, NULL); + + session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL); + + /* The early handler will intercept, and the normal handler will be skipped */ + msg = soup_message_new_from_uri ("GET", sd->base_uri); + soup_session_send_message (session, msg); + soup_test_assert_message_status (msg, SOUP_STATUS_FORBIDDEN); + g_assert_cmpint (msg->response_body->length, ==, 0); + g_object_unref (msg); + + /* The early handler will ignore this one */ + uri2 = soup_uri_new_with_base (sd->base_uri, "/subdir"); + msg = soup_message_new_from_uri ("GET", uri2); + soup_session_send_message (session, msg); + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + g_assert_cmpstr (msg->response_body->data, ==, "index"); + g_object_unref (msg); + soup_uri_free (uri2); + + soup_test_session_abort_unref (session); +} + +static void +early_multi_callback (SoupServer *server, SoupMessage *msg, + const char *path, GHashTable *query, + SoupClientContext *context, gpointer data) +{ + soup_message_headers_append (msg->response_headers, "X-Early", "yes"); +} + +static void +do_early_multi_test (ServerData *sd, gconstpointer test_data) +{ + SoupSession *session; + SoupMessage *msg; + SoupURI *uri; + struct { + const char *path; + gboolean expect_normal, expect_early; + } multi_tests[] = { + { "/", FALSE, FALSE }, + { "/normal", TRUE, FALSE }, + { "/normal/subdir", TRUE, FALSE }, + { "/normal/early", FALSE, TRUE }, + { "/normal/early/subdir", FALSE, TRUE }, + { "/early", FALSE, TRUE }, + { "/early/subdir", FALSE, TRUE }, + { "/early/normal", TRUE, FALSE }, + { "/early/normal/subdir", TRUE, FALSE }, + { "/both", TRUE, TRUE }, + { "/both/subdir", TRUE, TRUE } + }; + int i; + const char *header; + + server_add_handler (sd, "/normal", server_callback, NULL, NULL); + server_add_early_handler (sd, "/normal/early", early_multi_callback, NULL, NULL); + server_add_early_handler (sd, "/early", early_multi_callback, NULL, NULL); + server_add_handler (sd, "/early/normal", server_callback, NULL, NULL); + server_add_handler (sd, "/both", server_callback, NULL, NULL); + server_add_early_handler (sd, "/both", early_multi_callback, NULL, NULL); + + session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL); + + for (i = 0; i < G_N_ELEMENTS (multi_tests); i++) { + uri = soup_uri_new_with_base (sd->base_uri, multi_tests[i].path); + msg = soup_message_new_from_uri ("GET", uri); + soup_uri_free (uri); + + soup_session_send_message (session, msg); + + /* The normal handler sets status to OK. The early handler doesn't + * touch status, meaning that if it runs and the normal handler doesn't, + * then SoupServer will set the status to INTERNAL_SERVER_ERROR + * (since a handler ran, but didn't set the status). If neither handler + * runs then SoupServer will set the status to NOT_FOUND. + */ + if (multi_tests[i].expect_normal) + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + else if (multi_tests[i].expect_early) + soup_test_assert_message_status (msg, SOUP_STATUS_INTERNAL_SERVER_ERROR); + else + soup_test_assert_message_status (msg, SOUP_STATUS_NOT_FOUND); + + header = soup_message_headers_get_one (msg->response_headers, "X-Early"); + if (multi_tests[i].expect_early) + g_assert_cmpstr (header, ==, "yes"); + else + g_assert_cmpstr (header, ==, NULL); + if (multi_tests[i].expect_normal) + g_assert_cmpstr (msg->response_body->data, ==, "index"); + else + g_assert_cmpint (msg->response_body->length, ==, 0); + + g_object_unref (msg); + } + + soup_test_session_abort_unref (session); +} + +typedef struct { + GIOStream *iostream; + GInputStream *istream; + GOutputStream *ostream; + + gssize nread, nwrote; + guchar *buffer; +} TunnelEnd; + +typedef struct { + SoupServer *self; + SoupMessage *msg; + SoupClientContext *context; + GCancellable *cancellable; + + TunnelEnd client, server; +} Tunnel; + +#define BUFSIZE 8192 + +static void tunnel_read_cb (GObject *object, + GAsyncResult *result, + gpointer user_data); + +static void +tunnel_close (Tunnel *tunnel) +{ + if (tunnel->cancellable) { + g_cancellable_cancel (tunnel->cancellable); + g_object_unref (tunnel->cancellable); + } + + if (tunnel->client.iostream) { + g_io_stream_close (tunnel->client.iostream, NULL, NULL); + g_object_unref (tunnel->client.iostream); + } + if (tunnel->server.iostream) { + g_io_stream_close (tunnel->server.iostream, NULL, NULL); + g_object_unref (tunnel->server.iostream); + } + + g_free (tunnel->client.buffer); + g_free (tunnel->server.buffer); + + g_clear_object (&tunnel->self); + g_clear_object (&tunnel->msg); + + g_free (tunnel); +} + +static void +tunnel_wrote_cb (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + Tunnel *tunnel = user_data; + TunnelEnd *write_end, *read_end; + GError *error = NULL; + gssize nwrote; + + nwrote = g_output_stream_write_finish (G_OUTPUT_STREAM (object), result, &error); + if (nwrote <= 0) { + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + g_error_free (error); + return; + } else if (error) { + g_print ("Tunnel write failed: %s\n", error->message); + g_error_free (error); + } + tunnel_close (tunnel); + return; + } + + if (object == (GObject *)tunnel->client.ostream) { + write_end = &tunnel->client; + read_end = &tunnel->server; + } else { + write_end = &tunnel->server; + read_end = &tunnel->client; + } + + write_end->nwrote += nwrote; + if (write_end->nwrote < read_end->nread) { + g_output_stream_write_async (write_end->ostream, + read_end->buffer + write_end->nwrote, + read_end->nread - write_end->nwrote, + G_PRIORITY_DEFAULT, tunnel->cancellable, + tunnel_wrote_cb, tunnel); + } else { + g_input_stream_read_async (read_end->istream, + read_end->buffer, BUFSIZE, + G_PRIORITY_DEFAULT, tunnel->cancellable, + tunnel_read_cb, tunnel); + } +} + +static void +tunnel_read_cb (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + Tunnel *tunnel = user_data; + TunnelEnd *read_end, *write_end; + GError *error = NULL; + gssize nread; + + nread = g_input_stream_read_finish (G_INPUT_STREAM (object), result, &error); + if (nread <= 0) { + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + g_error_free (error); + return; + } else if (error) { + g_print ("Tunnel read failed: %s\n", error->message); + g_error_free (error); + } + tunnel_close (tunnel); + return; + } + + if (object == (GObject *)tunnel->client.istream) { + read_end = &tunnel->client; + write_end = &tunnel->server; + } else { + read_end = &tunnel->server; + write_end = &tunnel->client; + } + + read_end->nread = nread; + write_end->nwrote = 0; + g_output_stream_write_async (write_end->ostream, + read_end->buffer, read_end->nread, + G_PRIORITY_DEFAULT, tunnel->cancellable, + tunnel_wrote_cb, tunnel); +} + +static void +start_tunnel (SoupMessage *msg, gpointer user_data) +{ + Tunnel *tunnel = user_data; + + tunnel->client.iostream = soup_client_context_steal_connection (tunnel->context); + tunnel->client.istream = g_io_stream_get_input_stream (tunnel->client.iostream); + tunnel->client.ostream = g_io_stream_get_output_stream (tunnel->client.iostream); + g_clear_object (&tunnel->self); + g_clear_object (&tunnel->msg); + + tunnel->client.buffer = g_malloc (BUFSIZE); + tunnel->server.buffer = g_malloc (BUFSIZE); + + tunnel->cancellable = g_cancellable_new (); + + g_input_stream_read_async (tunnel->client.istream, + tunnel->client.buffer, BUFSIZE, + G_PRIORITY_DEFAULT, tunnel->cancellable, + tunnel_read_cb, tunnel); + g_input_stream_read_async (tunnel->server.istream, + tunnel->server.buffer, BUFSIZE, + G_PRIORITY_DEFAULT, tunnel->cancellable, + tunnel_read_cb, tunnel); +} + + +static void +tunnel_connected_cb (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + Tunnel *tunnel = user_data; + GError *error = NULL; + + tunnel->server.iostream = (GIOStream *) + g_socket_client_connect_to_host_finish (G_SOCKET_CLIENT (object), result, &error); + if (!tunnel->server.iostream) { + soup_message_set_status (tunnel->msg, SOUP_STATUS_BAD_GATEWAY); + soup_message_set_response (tunnel->msg, "text/plain", + SOUP_MEMORY_COPY, + error->message, strlen (error->message)); + g_error_free (error); + soup_server_unpause_message (tunnel->self, tunnel->msg); + tunnel_close (tunnel); + return; + } + + tunnel->server.istream = g_io_stream_get_input_stream (tunnel->server.iostream); + tunnel->server.ostream = g_io_stream_get_output_stream (tunnel->server.iostream); + + soup_message_set_status (tunnel->msg, SOUP_STATUS_OK); + soup_server_unpause_message (tunnel->self, tunnel->msg); + g_signal_connect (tunnel->msg, "wrote-body", + G_CALLBACK (start_tunnel), tunnel); +} + +static void +proxy_server_callback (SoupServer *server, SoupMessage *msg, + const char *path, GHashTable *query, + SoupClientContext *context, gpointer data) +{ + GSocketClient *sclient; + SoupURI *dest_uri; + Tunnel *tunnel; + + if (msg->method != SOUP_METHOD_CONNECT) { + soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED); + return; + } + + soup_server_pause_message (server, msg); + + tunnel = g_new0 (Tunnel, 1); + tunnel->self = g_object_ref (server); + tunnel->msg = g_object_ref (msg); + tunnel->context = context; + + dest_uri = soup_message_get_uri (msg); + sclient = g_socket_client_new (); + g_socket_client_connect_to_host_async (sclient, dest_uri->host, dest_uri->port, + NULL, tunnel_connected_cb, tunnel); + g_object_unref (sclient); +} + +static void +do_steal_connect_test (ServerData *sd, gconstpointer test_data) +{ + SoupServer *proxy; + SoupURI *proxy_uri; + SoupSession *session; + SoupMessage *msg; + const char *handled_by; + + SOUP_TEST_SKIP_IF_NO_TLS; + + proxy = soup_test_server_new (SOUP_TEST_SERVER_IN_THREAD); + proxy_uri = soup_test_server_get_uri (proxy, SOUP_URI_SCHEME_HTTP, "127.0.0.1"); + soup_server_add_handler (proxy, NULL, proxy_server_callback, NULL, NULL); + + session = soup_test_session_new (SOUP_TYPE_SESSION, + SOUP_SESSION_PROXY_URI, proxy_uri, + NULL); + msg = soup_message_new_from_uri ("GET", sd->ssl_base_uri); + soup_session_send_message (session, msg); + + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + handled_by = soup_message_headers_get_one (msg->response_headers, "X-Handled-By"); + g_assert_cmpstr (handled_by, ==, "server_callback"); + + g_object_unref (msg); + soup_test_session_abort_unref (session); + + soup_test_server_quit_unref (proxy); + soup_uri_free (proxy_uri); +} + +int +main (int argc, char **argv) +{ + int ret; + + test_init (argc, argv, NULL); + + g_test_add ("/server/OPTIONS *", ServerData, NULL, + server_setup, do_star_test, server_teardown); + g_test_add ("/server/aliases", ServerData, NULL, + server_setup, do_server_aliases_test, server_teardown); + g_test_add ("/server/..-in-path", ServerData, NULL, + server_setup, do_dot_dot_test, server_teardown); + g_test_add ("/server/ipv6", ServerData, NULL, + NULL, do_ipv6_test, server_teardown); + g_test_add ("/server/multi/port", ServerData, NULL, + NULL, do_multi_port_test, server_teardown); + g_test_add ("/server/multi/scheme", ServerData, NULL, + NULL, do_multi_scheme_test, server_teardown); + g_test_add ("/server/multi/family", ServerData, NULL, + NULL, do_multi_family_test, server_teardown); + g_test_add_func ("/server/import/gsocket", do_gsocket_import_test); + g_test_add_func ("/server/import/fd", do_fd_import_test); + g_test_add_func ("/server/accept/iostream", do_iostream_accept_test); + g_test_add ("/server/fail/404", ServerData, NULL, + server_setup_nohandler, do_fail_404_test, server_teardown); + g_test_add ("/server/fail/500", ServerData, GINT_TO_POINTER (FALSE), + server_setup_nohandler, do_fail_500_test, server_teardown); + g_test_add ("/server/fail/500-pause", ServerData, GINT_TO_POINTER (TRUE), + server_setup_nohandler, do_fail_500_test, server_teardown); + g_test_add ("/server/early/stream", ServerData, NULL, + server_setup_nohandler, do_early_stream_test, server_teardown); + g_test_add ("/server/early/respond", ServerData, NULL, + server_setup, do_early_respond_test, server_teardown); + g_test_add ("/server/early/multi", ServerData, NULL, + server_setup_nohandler, do_early_multi_test, server_teardown); + g_test_add ("/server/steal/CONNECT", ServerData, NULL, + server_setup, do_steal_connect_test, server_teardown); + + ret = g_test_run (); + + test_cleanup (); + return ret; +} diff --git a/tests/session-test.c b/tests/session-test.c new file mode 100644 index 0000000..8957a25 --- /dev/null +++ b/tests/session-test.c @@ -0,0 +1,399 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ + +#include "test-utils.h" + +static gboolean server_processed_message; +static gboolean timeout; +static GMainLoop *loop; +static SoupMessagePriority expected_priorities[3]; + +static gboolean +timeout_cb (gpointer user_data) +{ + gboolean *timeout = user_data; + + *timeout = TRUE; + return FALSE; +} + +static void +server_handler (SoupServer *server, + SoupMessage *msg, + const char *path, + GHashTable *query, + SoupClientContext *client, + gpointer user_data) +{ + if (!strcmp (path, "/request-timeout")) { + GMainContext *context = g_main_context_get_thread_default (); + GSource *timer; + + timer = g_timeout_source_new (100); + g_source_set_callback (timer, timeout_cb, &timeout, NULL); + g_source_attach (timer, context); + g_source_unref (timer); + } else + server_processed_message = TRUE; + + soup_message_set_status (msg, SOUP_STATUS_OK); + soup_message_set_response (msg, "text/plain", + SOUP_MEMORY_STATIC, + "ok\r\n", 4); +} + +static void +finished_cb (SoupSession *session, SoupMessage *msg, gpointer user_data) +{ + gboolean *finished = user_data; + + *finished = TRUE; +} + +static void +cancel_message_cb (SoupMessage *msg, gpointer session) +{ + soup_session_cancel_message (session, msg, SOUP_STATUS_CANCELLED); + g_main_loop_quit (loop); +} + +static void +do_test_for_session (SoupSession *session, SoupURI *uri, + gboolean queue_is_async, + gboolean send_is_blocking, + gboolean cancel_is_immediate) +{ + SoupMessage *msg; + gboolean finished, local_timeout; + guint timeout_id; + SoupURI *timeout_uri; + + debug_printf (1, " queue_message\n"); + debug_printf (2, " requesting timeout\n"); + timeout_uri = soup_uri_new_with_base (uri, "/request-timeout"); + msg = soup_message_new_from_uri ("GET", timeout_uri); + soup_uri_free (timeout_uri); + soup_session_send_message (session, msg); + g_object_unref (msg); + + msg = soup_message_new_from_uri ("GET", uri); + server_processed_message = timeout = finished = FALSE; + soup_session_queue_message (session, msg, finished_cb, &finished); + while (!timeout) + g_usleep (100); + debug_printf (2, " got timeout\n"); + + if (queue_is_async) { + g_assert_false (server_processed_message); + debug_printf (2, " waiting for finished\n"); + while (!finished) + g_main_context_iteration (NULL, TRUE); + g_assert_true (server_processed_message); + } else { + g_assert_true (server_processed_message); + g_assert_false (finished); + debug_printf (2, " waiting for finished\n"); + while (!finished) + g_main_context_iteration (NULL, TRUE); + } + + debug_printf (1, " send_message\n"); + msg = soup_message_new_from_uri ("GET", uri); + server_processed_message = local_timeout = FALSE; + timeout_id = g_idle_add_full (G_PRIORITY_HIGH, timeout_cb, &local_timeout, NULL); + soup_session_send_message (session, msg); + g_object_unref (msg); + + g_assert_true (server_processed_message); + + if (send_is_blocking) { + soup_test_assert (!local_timeout, + "send_message ran main loop"); + } else { + soup_test_assert (local_timeout, + "send_message didn't run main loop"); + } + + if (!local_timeout) + g_source_remove (timeout_id); + + if (!queue_is_async) + return; + + debug_printf (1, " cancel_message\n"); + msg = soup_message_new_from_uri ("GET", uri); + g_object_ref (msg); + finished = FALSE; + soup_session_queue_message (session, msg, finished_cb, &finished); + g_signal_connect (msg, "wrote-headers", + G_CALLBACK (cancel_message_cb), session); + + loop = g_main_loop_new (NULL, FALSE); + g_main_loop_run (loop); + + if (cancel_is_immediate) + g_assert_true (finished); + else + g_assert_false (finished); + + if (!finished) { + debug_printf (2, " waiting for finished\n"); + while (!finished) + g_main_context_iteration (NULL, TRUE); + } + g_main_loop_unref (loop); + + soup_test_assert_message_status (msg, SOUP_STATUS_CANCELLED); + g_object_unref (msg); +} + +static void +do_plain_tests (gconstpointer data) +{ + SoupURI *uri = (SoupURI *)data; + SoupSession *session; + + session = soup_test_session_new (SOUP_TYPE_SESSION, NULL); + do_test_for_session (session, uri, TRUE, TRUE, FALSE); + soup_test_session_abort_unref (session); +} + +static void +do_async_tests (gconstpointer data) +{ + SoupURI *uri = (SoupURI *)data; + SoupSession *session; + + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + do_test_for_session (session, uri, TRUE, FALSE, TRUE); + soup_test_session_abort_unref (session); +} + +static void +do_sync_tests (gconstpointer data) +{ + SoupURI *uri = (SoupURI *)data; + SoupSession *session; + + session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL); + do_test_for_session (session, uri, FALSE, TRUE, FALSE); + soup_test_session_abort_unref (session); +} + +static void +priority_test_finished_cb (SoupSession *session, SoupMessage *msg, gpointer user_data) +{ + guint *finished_count = user_data; + SoupMessagePriority priority = soup_message_get_priority (msg); + + debug_printf (1, " received message %d with priority %d\n", + *finished_count, priority); + + soup_test_assert (priority == expected_priorities[*finished_count], + "message %d should have priority %d (%d found)", + *finished_count, expected_priorities[*finished_count], priority); + + (*finished_count)++; +} + +static void +do_priority_tests (gconstpointer data) +{ + SoupURI *uri = (SoupURI *)data; + SoupSession *session; + int i, finished_count = 0; + SoupMessagePriority priorities[] = + { SOUP_MESSAGE_PRIORITY_LOW, + SOUP_MESSAGE_PRIORITY_HIGH, + SOUP_MESSAGE_PRIORITY_NORMAL }; + + g_test_bug ("696277"); + + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + g_object_set (session, "max-conns", 1, NULL); + + expected_priorities[0] = SOUP_MESSAGE_PRIORITY_HIGH; + expected_priorities[1] = SOUP_MESSAGE_PRIORITY_NORMAL; + expected_priorities[2] = SOUP_MESSAGE_PRIORITY_LOW; + + for (i = 0; i < 3; i++) { + SoupURI *msg_uri; + SoupMessage *msg; + char buf[5]; + + g_snprintf (buf, sizeof (buf), "%d", i); + msg_uri = soup_uri_new_with_base (uri, buf); + msg = soup_message_new_from_uri ("GET", msg_uri); + soup_uri_free (msg_uri); + + soup_message_set_priority (msg, priorities[i]); + soup_session_queue_message (session, msg, priority_test_finished_cb, &finished_count); + } + + debug_printf (2, " waiting for finished\n"); + while (finished_count != 3) + g_main_context_iteration (NULL, TRUE); + + soup_test_session_abort_unref (session); +} + +static void +test_session_properties (const char *name, + SoupSession *session, + GProxyResolver *expected_proxy_resolver, + GTlsDatabase *expected_tls_database) +{ + GProxyResolver *proxy_resolver = NULL; + GTlsDatabase *tlsdb = NULL; + + g_object_get (G_OBJECT (session), + SOUP_SESSION_PROXY_RESOLVER, &proxy_resolver, + SOUP_SESSION_TLS_DATABASE, &tlsdb, + NULL); + + soup_test_assert (proxy_resolver == expected_proxy_resolver, + "%s has %s proxy resolver", + name, proxy_resolver ? (expected_proxy_resolver ? "wrong" : "a") : "no"); + soup_test_assert (tlsdb == expected_tls_database, + "%s has %s TLS database", + name, tlsdb ? (expected_tls_database ? "wrong" : "a") : "no"); + + g_clear_object (&proxy_resolver); + g_clear_object (&tlsdb); +} + +static void +do_property_tests (void) +{ + SoupSession *session; + GProxyResolver *proxy_resolver, *default_proxy_resolver; + GTlsDatabase *tlsdb, *default_tlsdb; + SoupURI *uri; + + g_test_bug ("708696"); + + default_proxy_resolver = g_proxy_resolver_get_default (); + default_tlsdb = g_tls_backend_get_default_database (g_tls_backend_get_default ()); + + /* NOTE: We intentionally do not use soup_test_session_new() here */ + + session = g_object_new (SOUP_TYPE_SESSION, + NULL); + test_session_properties ("Base plain session", session, + default_proxy_resolver, default_tlsdb); + g_object_unref (session); + + session = g_object_new (SOUP_TYPE_SESSION, + SOUP_SESSION_PROXY_RESOLVER, NULL, + NULL); + test_session_properties ("Session with NULL :proxy-resolver", session, + NULL, default_tlsdb); + g_object_unref (session); + + proxy_resolver = g_simple_proxy_resolver_new (NULL, NULL); + session = g_object_new (SOUP_TYPE_SESSION, + SOUP_SESSION_PROXY_RESOLVER, proxy_resolver, + NULL); + test_session_properties ("Session with non-NULL :proxy-resolver", session, + proxy_resolver, default_tlsdb); + g_object_unref (proxy_resolver); + g_object_unref (session); + + session = g_object_new (SOUP_TYPE_SESSION, + SOUP_SESSION_PROXY_URI, NULL, + NULL); + test_session_properties ("Session with NULL :proxy-uri", session, + NULL, default_tlsdb); + g_object_unref (session); + + uri = soup_uri_new ("http://example.com/"); + session = g_object_new (SOUP_TYPE_SESSION, + SOUP_SESSION_PROXY_URI, uri, + NULL); + g_object_get (G_OBJECT (session), + SOUP_SESSION_PROXY_RESOLVER, &proxy_resolver, + NULL); + test_session_properties ("Session with non-NULL :proxy-uri", session, + proxy_resolver, default_tlsdb); + g_assert_cmpstr (G_OBJECT_TYPE_NAME (proxy_resolver), ==, "GSimpleProxyResolver"); + g_object_unref (proxy_resolver); + g_object_unref (session); + soup_uri_free (uri); + + G_GNUC_BEGIN_IGNORE_DEPRECATIONS; + session = g_object_new (SOUP_TYPE_SESSION, + SOUP_SESSION_REMOVE_FEATURE_BY_TYPE, SOUP_TYPE_PROXY_URI_RESOLVER, + NULL); + test_session_properties ("Session with removed proxy resolver feature", session, + NULL, default_tlsdb); + g_object_unref (session); + G_GNUC_END_IGNORE_DEPRECATIONS; + + session = g_object_new (SOUP_TYPE_SESSION, + SOUP_SESSION_TLS_DATABASE, NULL, + NULL); + test_session_properties ("Session with NULL :tls-database", session, + default_proxy_resolver, NULL); + g_object_unref (session); + + /* g_tls_file_database_new() will fail with the dummy backend, + * so we can only do this test if we have a real TLS backend. + */ + if (tls_available) { + GError *error = NULL; + + tlsdb = g_tls_file_database_new (g_test_get_filename (G_TEST_DIST, + "test-cert.pem", + NULL), &error); + g_assert_no_error (error); + + session = g_object_new (SOUP_TYPE_SESSION, + SOUP_SESSION_TLS_DATABASE, tlsdb, + NULL); + test_session_properties ("Session with non-NULL :tls-database", session, + default_proxy_resolver, tlsdb); + g_object_unref (tlsdb); + g_object_unref (session); + } + + session = g_object_new (SOUP_TYPE_SESSION, + SOUP_SESSION_SSL_USE_SYSTEM_CA_FILE, FALSE, + NULL); + test_session_properties ("Session with :ssl-use-system-ca-file FALSE", session, + default_proxy_resolver, NULL); + g_object_unref (session); + + session = g_object_new (SOUP_TYPE_SESSION, + SOUP_SESSION_SSL_USE_SYSTEM_CA_FILE, TRUE, + NULL); + test_session_properties ("Session with :ssl-use-system-ca-file TRUE", session, + default_proxy_resolver, default_tlsdb); + g_object_unref (session); +} + +int +main (int argc, char **argv) +{ + SoupServer *server; + SoupURI *uri; + int ret; + + test_init (argc, argv, NULL); + + server = soup_test_server_new (TRUE); + soup_server_add_handler (server, NULL, server_handler, NULL, NULL); + uri = soup_test_server_get_uri (server, "http", NULL); + + g_test_add_data_func ("/session/SoupSession", uri, do_plain_tests); + g_test_add_data_func ("/session/SoupSessionAsync", uri, do_async_tests); + g_test_add_data_func ("/session/SoupSessionSync", uri, do_sync_tests); + g_test_add_data_func ("/session/priority", uri, do_priority_tests); + g_test_add_func ("/session/property", do_property_tests); + + ret = g_test_run (); + + soup_uri_free (uri); + soup_test_server_quit_unref (server); + + test_cleanup (); + return ret; +} diff --git a/tests/sniffing-test.c b/tests/sniffing-test.c new file mode 100644 index 0000000..7b39117 --- /dev/null +++ b/tests/sniffing-test.c @@ -0,0 +1,618 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2009 Gustavo Noronha Silva . + */ + +#include "test-utils.h" + +SoupSession *session; +SoupURI *base_uri; +SoupMessageBody *chunk_data; + +static void +server_callback (SoupServer *server, SoupMessage *msg, + const char *path, GHashTable *query, + SoupClientContext *context, gpointer data) +{ + GError *error = NULL; + char *query_key; + SoupBuffer *response = NULL; + gsize offset; + gboolean empty_response = FALSE; + + if (msg->method != SOUP_METHOD_GET) { + soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED); + return; + } + + soup_message_set_status (msg, SOUP_STATUS_OK); + + if (query) { + query_key = g_hash_table_lookup (query, "chunked"); + if (query_key && g_str_equal (query_key, "yes")) { + soup_message_headers_set_encoding (msg->response_headers, + SOUP_ENCODING_CHUNKED); + } + + query_key = g_hash_table_lookup (query, "empty_response"); + if (query_key && g_str_equal (query_key, "yes")) + empty_response = TRUE; + } + + if (!strcmp (path, "/mbox")) { + if (!empty_response) { + response = soup_test_load_resource ("mbox", &error); + g_assert_no_error (error); + } + + soup_message_headers_append (msg->response_headers, + "Content-Type", "text/plain"); + } + + if (g_str_has_prefix (path, "/nosniff/")) { + char *base_name = g_path_get_basename (path); + + response = soup_test_load_resource (base_name, &error); + g_assert_no_error (error); + g_free (base_name); + + soup_message_headers_append (msg->response_headers, + "X-Content-Type-Options", "nosniff"); + + soup_message_headers_append (msg->response_headers, + "Content-Type", "no/sniffing-allowed"); + } + + if (g_str_has_prefix (path, "/text_or_binary/") || g_str_has_prefix (path, "/apache_bug/")) { + char *base_name = g_path_get_basename (path); + + response = soup_test_load_resource (base_name, &error); + g_assert_no_error (error); + g_free (base_name); + + soup_message_headers_append (msg->response_headers, + "Content-Type", "text/plain"); + } + + if (g_str_has_prefix (path, "/unknown/")) { + char *base_name = g_path_get_basename (path); + + response = soup_test_load_resource (base_name, &error); + g_assert_no_error (error); + g_free (base_name); + + soup_message_headers_append (msg->response_headers, + "Content-Type", "UNKNOWN/unknown"); + } + + if (g_str_has_prefix (path, "/type/")) { + char **components = g_strsplit (path, "/", 4); + char *ptr; + + char *base_name = g_path_get_basename (path); + + response = soup_test_load_resource (base_name, &error); + g_assert_no_error (error); + g_free (base_name); + + /* Hack to allow passing type in the URI */ + ptr = g_strrstr (components[2], "_"); + *ptr = '/'; + + soup_message_headers_append (msg->response_headers, + "Content-Type", components[2]); + g_strfreev (components); + } + + if (g_str_has_prefix (path, "/multiple_headers/")) { + char *base_name = g_path_get_basename (path); + + response = soup_test_load_resource (base_name, &error); + g_assert_no_error (error); + g_free (base_name); + + soup_message_headers_append (msg->response_headers, + "Content-Type", "text/xml"); + soup_message_headers_append (msg->response_headers, + "Content-Type", "text/plain"); + } + + if (response) { + for (offset = 0; offset < response->length; offset += 500) { + soup_message_body_append (msg->response_body, + SOUP_MEMORY_COPY, + response->data + offset, + MIN (500, response->length - offset)); + } + + soup_buffer_free (response); + } + + soup_message_body_complete (msg->response_body); +} + +static gboolean +unpause_msg (gpointer data) +{ + SoupMessage *msg = (SoupMessage*)data; + debug_printf (2, " unpause\n"); + soup_session_unpause_message (session, msg); + return FALSE; +} + + +static void +content_sniffed (SoupMessage *msg, char *content_type, GHashTable *params, gpointer data) +{ + gboolean should_pause = GPOINTER_TO_INT (data); + + debug_printf (2, " content-sniffed -> %s\n", content_type); + + soup_test_assert (g_object_get_data (G_OBJECT (msg), "got-chunk") == NULL, + "got-chunk got emitted before content-sniffed"); + + g_object_set_data (G_OBJECT (msg), "content-sniffed", GINT_TO_POINTER (TRUE)); + + if (should_pause) { + debug_printf (2, " pause\n"); + soup_session_pause_message (session, msg); + g_idle_add (unpause_msg, msg); + } +} + +static void +got_headers (SoupMessage *msg, gpointer data) +{ + gboolean should_pause = GPOINTER_TO_INT (data); + + debug_printf (2, " got-headers\n"); + + soup_test_assert (g_object_get_data (G_OBJECT (msg), "content-sniffed") == NULL, + "content-sniffed got emitted before got-headers"); + + g_object_set_data (G_OBJECT (msg), "got-headers", GINT_TO_POINTER (TRUE)); + + if (should_pause) { + debug_printf (2, " pause\n"); + soup_session_pause_message (session, msg); + g_idle_add (unpause_msg, msg); + } +} + +static void +got_chunk (SoupMessage *msg, SoupBuffer *chunk, gpointer data) +{ + gboolean should_accumulate = GPOINTER_TO_INT (data); + + debug_printf (2, " got-chunk\n"); + + g_object_set_data (G_OBJECT (msg), "got-chunk", GINT_TO_POINTER (TRUE)); + + if (!should_accumulate) { + if (!chunk_data) + chunk_data = soup_message_body_new (); + soup_message_body_append_buffer (chunk_data, chunk); + } +} + +static void +do_signals_test (gboolean should_content_sniff, + gboolean should_pause, + gboolean should_accumulate, + gboolean chunked_encoding, + gboolean empty_response) +{ + SoupURI *uri = soup_uri_new_with_base (base_uri, "/mbox"); + SoupMessage *msg = soup_message_new_from_uri ("GET", uri); + SoupBuffer *expected; + GError *error = NULL; + SoupBuffer *body = NULL; + + debug_printf (1, "do_signals_test(%ssniff, %spause, %saccumulate, %schunked, %sempty)\n", + should_content_sniff ? "" : "!", + should_pause ? "" : "!", + should_accumulate ? "" : "!", + chunked_encoding ? "" : "!", + empty_response ? "" : "!"); + + if (chunked_encoding) + soup_uri_set_query (uri, "chunked=yes"); + + if (empty_response) { + if (uri->query) { + char *tmp = uri->query; + uri->query = g_strdup_printf ("%s&empty_response=yes", tmp); + g_free (tmp); + } else + soup_uri_set_query (uri, "empty_response=yes"); + } + + soup_message_set_uri (msg, uri); + + soup_message_body_set_accumulate (msg->response_body, should_accumulate); + + g_object_connect (msg, + "signal::got-headers", got_headers, GINT_TO_POINTER (should_pause), + "signal::got-chunk", got_chunk, GINT_TO_POINTER (should_accumulate), + "signal::content_sniffed", content_sniffed, GINT_TO_POINTER (should_pause), + NULL); + + soup_session_send_message (session, msg); + + if (should_content_sniff) { + soup_test_assert (g_object_get_data (G_OBJECT (msg), "content-sniffed") != NULL, + "content-sniffed did not get emitted"); + } else { + soup_test_assert (g_object_get_data (G_OBJECT (msg), "content-sniffed") == NULL, + "content-sniffed got emitted without a sniffer"); + } + + if (empty_response) + expected = soup_buffer_new (SOUP_MEMORY_STATIC, "", 0); + else { + expected = soup_test_load_resource ("mbox", &error); + g_assert_no_error (error); + } + + if (!should_accumulate && chunk_data) + body = soup_message_body_flatten (chunk_data); + else if (msg->response_body) + body = soup_message_body_flatten (msg->response_body); + + if (body) { + soup_assert_cmpmem (body->data, body->length, + expected->data, expected->length); + } + + soup_buffer_free (expected); + if (body) + soup_buffer_free (body); + if (chunk_data) { + soup_message_body_free (chunk_data); + chunk_data = NULL; + } + + soup_uri_free (uri); + g_object_unref (msg); +} + +static void +do_signals_tests (gconstpointer data) +{ + gboolean should_content_sniff = GPOINTER_TO_INT (data); + + if (!should_content_sniff) + soup_session_remove_feature_by_type (session, SOUP_TYPE_CONTENT_SNIFFER); + + do_signals_test (should_content_sniff, + FALSE, FALSE, FALSE, FALSE); + do_signals_test (should_content_sniff, + FALSE, FALSE, TRUE, FALSE); + do_signals_test (should_content_sniff, + FALSE, TRUE, FALSE, FALSE); + do_signals_test (should_content_sniff, + FALSE, TRUE, TRUE, FALSE); + + do_signals_test (should_content_sniff, + TRUE, TRUE, FALSE, FALSE); + do_signals_test (should_content_sniff, + TRUE, TRUE, TRUE, FALSE); + do_signals_test (should_content_sniff, + TRUE, FALSE, FALSE, FALSE); + do_signals_test (should_content_sniff, + TRUE, FALSE, TRUE, FALSE); + + /* FIXME g_test_bug ("587907") */ + do_signals_test (should_content_sniff, + TRUE, TRUE, FALSE, TRUE); + do_signals_test (should_content_sniff, + TRUE, TRUE, TRUE, TRUE); + + if (!should_content_sniff) + soup_session_add_feature_by_type (session, SOUP_TYPE_CONTENT_SNIFFER); +} + +static void +sniffing_content_sniffed (SoupMessage *msg, const char *content_type, + GHashTable *params, gpointer data) +{ + char **sniffed_type = (char **)data; + GString *full_header; + GHashTableIter iter; + gpointer key, value; + + full_header = g_string_new (content_type); + + g_hash_table_iter_init (&iter, params); + while (g_hash_table_iter_next (&iter, &key, &value)) { + if (full_header->len) + g_string_append (full_header, "; "); + soup_header_g_string_append_param (full_header, + (const char *) key, + (const char *) value); + } + + *sniffed_type = g_string_free (full_header, FALSE); +} + +static void +test_sniffing (const char *path, const char *expected_type) +{ + SoupURI *uri; + SoupMessage *msg; + SoupRequest *req; + GInputStream *stream; + char *sniffed_type = NULL; + const char *req_sniffed_type; + GError *error = NULL; + + uri = soup_uri_new_with_base (base_uri, path); + msg = soup_message_new_from_uri ("GET", uri); + + g_signal_connect (msg, "content-sniffed", + G_CALLBACK (sniffing_content_sniffed), &sniffed_type); + + soup_session_send_message (session, msg); + g_assert_cmpstr (sniffed_type, ==, expected_type); + g_free (sniffed_type); + g_object_unref (msg); + + req = soup_session_request_uri (session, uri, NULL); + stream = soup_test_request_send (req, NULL, 0, &error); + if (stream) { + soup_test_request_close_stream (req, stream, NULL, &error); + g_object_unref (stream); + } + g_assert_no_error (error); + g_clear_error (&error); + + req_sniffed_type = soup_request_get_content_type (req); + g_assert_cmpstr (req_sniffed_type, ==, expected_type); + g_object_unref (req); + + soup_uri_free (uri); +} + +static void +do_sniffing_test (gconstpointer data) +{ + const char *path_and_result = data; + char **parts; + + parts = g_strsplit (path_and_result, " => ", -1); + g_assert (parts && parts[0] && parts[1] && !parts[2]); + + test_sniffing (parts[0], parts[1]); + g_strfreev (parts); +} + +static void +test_disabled (gconstpointer data) +{ + const char *path = data; + SoupURI *uri; + SoupMessage *msg; + SoupRequest *req; + GInputStream *stream; + char *sniffed_type = NULL; + const char *sniffed_content_type; + GError *error = NULL; + + g_test_bug ("574773"); + + uri = soup_uri_new_with_base (base_uri, path); + + msg = soup_message_new_from_uri ("GET", uri); + soup_message_disable_feature (msg, SOUP_TYPE_CONTENT_SNIFFER); + + g_signal_connect (msg, "content-sniffed", + G_CALLBACK (sniffing_content_sniffed), &sniffed_type); + + soup_session_send_message (session, msg); + + g_assert_null (sniffed_type); + g_object_unref (msg); + + req = soup_session_request_uri (session, uri, NULL); + msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (req)); + soup_message_disable_feature (msg, SOUP_TYPE_CONTENT_SNIFFER); + g_object_unref (msg); + stream = soup_test_request_send (req, NULL, 0, &error); + if (stream) { + soup_test_request_close_stream (req, stream, NULL, &error); + g_object_unref (stream); + } + g_assert_no_error (error); + + sniffed_content_type = soup_request_get_content_type (req); + g_assert_cmpstr (sniffed_content_type, ==, NULL); + + g_object_unref (req); + + soup_uri_free (uri); +} + +int +main (int argc, char **argv) +{ + SoupServer *server; + int ret; + + test_init (argc, argv, NULL); + + server = soup_test_server_new (SOUP_TEST_SERVER_IN_THREAD); + soup_server_add_handler (server, NULL, server_callback, NULL, NULL); + base_uri = soup_test_server_get_uri (server, "http", NULL); + + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, + SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, + NULL); + soup_session_add_feature_by_type (session, SOUP_TYPE_CONTENT_SNIFFER); + + g_test_add_data_func ("/sniffing/signals/no-sniffer", + GINT_TO_POINTER (FALSE), + do_signals_tests); + g_test_add_data_func ("/sniffing/signals/with-sniffer", + GINT_TO_POINTER (TRUE), + do_signals_tests); + + /* Test the apache bug sniffing path */ + g_test_add_data_func ("/sniffing/apache-bug/binary", + "/apache_bug/text_binary.txt => application/octet-stream", + do_sniffing_test); + g_test_add_data_func ("/sniffing/apache-bug/text", + "/apache_bug/text.txt => text/plain", + do_sniffing_test); + + /* X-Content-Type-Options: nosniff */ + g_test_add_data_func ("/sniffing/nosniff", + "nosniff/home.gif => no/sniffing-allowed", + do_sniffing_test); + + /* GIF is a 'safe' type */ + g_test_add_data_func ("/sniffing/type/gif", + "text_or_binary/home.gif => image/gif", + do_sniffing_test); + + /* With our current code, no sniffing is done using GIO, so + * the mbox will be identified as text/plain; should we change + * this? + */ + g_test_add_data_func ("/sniffing/type/mbox", + "text_or_binary/mbox => text/plain", + do_sniffing_test); + + /* HTML is considered unsafe for this algorithm, since it is + * scriptable, so going from text/plain to text/html is + * considered 'privilege escalation' + */ + g_test_add_data_func ("/sniffing/type/html-in-text-context", + "text_or_binary/test.html => text/plain", + do_sniffing_test); + + /* text/plain with binary content and unknown pattern should be + * application/octet-stream + */ + g_test_add_data_func ("/sniffing/type/text-binary", + "text_or_binary/text_binary.txt => application/octet-stream", + do_sniffing_test); + + /* text/html with binary content and scriptable pattern should be + * application/octet-stream to avoid 'privilege escalation' + */ + g_test_add_data_func ("/sniffing/type/html-binary", + "text_or_binary/html_binary.html => application/octet-stream", + do_sniffing_test); + + /* text/plain with binary content and non scriptable known pattern should + * be the given type + */ + g_test_add_data_func ("/sniffing/type/ps", + "text_or_binary/ps_binary.ps => application/postscript", + do_sniffing_test); + + /* Test the unknown sniffing path */ + g_test_add_data_func ("/sniffing/type/unknown-html", + "unknown/test.html => text/html", + do_sniffing_test); + g_test_add_data_func ("/sniffing/type/unknown-gif", + "unknown/home.gif => image/gif", + do_sniffing_test); + g_test_add_data_func ("/sniffing/type/unknown-mbox", + "unknown/mbox => text/plain", + do_sniffing_test); + g_test_add_data_func ("/sniffing/type/unknown-binary", + "unknown/text_binary.txt => application/octet-stream", + do_sniffing_test); + /* FIXME g_test_bug ("715126") */ + g_test_add_data_func ("/sniffing/type/unknown-leading-space", + "unknown/leading_space.html => text/html", + do_sniffing_test); + /* https://bugs.webkit.org/show_bug.cgi?id=173923 */ + g_test_add_data_func ("/sniffing/type/unknown-xml", + "unknown/misc.xml => text/xml", + do_sniffing_test); + + /* Test the XML sniffing path */ + g_test_add_data_func ("/sniffing/type/xml", + "type/text_xml/home.gif => text/xml", + do_sniffing_test); + g_test_add_data_func ("/sniffing/type/xml+xml", + "type/anice_type+xml/home.gif => anice/type+xml", + do_sniffing_test); + g_test_add_data_func ("/sniffing/type/application-xml", + "type/application_xml/home.gif => application/xml", + do_sniffing_test); + + /* Test the feed or html path */ + g_test_add_data_func ("/sniffing/type/html/html", + "type/text_html/test.html => text/html", + do_sniffing_test); + g_test_add_data_func ("/sniffing/type/html/rss", + "type/text_html/rss20.xml => application/rss+xml", + do_sniffing_test); + g_test_add_data_func ("/sniffing/type/html/atom", + "type/text_html/atom.xml => application/atom+xml", + do_sniffing_test); + g_test_add_data_func ("/sniffing/type/html/rdf", + "type/text_html/feed.rdf => application/rss+xml", + do_sniffing_test); + + /* Test the image sniffing path */ + g_test_add_data_func ("/sniffing/type/image/gif", + "type/image_png/home.gif => image/gif", + do_sniffing_test); + g_test_add_data_func ("/sniffing/type/image/png", + "type/image_gif/home.png => image/png", + do_sniffing_test); + g_test_add_data_func ("/sniffing/type/image/jpeg", + "type/image_png/home.jpg => image/jpeg", + do_sniffing_test); + g_test_add_data_func ("/sniffing/type/image/webp", + "type/image_png/tux.webp => image/webp", + do_sniffing_test); + + /* Test audio and video sniffing path */ + g_test_add_data_func ("/sniffing/type/audio/wav", + "type/audio_mpeg/test.wav => audio/wave", + do_sniffing_test); + g_test_add_data_func ("/sniffing/type/audio/aiff", + "type/audio_mpeg/test.aiff => audio/aiff", + do_sniffing_test); + g_test_add_data_func ("/sniffing/type/audio/ogg", + "type/audio_mpeg/test.ogg => application/ogg", + do_sniffing_test); + g_test_add_data_func ("/sniffing/type/video/webm", + "type/video_theora/test.webm => video/webm", + do_sniffing_test); + + /* Test the MP4 sniffing path */ + g_test_add_data_func ("/sniffing/type/video/mp4", + "unknown/test.mp4 => video/mp4", + do_sniffing_test); + + /* The spec tells us to only use the last Content-Type header */ + g_test_add_data_func ("/sniffing/multiple-headers", + "multiple_headers/home.gif => image/gif", + do_sniffing_test); + + /* Test that we keep the parameters when sniffing */ + g_test_add_data_func ("/sniffing/parameters", + "type/text_html; charset=UTF-8/test.html => text/html; charset=UTF-8", + do_sniffing_test); + + /* Test that disabling the sniffer works correctly */ + g_test_add_data_func ("/sniffing/disabled", + "/text_or_binary/home.gif", + test_disabled); + + ret = g_test_run (); + + soup_uri_free (base_uri); + + soup_test_session_abort_unref (session); + soup_test_server_quit_unref (server); + + test_cleanup (); + return ret; +} diff --git a/tests/socket-test.c b/tests/socket-test.c new file mode 100644 index 0000000..5b2b390 --- /dev/null +++ b/tests/socket-test.c @@ -0,0 +1,357 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright 2007-2012 Red Hat, Inc. + * Copyright 2012 Nokia Corporation + */ + +#include "test-utils.h" +#include "libsoup/soup-socket-private.h" + +#include +#include + +static void +do_unconnected_socket_test (void) +{ + SoupAddress *localhost; + SoupSocket *sock; + SoupSocket *client; + SoupAddress *addr; + guint res; + struct sockaddr_in in_localhost; + + g_test_bug ("673083"); + + in_localhost.sin_family = AF_INET; + in_localhost.sin_port = 0; + in_localhost.sin_addr.s_addr = htonl (INADDR_LOOPBACK); + + localhost = soup_address_new_from_sockaddr ( + (struct sockaddr *) &in_localhost, sizeof (in_localhost)); + g_assert_true (localhost != NULL); + res = soup_address_resolve_sync (localhost, NULL); + g_assert_cmpuint (res, ==, SOUP_STATUS_OK); + + sock = soup_socket_new (SOUP_SOCKET_LOCAL_ADDRESS, localhost, + NULL); + g_assert_true (sock != NULL); + + addr = soup_socket_get_local_address (sock); + g_assert_true (addr != NULL); + g_assert_cmpstr (soup_address_get_physical (addr), ==, "127.0.0.1"); + g_assert_cmpuint (soup_address_get_port (addr), ==, 0); + + /* fails with ENOTCONN */ + g_test_expect_message ("libsoup", G_LOG_LEVEL_WARNING, + "*socket not connected*"); + addr = soup_socket_get_remote_address (sock); + g_test_assert_expected_messages (); + g_assert_null (addr); + + res = soup_socket_listen (sock); + g_assert_true (res); + + addr = soup_socket_get_local_address (sock); + g_assert_true (addr != NULL); + g_assert_cmpstr (soup_address_get_physical (addr), ==, "127.0.0.1"); + g_assert_cmpuint (soup_address_get_port (addr), >, 0); + + client = soup_socket_new (SOUP_SOCKET_REMOTE_ADDRESS, + soup_socket_get_local_address (sock), + NULL); + res = soup_socket_connect_sync (client, NULL); + g_assert_cmpuint (res, ==, SOUP_STATUS_OK); + addr = soup_socket_get_local_address (client); + g_assert_true (addr != NULL); + addr = soup_socket_get_remote_address (client); + g_assert_true (addr != NULL); + g_assert_cmpstr (soup_address_get_physical (addr), ==, "127.0.0.1"); + g_assert_cmpuint (soup_address_get_port (addr), >, 0); + g_object_unref (client); + + client = soup_socket_new (SOUP_SOCKET_REMOTE_ADDRESS, + soup_socket_get_local_address (sock), + NULL); + /* save it for later */ + + /* listening socket fails with ENOTCONN */ + g_test_expect_message ("libsoup", G_LOG_LEVEL_WARNING, + /* We can't check the error message since it comes from + * libc and is locale-dependent. + */ + "*"); + addr = soup_socket_get_remote_address (sock); + g_test_assert_expected_messages (); + g_assert_null (addr); + + soup_socket_disconnect (sock); + + g_test_expect_message ("libsoup", G_LOG_LEVEL_WARNING, + /* This error message comes from soup-socket.c though */ + "*socket not connected*"); + addr = soup_socket_get_remote_address (sock); + g_test_assert_expected_messages (); + g_assert_null (addr); + + /* has never been connected */ + g_test_expect_message ("libsoup", G_LOG_LEVEL_WARNING, + "*socket not connected*"); + addr = soup_socket_get_local_address (client); + g_test_assert_expected_messages (); + g_assert_null (addr); + + res = soup_socket_connect_sync (client, NULL); + g_assert_cmpuint (res, ==, SOUP_STATUS_CANT_CONNECT); + + g_test_expect_message ("libsoup", G_LOG_LEVEL_WARNING, + "*socket not connected*"); + addr = soup_socket_get_local_address (client); + g_test_assert_expected_messages (); + g_assert_null (addr); + + g_object_unref (localhost); + g_object_unref (client); + g_object_unref (sock); +} + +static void +do_socket_from_fd_client_test (void) +{ + SoupServer *server; + SoupURI *uri; + GSocket *gsock; + SoupSocket *sock; + SoupAddress *local, *remote; + GSocketAddress *gaddr; + gboolean is_server; + GError *error = NULL; + + server = soup_test_server_new (SOUP_TEST_SERVER_DEFAULT); + uri = soup_test_server_get_uri (server, "http", "127.0.0.1"); + + gsock = g_socket_new (G_SOCKET_FAMILY_IPV4, + G_SOCKET_TYPE_STREAM, + G_SOCKET_PROTOCOL_DEFAULT, + &error); + g_assert_no_error (error); + + gaddr = g_inet_socket_address_new_from_string ("127.0.0.1", uri->port); + g_socket_connect (gsock, gaddr, NULL, &error); + g_object_unref (gaddr); + g_assert_no_error (error); + g_assert_true (g_socket_is_connected (gsock)); + + gaddr = g_socket_get_local_address (gsock, &error); + g_assert_no_error (error); + + sock = g_initable_new (SOUP_TYPE_SOCKET, NULL, &error, + SOUP_SOCKET_FD, g_socket_get_fd (gsock), + NULL); + g_assert_no_error (error); + g_assert_nonnull (sock); + + g_object_get (G_OBJECT (sock), + SOUP_SOCKET_LOCAL_ADDRESS, &local, + SOUP_SOCKET_REMOTE_ADDRESS, &remote, + SOUP_SOCKET_IS_SERVER, &is_server, + NULL); + g_assert_cmpint (soup_socket_get_fd (sock), ==, g_socket_get_fd (gsock)); + g_assert_false (is_server); + g_assert_true (soup_socket_is_connected (sock)); + + g_assert_cmpstr (soup_address_get_physical (local), ==, "127.0.0.1"); + g_assert_cmpint (soup_address_get_port (local), ==, g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (gaddr))); + g_assert_cmpstr (soup_address_get_physical (remote), ==, "127.0.0.1"); + g_assert_cmpint (soup_address_get_port (remote), ==, uri->port); + + g_object_unref (local); + g_object_unref (remote); + g_object_unref (gaddr); + + g_object_unref (sock); + g_object_unref (gsock); + + soup_test_server_quit_unref (server); + soup_uri_free (uri); +} + +static void +do_socket_from_fd_server_test (void) +{ + GSocket *gsock; + SoupSocket *sock; + SoupAddress *local; + GSocketAddress *gaddr; + gboolean is_server; + GError *error = NULL; + + gsock = g_socket_new (G_SOCKET_FAMILY_IPV4, + G_SOCKET_TYPE_STREAM, + G_SOCKET_PROTOCOL_DEFAULT, + &error); + g_assert_no_error (error); + + gaddr = g_inet_socket_address_new_from_string ("127.0.0.1", 0); + g_socket_bind (gsock, gaddr, TRUE, &error); + g_object_unref (gaddr); + g_assert_no_error (error); + g_socket_listen (gsock, &error); + g_assert_no_error (error); + g_assert_false (g_socket_is_connected (gsock)); + + gaddr = g_socket_get_local_address (gsock, &error); + g_assert_no_error (error); + + sock = g_initable_new (SOUP_TYPE_SOCKET, NULL, &error, + SOUP_SOCKET_GSOCKET, gsock, + NULL); + g_assert_no_error (error); + g_assert_nonnull (sock); + + g_object_get (G_OBJECT (sock), + SOUP_SOCKET_LOCAL_ADDRESS, &local, + SOUP_SOCKET_IS_SERVER, &is_server, + NULL); + g_assert_cmpint (soup_socket_get_fd (sock), ==, g_socket_get_fd (gsock)); + g_assert_true (is_server); + g_assert_true (soup_socket_is_connected (sock)); + + g_assert_cmpstr (soup_address_get_physical (local), ==, "127.0.0.1"); + g_assert_cmpint (soup_address_get_port (local), ==, g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (gaddr))); + g_object_unref (local); + g_object_unref (gaddr); + + g_object_unref (sock); + + /* Closing the SoupSocket should have closed the GSocket */ + g_assert_true (g_socket_is_closed (gsock)); + + g_object_unref (gsock); +} + +static void +do_socket_from_fd_bad_test (void) +{ + GSocket *gsock, *gsock2, *gsockcli; + SoupSocket *sock, *sock2; + SoupAddress *local, *remote; + GSocketAddress *gaddr; + gboolean is_server; + int fd; + GError *error = NULL; + + /* Importing a non-socket fd gives an error */ + fd = open (g_test_get_filename (G_TEST_DIST, "test-cert.pem", NULL), O_RDONLY); + g_assert_cmpint (fd, !=, -1); + + sock = g_initable_new (SOUP_TYPE_SOCKET, NULL, &error, + SOUP_SOCKET_FD, fd, + NULL); + g_assert_error (error, G_IO_ERROR, G_IO_ERROR_FAILED); + g_clear_error (&error); + g_assert_null (sock); + close (fd); + + /* Importing an unconnected socket gives an error */ + gsock = g_socket_new (G_SOCKET_FAMILY_IPV4, + G_SOCKET_TYPE_STREAM, + G_SOCKET_PROTOCOL_DEFAULT, + &error); + g_assert_no_error (error); + g_assert_false (g_socket_is_connected (gsock)); + + sock = g_initable_new (SOUP_TYPE_SOCKET, NULL, &error, + SOUP_SOCKET_FD, g_socket_get_fd (gsock), + NULL); + g_assert_error (error, G_IO_ERROR, G_IO_ERROR_FAILED); + g_clear_error (&error); + g_assert_null (sock); + g_object_unref (gsock); + + /* Importing a non-listening server-side socket works, but + * gives the wrong answer for soup_socket_is_server(). + */ + gsock = g_socket_new (G_SOCKET_FAMILY_IPV4, + G_SOCKET_TYPE_STREAM, + G_SOCKET_PROTOCOL_DEFAULT, + &error); + g_assert_no_error (error); + + gaddr = g_inet_socket_address_new_from_string ("127.0.0.1", 0); + g_socket_bind (gsock, gaddr, TRUE, &error); + g_object_unref (gaddr); + g_assert_no_error (error); + g_socket_listen (gsock, &error); + g_assert_no_error (error); + g_assert_false (g_socket_is_connected (gsock)); + + gaddr = g_socket_get_local_address (gsock, &error); + g_assert_no_error (error); + + gsockcli = g_socket_new (G_SOCKET_FAMILY_IPV4, + G_SOCKET_TYPE_STREAM, + G_SOCKET_PROTOCOL_DEFAULT, + &error); + g_assert_no_error (error); + + g_socket_connect (gsockcli, gaddr, NULL, &error); + g_assert_no_error (error); + g_assert_true (g_socket_is_connected (gsockcli)); + + gsock2 = g_socket_accept (gsock, NULL, &error); + g_assert_no_error (error); + g_assert_nonnull (gsock2); + + sock2 = g_initable_new (SOUP_TYPE_SOCKET, NULL, &error, + SOUP_SOCKET_GSOCKET, gsock2, + NULL); + g_assert_no_error (error); + g_assert_nonnull (sock2); + + g_object_get (G_OBJECT (sock2), + SOUP_SOCKET_LOCAL_ADDRESS, &local, + SOUP_SOCKET_REMOTE_ADDRESS, &remote, + SOUP_SOCKET_IS_SERVER, &is_server, + NULL); + g_assert_cmpint (soup_socket_get_fd (sock2), ==, g_socket_get_fd (gsock2)); + g_assert_true (soup_socket_is_connected (sock2)); + /* This is wrong, but can't be helped. */ + g_assert_false (is_server); + + g_assert_cmpstr (soup_address_get_physical (local), ==, "127.0.0.1"); + g_assert_cmpint (soup_address_get_port (local), ==, g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (gaddr))); + g_object_unref (gaddr); + + gaddr = g_socket_get_local_address (gsockcli, &error); + g_assert_no_error (error); + g_assert_cmpstr (soup_address_get_physical (remote), ==, "127.0.0.1"); + g_assert_cmpint (soup_address_get_port (remote), ==, g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (gaddr))); + g_object_unref (gaddr); + + g_object_unref (local); + g_object_unref (remote); + + g_object_unref (sock2); + + g_object_unref (gsock); + g_object_unref (gsock2); + g_object_unref (gsockcli); +} + +int +main (int argc, char **argv) +{ + int ret; + + test_init (argc, argv, NULL); + + g_test_add_func ("/sockets/unconnected", do_unconnected_socket_test); + g_test_add_func ("/sockets/from-fd/client", do_socket_from_fd_client_test); + g_test_add_func ("/sockets/from-fd/server", do_socket_from_fd_server_test); + g_test_add_func ("/sockets/from-fd/bad", do_socket_from_fd_bad_test); + + ret = g_test_run (); + + test_cleanup (); + return ret; +} diff --git a/tests/soup-tests.gresource.xml b/tests/soup-tests.gresource.xml new file mode 100644 index 0000000..9c08d17 --- /dev/null +++ b/tests/soup-tests.gresource.xml @@ -0,0 +1,29 @@ + + + + index.txt + resources/atom.xml + resources/feed.rdf + resources/home.gif + resources/home.jpg + resources/home.png + resources/html_binary.html + resources/leading_space.html + resources/mbox + resources/mbox.gz + resources/mbox.raw + resources/mbox.zlib + resources/misc.xml + resources/ps_binary.ps + resources/rss20.xml + resources/test.aiff + resources/test.html + resources/test.mp4 + resources/test.ogg + resources/test.wav + resources/test.webm + resources/text.txt + resources/text_binary.txt + resources/tux.webp + + diff --git a/tests/ssl-test.c b/tests/ssl-test.c new file mode 100644 index 0000000..735ba41 --- /dev/null +++ b/tests/ssl-test.c @@ -0,0 +1,471 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ + +#include "test-utils.h" + +SoupURI *uri; +GTlsDatabase *null_tlsdb; + +static void +do_properties_test_for_session (SoupSession *session) +{ + SoupMessage *msg; + GTlsCertificate *cert; + GTlsCertificateFlags flags; + + msg = soup_message_new_from_uri ("GET", uri); + soup_session_send_message (session, msg); + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + + if (soup_message_get_https_status (msg, &cert, &flags)) { + g_assert_true (G_IS_TLS_CERTIFICATE (cert)); + g_assert_cmpuint (flags, ==, G_TLS_CERTIFICATE_UNKNOWN_CA); + } else + soup_test_assert (FALSE, "Response not https"); + + g_test_bug ("665182"); + g_assert_false (soup_message_get_flags (msg) & SOUP_MESSAGE_CERTIFICATE_TRUSTED); + + g_object_unref (msg); +} + +static void +do_async_properties_tests (void) +{ + SoupSession *session; + + SOUP_TEST_SKIP_IF_NO_TLS; + + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + g_object_set (G_OBJECT (session), + SOUP_SESSION_TLS_DATABASE, null_tlsdb, + SOUP_SESSION_SSL_STRICT, FALSE, + NULL); + do_properties_test_for_session (session); + soup_test_session_abort_unref (session); +} + +static void +do_sync_properties_tests (void) +{ + SoupSession *session; + + SOUP_TEST_SKIP_IF_NO_TLS; + + session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL); + g_object_set (G_OBJECT (session), + SOUP_SESSION_TLS_DATABASE, null_tlsdb, + SOUP_SESSION_SSL_STRICT, FALSE, + NULL); + do_properties_test_for_session (session); + soup_test_session_abort_unref (session); +} + +typedef struct { + const char *name; + gboolean sync; + gboolean strict; + gboolean with_ca_list; + guint expected_status; +} StrictnessTest; + +static const StrictnessTest strictness_tests[] = { + { "/ssl/strictness/async/strict/with-ca", + FALSE, TRUE, TRUE, SOUP_STATUS_OK }, + { "/ssl/strictness/async/strict/without-ca", + FALSE, TRUE, FALSE, SOUP_STATUS_SSL_FAILED }, + { "/ssl/strictness/async/non-strict/with-ca", + FALSE, FALSE, TRUE, SOUP_STATUS_OK }, + { "/ssl/strictness/async/non-strict/without-ca", + FALSE, FALSE, FALSE, SOUP_STATUS_OK }, + { "/ssl/strictness/sync/strict/with-ca", + TRUE, TRUE, TRUE, SOUP_STATUS_OK }, + { "/ssl/strictness/sync/strict/without-ca", + TRUE, TRUE, FALSE, SOUP_STATUS_SSL_FAILED }, + { "/ssl/strictness/sync/non-strict/with-ca", + TRUE, FALSE, TRUE, SOUP_STATUS_OK }, + { "/ssl/strictness/sync/non-strict/without-ca", + TRUE, FALSE, FALSE, SOUP_STATUS_OK }, +}; + +static void +do_strictness_test (gconstpointer data) +{ + const StrictnessTest *test = data; + SoupSession *session; + SoupMessage *msg; + GTlsCertificateFlags flags = 0; + + SOUP_TEST_SKIP_IF_NO_TLS; + + session = soup_test_session_new (test->sync ? SOUP_TYPE_SESSION_SYNC : SOUP_TYPE_SESSION_ASYNC, + NULL); + if (!test->strict) { + g_object_set (G_OBJECT (session), + SOUP_SESSION_SSL_STRICT, FALSE, + NULL); + } + if (!test->with_ca_list) { + g_object_set (G_OBJECT (session), + SOUP_SESSION_TLS_DATABASE, null_tlsdb, + NULL); + } + + msg = soup_message_new_from_uri ("GET", uri); + soup_session_send_message (session, msg); + soup_test_assert_message_status (msg, test->expected_status); + + g_test_bug ("690176"); + g_assert_true (soup_message_get_https_status (msg, NULL, &flags)); + + g_test_bug ("665182"); + if (test->with_ca_list && SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) + g_assert_true (soup_message_get_flags (msg) & SOUP_MESSAGE_CERTIFICATE_TRUSTED); + else + g_assert_false (soup_message_get_flags (msg) & SOUP_MESSAGE_CERTIFICATE_TRUSTED); + + if (msg->status_code == SOUP_STATUS_SSL_FAILED && + test->expected_status != SOUP_STATUS_SSL_FAILED) + debug_printf (1, " tls error flags: 0x%x\n", flags); + + g_object_unref (msg); + + soup_test_session_abort_unref (session); +} + +static void +property_changed (GObject *object, GParamSpec *param, gpointer user_data) +{ + gboolean *changed = user_data; + + *changed = TRUE; +} + +static void +do_session_property_tests (void) +{ + gboolean use_system_changed, tlsdb_changed, ca_file_changed; + gboolean use_system; + GTlsDatabase *tlsdb; + char *ca_file; + SoupSession *session; + GParamSpec *pspec; + + g_test_bug ("673678"); + + SOUP_TEST_SKIP_IF_NO_TLS; + + G_GNUC_BEGIN_IGNORE_DEPRECATIONS; + session = soup_session_async_new (); + G_GNUC_END_IGNORE_DEPRECATIONS; + + /* Temporarily undeprecate SOUP_SESSION_SSL_CA_FILE to avoid warnings. */ + pspec = g_object_class_find_property (g_type_class_peek (SOUP_TYPE_SESSION), + SOUP_SESSION_SSL_CA_FILE); + pspec->flags &= ~G_PARAM_DEPRECATED; + + g_signal_connect (session, "notify::ssl-use-system-ca-file", + G_CALLBACK (property_changed), &use_system_changed); + g_signal_connect (session, "notify::tls-database", + G_CALLBACK (property_changed), &tlsdb_changed); + g_signal_connect (session, "notify::ssl-ca-file", + G_CALLBACK (property_changed), &ca_file_changed); + + g_object_get (G_OBJECT (session), + "ssl-use-system-ca-file", &use_system, + "tls-database", &tlsdb, + "ssl-ca-file", &ca_file, + NULL); + soup_test_assert (!use_system, + "ssl-use-system-ca-file defaults to TRUE"); + soup_test_assert (tlsdb == NULL, + "tls-database set by default"); + soup_test_assert (ca_file == NULL, + "ca-file set by default"); + + use_system_changed = tlsdb_changed = ca_file_changed = FALSE; + g_object_set (G_OBJECT (session), + "ssl-use-system-ca-file", TRUE, + NULL); + g_object_get (G_OBJECT (session), + "ssl-use-system-ca-file", &use_system, + "tls-database", &tlsdb, + "ssl-ca-file", &ca_file, + NULL); + soup_test_assert (use_system, + "setting ssl-use-system-ca-file failed"); + g_assert_true (use_system_changed); + soup_test_assert (tlsdb != NULL, + "setting ssl-use-system-ca-file didn't set tls-database"); + g_assert_true (tlsdb_changed); + g_clear_object (&tlsdb); + soup_test_assert (ca_file == NULL, + "setting ssl-use-system-ca-file set ssl-ca-file"); + g_assert_false (ca_file_changed); + + use_system_changed = tlsdb_changed = ca_file_changed = FALSE; + g_object_set (G_OBJECT (session), + "ssl-ca-file", g_test_get_filename (G_TEST_DIST, "/test-cert.pem", NULL), + NULL); + g_object_get (G_OBJECT (session), + "ssl-use-system-ca-file", &use_system, + "tls-database", &tlsdb, + "ssl-ca-file", &ca_file, + NULL); + soup_test_assert (!use_system, + "setting ssl-ca-file left ssl-use-system-ca-file set"); + g_assert_true (use_system_changed); + soup_test_assert (tlsdb != NULL, + "setting ssl-ca-file didn't set tls-database"); + g_assert_true (tlsdb_changed); + g_clear_object (&tlsdb); + soup_test_assert (ca_file != NULL, + "setting ssl-ca-file failed"); + g_assert_true (ca_file_changed); + g_free (ca_file); + + use_system_changed = tlsdb_changed = ca_file_changed = FALSE; + g_object_set (G_OBJECT (session), + "tls-database", NULL, + NULL); + g_object_get (G_OBJECT (session), + "ssl-use-system-ca-file", &use_system, + "tls-database", &tlsdb, + "ssl-ca-file", &ca_file, + NULL); + soup_test_assert (!use_system, + "setting tls-database NULL left ssl-use-system-ca-file set"); + g_assert_false (use_system_changed); + soup_test_assert (tlsdb == NULL, + "setting tls-database NULL failed"); + g_assert_true (tlsdb_changed); + soup_test_assert (ca_file == NULL, + "setting tls-database didn't clear ssl-ca-file"); + g_assert_true (ca_file_changed); + + soup_test_session_abort_unref (session); + + /* Re-deprecate SOUP_SESSION_SSL_CA_FILE */ + pspec->flags |= G_PARAM_DEPRECATED; +} + +/* GTlsInteraction subclass for do_interaction_test */ +typedef GTlsInteraction TestTlsInteraction; +typedef GTlsInteractionClass TestTlsInteractionClass; + +GType test_tls_interaction_get_type (void); + +G_DEFINE_TYPE (TestTlsInteraction, test_tls_interaction, G_TYPE_TLS_INTERACTION); + +static void +test_tls_interaction_init (TestTlsInteraction *interaction) +{ + +} + +static GTlsInteractionResult +test_tls_interaction_request_certificate (GTlsInteraction *interaction, + GTlsConnection *connection, + GTlsCertificateRequestFlags flags, + GCancellable *cancellable, + GError **error) +{ + GTlsCertificate *cert; + const char *ssl_cert_file, *ssl_key_file; + GError *my_error = NULL; + + /* Yes, we use the same certificate for the client as for the server. Shrug */ + ssl_cert_file = g_test_get_filename (G_TEST_DIST, "test-cert.pem", NULL); + ssl_key_file = g_test_get_filename (G_TEST_DIST, "test-key.pem", NULL); + cert = g_tls_certificate_new_from_files (ssl_cert_file, + ssl_key_file, + &my_error); + g_assert_no_error (my_error); + + g_tls_connection_set_certificate (connection, cert); + g_object_unref (cert); + + return G_TLS_INTERACTION_HANDLED; +} + +static void +test_tls_interaction_class_init (TestTlsInteractionClass *klass) +{ + GTlsInteractionClass *interaction_class = G_TLS_INTERACTION_CLASS (klass); + + interaction_class->request_certificate = test_tls_interaction_request_certificate; +} + + +#define INTERACTION_TEST_HTTP_RESPONSE "HTTP/1.1 200 OK\r\nConnection: close\r\n\r\nOK\r\n" + +static gboolean +accept_client_certificate (GTlsConnection *server, + GTlsCertificate *client_cert, + GTlsCertificateFlags errors) +{ + return TRUE; +} + +static void +got_connection (GThreadedSocketService *service, + GSocketConnection *connection, + GObject *source_object) +{ + GIOStream *tls; + GTlsCertificate *server_cert; + GError *error = NULL; + const char *ssl_cert_file, *ssl_key_file; + GMainContext *thread_context; + + thread_context = g_main_context_new (); + g_main_context_push_thread_default (thread_context); + + ssl_cert_file = g_test_get_filename (G_TEST_DIST, "test-cert.pem", NULL); + ssl_key_file = g_test_get_filename (G_TEST_DIST, "test-key.pem", NULL); + server_cert = g_tls_certificate_new_from_files (ssl_cert_file, + ssl_key_file, + &error); + g_assert_no_error (error); + + tls = g_tls_server_connection_new (G_IO_STREAM (connection), + server_cert, &error); + g_assert_no_error (error); + g_object_unref (server_cert); + + g_object_set (G_OBJECT (tls), + "authentication-mode", G_TLS_AUTHENTICATION_REQUIRED, + NULL); + g_signal_connect (tls, "accept-certificate", + G_CALLBACK (accept_client_certificate), NULL); + + if (g_tls_connection_handshake (G_TLS_CONNECTION (tls), NULL, &error)) { + g_output_stream_write_all (g_io_stream_get_output_stream (tls), + INTERACTION_TEST_HTTP_RESPONSE, + strlen (INTERACTION_TEST_HTTP_RESPONSE), + NULL, NULL, &error); + g_assert_no_error (error); + } else { + g_assert_error (error, G_TLS_ERROR, G_TLS_ERROR_CERTIFICATE_REQUIRED); + g_clear_error (&error); + } + + g_io_stream_close (tls, NULL, &error); + g_assert_no_error (error); + + g_object_unref (tls); + + g_main_context_pop_thread_default (thread_context); + g_main_context_unref (thread_context); +} + +static void +do_tls_interaction_test (void) +{ + GSocketService *service; + GSocketAddress *address, *bound_address; + SoupSession *session; + SoupMessage *msg; + GTlsInteraction *interaction; + SoupURI *test_uri; + GError *error = NULL; + + SOUP_TEST_SKIP_IF_NO_TLS; + + service = g_threaded_socket_service_new (1); + address = g_inet_socket_address_new_from_string ("127.0.0.1", 0); + g_socket_listener_add_address (G_SOCKET_LISTENER (service), address, + G_SOCKET_TYPE_STREAM, + G_SOCKET_PROTOCOL_TCP, + NULL, &bound_address, &error); + g_assert_no_error (error); + g_object_unref (address); + g_signal_connect (service, "run", G_CALLBACK (got_connection), NULL); + g_socket_service_start (service); + + test_uri = soup_uri_new ("https://127.0.0.1"); + soup_uri_set_port (test_uri, g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (bound_address))); + g_object_unref (bound_address); + + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + + /* Without a GTlsInteraction */ + msg = soup_message_new_from_uri ("GET", test_uri); + soup_session_send_message (session, msg); + soup_test_assert_message_status (msg, SOUP_STATUS_SSL_FAILED); + g_object_unref (msg); + + interaction = g_object_new (test_tls_interaction_get_type (), NULL); + g_object_set (G_OBJECT (session), + SOUP_SESSION_TLS_INTERACTION, interaction, + NULL); + g_object_unref (interaction); + + /* With a GTlsInteraction */ + msg = soup_message_new_from_uri ("GET", test_uri); + soup_session_send_message (session, msg); + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + g_assert_true (soup_message_get_https_status (msg, NULL, NULL)); + g_object_unref (msg); + + soup_uri_free (test_uri); + soup_test_session_abort_unref (session); + + g_socket_service_stop (service); + g_object_unref (service); +} + +static void +server_handler (SoupServer *server, + SoupMessage *msg, + const char *path, + GHashTable *query, + SoupClientContext *client, + gpointer user_data) +{ + soup_message_set_status (msg, SOUP_STATUS_OK); + soup_message_set_response (msg, "text/plain", + SOUP_MEMORY_STATIC, + "ok\r\n", 4); +} + +int +main (int argc, char **argv) +{ + SoupServer *server = NULL; + int i, ret; + GError *error = NULL; + + test_init (argc, argv, NULL); + + if (tls_available) { + server = soup_test_server_new (SOUP_TEST_SERVER_IN_THREAD); + soup_server_add_handler (server, NULL, server_handler, NULL, NULL); + uri = soup_test_server_get_uri (server, "https", "127.0.0.1"); + + null_tlsdb = g_tls_file_database_new ("/dev/null", &error); + g_assert_no_error (error); + } else + uri = NULL; + + g_test_add_func ("/ssl/session-properties", do_session_property_tests); + g_test_add_func ("/ssl/message-properties/async", do_async_properties_tests); + g_test_add_func ("/ssl/message-properties/sync", do_sync_properties_tests); + g_test_add_func ("/ssl/tls-interaction", do_tls_interaction_test); + + for (i = 0; i < G_N_ELEMENTS (strictness_tests); i++) { + g_test_add_data_func (strictness_tests[i].name, + &strictness_tests[i], + do_strictness_test); + } + + ret = g_test_run (); + + if (tls_available) { + soup_uri_free (uri); + soup_test_server_quit_unref (server); + g_object_unref (null_tlsdb); + } + + test_cleanup (); + return ret; +} diff --git a/tests/streaming-test.c b/tests/streaming-test.c new file mode 100644 index 0000000..bd4a519 --- /dev/null +++ b/tests/streaming-test.c @@ -0,0 +1,173 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2008 Red Hat, Inc. + */ + +#include "test-utils.h" + +#define RESPONSE_CHUNK_SIZE 1024 + +SoupBuffer *full_response; +char *full_response_md5; + +static void +write_next_chunk (SoupMessage *msg, gpointer user_data) +{ + gsize *offset = user_data; + gsize chunk_length; + + chunk_length = MIN (RESPONSE_CHUNK_SIZE, full_response->length - *offset); + if (chunk_length > 0) { + debug_printf (2, " writing chunk\n"); + soup_message_body_append (msg->response_body, + SOUP_MEMORY_STATIC, + full_response->data + *offset, + chunk_length); + *offset += chunk_length; + } else { + debug_printf (2, " done\n"); + /* This is only actually needed in the chunked and eof + * cases, but it's harmless in the content-length + * case. + */ + soup_message_body_complete (msg->response_body); + } +} + +static void +free_offset (SoupMessage *msg, gpointer offset) +{ + g_free (offset); +} + +static void +server_callback (SoupServer *server, SoupMessage *msg, + const char *path, GHashTable *query, + SoupClientContext *context, gpointer data) +{ + gsize *offset; + + if (!strcmp (path, "/chunked")) { + soup_message_headers_set_encoding (msg->response_headers, + SOUP_ENCODING_CHUNKED); + } else if (!strcmp (path, "/content-length")) { + soup_message_headers_set_encoding (msg->response_headers, + SOUP_ENCODING_CONTENT_LENGTH); + soup_message_headers_set_content_length (msg->response_headers, + full_response->length); + } else if (!strcmp (path, "/eof")) { + soup_message_headers_set_encoding (msg->response_headers, + SOUP_ENCODING_EOF); + } else { + soup_message_set_status (msg, SOUP_STATUS_NOT_FOUND); + return; + } + soup_message_set_status (msg, SOUP_STATUS_OK); + + offset = g_new0 (gsize, 1); + g_signal_connect (msg, "wrote_headers", + G_CALLBACK (write_next_chunk), offset); + g_signal_connect (msg, "wrote_chunk", + G_CALLBACK (write_next_chunk), offset); + g_signal_connect (msg, "finished", + G_CALLBACK (free_offset), offset); +} + +static void +do_request (SoupSession *session, SoupURI *base_uri, char *path) +{ + SoupURI *uri; + SoupMessage *msg; + char *md5; + + uri = soup_uri_new_with_base (base_uri, path); + msg = soup_message_new_from_uri ("GET", uri); + soup_uri_free (uri); + + soup_session_send_message (session, msg); + + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + g_assert_cmpint (msg->response_body->length, ==, full_response->length); + + md5 = g_compute_checksum_for_data (G_CHECKSUM_MD5, + (guchar *)msg->response_body->data, + msg->response_body->length); + g_assert_cmpstr (md5, ==, full_response_md5); + g_free (md5); + + g_object_unref (msg); +} + +static void +do_chunked_test (gconstpointer data) +{ + SoupURI *base_uri = (SoupURI *)data; + SoupSession *session; + + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + do_request (session, base_uri, "chunked"); + soup_test_session_abort_unref (session); +} + +static void +do_content_length_test (gconstpointer data) +{ + SoupURI *base_uri = (SoupURI *)data; + SoupSession *session; + + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + do_request (session, base_uri, "content-length"); + soup_test_session_abort_unref (session); +} + +static void +do_eof_test (gconstpointer data) +{ + SoupURI *base_uri = (SoupURI *)data; + SoupSession *session; + + g_test_bug ("572153"); + + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + do_request (session, base_uri, "eof"); + soup_test_session_abort_unref (session); +} + +int +main (int argc, char **argv) +{ + GMainLoop *loop; + SoupServer *server; + SoupURI *base_uri; + int ret; + + test_init (argc, argv, NULL); + + full_response = soup_test_get_index (); + full_response_md5 = g_compute_checksum_for_data (G_CHECKSUM_MD5, + (guchar *)full_response->data, + full_response->length); + + server = soup_test_server_new (SOUP_TEST_SERVER_DEFAULT); + soup_server_add_handler (server, NULL, + server_callback, NULL, NULL); + + loop = g_main_loop_new (NULL, TRUE); + + base_uri = soup_test_server_get_uri (server, "http", NULL); + + g_test_add_data_func ("/streaming/chunked", base_uri, do_chunked_test); + g_test_add_data_func ("/streaming/content-length", base_uri, do_content_length_test); + g_test_add_data_func ("/streaming/eof", base_uri, do_eof_test); + + ret = g_test_run (); + + soup_uri_free (base_uri); + g_main_loop_unref (loop); + + g_free (full_response_md5); + soup_test_server_quit_unref (server); + test_cleanup (); + + return ret; +} diff --git a/tests/test-cert.pem b/tests/test-cert.pem new file mode 100644 index 0000000..ff863b4 --- /dev/null +++ b/tests/test-cert.pem @@ -0,0 +1,18 @@ +-----BEGIN CERTIFICATE----- +MIIC2zCCAcOgAwIBAgIJALRbg2WnuAAqMA0GCSqGSIb3DQEBCwUAMBQxEjAQBgNV +BAMMCTEyNy4wLjAuMTAeFw0xNzA2MjAxNDI3MzBaFw0yNzA2MTgxNDI3MzBaMBQx +EjAQBgNVBAMMCTEyNy4wLjAuMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBAKs4fuRuW77nORhOT9kbbU6BsjKW3GEsMc+ZSmXjINQWpfkES2hV+DQyzhm5 +qh4OLi1vYtXoSbdQNDCbA8ybZJqR8m9F3ed8vobdSSQGxWpPdXTgz27x+TpiAc9P +w83UuPvlu/0AxHJBFXVAg+id0yFu3wmGWYJHoAtvFi2xeRtAXurNuPtjZyO+gfM9 +BKTRCkGsRSmPpJyGbU2Q96fjxnVfV9oYvQXeugUcSx/pTUCM/kDgD9QZCxG2rflX +NWcqDFY3uO6ZR68Qwi/KouOa8rzrgAcwhFUI6Wz0Zwi1rzRtWK5WqC24aBUYz/tK +hl8i88UDXSMh7spChdYDBGLhZyUCAwEAAaMwMC4wLAYDVR0RBCUwI4IJbG9jYWxo +b3N0hwR/AAABhxAAAAAAAAAAAAAAAAAAAAABMA0GCSqGSIb3DQEBCwUAA4IBAQBj ++U8tebwg5/pof5Rht6TMHqeg6Fcr4OJkL2ph2g+T/AMTS7kEGeFIKJN5AZ+S/qIY +cdoDKHwc8+bCK/mG6DPmJ4z/2Eamb85YhplOLVrLRwfxRebTK9CtnjcjnflAiU9H +7vPVwXIvkwebhBSQNKTdkBlPXKaTNWXuygeFG2OVQkPf/KAxSdtg2R+owv/s802Z +HISk26wY9oFIQz6AiXWdrY1QqNOltZ7rlU5iofAH7X+9ryZlxPWj/gHg2YQRvvLl +dq6nCF+ED0ke7h0lg5nU0beKEygwli8DlLVbu0JK0PkARFp5t7wUtzC9DCjzvfOc +gxR44PyZX7/2oaTDm4PS +-----END CERTIFICATE----- diff --git a/tests/test-key.pem b/tests/test-key.pem new file mode 100644 index 0000000..36bbcc2 --- /dev/null +++ b/tests/test-key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAqzh+5G5bvuc5GE5P2RttToGyMpbcYSwxz5lKZeMg1Bal+QRL +aFX4NDLOGbmqHg4uLW9i1ehJt1A0MJsDzJtkmpHyb0Xd53y+ht1JJAbFak91dODP +bvH5OmIBz0/DzdS4++W7/QDEckEVdUCD6J3TIW7fCYZZgkegC28WLbF5G0Be6s24 ++2NnI76B8z0EpNEKQaxFKY+knIZtTZD3p+PGdV9X2hi9Bd66BRxLH+lNQIz+QOAP +1BkLEbat+Vc1ZyoMVje47plHrxDCL8qi45ryvOuABzCEVQjpbPRnCLWvNG1Yrlao +LbhoFRjP+0qGXyLzxQNdIyHuykKF1gMEYuFnJQIDAQABAoIBABh+MXC99LPfYcR/ +V17IVJ+ZYANqn0XrS4jV9dWTYxvTzZRMr/jR63qUFfWKILLB9osbVvkgjIMDnyOg +2S9Iv2B5JkQSq4a0ypCCUTctHMpzaWr5ydKmHK/kWzvrvifQmVG3cGfl1zQ86TPn +sbbx9MTglllHdcB0PInGL1cD/z4NgEbRr1B6aBcq0AHqJJIIHvQNPmH6HGASg48j +hVAZ2sYjp9DSK97HKSABpBCsRN8XrMgYOAsu5a1rtXhjtMUZo6LpEwEwH94rDOgv +ZvJLGrpSvKKWPGcyANyK1a5nzO8INcXY+X54a8VB1YAjymzDy/WM1OX/jBfZem53 +HwC7m5UCgYEA3crcBI9f3aDgCYEUDWZ8hTQUVhvN3pi8QWr7QubMJmIyxBj394wm +hTo8woYxNqy9VkO0X+jxHA0rzN1KvS9j2CAzJ+tYNhEsRc6onjEXKGLhO/1gHbkT +rRx2J1uA2HQTbZNGhws9Qdl3A7syw6fFw9T/5rooWbiv5SDqSCRFzlcCgYEAxaDj +JYyLLl+Jbsltkv71th5TvLi14q6KlZJGEUeSsymUx9evBS7s/h62Boe9/7Y63Zkl +dR3IvxX7HNqW/fGjuQr9jQvMMduil8L218lChuR/4HEsXrSvyw8MIMlDtjTWajB6 +c8eiU+z/5zrlhzooKk2LaQHTUrrbxk9rN0raEOMCgYEA2Klz1wyMVL/0O7SZdyG3 +4JPojdmpeZrwxGMSwt8dbR2ehAv0KCID+z/R3SEj8Eo8x4lqKgsvhfyj3gQLH9as +jZOfBY8U4/RQsHzaIXbJLY2yg1zYSRDkVMap8Xak3k4+MFufmQp0s+ARMFbtl05M +lip8NdOC2WregVFvLDwq6Q8CgYBy3gyoqoPLNGRhLFqv8dlHPWFWc9XkJ6cNQLPR +H1S5JhYAAfEMhjXhjmAmc4ePtY+JdZY7+E/SISiPoM3aVDThPO4aqRzKbeqXYw6u +ZaBxXyakgaNUeJkk4V4fQFxG73cgyYSi/wnu1fX3pFf8vWTTEbdSFWmK0GklXsvm +m28cGQKBgGvG//W8NGfXWL/komyKXw8GJ41Ip0sa20KNkNZwAaA1BVTaHIYT+rxo +SgVQPHmzP8J9p4U0d9lQ5BW0LWERVkFHOg8k0evDsSm3FVbeRCBjlKqVUOLoo4Hk +A+fSYWWWl1j9E9urpiT/d4AQY1bFUxcUebDSK9XT6ZPOusyX0fSe +-----END RSA PRIVATE KEY----- diff --git a/tests/test-utils.c b/tests/test-utils.c new file mode 100644 index 0000000..9c74206 --- /dev/null +++ b/tests/test-utils.c @@ -0,0 +1,814 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ + +#include "test-utils.h" + +#include + +#include +#include + +#ifdef HAVE_APACHE +static gboolean apache_running; +#endif + +static SoupLogger *logger; +static SoupBuffer *index_buffer; + +int debug_level; +gboolean expect_warning, tls_available; +static int http_debug_level; + +static gboolean +increment_debug_level (const char *option_name, const char *value, + gpointer data, GError **error) +{ + debug_level++; + return TRUE; +} + +static gboolean +increment_http_debug_level (const char *option_name, const char *value, + gpointer data, GError **error) +{ + http_debug_level++; + return TRUE; +} + +static GOptionEntry debug_entry[] = { + { "debug", 'd', G_OPTION_FLAG_NO_ARG, + G_OPTION_ARG_CALLBACK, increment_debug_level, + "Enable (or increase) test-specific debugging", NULL }, + { "http-debug", 'H', G_OPTION_FLAG_NO_ARG, + G_OPTION_ARG_CALLBACK, increment_http_debug_level, + "Enable (or increase) HTTP-level debugging", NULL }, + { NULL } +}; + +static void +quit (int sig) +{ +#ifdef HAVE_APACHE + if (apache_running) + apache_cleanup (); +#endif + + exit (1); +} + +void +test_init (int argc, char **argv, GOptionEntry *entries) +{ + GOptionContext *opts; + char *name; + GError *error = NULL; + GTlsBackend *tls_backend; + + setlocale (LC_ALL, ""); + g_setenv ("GSETTINGS_BACKEND", "memory", TRUE); + g_setenv ("GIO_USE_PROXY_RESOLVER", "dummy", TRUE); + g_setenv ("GIO_USE_VFS", "local", TRUE); + + name = strrchr (argv[0], '/'); + if (!name++) + name = argv[0]; + if (!strncmp (name, "lt-", 3)) + name += 3; + g_set_prgname (name); + + g_test_init (&argc, &argv, NULL); + g_test_set_nonfatal_assertions (); + g_test_bug_base ("https://bugzilla.gnome.org/"); + + opts = g_option_context_new (NULL); + g_option_context_add_main_entries (opts, debug_entry, NULL); + if (entries) + g_option_context_add_main_entries (opts, entries, NULL); + + if (!g_option_context_parse (opts, &argc, &argv, &error)) { + g_printerr ("Could not parse arguments: %s\n", + error->message); + g_printerr ("%s", + g_option_context_get_help (opts, TRUE, NULL)); + exit (1); + } + g_option_context_free (opts); + + /* Exit cleanly on ^C in case we're valgrinding. */ + signal (SIGINT, quit); + + tls_backend = g_tls_backend_get_default (); + tls_available = g_tls_backend_supports_tls (tls_backend); +} + +void +test_cleanup (void) +{ +#ifdef HAVE_APACHE + if (apache_running) + apache_cleanup (); +#endif + + if (logger) + g_object_unref (logger); + if (index_buffer) + soup_buffer_free (index_buffer); + + g_main_context_unref (g_main_context_default ()); + + debug_printf (1, "\n"); +} + +void +debug_printf (int level, const char *format, ...) +{ + va_list args; + + if (debug_level < level) + return; + + va_start (args, format); + g_vprintf (format, args); + va_end (args); +} + +#ifdef HAVE_APACHE + +static gboolean +apache_cmd (const char *cmd) +{ + GPtrArray *argv; + char *server_root, *cwd, *pid_file; +#ifdef HAVE_APACHE_2_4 + char *default_runtime_dir; +#endif + int status; + gboolean ok; + + server_root = g_test_build_filename (G_TEST_BUILT, "", NULL); + + cwd = g_get_current_dir (); +#ifdef HAVE_APACHE_2_4 + default_runtime_dir = g_strdup_printf ("DefaultRuntimeDir %s", cwd); +#endif + pid_file = g_strdup_printf ("PidFile %s/httpd.pid", cwd); + + argv = g_ptr_array_new (); + g_ptr_array_add (argv, APACHE_HTTPD); + g_ptr_array_add (argv, "-d"); + g_ptr_array_add (argv, server_root); + g_ptr_array_add (argv, "-f"); + g_ptr_array_add (argv, "httpd.conf"); + +#ifdef HAVE_APACHE_2_4 + g_ptr_array_add (argv, "-c"); + g_ptr_array_add (argv, default_runtime_dir); +#endif + g_ptr_array_add (argv, "-c"); + g_ptr_array_add (argv, pid_file); + + g_ptr_array_add (argv, "-k"); + g_ptr_array_add (argv, (char *)cmd); + g_ptr_array_add (argv, NULL); + + ok = g_spawn_sync (cwd, (char **)argv->pdata, NULL, 0, NULL, NULL, + NULL, NULL, &status, NULL); + if (ok) + ok = (status == 0); + + g_free (server_root); + g_free (cwd); + g_free (pid_file); +#ifdef HAVE_APACHE_2_4 + g_free (default_runtime_dir); +#endif + g_ptr_array_free (argv, TRUE); + + return ok; +} + +void +apache_init (void) +{ + if (g_getenv ("SOUP_TESTS_IN_MAKE_CHECK")) + return; + + if (!apache_cmd ("start")) { + g_printerr ("Could not start apache\n"); + exit (1); + } + apache_running = TRUE; +} + +void +apache_cleanup (void) +{ + pid_t pid; + char *contents; + + if (g_file_get_contents ("httpd.pid", &contents, NULL, NULL)) { + pid = strtoul (contents, NULL, 10); + g_free (contents); + } else + pid = 0; + + if (!apache_cmd ("graceful-stop")) + return; + apache_running = FALSE; + + if (pid) { + while (kill (pid, 0) == 0) + g_usleep (100); + } +} + +#endif /* HAVE_APACHE */ + +SoupSession * +soup_test_session_new (GType type, ...) +{ + va_list args; + const char *propname; + SoupSession *session; + GTlsDatabase *tlsdb; + char *cafile; + GError *error = NULL; + + va_start (args, type); + propname = va_arg (args, const char *); + session = (SoupSession *)g_object_new_valist (type, propname, args); + va_end (args); + + if (tls_available) { + cafile = g_test_build_filename (G_TEST_DIST, "test-cert.pem", NULL); + tlsdb = g_tls_file_database_new (cafile, &error); + g_free (cafile); + if (error) { + if (g_strcmp0 (g_getenv ("GIO_USE_TLS"), "dummy") == 0) + g_clear_error (&error); + else + g_assert_no_error (error); + } + + g_object_set (G_OBJECT (session), + SOUP_SESSION_TLS_DATABASE, tlsdb, + NULL); + g_clear_object (&tlsdb); + } + + if (http_debug_level && !logger) { + SoupLoggerLogLevel level = MIN ((SoupLoggerLogLevel)http_debug_level, SOUP_LOGGER_LOG_BODY); + + logger = soup_logger_new (level, -1); + } + + if (logger) + soup_session_add_feature (session, SOUP_SESSION_FEATURE (logger)); + + return session; +} + +void +soup_test_session_abort_unref (SoupSession *session) +{ + soup_session_abort (session); + + g_assert_cmpint (G_OBJECT (session)->ref_count, ==, 1); + g_object_unref (session); +} + +static void +server_listen (SoupServer *server) +{ + GError *error = NULL; + + soup_server_listen_local (server, 0, 0, &error); + if (error) { + g_printerr ("Unable to create server: %s\n", error->message); + exit (1); + } +} + +static GMutex server_start_mutex; +static GCond server_start_cond; + +static gpointer +run_server_thread (gpointer user_data) +{ + SoupServer *server = user_data; + SoupTestServerOptions options = + GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (server), "options")); + GMainContext *context; + GMainLoop *loop; + + context = g_main_context_new (); + g_main_context_push_thread_default (context); + loop = g_main_loop_new (context, FALSE); + g_object_set_data (G_OBJECT (server), "GMainLoop", loop); + + if (!(options & SOUP_TEST_SERVER_NO_DEFAULT_LISTENER)) + server_listen (server); + + g_mutex_lock (&server_start_mutex); + g_cond_signal (&server_start_cond); + g_mutex_unlock (&server_start_mutex); + + g_main_loop_run (loop); + g_main_loop_unref (loop); + + soup_server_disconnect (server); + + g_main_context_pop_thread_default (context); + g_main_context_unref (context); + + return NULL; +} + +SoupServer * +soup_test_server_new (SoupTestServerOptions options) +{ + SoupServer *server; + GTlsCertificate *cert = NULL; + GError *error = NULL; + + if (tls_available) { + char *ssl_cert_file, *ssl_key_file; + + ssl_cert_file = g_test_build_filename (G_TEST_DIST, "test-cert.pem", NULL); + ssl_key_file = g_test_build_filename (G_TEST_DIST, "test-key.pem", NULL); + cert = g_tls_certificate_new_from_files (ssl_cert_file, + ssl_key_file, + &error); + g_free (ssl_cert_file); + g_free (ssl_key_file); + if (error) { + g_printerr ("Unable to create server: %s\n", error->message); + exit (1); + } + } + + server = soup_server_new (SOUP_SERVER_TLS_CERTIFICATE, cert, + NULL); + g_clear_object (&cert); + + g_object_set_data (G_OBJECT (server), "options", GUINT_TO_POINTER (options)); + + if (options & SOUP_TEST_SERVER_IN_THREAD) { + GThread *thread; + + g_mutex_lock (&server_start_mutex); + + thread = g_thread_new ("server_thread", run_server_thread, server); + g_cond_wait (&server_start_cond, &server_start_mutex); + g_mutex_unlock (&server_start_mutex); + + g_object_set_data (G_OBJECT (server), "thread", thread); + } else if (!(options & SOUP_TEST_SERVER_NO_DEFAULT_LISTENER)) + server_listen (server); + + return server; +} + +static SoupURI * +find_server_uri (SoupServer *server, const char *scheme, const char *host) +{ + GSList *uris, *u; + SoupURI *uri, *ret_uri = NULL; + + uris = soup_server_get_uris (server); + for (u = uris; u; u = u->next) { + uri = u->data; + + if (scheme && strcmp (uri->scheme, scheme) != 0) + continue; + if (host && strcmp (uri->host, host) != 0) + continue; + + ret_uri = soup_uri_copy (uri); + break; + } + g_slist_free_full (uris, (GDestroyNotify)soup_uri_free); + + return ret_uri; +} + +static SoupURI * +add_listener (SoupServer *server, const char *scheme, const char *host) +{ + SoupServerListenOptions options = 0; + GError *error = NULL; + + if (!g_strcmp0 (scheme, SOUP_URI_SCHEME_HTTPS)) + options |= SOUP_SERVER_LISTEN_HTTPS; + if (!g_strcmp0 (host, "127.0.0.1")) + options |= SOUP_SERVER_LISTEN_IPV4_ONLY; + else if (!g_strcmp0 (host, "::1")) + options |= SOUP_SERVER_LISTEN_IPV6_ONLY; + + soup_server_listen_local (server, 0, options, &error); + g_assert_no_error (error); + + return find_server_uri (server, scheme, host); +} + +typedef struct { + GMutex mutex; + GCond cond; + + SoupServer *server; + const char *scheme; + const char *host; + + SoupURI *uri; +} AddListenerData; + +static gboolean +add_listener_in_thread (gpointer user_data) +{ + AddListenerData *data = user_data; + + data->uri = add_listener (data->server, data->scheme, data->host); + g_mutex_lock (&data->mutex); + g_cond_signal (&data->cond); + g_mutex_unlock (&data->mutex); + + return FALSE; +} + +SoupURI * +soup_test_server_get_uri (SoupServer *server, + const char *scheme, + const char *host) +{ + SoupURI *uri; + GMainLoop *loop; + + uri = find_server_uri (server, scheme, host); + if (uri) + return uri; + + /* Need to add a new listener */ + loop = g_object_get_data (G_OBJECT (server), "GMainLoop"); + if (loop) { + GMainContext *context = g_main_loop_get_context (loop); + AddListenerData data; + + g_mutex_init (&data.mutex); + g_cond_init (&data.cond); + data.server = server; + data.scheme = scheme; + data.host = host; + data.uri = NULL; + + g_mutex_lock (&data.mutex); + soup_add_completion (context, add_listener_in_thread, &data); + + while (!data.uri) + g_cond_wait (&data.cond, &data.mutex); + + g_mutex_unlock (&data.mutex); + g_mutex_clear (&data.mutex); + g_cond_clear (&data.cond); + uri = data.uri; + } else + uri = add_listener (server, scheme, host); + + return uri; +} + +static gboolean +done_waiting (gpointer user_data) +{ + gboolean *done = user_data; + + *done = TRUE; + return FALSE; +} + +static void +disconnect_and_wait (SoupServer *server, + GMainContext *context) +{ + GSource *source; + gboolean done = FALSE; + + source = g_idle_source_new (); + g_source_set_priority (source, G_PRIORITY_LOW); + g_source_set_callback (source, done_waiting, &done, NULL); + g_source_attach (source, context); + g_source_unref (source); + + soup_server_disconnect (server); + while (!done) + g_main_context_iteration (context, TRUE); +} + +static gboolean +idle_quit_server (gpointer user_data) +{ + SoupServer *server = user_data; + GMainLoop *loop = g_object_get_data (G_OBJECT (server), "GMainLoop"); + + disconnect_and_wait (server, g_main_loop_get_context (loop)); + g_main_loop_quit (loop); + return FALSE; +} + +void +soup_test_server_quit_unref (SoupServer *server) +{ + GThread *thread; + + thread = g_object_get_data (G_OBJECT (server), "thread"); + if (thread) { + GMainLoop *loop; + GMainContext *context; + + loop = g_object_get_data (G_OBJECT (server), "GMainLoop"); + context = g_main_loop_get_context (loop); + g_main_context_ref (context); + soup_add_completion (context, idle_quit_server, server); + g_main_context_unref (context); + g_thread_join (thread); + } else + disconnect_and_wait (server, NULL); + + g_assert_cmpint (G_OBJECT (server)->ref_count, ==, 1); + g_object_unref (server); +} + +typedef struct { + GMainLoop *loop; + GAsyncResult *result; +} AsyncAsSyncData; + +static void +async_as_sync_callback (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + AsyncAsSyncData *data = user_data; + GMainContext *context; + + data->result = g_object_ref (result); + context = g_main_loop_get_context (data->loop); + while (g_main_context_pending (context)) + g_main_context_iteration (context, FALSE); + g_main_loop_quit (data->loop); +} + +typedef struct { + SoupRequest *req; + GCancellable *cancellable; + SoupTestRequestFlags flags; +} CancelData; + +static CancelData * +create_cancel_data (SoupRequest *req, + GCancellable *cancellable, + SoupTestRequestFlags flags) +{ + CancelData *cancel_data; + + if (!flags) + return NULL; + + cancel_data = g_slice_new0 (CancelData); + cancel_data->flags = flags; + if (flags & SOUP_TEST_REQUEST_CANCEL_MESSAGE && SOUP_IS_REQUEST_HTTP (req)) + cancel_data->req = g_object_ref (req); + else if (flags & SOUP_TEST_REQUEST_CANCEL_CANCELLABLE) + cancel_data->cancellable = g_object_ref (cancellable); + return cancel_data; +} + +inline static void +cancel_message_or_cancellable (CancelData *cancel_data) +{ + if (cancel_data->flags & SOUP_TEST_REQUEST_CANCEL_MESSAGE) { + SoupRequest *req = cancel_data->req; + SoupMessage *msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (req)); + soup_session_cancel_message (soup_request_get_session (req), msg, + SOUP_STATUS_CANCELLED); + g_object_unref (msg); + g_object_unref (req); + } else if (cancel_data->flags & SOUP_TEST_REQUEST_CANCEL_CANCELLABLE) { + g_cancellable_cancel (cancel_data->cancellable); + g_object_unref (cancel_data->cancellable); + } + g_slice_free (CancelData, cancel_data); +} + +static gboolean +cancel_request_timeout (gpointer data) +{ + cancel_message_or_cancellable ((CancelData *) data); + return FALSE; +} + +static gpointer +cancel_request_thread (gpointer data) +{ + g_usleep (100000); /* .1s */ + cancel_message_or_cancellable ((CancelData *) data); + return NULL; +} + +GInputStream * +soup_test_request_send (SoupRequest *req, + GCancellable *cancellable, + guint flags, + GError **error) +{ + AsyncAsSyncData data; + GInputStream *stream; + CancelData *cancel_data = create_cancel_data (req, cancellable, flags); + + if (SOUP_IS_SESSION_SYNC (soup_request_get_session (req))) { + GThread *thread; + + if (cancel_data) + thread = g_thread_new ("cancel_request_thread", cancel_request_thread, + cancel_data); + stream = soup_request_send (req, cancellable, error); + if (cancel_data) + g_thread_unref (thread); + return stream; + } + + data.loop = g_main_loop_new (g_main_context_get_thread_default (), FALSE); + if (cancel_data && + (flags & SOUP_TEST_REQUEST_CANCEL_SOON || flags & SOUP_TEST_REQUEST_CANCEL_IMMEDIATE)) { + guint interval = flags & SOUP_TEST_REQUEST_CANCEL_SOON ? 100 : 0; + g_timeout_add_full (G_PRIORITY_HIGH, interval, cancel_request_timeout, cancel_data, NULL); + } + if (cancel_data && (flags & SOUP_TEST_REQUEST_CANCEL_PREEMPTIVE)) + cancel_message_or_cancellable (cancel_data); + soup_request_send_async (req, cancellable, async_as_sync_callback, &data); + g_main_loop_run (data.loop); + + stream = soup_request_send_finish (req, data.result, error); + + if (cancel_data && (flags & SOUP_TEST_REQUEST_CANCEL_AFTER_SEND_FINISH)) { + GMainContext *context; + + cancel_message_or_cancellable (cancel_data); + + context = g_main_loop_get_context (data.loop); + while (g_main_context_pending (context)) + g_main_context_iteration (context, FALSE); + } + + g_main_loop_unref (data.loop); + g_object_unref (data.result); + + return stream; +} + +gboolean +soup_test_request_read_all (SoupRequest *req, + GInputStream *stream, + GCancellable *cancellable, + GError **error) +{ + char buf[8192]; + AsyncAsSyncData data; + gsize nread; + + if (!SOUP_IS_SESSION_SYNC (soup_request_get_session (req))) + data.loop = g_main_loop_new (g_main_context_get_thread_default (), FALSE); + + do { + if (SOUP_IS_SESSION_SYNC (soup_request_get_session (req))) { + nread = g_input_stream_read (stream, buf, sizeof (buf), + cancellable, error); + } else { + g_input_stream_read_async (stream, buf, sizeof (buf), + G_PRIORITY_DEFAULT, cancellable, + async_as_sync_callback, &data); + g_main_loop_run (data.loop); + nread = g_input_stream_read_finish (stream, data.result, error); + g_object_unref (data.result); + } + } while (nread > 0); + + if (!SOUP_IS_SESSION_SYNC (soup_request_get_session (req))) + g_main_loop_unref (data.loop); + + return nread == 0; +} + +gboolean +soup_test_request_close_stream (SoupRequest *req, + GInputStream *stream, + GCancellable *cancellable, + GError **error) +{ + AsyncAsSyncData data; + gboolean ok; + + if (SOUP_IS_SESSION_SYNC (soup_request_get_session (req))) + return g_input_stream_close (stream, cancellable, error); + + data.loop = g_main_loop_new (g_main_context_get_thread_default (), FALSE); + + g_input_stream_close_async (stream, G_PRIORITY_DEFAULT, cancellable, + async_as_sync_callback, &data); + g_main_loop_run (data.loop); + + ok = g_input_stream_close_finish (stream, data.result, error); + + g_main_loop_unref (data.loop); + g_object_unref (data.result); + + return ok; +} + +void +soup_test_register_resources (void) +{ + static gboolean registered = FALSE; + GResource *resource; + char *path; + GError *error = NULL; + + if (registered) + return; + + path = g_test_build_filename (G_TEST_BUILT, "soup-tests.gresource", NULL); + resource = g_resource_load (path, &error); + if (!resource) { + g_printerr ("Could not load resource soup-tests.gresource: %s\n", + error->message); + exit (1); + } + g_free (path); + + g_resources_register (resource); + g_resource_unref (resource); + + registered = TRUE; +} + +SoupBuffer * +soup_test_load_resource (const char *name, + GError **error) +{ + GBytes *bytes; + char *path; + + soup_test_register_resources (); + + path = g_build_path ("/", "/org/gnome/libsoup/tests/resources", name, NULL); + bytes = g_resources_lookup_data (path, G_RESOURCE_LOOKUP_FLAGS_NONE, error); + g_free (path); + + if (!bytes) + return NULL; + + return soup_buffer_new_with_owner (g_bytes_get_data (bytes, NULL), + g_bytes_get_size (bytes), + bytes, + (GDestroyNotify) g_bytes_unref); +} + +SoupBuffer * +soup_test_get_index (void) +{ + if (!index_buffer) { + char *path, *contents; + gsize length; + GError *error = NULL; + + path = g_test_build_filename (G_TEST_DIST, "index.txt", NULL); + if (!g_file_get_contents (path, &contents, &length, &error)) { + g_printerr ("Could not read index.txt: %s\n", + error->message); + exit (1); + } + g_free (path); + + index_buffer = soup_buffer_new (SOUP_MEMORY_TAKE, contents, length); + } + + return index_buffer; +} + +#ifndef G_HAVE_ISO_VARARGS +void +soup_test_assert (gboolean expr, const char *fmt, ...) +{ + char *message; + va_list args; + + if (G_UNLIKELY (!expr)) { + va_start (args, fmt); + message = g_strdup_vprintf (fmt, args); + va_end (args); + + g_assertion_message (G_LOG_DOMAIN, + "???", 0, "???" + message); + g_free (message); + } +} +#endif diff --git a/tests/test-utils.h b/tests/test-utils.h new file mode 100644 index 0000000..0bc065f --- /dev/null +++ b/tests/test-utils.h @@ -0,0 +1,139 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#define LIBSOUP_USE_UNSTABLE_REQUEST_API + +#include "libsoup/soup.h" +#include "libsoup/soup-requester.h" + +void test_init (int argc, char **argv, GOptionEntry *entries); +void test_cleanup (void); + +extern int debug_level; +extern gboolean tls_available; +extern gboolean apache_available; +void debug_printf (int level, const char *format, ...) G_GNUC_PRINTF (2, 3); + +#define SOUP_TEST_SKIP_IF_NO_TLS \ + G_STMT_START { \ + if (!tls_available) { \ + g_test_skip ("TLS is not available"); \ + return; \ + } \ + } G_STMT_END + +#ifdef HAVE_APACHE +void apache_init (void); +void apache_cleanup (void); +#define SOUP_TEST_SKIP_IF_NO_APACHE +#else +#define apache_init() +#define apache_cleanup() +#define SOUP_TEST_SKIP_IF_NO_APACHE \ + G_STMT_START { \ + g_test_skip ("apache is not available"); \ + return; \ + } G_STMT_END +#endif + +typedef enum { + SOUP_TEST_REQUEST_NONE = 0, + SOUP_TEST_REQUEST_CANCEL_MESSAGE = (1 << 0), + SOUP_TEST_REQUEST_CANCEL_CANCELLABLE = (1 << 1), + SOUP_TEST_REQUEST_CANCEL_SOON = (1 << 2), + SOUP_TEST_REQUEST_CANCEL_IMMEDIATE = (1 << 3), + SOUP_TEST_REQUEST_CANCEL_PREEMPTIVE = (1 << 4), + SOUP_TEST_REQUEST_CANCEL_AFTER_SEND_FINISH = (1 << 5), +} SoupTestRequestFlags; + +#undef SOUP_TYPE_SESSION_ASYNC +#define SOUP_TYPE_SESSION_ASYNC (_soup_session_async_get_type_undeprecated ()) +#undef SOUP_TYPE_SESSION_SYNC +#define SOUP_TYPE_SESSION_SYNC (_soup_session_sync_get_type_undeprecated ()) + +SoupSession *soup_test_session_new (GType type, ...); +void soup_test_session_abort_unref (SoupSession *session); + +typedef enum { + SOUP_TEST_SERVER_DEFAULT = 0, + SOUP_TEST_SERVER_IN_THREAD = (1 << 0), + SOUP_TEST_SERVER_NO_DEFAULT_LISTENER = (1 << 1) +} SoupTestServerOptions; + +SoupServer *soup_test_server_new (SoupTestServerOptions options); +SoupURI *soup_test_server_get_uri (SoupServer *server, + const char *scheme, + const char *host); +void soup_test_server_quit_unref (SoupServer *server); + +GInputStream *soup_test_request_send (SoupRequest *req, + GCancellable *cancellable, + guint flags, + GError **error); +gboolean soup_test_request_read_all (SoupRequest *req, + GInputStream *stream, + GCancellable *cancellable, + GError **error); +gboolean soup_test_request_close_stream (SoupRequest *req, + GInputStream *stream, + GCancellable *cancellable, + GError **error); + +void soup_test_register_resources (void); +SoupBuffer *soup_test_load_resource (const char *name, + GError **error); + +SoupBuffer *soup_test_get_index (void); + +#ifdef G_HAVE_ISO_VARARGS +#define soup_test_assert(expr, ...) \ +G_STMT_START { \ + char *_message; \ + if (G_UNLIKELY (!(expr))) { \ + _message = g_strdup_printf (__VA_ARGS__); \ + g_assertion_message (G_LOG_DOMAIN, \ + __FILE__, __LINE__, G_STRFUNC, \ + _message); \ + g_free (_message); \ + } \ +} G_STMT_END +#else +void soup_test_assert (gboolean expr, const char *fmt, ...); +#endif + +#define soup_test_assert_message_status(msg, status) \ +G_STMT_START { \ + SoupMessage *_msg = (msg); \ + guint _status = (status); \ + char *_message; \ + \ + if (G_UNLIKELY (_msg->status_code != _status)) { \ + _message = g_strdup_printf ("Unexpected status %d %s (expected %d %s)", \ + _msg->status_code, _msg->reason_phrase, \ + _status, soup_status_get_phrase (_status)); \ + g_assertion_message (G_LOG_DOMAIN, \ + __FILE__, __LINE__, G_STRFUNC, \ + _message); \ + g_free (_message); \ + } \ +} G_STMT_END + +#define soup_assert_cmpmem(s1, l1, s2, l2) \ +G_STMT_START { \ + int __l1 = l1, __l2 = l2; \ + gconstpointer __s1 = s1, __s2 = s2; \ + if (G_UNLIKELY ((__l1) != (__l2))) { \ + g_assertion_message_cmpnum (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \ + "len(" #s1 ") == len(" #s2 ")", __l1, "==", __l2, \ + 'i'); \ + } else if (G_UNLIKELY (memcmp (__s1, __s2, __l1) != 0)) { \ + g_assertion_message (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \ + "assertion failed (" #s1 " == " #s2 ")"); \ + } \ +} G_STMT_END diff --git a/tests/timeout-test.c b/tests/timeout-test.c new file mode 100644 index 0000000..96505e9 --- /dev/null +++ b/tests/timeout-test.c @@ -0,0 +1,355 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ + +#include "test-utils.h" + +static gboolean slow_https; + +static void +message_finished (SoupMessage *msg, gpointer user_data) +{ + gboolean *finished = user_data; + + *finished = TRUE; +} + +static void +request_started_cb (SoupSession *session, SoupMessage *msg, + SoupSocket *socket, gpointer user_data) +{ + SoupSocket **ret = user_data; + + *ret = socket; +} + +static void +do_message_to_session (SoupSession *session, SoupURI *uri, + const char *comment, guint expected_status) +{ + SoupMessage *msg; + gboolean finished = FALSE; + + if (comment) + debug_printf (1, " msg %s\n", comment); + msg = soup_message_new_from_uri ("GET", uri); + + g_signal_connect (msg, "finished", + G_CALLBACK (message_finished), &finished); + soup_session_send_message (session, msg); + + soup_test_assert_message_status (msg, expected_status); + if (SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) + g_assert_true (soup_message_is_keepalive (msg)); + g_assert_true (finished); + + g_signal_handlers_disconnect_by_func (msg, + G_CALLBACK (message_finished), + &finished); + g_object_unref (msg); +} + +static void +do_msg_tests_for_session (SoupSession *timeout_session, + SoupSession *idle_session, + SoupSession *plain_session, + SoupURI *fast_uri, + SoupURI *slow_uri) +{ + SoupSocket *ret, *idle_first = NULL, *idle_second; + SoupSocket *plain_first = NULL, *plain_second; + + if (idle_session) { + g_signal_connect (idle_session, "request-started", + G_CALLBACK (request_started_cb), &ret); + do_message_to_session (idle_session, fast_uri, "fast to idle", SOUP_STATUS_OK); + idle_first = g_object_ref (ret); + } + + if (plain_session) { + g_signal_connect (plain_session, "request-started", + G_CALLBACK (request_started_cb), &ret); + do_message_to_session (plain_session, fast_uri, "fast to plain", SOUP_STATUS_OK); + plain_first = g_object_ref (ret); + } + + do_message_to_session (timeout_session, fast_uri, "fast to timeout", SOUP_STATUS_OK); + do_message_to_session (timeout_session, slow_uri, "slow to timeout", SOUP_STATUS_IO_ERROR); + + if (idle_session) { + do_message_to_session (idle_session, fast_uri, "fast to idle", SOUP_STATUS_OK); + idle_second = ret; + g_signal_handlers_disconnect_by_func (idle_session, + (gpointer)request_started_cb, + &ret); + + soup_test_assert (idle_first != idle_second, + "idle_session did not close first connection"); + g_object_unref (idle_first); + } + + if (plain_session) { + do_message_to_session (plain_session, fast_uri, "fast to plain", SOUP_STATUS_OK); + plain_second = ret; + g_signal_handlers_disconnect_by_func (plain_session, + (gpointer)request_started_cb, + &ret); + + soup_test_assert (plain_first == plain_second, + "plain_session closed connection"); + g_object_unref (plain_first); + } +} + +static void +do_request_to_session (SoupSession *session, SoupURI *uri, + const char *comment, gboolean expect_timeout) +{ + SoupRequest *req; + SoupMessage *msg; + GInputStream *stream; + GError *error = NULL; + gboolean finished = FALSE; + + debug_printf (1, " req %s\n", comment); + req = soup_session_request_uri (session, uri, NULL); + msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (req)); + + g_signal_connect (msg, "finished", + G_CALLBACK (message_finished), &finished); + stream = soup_test_request_send (req, NULL, 0, &error); + + if (expect_timeout) + g_assert_error (error, G_IO_ERROR, G_IO_ERROR_TIMED_OUT); + else + g_assert_no_error (error); + g_clear_error (&error); + + if (stream) { + soup_test_request_read_all (req, stream, NULL, &error); + g_assert_no_error (error); + } + + if (stream) { + soup_test_request_close_stream (req, stream, NULL, &error); + g_assert_no_error (error); + g_object_unref (stream); + } + + if (SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) + g_assert_true (soup_message_is_keepalive (msg)); + g_assert_true (finished); + + g_signal_handlers_disconnect_by_func (msg, + G_CALLBACK (message_finished), + &finished); + g_object_unref (msg); + g_object_unref (req); +} + +static void +do_req_tests_for_session (SoupSession *timeout_session, + SoupSession *idle_session, + SoupSession *plain_session, + SoupURI *fast_uri, + SoupURI *slow_uri) +{ + SoupSocket *ret, *idle_first = NULL, *idle_second; + SoupSocket *plain_first = NULL, *plain_second; + + if (idle_session) { + g_signal_connect (idle_session, "request-started", + G_CALLBACK (request_started_cb), &ret); + do_request_to_session (idle_session, fast_uri, "fast to idle", FALSE); + idle_first = g_object_ref (ret); + } + + if (plain_session) { + g_signal_connect (plain_session, "request-started", + G_CALLBACK (request_started_cb), &ret); + do_request_to_session (plain_session, fast_uri, "fast to plain", FALSE); + plain_first = g_object_ref (ret); + } + + do_request_to_session (timeout_session, fast_uri, "fast to timeout", FALSE); + do_request_to_session (timeout_session, slow_uri, "slow to timeout", TRUE); + + if (idle_session) { + do_request_to_session (idle_session, fast_uri, "fast to idle", FALSE); + idle_second = ret; + g_signal_handlers_disconnect_by_func (idle_session, + (gpointer)request_started_cb, + &ret); + + soup_test_assert (idle_first != idle_second, + "idle_session did not close first connection"); + g_object_unref (idle_first); + } + + if (plain_session) { + do_request_to_session (plain_session, fast_uri, "fast to plain", FALSE); + plain_second = ret; + g_signal_handlers_disconnect_by_func (plain_session, + (gpointer)request_started_cb, + &ret); + + soup_test_assert (plain_first == plain_second, + "plain_session closed connection"); + g_object_unref (plain_first); + } +} + +static void +do_async_timeout_tests (gconstpointer data) +{ + SoupSession *timeout_session, *idle_session, *plain_session; + SoupURI *fast_uri = (SoupURI *)data; + SoupURI *slow_uri = soup_uri_new_with_base (fast_uri, "/slow"); + gboolean extra_slow; + + if (fast_uri->scheme == SOUP_URI_SCHEME_HTTPS) { + SOUP_TEST_SKIP_IF_NO_TLS; + + extra_slow = slow_https; + } else + extra_slow = FALSE; + + timeout_session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, + SOUP_SESSION_TIMEOUT, extra_slow ? 3 : 1, + SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, + NULL); + idle_session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, + SOUP_SESSION_IDLE_TIMEOUT, extra_slow ? 2 : 1, + SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, + NULL); + /* The "plain" session also has an idle timeout, but it's longer + * than the test takes, so for our purposes it should behave like + * it has no timeout. + */ + plain_session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, + SOUP_SESSION_IDLE_TIMEOUT, 20, + SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, + NULL); + + do_msg_tests_for_session (timeout_session, idle_session, plain_session, + fast_uri, slow_uri); + do_req_tests_for_session (timeout_session, idle_session, plain_session, + fast_uri, slow_uri); + soup_test_session_abort_unref (timeout_session); + soup_test_session_abort_unref (idle_session); + soup_test_session_abort_unref (plain_session); + + soup_uri_free (slow_uri); +} + +static void +do_sync_timeout_tests (gconstpointer data) +{ + SoupSession *timeout_session, *plain_session; + SoupURI *fast_uri = (SoupURI *)data; + SoupURI *slow_uri = soup_uri_new_with_base (fast_uri, "/slow"); + gboolean extra_slow; + + if (fast_uri->scheme == SOUP_URI_SCHEME_HTTPS) { + SOUP_TEST_SKIP_IF_NO_TLS; + + extra_slow = slow_https; + } else + extra_slow = FALSE; + + timeout_session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, + SOUP_SESSION_TIMEOUT, extra_slow ? 3 : 1, + NULL); + /* SOUP_SESSION_TIMEOUT doesn't work with sync sessions */ + plain_session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, + NULL); + do_msg_tests_for_session (timeout_session, NULL, plain_session, fast_uri, slow_uri); + do_req_tests_for_session (timeout_session, NULL, plain_session, fast_uri, slow_uri); + soup_test_session_abort_unref (timeout_session); + soup_test_session_abort_unref (plain_session); + + soup_uri_free (slow_uri); +} + +static gboolean +timeout_finish_message (gpointer msg) +{ + SoupServer *server = g_object_get_data (G_OBJECT (msg), "server"); + + soup_server_unpause_message (server, msg); + return FALSE; +} + +static void +server_handler (SoupServer *server, + SoupMessage *msg, + const char *path, + GHashTable *query, + SoupClientContext *client, + gpointer user_data) +{ + soup_message_set_status (msg, SOUP_STATUS_OK); + soup_message_set_response (msg, "text/plain", + SOUP_MEMORY_STATIC, + "ok\r\n", 4); + + if (!strcmp (path, "/slow")) { + soup_server_pause_message (server, msg); + g_object_set_data (G_OBJECT (msg), "server", server); + soup_add_timeout (g_main_context_get_thread_default (), + 4000, timeout_finish_message, msg); + } +} + +int +main (int argc, char **argv) +{ + SoupServer *server, *https_server = NULL; + SoupURI *uri, *https_uri = NULL; + int ret; + + test_init (argc, argv, NULL); + + server = soup_test_server_new (TRUE); + soup_server_add_handler (server, NULL, server_handler, NULL, NULL); + uri = soup_test_server_get_uri (server, "http", NULL); + + if (tls_available) { + SoupSession *test_session; + gint64 start, end; + + https_server = soup_test_server_new (SOUP_TEST_SERVER_IN_THREAD); + soup_server_add_handler (https_server, NULL, server_handler, NULL, NULL); + https_uri = soup_test_server_get_uri (server, "https", "127.0.0.1"); + + /* The 1-second timeouts are too fast for some machines... */ + test_session = soup_test_session_new (SOUP_TYPE_SESSION, NULL); + start = g_get_monotonic_time (); + do_message_to_session (test_session, uri, NULL, SOUP_STATUS_OK); + end = g_get_monotonic_time (); + soup_test_session_abort_unref (test_session); + debug_printf (2, " (https request took %0.3fs)\n", (end - start) / 1000000.0); + if (end - start > 750000) { + debug_printf (1, " (using extra-slow mode)\n\n"); + slow_https = TRUE; + } else { + debug_printf (2, "\n"); + slow_https = FALSE; + } + } else + https_uri = soup_uri_new ("https://fail."); + + g_test_add_data_func ("/timeout/http/async", uri, do_async_timeout_tests); + g_test_add_data_func ("/timeout/http/sync", uri, do_sync_timeout_tests); + g_test_add_data_func ("/timeout/https/async", https_uri, do_async_timeout_tests); + g_test_add_data_func ("/timeout/https/sync", https_uri, do_sync_timeout_tests); + + ret = g_test_run (); + + soup_uri_free (uri); + soup_uri_free (https_uri); + soup_test_server_quit_unref (server); + if (https_server) + soup_test_server_quit_unref (https_server); + + test_cleanup (); + return ret; +} diff --git a/tests/tld-test.c b/tests/tld-test.c new file mode 100644 index 0000000..aae563c --- /dev/null +++ b/tests/tld-test.c @@ -0,0 +1,195 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2012 Igalia S.L. + */ + +#include "test-utils.h" + +/* From http://publicsuffix.org/list/test.txt */ +static struct { + const char *hostname; + const char *result; + SoupTLDError error; +} tld_tests[] = { + /* NULL input. Not checked here because the API requires a valid hostname. */ + /* { NULL, NULL, -1 }, */ + /* Mixed case. Not checked because the API requires a valid hostname. */ + /* { "COM", NULL, -1 }, */ + /* { "example.COM", "example.com", -1 }, */ + /* { "WwW.example.COM", "example.com", -1 }, */ + /* Leading dot. */ + { ".com", NULL, SOUP_TLD_ERROR_INVALID_HOSTNAME }, + { ".example", NULL, SOUP_TLD_ERROR_INVALID_HOSTNAME }, + { ".example.com", NULL, SOUP_TLD_ERROR_INVALID_HOSTNAME }, + { ".example.example", NULL, SOUP_TLD_ERROR_INVALID_HOSTNAME }, + /* Trailing dot. */ + { ".com.", NULL, SOUP_TLD_ERROR_INVALID_HOSTNAME }, + { "domain.biz.", "domain.biz.", -1 }, + /* TLD with only 1 rule. */ + { "biz", NULL, SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS }, + { "domain.biz", "domain.biz", -1 }, + { "b.domain.biz", "domain.biz", -1 }, + { "a.b.domain.biz", "domain.biz", -1 }, + /* TLD with some 2-level rules. */ + { "com", NULL, SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS }, + { "example.com", "example.com", -1 }, + { "b.example.com", "example.com", -1 }, + { "a.b.example.com", "example.com", -1 }, + { "uk.com", NULL, SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS }, + { "example.uk.com", "example.uk.com", -1 }, + { "b.example.uk.com", "example.uk.com", -1 }, + { "a.b.example.uk.com", "example.uk.com", -1 }, + { "test.ac", "test.ac", -1 }, + /* TLD with only 1 (wildcard) rule. */ + { "bn", NULL, SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS }, + { "c.bn", NULL, SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS }, + { "b.c.bn", "b.c.bn", -1 }, + { "a.b.c.bn", "b.c.bn", -1 }, + /* More complex TLD. */ + { "jp", NULL, SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS }, + { "test.jp", "test.jp", -1 }, + { "www.test.jp", "test.jp", -1 }, + { "ac.jp", NULL, SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS }, + { "test.ac.jp", "test.ac.jp", -1 }, + { "www.test.ac.jp", "test.ac.jp", -1 }, + { "kyoto.jp", NULL, SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS }, + { "minami.kyoto.jp", NULL, SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS }, + { "b.minami.kyoto.jp", "b.minami.kyoto.jp", -1 }, + { "a.b.minami.kyoto.jp", "b.minami.kyoto.jp", -1 }, + { "pref.kyoto.jp", "pref.kyoto.jp", -1 }, + { "www.pref.kyoto.jp", "pref.kyoto.jp", -1 }, + { "city.kyoto.jp", "city.kyoto.jp", -1 }, + { "www.city.kyoto.jp", "city.kyoto.jp", -1 }, + /* TLD with a wildcard rule and exceptions. */ + { "ck", NULL, SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS }, + { "test.ck", NULL, SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS }, + { "b.test.ck", "b.test.ck", -1 }, + { "a.b.test.ck", "b.test.ck", -1 }, + { "www.ck", "www.ck", -1 }, + { "www.www.ck", "www.ck", -1 }, + /* US K12. */ + { "us", NULL, SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS }, + { "test.us", "test.us", -1 }, + { "www.test.us", "test.us", -1 }, + { "ak.us", NULL, SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS }, + { "test.ak.us", "test.ak.us", -1 }, + { "www.test.ak.us", "test.ak.us", -1 }, + { "k12.ak.us", NULL, SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS }, + { "test.k12.ak.us", "test.k12.ak.us", -1 }, + { "www.test.k12.ak.us", "test.k12.ak.us", -1 }, + /* IDN labels. */ + { "食狮.com.cn", "食狮.com.cn", -1 }, + { "食狮.公司.cn", "食狮.公司.cn", -1 }, + { "www.食狮.公司.cn", "食狮.公司.cn", -1 }, + { "shishi.公司.cn", "shishi.公司.cn", -1 }, + { "公司.cn", NULL, SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS }, + { "食狮.中国", "食狮.中国", -1 }, + { "www.食狮.中国", "食狮.中国", -1 }, + { "shishi.中国", "shishi.中国", -1 }, + { "中国", NULL, SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS }, + /* Same as above, but punycoded. */ + { "xn--85x722f.com.cn", "xn--85x722f.com.cn", -1 }, + { "xn--85x722f.xn--55qx5d.cn", "xn--85x722f.xn--55qx5d.cn", -1 }, + { "www.xn--85x722f.xn--55qx5d.cn", "xn--85x722f.xn--55qx5d.cn", -1 }, + { "shishi.xn--55qx5d.cn", "shishi.xn--55qx5d.cn", -1 }, + { "xn--55qx5d.cn", NULL, SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS }, + { "xn--85x722f.xn--fiqs8s", "xn--85x722f.xn--fiqs8s", -1 }, + { "www.xn--85x722f.xn--fiqs8s", "xn--85x722f.xn--fiqs8s", -1 }, + { "shishi.xn--fiqs8s", "shishi.xn--fiqs8s", -1 }, + { "xn--fiqs8s", NULL, SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS }, + /* End of publicsuffix.org tests */ + + /* Let's just double-check this one... */ + { "co.uk", NULL, SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS }, + { "test.co.uk", "test.co.uk", -1 }, + { "www.test.co.uk", "test.co.uk", -1 }, + + /* Two levels of non-ASCII */ + { "våler.østfold.no", NULL, SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS }, + { "test.våler.østfold.no", "test.våler.østfold.no", -1 }, + { "www.test.våler.østfold.no", "test.våler.østfold.no", -1 }, + { "xn--vler-qoa.xn--stfold-9xa.no", NULL, SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS }, + { "test.xn--vler-qoa.xn--stfold-9xa.no", "test.xn--vler-qoa.xn--stfold-9xa.no", -1 }, + { "www.test.xn--vler-qoa.xn--stfold-9xa.no", "test.xn--vler-qoa.xn--stfold-9xa.no", -1 }, +}, + +/* Non Internet TLDs have NULL as expected result + */ +non_inet_tld_tests[] = { + /* Unlisted TLD.*/ + { "example", NULL }, + { "example.example", NULL }, + { "b.example.example", NULL }, + { "a.b.example.example", NULL }, + /* Listed, but non-Internet, TLD. */ + { "local", NULL }, + { "example.local", NULL }, + { "b.example.local", NULL }, + { "a.b.example.local", NULL } +}; + +static void +do_inet_tests (void) +{ + int i; + + for (i = 0; i < G_N_ELEMENTS (tld_tests); i++) { + GError *error = NULL; + gboolean is_public; + const char *base_domain; + + debug_printf (1, "Testing %s\n", tld_tests[i].hostname); + + is_public = soup_tld_domain_is_public_suffix (tld_tests[i].hostname); + base_domain = soup_tld_get_base_domain (tld_tests[i].hostname, &error); + + if (base_domain) { + g_assert_no_error (error); + g_assert_false (is_public); + g_assert_cmpstr (base_domain, ==, tld_tests[i].result); + } else { + g_assert_null (tld_tests[i].result); + g_assert_error (error, SOUP_TLD_ERROR, tld_tests[i].error); + g_clear_error (&error); + } + } +} + +static void +do_non_inet_tests (void) +{ + int i; + + g_test_bug ("679230"); + g_test_bug ("681085"); + + for (i = 0; i < G_N_ELEMENTS (non_inet_tld_tests); i++) { + gboolean is_public; + const char *base_domain; + + debug_printf (1, "Testing %s\n", non_inet_tld_tests[i].hostname); + + is_public = soup_tld_domain_is_public_suffix (non_inet_tld_tests[i].hostname); + base_domain = soup_tld_get_base_domain (non_inet_tld_tests[i].hostname, NULL); + + g_assert_false (is_public); + g_assert_null (base_domain); + } +} + +int +main (int argc, char **argv) +{ + int ret; + + test_init (argc, argv, NULL); + + g_test_add_func ("/tld/inet", do_inet_tests); + g_test_add_func ("/tld/non-inet", do_non_inet_tests); + + ret = g_test_run (); + + test_cleanup (); + + return ret; +} diff --git a/tests/uri-parsing.c b/tests/uri-parsing.c new file mode 100644 index 0000000..85f09b9 --- /dev/null +++ b/tests/uri-parsing.c @@ -0,0 +1,584 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ + +#include "test-utils.h" + +static struct { + const char *uri_string, *result, *bugref; + const SoupURI bits; +} abs_tests[] = { + { "foo:", "foo:", NULL, + { "foo", NULL, NULL, NULL, 0, "", NULL, NULL } }, + { "file:/dev/null", "file:/dev/null", NULL, + { "file", NULL, NULL, NULL, 0, "/dev/null", NULL, NULL } }, + { "file:///dev/null", "file:///dev/null", NULL, + { "file", NULL, NULL, "", 0, "/dev/null", NULL, NULL } }, + { "ftp://user@host/path", "ftp://user@host/path", NULL, + { "ftp", "user", NULL, "host", 21, "/path", NULL, NULL } }, + { "ftp://user@host:9999/path", "ftp://user@host:9999/path", NULL, + { "ftp", "user", NULL, "host", 9999, "/path", NULL, NULL } }, + { "ftp://user:password@host/path", "ftp://user@host/path", NULL, + { "ftp", "user", "password", "host", 21, "/path", NULL, NULL } }, + { "ftp://user:password@host:9999/path", "ftp://user@host:9999/path", NULL, + { "ftp", "user", "password", "host", 9999, "/path", NULL, NULL } }, + { "ftp://user:password@host", "ftp://user@host", NULL, + { "ftp", "user", "password", "host", 21, "", NULL, NULL } }, + { "http://us%65r@host", "http://user@host/", NULL, + { "http", "user", NULL, "host", 80, "/", NULL, NULL } }, + { "http://us%40r@host", "http://us%40r@host/", NULL, + { "http", "us\x40r", NULL, "host", 80, "/", NULL, NULL } }, + { "http://us%3ar@host", "http://us%3Ar@host/", NULL, + { "http", "us\x3ar", NULL, "host", 80, "/", NULL, NULL } }, + { "http://us%2fr@host", "http://us%2Fr@host/", NULL, + { "http", "us\x2fr", NULL, "host", 80, "/", NULL, NULL } }, + { "http://us%3fr@host", "http://us%3Fr@host/", NULL, + { "http", "us\x3fr", NULL, "host", 80, "/", NULL, NULL } }, + { "http://host?query", "http://host/?query", NULL, + { "http", NULL, NULL, "host", 80, "/", "query", NULL } }, + { "http://host/path?query=http%3A%2F%2Fhost%2Fpath%3Fchildparam%3Dchildvalue¶m=value", + "http://host/path?query=http%3A%2F%2Fhost%2Fpath%3Fchildparam%3Dchildvalue¶m=value", NULL, + { "http", NULL, NULL, "host", 80, "/path", "query=http%3A%2F%2Fhost%2Fpath%3Fchildparam%3Dchildvalue¶m=value", NULL } }, + { "http://control-chars/%01%02%03%04%05%06%07%08%09%0A%0B%0C%0D%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%7F", + "http://control-chars/%01%02%03%04%05%06%07%08%09%0A%0B%0C%0D%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%7F", NULL, + { "http", NULL, NULL, "control-chars", 80, "/%01%02%03%04%05%06%07%08%09%0A%0B%0C%0D%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%7F", NULL, NULL } }, + { "http://space/%20", + "http://space/%20", NULL, + { "http", NULL, NULL, "space", 80, "/%20", NULL, NULL } }, + { "http://delims/%3C%3E%23%25%22", + "http://delims/%3C%3E%23%25%22", NULL, + { "http", NULL, NULL, "delims", 80, "/%3C%3E%23%25%22", NULL, NULL } }, + { "http://unwise-chars/%7B%7D%7C%5C%5E%5B%5D%60", + "http://unwise-chars/%7B%7D%7C%5C%5E%5B%5D%60", NULL, + { "http", NULL, NULL, "unwise-chars", 80, "/%7B%7D%7C%5C%5E%5B%5D%60", NULL, NULL } }, + + /* From RFC 2732 */ + { "http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80/index.html", + "http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]/index.html", NULL, + { "http", NULL, NULL, "FEDC:BA98:7654:3210:FEDC:BA98:7654:3210", 80, "/index.html", NULL, NULL } }, + { "http://[1080:0:0:0:8:800:200C:417A]/index.html", + "http://[1080:0:0:0:8:800:200C:417A]/index.html", NULL, + { "http", NULL, NULL, "1080:0:0:0:8:800:200C:417A", 80, "/index.html", NULL, NULL } }, + { "http://[3ffe:2a00:100:7031::1]", + "http://[3ffe:2a00:100:7031::1]/", NULL, + { "http", NULL, NULL, "3ffe:2a00:100:7031::1", 80, "/", NULL, NULL } }, + { "http://[1080::8:800:200C:417A]/foo", + "http://[1080::8:800:200C:417A]/foo", NULL, + { "http", NULL, NULL, "1080::8:800:200C:417A", 80, "/foo", NULL, NULL } }, + { "http://[::192.9.5.5]/ipng", + "http://[::192.9.5.5]/ipng", NULL, + { "http", NULL, NULL, "::192.9.5.5", 80, "/ipng", NULL, NULL } }, + { "http://[::FFFF:129.144.52.38]:80/index.html", + "http://[::FFFF:129.144.52.38]/index.html", NULL, + { "http", NULL, NULL, "::FFFF:129.144.52.38", 80, "/index.html", NULL, NULL } }, + { "http://[2010:836B:4179::836B:4179]", + "http://[2010:836B:4179::836B:4179]/", NULL, + { "http", NULL, NULL, "2010:836B:4179::836B:4179", 80, "/", NULL, NULL } }, + + /* Try to recover certain kinds of invalid URIs */ + { "http://host/path with spaces", + "http://host/path%20with%20spaces", "566530", + { "http", NULL, NULL, "host", 80, "/path%20with%20spaces", NULL, NULL } }, + { " http://host/path", "http://host/path", "594405", + { "http", NULL, NULL, "host", 80, "/path", NULL, NULL } }, + { "http://host/path ", "http://host/path", "594405", + { "http", NULL, NULL, "host", 80, "/path", NULL, NULL } }, + { "http://host ", "http://host/", "594405", + { "http", NULL, NULL, "host", 80, "/", NULL, NULL } }, + { "http://host:999 ", "http://host:999/", "594405", + { "http", NULL, NULL, "host", 999, "/", NULL, NULL } }, + { "http://host/pa\nth", "http://host/path", "594405", + { "http", NULL, NULL, "host", 80, "/path", NULL, NULL } }, + { "http:\r\n//host/path", "http://host/path", "594405", + { "http", NULL, NULL, "host", 80, "/path", NULL, NULL } }, + { "http://\thost/path", "http://host/path", "594405", + { "http", NULL, NULL, "host", 80, "/path", NULL, NULL } }, + + /* 0-length is different from not-present */ + { "http://host/path?", "http://host/path?", "594405", + { "http", NULL, NULL, "host", 80, "/path", "", NULL } }, + { "http://host/path#", "http://host/path#", "594405", + { "http", NULL, NULL, "host", 80, "/path", NULL, "" } }, + + /* ignore bad %-encoding */ + { "http://host/path%", "http://host/path%", "590524", + { "http", NULL, NULL, "host", 80, "/path%", NULL, NULL } }, + { "http://h%ost/path", "http://h%25ost/path", "590524", + { "http", NULL, NULL, "h%ost", 80, "/path", NULL, NULL } }, + { "http://host/path%%", "http://host/path%%", "590524", + { "http", NULL, NULL, "host", 80, "/path%%", NULL, NULL } }, + { "http://host/path%%%", "http://host/path%%%", "590524", + { "http", NULL, NULL, "host", 80, "/path%%%", NULL, NULL } }, + { "http://host/path%/x/", "http://host/path%/x/", "590524", + { "http", NULL, NULL, "host", 80, "/path%/x/", NULL, NULL } }, + { "http://host/path%0x/", "http://host/path%0x/", "590524", + { "http", NULL, NULL, "host", 80, "/path%0x/", NULL, NULL } }, + { "http://host/path%ax", "http://host/path%ax", "590524", + { "http", NULL, NULL, "host", 80, "/path%ax", NULL, NULL } }, + + /* %-encode non-ASCII characters */ + { "http://host/p\xc3\xa4th/", "http://host/p%C3%A4th/", "662806", + { "http", NULL, NULL, "host", 80, "/p%C3%A4th/", NULL, NULL } }, + + { "HTTP:////////////////", "http:////////////////", "667637", + { "http", NULL, NULL, "", 80, "//////////////", NULL, NULL } }, + + { "http://@host", "http://@host/", NULL, + { "http", "", NULL, "host", 80, "/", NULL, NULL } }, + { "http://:@host", "http://@host/", NULL, + { "http", "", "", "host", 80, "/", NULL, NULL } }, + + { "http://host/keep%00nuls", "http://host/keep%00nuls", NULL, + { "http", NULL, NULL, "host", 80, "/keep%00nuls", NULL, NULL } }, + + /* scheme parsing */ + { "foo0://host/path", "foo0://host/path", "703776", + { "foo0", NULL, NULL, "host", 0, "/path", NULL, NULL } }, + { "f0.o://host/path", "f0.o://host/path", "703776", + { "f0.o", NULL, NULL, "host", 0, "/path", NULL, NULL } }, + { "http++://host/path", "http++://host/path", "703776", + { "http++", NULL, NULL, "host", 0, "/path", NULL, NULL } }, + { "http-ish://host/path", "http-ish://host/path", "703776", + { "http-ish", NULL, NULL, "host", 0, "/path", NULL, NULL } }, + { "99http://host/path", NULL, "703776", + { NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL } }, + { ".http://host/path", NULL, "703776", + { NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL } }, + { "+http://host/path", NULL, "703776", + { NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL } }, + + /* IPv6 scope ID parsing (both correct and incorrect) */ + { "http://[fe80::dead:beef%em1]/", "http://[fe80::dead:beef%25em1]/", NULL, + { "http", NULL, NULL, "fe80::dead:beef%em1", 80, "/", NULL, NULL } }, + { "http://[fe80::dead:beef%25em1]/", "http://[fe80::dead:beef%25em1]/", NULL, + { "http", NULL, NULL, "fe80::dead:beef%em1", 80, "/", NULL, NULL } }, + { "http://[fe80::dead:beef%10]/", "http://[fe80::dead:beef%2510]/", NULL, + { "http", NULL, NULL, "fe80::dead:beef%10", 80, "/", NULL, NULL } }, + + /* ".." past top */ + { "http://example.com/..", "http://example.com/", "785042", + { "http", NULL, NULL, "example.com", 80, "/", NULL, NULL } }, +}; +static int num_abs_tests = G_N_ELEMENTS(abs_tests); + +/* From RFC 3986. */ +static const char *base = "http://a/b/c/d;p?q"; +static struct { + const char *uri_string, *result; + const SoupURI bits; +} rel_tests[] = { + { "g:h", "g:h", + { "g", NULL, NULL, NULL, 0, "h", NULL, NULL } }, + { "g", "http://a/b/c/g", + { "http", NULL, NULL, "a", 80, "/b/c/g", NULL, NULL } }, + { "./g", "http://a/b/c/g", + { "http", NULL, NULL, "a", 80, "/b/c/g", NULL, NULL } }, + { "g/", "http://a/b/c/g/", + { "http", NULL, NULL, "a", 80, "/b/c/g/", NULL, NULL } }, + { "/g", "http://a/g", + { "http", NULL, NULL, "a", 80, "/g", NULL, NULL } }, + { "//g", "http://g/", + { "http", NULL, NULL, "g", 80, "/", NULL, NULL } }, + { "?y", "http://a/b/c/d;p?y", + { "http", NULL, NULL, "a", 80, "/b/c/d;p", "y", NULL } }, + { "g?y", "http://a/b/c/g?y", + { "http", NULL, NULL, "a", 80, "/b/c/g", "y", NULL } }, + { "#s", "http://a/b/c/d;p?q#s", + { "http", NULL, NULL, "a", 80, "/b/c/d;p", "q", "s" } }, + { "g#s", "http://a/b/c/g#s", + { "http", NULL, NULL, "a", 80, "/b/c/g", NULL, "s" } }, + { "g?y#s", "http://a/b/c/g?y#s", + { "http", NULL, NULL, "a", 80, "/b/c/g", "y", "s" } }, + { ";x", "http://a/b/c/;x", + { "http", NULL, NULL, "a", 80, "/b/c/;x", NULL, NULL } }, + { "g;x", "http://a/b/c/g;x", + { "http", NULL, NULL, "a", 80, "/b/c/g;x", NULL, NULL } }, + { "g;x?y#s", "http://a/b/c/g;x?y#s", + { "http", NULL, NULL, "a", 80, "/b/c/g;x", "y", "s" } }, + { ".", "http://a/b/c/", + { "http", NULL, NULL, "a", 80, "/b/c/", NULL, NULL } }, + { "./", "http://a/b/c/", + { "http", NULL, NULL, "a", 80, "/b/c/", NULL, NULL } }, + { "..", "http://a/b/", + { "http", NULL, NULL, "a", 80, "/b/", NULL, NULL } }, + { "../", "http://a/b/", + { "http", NULL, NULL, "a", 80, "/b/", NULL, NULL } }, + { "../g", "http://a/b/g", + { "http", NULL, NULL, "a", 80, "/b/g", NULL, NULL } }, + { "../..", "http://a/", + { "http", NULL, NULL, "a", 80, "/", NULL, NULL } }, + { "../../", "http://a/", + { "http", NULL, NULL, "a", 80, "/", NULL, NULL } }, + { "../../g", "http://a/g", + { "http", NULL, NULL, "a", 80, "/g", NULL, NULL } }, + { "", "http://a/b/c/d;p?q", + { "http", NULL, NULL, "a", 80, "/b/c/d;p", "q", NULL } }, + { "../../../g", "http://a/g", + { "http", NULL, NULL, "a", 80, "/g", NULL, NULL } }, + { "../../../../g", "http://a/g", + { "http", NULL, NULL, "a", 80, "/g", NULL, NULL } }, + { "/./g", "http://a/g", + { "http", NULL, NULL, "a", 80, "/g", NULL, NULL } }, + { "/../g", "http://a/g", + { "http", NULL, NULL, "a", 80, "/g", NULL, NULL } }, + { "g.", "http://a/b/c/g.", + { "http", NULL, NULL, "a", 80, "/b/c/g.", NULL, NULL } }, + { ".g", "http://a/b/c/.g", + { "http", NULL, NULL, "a", 80, "/b/c/.g", NULL, NULL } }, + { "g..", "http://a/b/c/g..", + { "http", NULL, NULL, "a", 80, "/b/c/g..", NULL, NULL } }, + { "..g", "http://a/b/c/..g", + { "http", NULL, NULL, "a", 80, "/b/c/..g", NULL, NULL } }, + { "./../g", "http://a/b/g", + { "http", NULL, NULL, "a", 80, "/b/g", NULL, NULL } }, + { "./g/.", "http://a/b/c/g/", + { "http", NULL, NULL, "a", 80, "/b/c/g/", NULL, NULL } }, + { "g/./h", "http://a/b/c/g/h", + { "http", NULL, NULL, "a", 80, "/b/c/g/h", NULL, NULL } }, + { "g/../h", "http://a/b/c/h", + { "http", NULL, NULL, "a", 80, "/b/c/h", NULL, NULL } }, + { "g;x=1/./y", "http://a/b/c/g;x=1/y", + { "http", NULL, NULL, "a", 80, "/b/c/g;x=1/y", NULL, NULL } }, + { "g;x=1/../y", "http://a/b/c/y", + { "http", NULL, NULL, "a", 80, "/b/c/y", NULL, NULL } }, + { "g?y/./x", "http://a/b/c/g?y/./x", + { "http", NULL, NULL, "a", 80, "/b/c/g", "y/./x", NULL } }, + { "g?y/../x", "http://a/b/c/g?y/../x", + { "http", NULL, NULL, "a", 80, "/b/c/g", "y/../x", NULL } }, + { "g#s/./x", "http://a/b/c/g#s/./x", + { "http", NULL, NULL, "a", 80, "/b/c/g", NULL, "s/./x" } }, + { "g#s/../x", "http://a/b/c/g#s/../x", + { "http", NULL, NULL, "a", 80, "/b/c/g", NULL, "s/../x" } }, + + /* RFC 3986 notes that some old parsers will parse this as + * a relative URL ("http://a/b/c/g"), but it should be + * interpreted as absolute. libsoup should parse it + * correctly as being absolute, but then reject it since it's + * an http URL with no host. + */ + { "http:g", NULL, { NULL } } +}; +static int num_rel_tests = G_N_ELEMENTS(rel_tests); + +static struct { + const char *one, *two, *bugref; +} eq_tests[] = { + { "example://a/b/c/%7Bfoo%7D", "eXAMPLE://a/./b/../b/%63/%7Bfoo%7D", "628728" }, + { "http://example.com", "http://example.com/", NULL }, + /* From RFC 2616 */ + { "http://abc.com:80/~smith/home.html", "http://abc.com:80/~smith/home.html", NULL }, + { "http://abc.com:80/~smith/home.html", "http://ABC.com/%7Esmith/home.html", NULL }, + { "http://abc.com:80/~smith/home.html", "http://ABC.com:/%7esmith/home.html", NULL }, +}; +static int num_eq_tests = G_N_ELEMENTS(eq_tests); + +static void +do_uri (SoupURI *base_uri, const char *base_str, + const char *in_uri, const char *out_uri, + const SoupURI *bits) +{ + SoupURI *uri; + char *uri_string; + + if (base_uri) { + debug_printf (1, "<%s> + <%s> = <%s>\n", base_str, in_uri, + out_uri ? out_uri : "ERR"); + uri = soup_uri_new_with_base (base_uri, in_uri); + } else { + debug_printf (1, "<%s> => <%s>\n", in_uri, + out_uri ? out_uri : "ERR"); + uri = soup_uri_new (in_uri); + } + + if (!uri) { + g_assert_null (out_uri); + return; + } + + if (bits != NULL) { + g_assert_cmpstr (uri->scheme, ==, bits->scheme); + g_assert_cmpstr (uri->user, ==, bits->user); + g_assert_cmpstr (uri->password, ==, bits->password); + g_assert_cmpstr (uri->host, ==, bits->host); + g_assert_cmpuint (uri->port, ==, bits->port); + g_assert_cmpstr (uri->path, ==, bits->path); + g_assert_cmpstr (uri->query, ==, bits->query); + g_assert_cmpstr (uri->fragment, ==, bits->fragment); + } + + uri_string = soup_uri_to_string (uri, FALSE); + soup_uri_free (uri); + + g_assert_cmpstr (uri_string, ==, out_uri); + g_free (uri_string); +} + +static void +do_absolute_uri_tests (void) +{ + int i; + + for (i = 0; i < num_abs_tests; i++) { + if (abs_tests[i].bugref) + g_test_bug (abs_tests[i].bugref); + do_uri (NULL, NULL, abs_tests[i].uri_string, + abs_tests[i].result, &abs_tests[i].bits); + } +} + +static void +do_relative_uri_tests (void) +{ + SoupURI *base_uri; + char *uri_string; + int i; + + base_uri = soup_uri_new (base); + if (!base_uri) { + g_printerr ("Could not parse %s!\n", base); + exit (1); + } + + uri_string = soup_uri_to_string (base_uri, FALSE); + g_assert_cmpstr (uri_string, ==, base); + g_free (uri_string); + + for (i = 0; i < num_rel_tests; i++) { + do_uri (base_uri, base, rel_tests[i].uri_string, + rel_tests[i].result, &rel_tests[i].bits); + } + soup_uri_free (base_uri); +} + +static void +do_equality_tests (void) +{ + SoupURI *uri1, *uri2; + int i; + + for (i = 0; i < num_eq_tests; i++) { + if (eq_tests[i].bugref) + g_test_bug (eq_tests[i].bugref); + + uri1 = soup_uri_new (eq_tests[i].one); + uri2 = soup_uri_new (eq_tests[i].two); + + debug_printf (1, "<%s> == <%s>\n", eq_tests[i].one, eq_tests[i].two); + g_assert_true (soup_uri_equal (uri1, uri2)); + + soup_uri_free (uri1); + soup_uri_free (uri2); + } +} + +static void +do_soup_uri_null_tests (void) +{ + SoupURI *uri, *uri2; + char *uri_string; + + g_test_bug ("667637"); + g_test_bug ("670431"); + + uri = soup_uri_new (NULL); + g_assert_false (SOUP_URI_IS_VALID (uri)); + g_assert_false (SOUP_URI_VALID_FOR_HTTP (uri)); + + /* This implicitly also verifies that none of these methods g_warn */ + g_assert_null (soup_uri_get_scheme (uri)); + g_assert_null (soup_uri_get_user (uri)); + g_assert_null (soup_uri_get_password (uri)); + g_assert_null (soup_uri_get_host (uri)); + g_assert_cmpint (soup_uri_get_port (uri), ==, 0); + g_assert_null (soup_uri_get_path (uri)); + g_assert_null (soup_uri_get_query (uri)); + g_assert_null (soup_uri_get_fragment (uri)); + + g_test_expect_message ("libsoup", G_LOG_LEVEL_CRITICAL, + "*base == NULL*"); + uri2 = soup_uri_new_with_base (uri, "/path"); + g_test_assert_expected_messages (); + g_assert_null (uri2); + + g_test_expect_message ("libsoup", G_LOG_LEVEL_WARNING, + "*SOUP_URI_IS_VALID*"); + uri_string = soup_uri_to_string (uri, FALSE); + g_test_assert_expected_messages (); + g_assert_cmpstr (uri_string, ==, ""); + g_free (uri_string); + + soup_uri_set_scheme (uri, SOUP_URI_SCHEME_HTTP); + g_assert_false (SOUP_URI_IS_VALID (uri)); + g_assert_false (SOUP_URI_VALID_FOR_HTTP (uri)); + + g_test_expect_message ("libsoup", G_LOG_LEVEL_WARNING, + "*SOUP_URI_IS_VALID*"); + uri_string = soup_uri_to_string (uri, FALSE); + g_test_assert_expected_messages (); + g_assert_cmpstr (uri_string, ==, "http:"); + g_free (uri_string); + + soup_uri_set_host (uri, "localhost"); + g_assert_false (SOUP_URI_IS_VALID (uri)); + g_assert_false (SOUP_URI_VALID_FOR_HTTP (uri)); + + g_test_expect_message ("libsoup", G_LOG_LEVEL_WARNING, + "*SOUP_URI_IS_VALID*"); + uri_string = soup_uri_to_string (uri, FALSE); + g_test_assert_expected_messages (); + g_assert_cmpstr (uri_string, ==, "http://localhost/"); + g_free (uri_string); + + g_test_expect_message ("libsoup", G_LOG_LEVEL_WARNING, + "*SOUP_URI_IS_VALID*"); + uri2 = soup_uri_new_with_base (uri, "/path"); + g_test_assert_expected_messages (); + g_assert_true (uri2 != NULL); + + if (uri2) { + uri_string = soup_uri_to_string (uri2, FALSE); + g_assert_cmpstr (uri_string, ==, "http://localhost/path"); + g_free (uri_string); + soup_uri_free (uri2); + } + + g_test_expect_message ("libsoup", G_LOG_LEVEL_WARNING, + "*path != NULL*"); + soup_uri_set_path (uri, NULL); + g_test_assert_expected_messages (); + g_assert_cmpstr (uri->path, ==, ""); + + uri_string = soup_uri_to_string (uri, FALSE); + g_assert_cmpstr (uri_string, ==, "http://localhost/"); + g_free (uri_string); + + g_assert_true (SOUP_URI_IS_VALID (uri)); + g_assert_true (SOUP_URI_VALID_FOR_HTTP (uri)); + + soup_uri_free (uri); +} + +static struct { + const char *uri_string, *unescape_extra, *result; +} normalization_tests[] = { + { "fo%6fbar", NULL, "foobar" }, + { "foo%2fbar", NULL, "foo%2fbar" }, + { "foo%2Fbar", NULL, "foo%2Fbar" }, + { "foo%2fbar", "/", "foo/bar" }, + { "foo bar", NULL, "foo%20bar" }, + { "foo bar", " ", "foo bar" }, + { "fo\xc3\xb6" "bar", NULL, "fo%C3%B6bar" }, + { "fo\xc3\xb6 bar", " ", "fo%C3%B6 bar" } +}; +static int num_normalization_tests = G_N_ELEMENTS (normalization_tests); + +static void +do_normalization_tests (void) +{ + char *normalized; + int i; + + g_test_bug ("680018"); + + for (i = 0; i < num_normalization_tests; i++) { + if (normalization_tests[i].unescape_extra) { + debug_printf (1, "<%s> unescaping <%s> => <%s>\n", + normalization_tests[i].uri_string, + normalization_tests[i].unescape_extra, + normalization_tests[i].result); + } else { + debug_printf (1, "<%s> => <%s>\n", + normalization_tests[i].uri_string, + normalization_tests[i].result); + } + + normalized = soup_uri_normalize (normalization_tests[i].uri_string, + normalization_tests[i].unescape_extra); + g_assert_cmpstr (normalized, ==, normalization_tests[i].result); + g_free (normalized); + } +} + +typedef struct { + const char *uri; + const char *mime_type; + const char *body; +} DataURITest; + +static const DataURITest data_tests[] = { + { "data:text/plain,foo%20bar", + "text/plain", + "foo bar" }, + { "data:text/plain;charset=utf-8,foo%20bar", + "text/plain;charset=utf-8", + "foo bar" }, + { "data:text/plain;base64,Zm9vIGJhcg==", + "text/plain", + "foo bar" }, + { "data:,foo%20bar", + "text/plain;charset=US-ASCII", + "foo bar" }, + { "data:;base64,Zm9vIGJhcg==", + "text/plain;charset=US-ASCII", + "foo bar" }, + { "data:,", + "text/plain;charset=US-ASCII", + "" }, + { "data:text/plain,", + "text/plain", + "" } +}; + +static void +do_data_tests (void) +{ + SoupSession *session; + SoupRequest *req; + GInputStream *stream; + char buf[128]; + gsize nread; + int i; + GError *error = NULL; + + session = soup_test_session_new (SOUP_TYPE_SESSION, NULL); + for (i = 0; i < G_N_ELEMENTS (data_tests); i++) { + req = soup_session_request (session, data_tests[i].uri, &error); + g_assert_no_error (error); + + stream = soup_request_send (req, NULL, &error); + g_assert_no_error (error); + + g_input_stream_read_all (stream, buf, sizeof (buf), &nread, NULL, &error); + + g_assert_no_error (error); + g_assert_cmpint (nread, ==, strlen (data_tests[i].body)); + buf[nread] = 0; + g_assert_cmpstr (buf, ==, data_tests[i].body); + + g_assert_cmpstr (soup_request_get_content_type (req), ==, data_tests[i].mime_type); + + g_input_stream_close (stream, NULL, &error); + g_assert_no_error (error); + g_object_unref (stream); + g_object_unref (req); + } + soup_test_session_abort_unref (session); +} + +int +main (int argc, char **argv) +{ + int ret; + + test_init (argc, argv, NULL); + + g_test_add_func ("/uri/absolute", do_absolute_uri_tests); + g_test_add_func ("/uri/relative", do_relative_uri_tests); + g_test_add_func ("/uri/equality", do_equality_tests); + g_test_add_func ("/uri/null", do_soup_uri_null_tests); + g_test_add_func ("/uri/normalization", do_normalization_tests); + g_test_add_func ("/uri/data", do_data_tests); + + ret = g_test_run (); + + test_cleanup (); + return ret; +} diff --git a/tests/websocket-test.c b/tests/websocket-test.c new file mode 100644 index 0000000..722ccbd --- /dev/null +++ b/tests/websocket-test.c @@ -0,0 +1,971 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * This file was originally part of Cockpit. + * + * Copyright (C) 2013 Red Hat, Inc. + * + * Cockpit is free software; you can redistribute it 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. + * + * Cockpit is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Cockpit; If not, see . + */ + +#include "test-utils.h" + +typedef struct { + GSocket *listener; + gushort port; + + SoupSession *session; + SoupMessage *msg; + SoupWebsocketConnection *client; + GError *client_error; + + SoupServer *soup_server; + SoupWebsocketConnection *server; + + gboolean no_server; + GIOStream *raw_server; + + GMutex mutex; +} Test; + +#define WAIT_UNTIL(cond) \ + G_STMT_START \ + while (!(cond)) g_main_context_iteration (NULL, TRUE); \ + G_STMT_END + +static void +on_error_not_reached (SoupWebsocketConnection *ws, + GError *error, + gpointer user_data) +{ + /* At this point we know this will fail, but is informative */ + g_assert_no_error (error); +} + +static void +on_error_copy (SoupWebsocketConnection *ws, + GError *error, + gpointer user_data) +{ + GError **copy = user_data; + g_assert (*copy == NULL); + *copy = g_error_copy (error); +} + +static void +setup_listener (Test *test) +{ + GSocketAddress *addr; + GError *error = NULL; + + test->listener = g_socket_new (G_SOCKET_FAMILY_IPV4, + G_SOCKET_TYPE_STREAM, + G_SOCKET_PROTOCOL_TCP, + &error); + g_assert_no_error (error); + + addr = g_inet_socket_address_new_from_string ("127.0.0.1", 0); + g_assert_no_error (error); + + g_socket_bind (test->listener, addr, TRUE, &error); + g_assert_no_error (error); + g_object_unref (addr); + + addr = g_socket_get_local_address (test->listener, &error); + g_assert_no_error (error); + + test->port = g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (addr)); + g_object_unref (addr); + + g_socket_listen (test->listener, &error); + g_assert_no_error (error); +} + +static void +direct_connection_complete (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + Test *test = user_data; + GSocketConnection *conn; + SoupURI *uri; + GError *error = NULL; + + conn = g_socket_client_connect_to_host_finish (G_SOCKET_CLIENT (object), + result, &error); + g_assert_no_error (error); + + uri = soup_uri_new ("http://127.0.0.1/"); + test->client = soup_websocket_connection_new (G_IO_STREAM (conn), uri, + SOUP_WEBSOCKET_CONNECTION_CLIENT, + NULL, NULL); + soup_uri_free (uri); + g_object_unref (conn); +} + +static gboolean +got_connection (GSocket *listener, + GIOCondition cond, + gpointer user_data) +{ + Test *test = user_data; + GSocket *sock; + GSocketConnection *conn; + SoupURI *uri; + GError *error = NULL; + + sock = g_socket_accept (listener, NULL, &error); + g_assert_no_error (error); + + conn = g_socket_connection_factory_create_connection (sock); + g_assert (conn != NULL); + g_object_unref (sock); + + if (test->no_server) + test->raw_server = G_IO_STREAM (conn); + else { + uri = soup_uri_new ("http://127.0.0.1/"); + test->server = soup_websocket_connection_new (G_IO_STREAM (conn), uri, + SOUP_WEBSOCKET_CONNECTION_SERVER, + NULL, NULL); + soup_uri_free (uri); + g_object_unref (conn); + } + + return FALSE; +} + +static void +setup_direct_connection (Test *test, + gconstpointer data) +{ + GSocketClient *client; + GSource *listen_source; + + setup_listener (test); + + client = g_socket_client_new (); + g_socket_client_connect_to_host_async (client, "127.0.0.1", test->port, + NULL, direct_connection_complete, test); + + listen_source = g_socket_create_source (test->listener, G_IO_IN, NULL); + g_source_set_callback (listen_source, (GSourceFunc) got_connection, test, NULL); + g_source_attach (listen_source, NULL); + + while (test->client == NULL || (test->server == NULL && test->raw_server == NULL)) + g_main_context_iteration (NULL, TRUE); + + g_source_destroy (listen_source); + g_source_unref (listen_source); + g_object_unref (client); +} + +static void +setup_half_direct_connection (Test *test, + gconstpointer data) +{ + test->no_server = TRUE; + setup_direct_connection (test, data); +} + +static void +teardown_direct_connection (Test *test, + gconstpointer data) +{ + g_clear_object (&test->listener); + g_clear_object (&test->client); + g_clear_object (&test->server); + g_clear_object (&test->raw_server); +} + +static void +setup_soup_server (Test *test, + const char *origin, + const char **protocols, + SoupServerWebsocketCallback callback, + gpointer user_data) +{ + GError *error = NULL; + + setup_listener (test); + + test->soup_server = soup_test_server_new (SOUP_TEST_SERVER_IN_THREAD); + soup_server_listen_socket (test->soup_server, test->listener, 0, &error); + g_assert_no_error (error); + + soup_server_add_websocket_handler (test->soup_server, "/unix", + origin, (char **) protocols, + callback, user_data, NULL); +} + +static void +client_connect (Test *test, + const char *origin, + const char **protocols, + GAsyncReadyCallback callback, + gpointer user_data) +{ + char *url; + + if (!test->session) + test->session = soup_test_session_new (SOUP_TYPE_SESSION, NULL); + + url = g_strdup_printf ("ws://127.0.0.1:%u/unix", test->port); + test->msg = soup_message_new ("GET", url); + g_free (url); + + soup_session_websocket_connect_async (test->session, test->msg, + origin, (char **) protocols, + NULL, callback, user_data); +} + +static void +got_server_connection (SoupServer *server, + SoupWebsocketConnection *connection, + const char *path, + SoupClientContext *client, + gpointer user_data) +{ + Test *test = user_data; + + test->server = g_object_ref (connection); +} + +static void +got_client_connection (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + Test *test = user_data; + + test->client = soup_session_websocket_connect_finish (SOUP_SESSION (object), + result, &test->client_error); +} + +static void +setup_soup_connection (Test *test, + gconstpointer data) +{ + setup_soup_server (test, NULL, NULL, got_server_connection, test); + client_connect (test, NULL, NULL, got_client_connection, test); + WAIT_UNTIL (test->server != NULL); + WAIT_UNTIL (test->client != NULL || test->client_error != NULL); + g_assert_no_error (test->client_error); +} + +static void +teardown_soup_connection (Test *test, + gconstpointer data) +{ + teardown_direct_connection (test, data); + + g_clear_object (&test->msg); + g_clear_error (&test->client_error); + g_clear_pointer (&test->session, soup_test_session_abort_unref); + g_clear_pointer (&test->soup_server, soup_test_server_quit_unref); +} + + +static void +on_text_message (SoupWebsocketConnection *ws, + SoupWebsocketDataType type, + GBytes *message, + gpointer user_data) +{ + GBytes **receive = user_data; + + g_assert_cmpint (type, ==, SOUP_WEBSOCKET_DATA_TEXT); + g_assert (*receive == NULL); + g_assert (message != NULL); + + *receive = g_bytes_ref (message); +} + +static void +on_close_set_flag (SoupWebsocketConnection *ws, + gpointer user_data) +{ + gboolean *flag = user_data; + + g_assert (*flag == FALSE); + + *flag = TRUE; +} + + +static void +test_handshake (Test *test, + gconstpointer data) +{ + g_assert_cmpint (soup_websocket_connection_get_state (test->client), ==, SOUP_WEBSOCKET_STATE_OPEN); + g_assert_cmpint (soup_websocket_connection_get_state (test->server), ==, SOUP_WEBSOCKET_STATE_OPEN); +} + +#define TEST_STRING "this is a test" + +static void +test_send_client_to_server (Test *test, + gconstpointer data) +{ + GBytes *received = NULL; + const char *contents; + gsize len; + + g_signal_connect (test->server, "message", G_CALLBACK (on_text_message), &received); + + soup_websocket_connection_send_text (test->client, TEST_STRING); + + WAIT_UNTIL (received != NULL); + + /* Received messages should be null terminated (outside of len) */ + contents = g_bytes_get_data (received, &len); + g_assert_cmpstr (contents, ==, TEST_STRING); + g_assert_cmpint (len, ==, strlen (TEST_STRING)); + + g_bytes_unref (received); +} + +static void +test_send_server_to_client (Test *test, + gconstpointer data) +{ + GBytes *received = NULL; + const char *contents; + gsize len; + + g_signal_connect (test->client, "message", G_CALLBACK (on_text_message), &received); + + soup_websocket_connection_send_text (test->server, TEST_STRING); + + WAIT_UNTIL (received != NULL); + + /* Received messages should be null terminated (outside of len) */ + contents = g_bytes_get_data (received, &len); + g_assert_cmpstr (contents, ==, TEST_STRING); + g_assert_cmpint (len, ==, strlen (TEST_STRING)); + + g_bytes_unref (received); +} + +static void +test_send_big_packets (Test *test, + gconstpointer data) +{ + GBytes *sent = NULL; + GBytes *received = NULL; + + g_signal_connect (test->client, "message", G_CALLBACK (on_text_message), &received); + + sent = g_bytes_new_take (g_strnfill (400, '!'), 400); + soup_websocket_connection_send_text (test->server, g_bytes_get_data (sent, NULL)); + WAIT_UNTIL (received != NULL); + g_assert (g_bytes_equal (sent, received)); + g_bytes_unref (sent); + g_bytes_unref (received); + received = NULL; + + sent = g_bytes_new_take (g_strnfill (100 * 1000, '?'), 100 * 1000); + soup_websocket_connection_send_text (test->server, g_bytes_get_data (sent, NULL)); + WAIT_UNTIL (received != NULL); + g_assert (g_bytes_equal (sent, received)); + g_bytes_unref (sent); + g_bytes_unref (received); + received = NULL; + + soup_websocket_connection_set_max_incoming_payload_size (test->client, 1000 * 1000 + 1); + g_assert (soup_websocket_connection_get_max_incoming_payload_size (test->client) == (1000 * 1000 + 1)); + soup_websocket_connection_set_max_incoming_payload_size (test->server, 1000 * 1000 + 1); + g_assert (soup_websocket_connection_get_max_incoming_payload_size (test->server) == (1000 * 1000 + 1)); + + sent = g_bytes_new_take (g_strnfill (1000 * 1000, '?'), 1000 * 1000); + soup_websocket_connection_send_text (test->server, g_bytes_get_data (sent, NULL)); + WAIT_UNTIL (received != NULL); + g_assert (g_bytes_equal (sent, received)); + g_bytes_unref (sent); + g_bytes_unref (received); +} + +static void +test_send_bad_data (Test *test, + gconstpointer unused) +{ + GError *error = NULL; + GIOStream *io; + gsize written; + const char *frame; + + g_signal_handlers_disconnect_by_func (test->server, on_error_not_reached, NULL); + g_signal_connect (test->server, "error", G_CALLBACK (on_error_copy), &error); + + io = soup_websocket_connection_get_io_stream (test->client); + + /* Bad UTF-8 frame */ + frame = "\x81\x04\xEE\xEE\xEE\xEE"; + if (!g_output_stream_write_all (g_io_stream_get_output_stream (io), + frame, 6, &written, NULL, NULL)) + g_assert_not_reached (); + g_assert_cmpuint (written, ==, 6); + + WAIT_UNTIL (error != NULL); + g_assert_error (error, SOUP_WEBSOCKET_ERROR, SOUP_WEBSOCKET_CLOSE_BAD_DATA); + g_clear_error (&error); + + WAIT_UNTIL (soup_websocket_connection_get_state (test->client) == SOUP_WEBSOCKET_STATE_CLOSED); + + g_assert_cmpuint (soup_websocket_connection_get_close_code (test->client), ==, SOUP_WEBSOCKET_CLOSE_BAD_DATA); +} + +static const char *negotiate_client_protocols[] = { "bbb", "ccc", NULL }; +static const char *negotiate_server_protocols[] = { "aaa", "bbb", "ccc", NULL }; +static const char *negotiated_protocol = "bbb"; + +static void +test_protocol_negotiate_direct (Test *test, + gconstpointer unused) +{ + SoupMessage *msg; + gboolean ok; + const char *protocol; + GError *error = NULL; + + msg = soup_message_new ("GET", "http://127.0.0.1"); + soup_websocket_client_prepare_handshake (msg, NULL, + (char **) negotiate_client_protocols); + + ok = soup_websocket_server_check_handshake (msg, NULL, + (char **) negotiate_server_protocols, + &error); + g_assert_no_error (error); + g_assert_true (ok); + + ok = soup_websocket_server_process_handshake (msg, NULL, + (char **) negotiate_server_protocols); + g_assert_true (ok); + + protocol = soup_message_headers_get_one (msg->response_headers, "Sec-WebSocket-Protocol"); + g_assert_cmpstr (protocol, ==, negotiated_protocol); + + ok = soup_websocket_client_verify_handshake (msg, &error); + g_assert_no_error (error); + g_assert_true (ok); + + g_object_unref (msg); +} + +static void +test_protocol_negotiate_soup (Test *test, + gconstpointer unused) +{ + setup_soup_server (test, NULL, negotiate_server_protocols, got_server_connection, test); + client_connect (test, NULL, negotiate_client_protocols, got_client_connection, test); + WAIT_UNTIL (test->server != NULL); + WAIT_UNTIL (test->client != NULL || test->client_error != NULL); + g_assert_no_error (test->client_error); + + g_assert_cmpstr (soup_websocket_connection_get_protocol (test->client), ==, negotiated_protocol); + g_assert_cmpstr (soup_websocket_connection_get_protocol (test->server), ==, negotiated_protocol); +} + +static const char *mismatch_client_protocols[] = { "ddd", NULL }; +static const char *mismatch_server_protocols[] = { "aaa", "bbb", "ccc", NULL }; + +static void +test_protocol_mismatch_direct (Test *test, + gconstpointer unused) +{ + SoupMessage *msg; + gboolean ok; + const char *protocol; + GError *error = NULL; + + msg = soup_message_new ("GET", "http://127.0.0.1"); + soup_websocket_client_prepare_handshake (msg, NULL, + (char **) mismatch_client_protocols); + + ok = soup_websocket_server_check_handshake (msg, NULL, + (char **) mismatch_server_protocols, + &error); + g_assert_error (error, SOUP_WEBSOCKET_ERROR, SOUP_WEBSOCKET_ERROR_BAD_HANDSHAKE); + g_clear_error (&error); + g_assert_false (ok); + + ok = soup_websocket_server_process_handshake (msg, NULL, + (char **) mismatch_server_protocols); + g_assert_false (ok); + soup_test_assert_message_status (msg, SOUP_STATUS_BAD_REQUEST); + + protocol = soup_message_headers_get_one (msg->response_headers, "Sec-WebSocket-Protocol"); + g_assert_cmpstr (protocol, ==, NULL); + + ok = soup_websocket_client_verify_handshake (msg, &error); + g_assert_error (error, SOUP_WEBSOCKET_ERROR, SOUP_WEBSOCKET_ERROR_BAD_HANDSHAKE); + g_clear_error (&error); + g_assert_false (ok); + + g_object_unref (msg); +} + +static void +test_protocol_mismatch_soup (Test *test, + gconstpointer unused) +{ + setup_soup_server (test, NULL, mismatch_server_protocols, got_server_connection, test); + client_connect (test, NULL, mismatch_client_protocols, got_client_connection, test); + WAIT_UNTIL (test->client_error != NULL); + + g_assert_error (test->client_error, SOUP_WEBSOCKET_ERROR, SOUP_WEBSOCKET_ERROR_NOT_WEBSOCKET); +} + +static const char *all_protocols[] = { "aaa", "bbb", "ccc", NULL }; + +static void +test_protocol_server_any_direct (Test *test, + gconstpointer unused) +{ + SoupMessage *msg; + gboolean ok; + const char *protocol; + GError *error = NULL; + + msg = soup_message_new ("GET", "http://127.0.0.1"); + soup_websocket_client_prepare_handshake (msg, NULL, (char **) all_protocols); + + ok = soup_websocket_server_check_handshake (msg, NULL, NULL, &error); + g_assert_no_error (error); + g_assert_true (ok); + + ok = soup_websocket_server_process_handshake (msg, NULL, NULL); + g_assert_true (ok); + + protocol = soup_message_headers_get_one (msg->response_headers, "Sec-WebSocket-Protocol"); + g_assert_cmpstr (protocol, ==, NULL); + + ok = soup_websocket_client_verify_handshake (msg, &error); + g_assert_no_error (error); + g_assert_true (ok); + + g_object_unref (msg); +} + +static void +test_protocol_server_any_soup (Test *test, + gconstpointer unused) +{ + setup_soup_server (test, NULL, NULL, got_server_connection, test); + client_connect (test, NULL, all_protocols, got_client_connection, test); + WAIT_UNTIL (test->server != NULL); + WAIT_UNTIL (test->client != NULL || test->client_error != NULL); + g_assert_no_error (test->client_error); + + g_assert_cmpstr (soup_websocket_connection_get_protocol (test->client), ==, NULL); + g_assert_cmpstr (soup_websocket_connection_get_protocol (test->server), ==, NULL); + g_assert_cmpstr (soup_message_headers_get_one (test->msg->response_headers, "Sec-WebSocket-Protocol"), ==, NULL); +} + +static void +test_protocol_client_any_direct (Test *test, + gconstpointer unused) +{ + SoupMessage *msg; + gboolean ok; + const char *protocol; + GError *error = NULL; + + msg = soup_message_new ("GET", "http://127.0.0.1"); + soup_websocket_client_prepare_handshake (msg, NULL, NULL); + + ok = soup_websocket_server_check_handshake (msg, NULL, (char **) all_protocols, &error); + g_assert_no_error (error); + g_assert_true (ok); + + ok = soup_websocket_server_process_handshake (msg, NULL, (char **) all_protocols); + g_assert_true (ok); + + protocol = soup_message_headers_get_one (msg->response_headers, "Sec-WebSocket-Protocol"); + g_assert_cmpstr (protocol, ==, NULL); + + ok = soup_websocket_client_verify_handshake (msg, &error); + g_assert_no_error (error); + g_assert_true (ok); + + g_object_unref (msg); +} + +static void +test_protocol_client_any_soup (Test *test, + gconstpointer unused) +{ + setup_soup_server (test, NULL, all_protocols, got_server_connection, test); + client_connect (test, NULL, NULL, got_client_connection, test); + WAIT_UNTIL (test->server != NULL); + WAIT_UNTIL (test->client != NULL || test->client_error != NULL); + g_assert_no_error (test->client_error); + + g_assert_cmpstr (soup_websocket_connection_get_protocol (test->client), ==, NULL); + g_assert_cmpstr (soup_websocket_connection_get_protocol (test->server), ==, NULL); + g_assert_cmpstr (soup_message_headers_get_one (test->msg->response_headers, "Sec-WebSocket-Protocol"), ==, NULL); +} + +static void +test_close_clean_client (Test *test, + gconstpointer data) +{ + gboolean close_event_client = FALSE; + gboolean close_event_server = FALSE; + + g_signal_connect (test->client, "closed", G_CALLBACK (on_close_set_flag), &close_event_client); + g_signal_connect (test->server, "closed", G_CALLBACK (on_close_set_flag), &close_event_server); + + soup_websocket_connection_close (test->client, SOUP_WEBSOCKET_CLOSE_GOING_AWAY, "give me a reason"); + g_assert_cmpint (soup_websocket_connection_get_state (test->client), ==, SOUP_WEBSOCKET_STATE_CLOSING); + + WAIT_UNTIL (soup_websocket_connection_get_state (test->server) == SOUP_WEBSOCKET_STATE_CLOSED); + WAIT_UNTIL (soup_websocket_connection_get_state (test->client) == SOUP_WEBSOCKET_STATE_CLOSED); + + g_assert (close_event_client); + g_assert (close_event_server); + + g_assert_cmpint (soup_websocket_connection_get_close_code (test->client), ==, SOUP_WEBSOCKET_CLOSE_GOING_AWAY); + g_assert_cmpint (soup_websocket_connection_get_close_code (test->server), ==, SOUP_WEBSOCKET_CLOSE_GOING_AWAY); + g_assert_cmpstr (soup_websocket_connection_get_close_data (test->server), ==, "give me a reason"); +} + +static void +test_close_clean_server (Test *test, + gconstpointer data) +{ + gboolean close_event_client = FALSE; + gboolean close_event_server = FALSE; + + g_signal_connect (test->client, "closed", G_CALLBACK (on_close_set_flag), &close_event_client); + g_signal_connect (test->server, "closed", G_CALLBACK (on_close_set_flag), &close_event_server); + + soup_websocket_connection_close (test->server, SOUP_WEBSOCKET_CLOSE_GOING_AWAY, "another reason"); + g_assert_cmpint (soup_websocket_connection_get_state (test->server), ==, SOUP_WEBSOCKET_STATE_CLOSING); + + WAIT_UNTIL (soup_websocket_connection_get_state (test->server) == SOUP_WEBSOCKET_STATE_CLOSED); + WAIT_UNTIL (soup_websocket_connection_get_state (test->client) == SOUP_WEBSOCKET_STATE_CLOSED); + + g_assert (close_event_client); + g_assert (close_event_server); + + g_assert_cmpint (soup_websocket_connection_get_close_code (test->server), ==, SOUP_WEBSOCKET_CLOSE_GOING_AWAY); + g_assert_cmpint (soup_websocket_connection_get_close_code (test->client), ==, SOUP_WEBSOCKET_CLOSE_GOING_AWAY); + g_assert_cmpstr (soup_websocket_connection_get_close_data (test->client), ==, "another reason"); +} + +static gboolean +on_closing_send_message (SoupWebsocketConnection *ws, + gpointer data) +{ + GBytes *message = data; + + soup_websocket_connection_send_text (ws, g_bytes_get_data (message, NULL)); + g_signal_handlers_disconnect_by_func (ws, on_closing_send_message, data); + return TRUE; +} + +static void +test_message_after_closing (Test *test, + gconstpointer data) +{ + gboolean close_event_client = FALSE; + gboolean close_event_server = FALSE; + GBytes *received = NULL; + GBytes *message; + + message = g_bytes_new_static ("another test because", strlen ("another test because")); + g_signal_connect (test->client, "closed", G_CALLBACK (on_close_set_flag), &close_event_client); + g_signal_connect (test->client, "message", G_CALLBACK (on_text_message), &received); + g_signal_connect (test->server, "closed", G_CALLBACK (on_close_set_flag), &close_event_server); + g_signal_connect (test->server, "closing", G_CALLBACK (on_closing_send_message), message); + + soup_websocket_connection_close (test->client, SOUP_WEBSOCKET_CLOSE_GOING_AWAY, "another reason"); + g_assert_cmpint (soup_websocket_connection_get_state (test->client), ==, SOUP_WEBSOCKET_STATE_CLOSING); + + WAIT_UNTIL (soup_websocket_connection_get_state (test->server) == SOUP_WEBSOCKET_STATE_CLOSED); + WAIT_UNTIL (soup_websocket_connection_get_state (test->client) == SOUP_WEBSOCKET_STATE_CLOSED); + + g_assert (close_event_client); + g_assert (close_event_server); + + g_assert (received != NULL); + g_assert (g_bytes_equal (message, received)); + + g_bytes_unref (received); + g_bytes_unref (message); +} + +static gpointer +timeout_server_thread (gpointer user_data) +{ + Test *test = user_data; + GError *error = NULL; + + /* don't close until the client has timed out */ + g_mutex_lock (&test->mutex); + g_mutex_unlock (&test->mutex); + + g_io_stream_close (test->raw_server, NULL, &error); + g_assert_no_error (error); + + return NULL; +} + +static void +test_close_after_timeout (Test *test, + gconstpointer data) +{ + gboolean close_event = FALSE; + GThread *thread; + + g_mutex_lock (&test->mutex); + + /* Note that no real server is around in this test, so no close happens */ + thread = g_thread_new ("timeout-thread", timeout_server_thread, test); + + g_signal_connect (test->client, "closed", G_CALLBACK (on_close_set_flag), &close_event); + g_signal_connect (test->client, "error", G_CALLBACK (on_error_not_reached), NULL); + + /* Now try and close things */ + soup_websocket_connection_close (test->client, 0, NULL); + g_assert_cmpint (soup_websocket_connection_get_state (test->client), ==, SOUP_WEBSOCKET_STATE_CLOSING); + + WAIT_UNTIL (soup_websocket_connection_get_state (test->client) == SOUP_WEBSOCKET_STATE_CLOSED); + + g_assert (close_event == TRUE); + + /* Now actually close the server side stream */ + g_mutex_unlock (&test->mutex); + g_thread_join (thread); +} + +static gpointer +send_fragments_server_thread (gpointer user_data) +{ + Test *test = user_data; + gsize written; + const char fragments[] = "\x01\x04""one " /* !fin | opcode */ + "\x00\x04""two " /* !fin | no opcode */ + "\x80\x05""three"; /* fin | no opcode */ + GError *error = NULL; + + g_output_stream_write_all (g_io_stream_get_output_stream (test->raw_server), + fragments, sizeof (fragments) -1, &written, NULL, &error); + g_assert_no_error (error); + g_assert_cmpuint (written, ==, sizeof (fragments) - 1); + g_io_stream_close (test->raw_server, NULL, &error); + g_assert_no_error (error); + + return NULL; +} + +static void +test_receive_fragmented (Test *test, + gconstpointer data) +{ + GThread *thread; + GBytes *received = NULL; + GBytes *expect; + + thread = g_thread_new ("fragment-thread", send_fragments_server_thread, test); + + g_signal_connect (test->client, "error", G_CALLBACK (on_error_not_reached), NULL); + g_signal_connect (test->client, "message", G_CALLBACK (on_text_message), &received); + + WAIT_UNTIL (received != NULL); + expect = g_bytes_new ("one two three", 13); + g_assert (g_bytes_equal (expect, received)); + g_bytes_unref (expect); + g_bytes_unref (received); + + g_thread_join (thread); + + WAIT_UNTIL (soup_websocket_connection_get_state (test->client) == SOUP_WEBSOCKET_STATE_CLOSED); +} + +static void +test_client_context_got_server_connection (SoupServer *server, + SoupWebsocketConnection *connection, + const char *path, + SoupClientContext *client, + gpointer user_data) +{ + Test *test = user_data; + GSocketAddress *addr; + GInetAddress *iaddr; + char *str; + const char *remote_ip; + + addr = soup_client_context_get_local_address (client); + iaddr = g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (addr)); + str = g_inet_address_to_string (iaddr); + if (g_inet_address_get_family (iaddr) == G_SOCKET_FAMILY_IPV4) + g_assert_cmpstr (str, ==, "127.0.0.1"); + else + g_assert_cmpstr (str, ==, "::1"); + g_free (str); + + addr = soup_client_context_get_remote_address (client); + iaddr = g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (addr)); + str = g_inet_address_to_string (iaddr); + if (g_inet_address_get_family (iaddr) == G_SOCKET_FAMILY_IPV4) + g_assert_cmpstr (str, ==, "127.0.0.1"); + else + g_assert_cmpstr (str, ==, "::1"); + + remote_ip = soup_client_context_get_host (client); + g_assert_cmpstr (remote_ip, ==, str); + g_free (str); + + test->server = g_object_ref (connection); +} + +static void +test_client_context (Test *test, + gconstpointer unused) +{ + setup_soup_server (test, NULL, NULL, test_client_context_got_server_connection, test); + client_connect (test, NULL, NULL, got_client_connection, test); + WAIT_UNTIL (test->server != NULL); + WAIT_UNTIL (test->client != NULL || test->client_error != NULL); + g_assert_no_error (test->client_error); +} + +int +main (int argc, + char *argv[]) +{ + int ret; + + test_init (argc, argv, NULL); + + g_test_add ("/websocket/soup/handshake", Test, NULL, + setup_soup_connection, + test_handshake, + teardown_soup_connection); + + g_test_add ("/websocket/direct/send-client-to-server", Test, NULL, + setup_direct_connection, + test_send_client_to_server, + teardown_direct_connection); + g_test_add ("/websocket/soup/send-client-to-server", Test, NULL, + setup_soup_connection, + test_send_client_to_server, + teardown_soup_connection); + + g_test_add ("/websocket/direct/send-server-to-client", Test, NULL, + setup_direct_connection, + test_send_server_to_client, + teardown_direct_connection); + g_test_add ("/websocket/soup/send-server-to-client", Test, NULL, + setup_soup_connection, + test_send_server_to_client, + teardown_soup_connection); + + g_test_add ("/websocket/direct/send-big-packets", Test, NULL, + setup_direct_connection, + test_send_big_packets, + teardown_direct_connection); + g_test_add ("/websocket/soup/send-big-packets", Test, NULL, + setup_soup_connection, + test_send_big_packets, + teardown_soup_connection); + + g_test_add ("/websocket/direct/send-bad-data", Test, NULL, + setup_direct_connection, + test_send_bad_data, + teardown_direct_connection); + g_test_add ("/websocket/soup/send-bad-data", Test, NULL, + setup_soup_connection, + test_send_bad_data, + teardown_soup_connection); + + g_test_add ("/websocket/direct/close-clean-client", Test, NULL, + setup_direct_connection, + test_close_clean_client, + teardown_direct_connection); + g_test_add ("/websocket/soup/close-clean-client", Test, NULL, + setup_soup_connection, + test_close_clean_client, + teardown_soup_connection); + + g_test_add ("/websocket/direct/close-clean-server", Test, NULL, + setup_direct_connection, + test_close_clean_server, + teardown_direct_connection); + g_test_add ("/websocket/soup/close-clean-server", Test, NULL, + setup_soup_connection, + test_close_clean_server, + teardown_soup_connection); + + g_test_add ("/websocket/direct/message-after-closing", Test, NULL, + setup_direct_connection, + test_message_after_closing, + teardown_direct_connection); + g_test_add ("/websocket/soup/message-after-closing", Test, NULL, + setup_soup_connection, + test_message_after_closing, + teardown_soup_connection); + + + g_test_add ("/websocket/direct/protocol-negotiate", Test, NULL, NULL, + test_protocol_negotiate_direct, + NULL); + g_test_add ("/websocket/soup/protocol-negotiate", Test, NULL, NULL, + test_protocol_negotiate_soup, + teardown_soup_connection); + + g_test_add ("/websocket/direct/protocol-mismatch", Test, NULL, NULL, + test_protocol_mismatch_direct, + NULL); + g_test_add ("/websocket/soup/protocol-mismatch", Test, NULL, NULL, + test_protocol_mismatch_soup, + teardown_soup_connection); + + g_test_add ("/websocket/direct/protocol-server-any", Test, NULL, NULL, + test_protocol_server_any_direct, + NULL); + g_test_add ("/websocket/soup/protocol-server-any", Test, NULL, NULL, + test_protocol_server_any_soup, + teardown_soup_connection); + + g_test_add ("/websocket/direct/protocol-client-any", Test, NULL, NULL, + test_protocol_client_any_direct, + NULL); + g_test_add ("/websocket/soup/protocol-client-any", Test, NULL, NULL, + test_protocol_client_any_soup, + teardown_soup_connection); + + + g_test_add ("/websocket/direct/receive-fragmented", Test, NULL, + setup_half_direct_connection, + test_receive_fragmented, + teardown_direct_connection); + + if (g_test_slow ()) { + g_test_add ("/websocket/direct/close-after-timeout", Test, NULL, + setup_half_direct_connection, + test_close_after_timeout, + teardown_direct_connection); + } + + g_test_add ("/websocket/soup/client-context", Test, NULL, NULL, + test_client_context, + teardown_soup_connection); + + ret = g_test_run (); + + test_cleanup (); + return ret; +} diff --git a/tests/xmlrpc-old-server-test.c b/tests/xmlrpc-old-server-test.c new file mode 100644 index 0000000..a7076b5 --- /dev/null +++ b/tests/xmlrpc-old-server-test.c @@ -0,0 +1,374 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2008 Red Hat, Inc. + */ + +#include "test-utils.h" + +static char *uri; + +#ifdef G_GNUC_BEGIN_IGNORE_DEPRECATIONS +G_GNUC_BEGIN_IGNORE_DEPRECATIONS +#endif + +static void +type_error (SoupMessage *msg, GType expected, GValueArray *params, int bad_value) +{ + soup_xmlrpc_set_fault (msg, + SOUP_XMLRPC_FAULT_SERVER_ERROR_INVALID_METHOD_PARAMETERS, + "Bad parameter #%d: expected %s, got %s", + bad_value + 1, g_type_name (expected), + g_type_name (G_VALUE_TYPE (¶ms->values[bad_value]))); +} + +static void +args_error (SoupMessage *msg, GValueArray *params, int expected) +{ + soup_xmlrpc_set_fault (msg, + SOUP_XMLRPC_FAULT_SERVER_ERROR_INVALID_METHOD_PARAMETERS, + "Wrong number of parameters: expected %d, got %d", + expected, params->n_values); +} + +static void +do_sum (SoupMessage *msg, GValueArray *params) +{ + int i; + double sum = 0.0, val; + GValueArray *nums; + + if (params->n_values != 1) { + args_error (msg, params, 1); + return; + } + if (!soup_value_array_get_nth (params, 0, G_TYPE_VALUE_ARRAY, &nums)) { + type_error (msg, G_TYPE_VALUE_ARRAY, params, 0); + return; + } + + for (i = 0; i < nums->n_values; i++) { + if (!soup_value_array_get_nth (nums, i, G_TYPE_DOUBLE, &val)) { + type_error (msg, G_TYPE_DOUBLE, nums, i); + return; + } + sum += val; + } + + soup_xmlrpc_set_response (msg, G_TYPE_DOUBLE, sum); + +} + +static void +do_countBools (SoupMessage *msg, GValueArray *params) +{ + int i, trues = 0, falses = 0; + GValueArray *bools; + GHashTable *ret = soup_value_hash_new (); + gboolean val; + + if (params->n_values != 1) { + args_error (msg, params, 1); + return; + } + if (!soup_value_array_get_nth (params, 0, G_TYPE_VALUE_ARRAY, &bools)) { + type_error (msg, G_TYPE_VALUE_ARRAY, params, 0); + return; + } + + for (i = 0; i < bools->n_values; i++) { + if (!soup_value_array_get_nth (bools, i, G_TYPE_BOOLEAN, &val)) { + type_error (msg, G_TYPE_BOOLEAN, params, i); + return; + } + if (val) + trues++; + else + falses++; + } + + soup_value_hash_insert (ret, "true", G_TYPE_INT, trues); + soup_value_hash_insert (ret, "false", G_TYPE_INT, falses); + soup_xmlrpc_set_response (msg, G_TYPE_HASH_TABLE, ret); + g_hash_table_destroy (ret); + +} + +static void +do_md5sum (SoupMessage *msg, GValueArray *params) +{ + GChecksum *checksum; + GByteArray *data, *digest; + gsize digest_len = 16; + + if (params->n_values != 1) { + args_error (msg, params, 1); + return; + } + + if (!soup_value_array_get_nth (params, 0, SOUP_TYPE_BYTE_ARRAY, &data)) { + type_error (msg, SOUP_TYPE_BYTE_ARRAY, params, 0); + return; + } + checksum = g_checksum_new (G_CHECKSUM_MD5); + g_checksum_update (checksum, data->data, data->len); + digest = g_byte_array_new (); + g_byte_array_set_size (digest, digest_len); + g_checksum_get_digest (checksum, digest->data, &digest_len); + g_checksum_free (checksum); + + soup_xmlrpc_set_response (msg, SOUP_TYPE_BYTE_ARRAY, digest); + g_byte_array_free (digest, TRUE); +} + + +static void +do_dateChange (SoupMessage *msg, GValueArray *params) +{ + GHashTable *arg; + SoupDate *date; + int val; + + if (params->n_values != 2) { + args_error (msg, params, 2); + return; + } + + if (!soup_value_array_get_nth (params, 0, SOUP_TYPE_DATE, &date)) { + type_error (msg, SOUP_TYPE_DATE, params, 0); + return; + } + if (!soup_value_array_get_nth (params, 1, G_TYPE_HASH_TABLE, &arg)) { + type_error (msg, G_TYPE_HASH_TABLE, params, 1); + return; + } + + if (soup_value_hash_lookup (arg, "tm_year", G_TYPE_INT, &val)) + date->year = val + 1900; + if (soup_value_hash_lookup (arg, "tm_mon", G_TYPE_INT, &val)) + date->month = val + 1; + if (soup_value_hash_lookup (arg, "tm_mday", G_TYPE_INT, &val)) + date->day = val; + if (soup_value_hash_lookup (arg, "tm_hour", G_TYPE_INT, &val)) + date->hour = val; + if (soup_value_hash_lookup (arg, "tm_min", G_TYPE_INT, &val)) + date->minute = val; + if (soup_value_hash_lookup (arg, "tm_sec", G_TYPE_INT, &val)) + date->second = val; + + soup_xmlrpc_set_response (msg, SOUP_TYPE_DATE, date); +} + +static void +do_echo (SoupMessage *msg, GValueArray *params) +{ + int i; + const char *val; + GValueArray *in, *out; + + if (!soup_value_array_get_nth (params, 0, G_TYPE_VALUE_ARRAY, &in)) { + type_error (msg, G_TYPE_VALUE_ARRAY, params, 0); + return; + } + + out = g_value_array_new (in->n_values); + for (i = 0; i < in->n_values; i++) { + if (!soup_value_array_get_nth (in, i, G_TYPE_STRING, &val)) { + type_error (msg, G_TYPE_STRING, in, i); + return; + } + soup_value_array_append (out, G_TYPE_STRING, val); + } + + soup_xmlrpc_set_response (msg, G_TYPE_VALUE_ARRAY, out); + g_value_array_free (out); +} + +static void +do_ping (SoupMessage *msg, GValueArray *params) +{ + if (params->n_values) { + args_error (msg, params, 0); + return; + } + + soup_xmlrpc_set_response (msg, G_TYPE_STRING, "pong"); +} + +static void +server_callback (SoupServer *server, SoupMessage *msg, + const char *path, GHashTable *query, + SoupClientContext *context, gpointer data) +{ + char *method_name; + GValueArray *params; + + if (msg->method != SOUP_METHOD_POST) { + soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED); + return; + } + + soup_message_set_status (msg, SOUP_STATUS_OK); + + if (!soup_xmlrpc_parse_method_call (msg->request_body->data, + msg->request_body->length, + &method_name, ¶ms)) { + soup_xmlrpc_set_fault (msg, SOUP_XMLRPC_FAULT_PARSE_ERROR_NOT_WELL_FORMED, + "Could not parse method call"); + return; + } + + if (!strcmp (method_name, "sum")) + do_sum (msg, params); + else if (!strcmp (method_name, "countBools")) + do_countBools (msg, params); + else if (!strcmp (method_name, "md5sum")) + do_md5sum (msg, params); + else if (!strcmp (method_name, "dateChange")) + do_dateChange (msg, params); + else if (!strcmp (method_name, "echo")) + do_echo (msg, params); + else if (!strcmp (method_name, "ping")) + do_ping (msg, params); + else { + soup_xmlrpc_set_fault (msg, SOUP_XMLRPC_FAULT_SERVER_ERROR_REQUESTED_METHOD_NOT_FOUND, + "Unknown method %s", method_name); + } + + g_free (method_name); + g_value_array_free (params); +} + +static gboolean +run_xmlrpc_test (char **argv, + char **stdout_out, + char **stderr_out, + GError **error) +{ + gboolean ok; + int status; + + argv[0] = g_test_build_filename (G_TEST_BUILT, "xmlrpc-old-test", NULL); + ok = g_spawn_sync (NULL, argv, NULL, 0, NULL, NULL, + stdout_out, stderr_out, &status, + error); + g_free (argv[0]); + + if (!ok) + return FALSE; + + return g_spawn_check_exit_status (status, error); +} + +static void +do_one_xmlrpc_test (gconstpointer data) +{ + const char *path = data; + char *argv[12]; + char *stdout_out, *stderr_out; + GError *error = NULL; + int arg; + + argv[0] = NULL; + argv[1] = "-S"; + argv[2] = "-U"; + argv[3] = uri; + argv[4] = "-q"; + argv[5] = "-p"; + argv[6] = (char *) path; + + for (arg = 0; arg < debug_level && arg < 3; arg++) + argv[arg + 7] = "-d"; + argv[arg + 7] = NULL; + + run_xmlrpc_test (argv, &stdout_out, &stderr_out, &error); + if (stdout_out) { + g_print ("%s", stdout_out); + g_free (stdout_out); + } + if (stderr_out) { + g_printerr ("%s", stderr_out); + g_free (stderr_out); + } + + if ( g_error_matches (error, G_SPAWN_EXIT_ERROR, 1) + || g_error_matches (error, G_SPAWN_EXIT_ERROR, 77)) + g_test_fail (); + else + g_assert_no_error (error); + g_clear_error (&error); +} + +gboolean run_tests = TRUE; + +static GOptionEntry no_test_entry[] = { + { "no-tests", 'n', G_OPTION_FLAG_REVERSE, + G_OPTION_ARG_NONE, &run_tests, + "Don't run tests, just run the test server", NULL }, + { NULL } +}; + +int +main (int argc, char **argv) +{ + SoupServer *server; + SoupURI *server_uri; + int ret; + + test_init (argc, argv, no_test_entry); + + server = soup_test_server_new (run_tests ? SOUP_TEST_SERVER_IN_THREAD : SOUP_TEST_SERVER_DEFAULT); + soup_server_add_handler (server, "/xmlrpc-server.php", + server_callback, NULL, NULL); + server_uri = soup_test_server_get_uri (server, "http", NULL); + soup_uri_set_path (server_uri, "/xmlrpc-server.php"); + uri = soup_uri_to_string (server_uri, FALSE); + + if (run_tests) { + char *out, **tests, *path; + char *list_argv[4]; + GError *error = NULL; + int i; + + list_argv[0] = NULL; + list_argv[1] = "-S"; + list_argv[2] = "-l"; + list_argv[3] = NULL; + + if (!run_xmlrpc_test (list_argv, &out, NULL, &error)) { + g_printerr ("'xmlrpc-old-test -l' failed: %s\n", error->message); + g_error_free (error); + return 1; + } + + tests = g_strsplit (out, "\n", -1); + g_free (out); + + for (i = 0; tests[i] && *tests[i]; i++) { + g_assert_true (g_str_has_prefix (tests[i], "/xmlrpc-old/")); + path = g_strdup_printf ("/xmlrpc-old-server/%s", tests[i] + strlen ("/xmlrpc-old/")); + g_test_add_data_func (path, tests[i], do_one_xmlrpc_test); + g_free (path); + } + + ret = g_test_run (); + + g_strfreev (tests); + } else { + GMainLoop *loop; + + g_print ("Listening on port %d\n", server_uri->port); + + loop = g_main_loop_new (NULL, TRUE); + g_main_loop_run (loop); + g_main_loop_unref (loop); + + ret = 0; + } + + soup_test_server_quit_unref (server); + soup_uri_free (server_uri); + g_free (uri); + if (run_tests) + test_cleanup (); + return ret; +} diff --git a/tests/xmlrpc-old-test.c b/tests/xmlrpc-old-test.c new file mode 100644 index 0000000..ab7b34d --- /dev/null +++ b/tests/xmlrpc-old-test.c @@ -0,0 +1,502 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2001-2003, Ximian, Inc. + */ + +#include "test-utils.h" + +#ifdef G_GNUC_BEGIN_IGNORE_DEPRECATIONS +G_GNUC_BEGIN_IGNORE_DEPRECATIONS +#endif + +static SoupSession *session; +static const char *default_uri = "http://127.0.0.1:47524/xmlrpc-server.php"; +static const char *uri = NULL; +static gboolean server_test = FALSE; + +#ifdef HAVE_PHP_XMLRPC +#define SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER +#else +#define SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER \ + G_STMT_START { \ + if (!server_test) { \ + g_test_skip ("php-xmlrpc is not available"); \ + return; \ + } \ + } G_STMT_END +#endif + +static gboolean +send_xmlrpc (const char *body, GValue *retval) +{ + SoupMessage *msg; + GError *err = NULL; + + msg = soup_message_new ("POST", uri); + soup_message_set_request (msg, "text/xml", SOUP_MEMORY_COPY, + body, strlen (body)); + soup_session_send_message (session, msg); + + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + + if (!soup_xmlrpc_parse_method_response (msg->response_body->data, + msg->response_body->length, + retval, &err)) { + if (err) { + soup_test_assert (FALSE, "FAULT: %d %s\n", err->code, err->message); + g_error_free (err); + } else + soup_test_assert (FALSE, "ERROR: could not parse response\n"); + g_object_unref (msg); + return FALSE; + } + g_object_unref (msg); + + return TRUE; +} + +static gboolean +do_xmlrpc (const char *method, GValue *retval, ...) +{ + va_list args; + GValueArray *params; + char *body; + gboolean ret; + + va_start (args, retval); + params = soup_value_array_from_args (args); + va_end (args); + + body = soup_xmlrpc_build_method_call (method, params->values, + params->n_values); + g_value_array_free (params); + if (!body) + return FALSE; + + ret = send_xmlrpc (body, retval); + g_free (body); + + return ret; +} + +static gboolean +check_xmlrpc (GValue *value, GType type, ...) +{ + va_list args; + + if (!G_VALUE_HOLDS (value, type)) { + g_assert_true (G_VALUE_HOLDS (value, type)); + return FALSE; + } + + va_start (args, type); + SOUP_VALUE_GETV (value, type, args); + va_end (args); + return TRUE; +} + +static void +test_sum (void) +{ + GValueArray *dbls; + int i; + double val, sum, result; + GValue retval; + gboolean ok; + + SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER; + + debug_printf (2, "sum (array of double -> double): "); + + dbls = g_value_array_new (10); + for (i = sum = 0; i < 10; i++) { + val = g_random_int_range (0, 400) / 4.0; + debug_printf (2, "%s%.2f", i == 0 ? "[" : ", ", val); + soup_value_array_append (dbls, G_TYPE_DOUBLE, val); + sum += val; + } + debug_printf (2, "] -> "); + + ok = (do_xmlrpc ("sum", &retval, + G_TYPE_VALUE_ARRAY, dbls, + G_TYPE_INVALID) && + check_xmlrpc (&retval, G_TYPE_DOUBLE, &result)); + g_value_array_free (dbls); + + if (!ok) + return; + + debug_printf (2, "%.2f\n", result); + g_assert_cmpfloat (result, ==, sum); +} + +static void +test_countBools (void) +{ + GValueArray *bools; + int i, trues, falses; + GValue retval; + int ret_trues, ret_falses; + gboolean val, ok; + GHashTable *result; + + SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER; + + debug_printf (2, "countBools (array of boolean -> struct of ints): "); + + bools = g_value_array_new (10); + for (i = trues = falses = 0; i < 10; i++) { + val = g_random_boolean (); + debug_printf (2, "%s%c", i == 0 ? "[" : ", ", val ? 'T' : 'F'); + soup_value_array_append (bools, G_TYPE_BOOLEAN, val); + if (val) + trues++; + else + falses++; + } + debug_printf (2, "] -> "); + + ok = (do_xmlrpc ("countBools", &retval, + G_TYPE_VALUE_ARRAY, bools, + G_TYPE_INVALID) && + check_xmlrpc (&retval, G_TYPE_HASH_TABLE, &result)); + g_value_array_free (bools); + if (!ok) + return; + + g_assert_true (soup_value_hash_lookup (result, "true", G_TYPE_INT, &ret_trues)); + g_assert_true (soup_value_hash_lookup (result, "false", G_TYPE_INT, &ret_falses)); + + g_hash_table_destroy (result); + + debug_printf (2, "{ true: %d, false: %d }\n", ret_trues, ret_falses); + g_assert_cmpint (trues, ==, ret_trues); + g_assert_cmpint (falses, ==, ret_falses); +} + +static void +test_md5sum (void) +{ + GByteArray *data, *result; + int i; + GChecksum *checksum; + guchar digest[16]; + gsize digest_len = sizeof (digest); + GValue retval; + gboolean ok; + + SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER; + + debug_printf (2, "md5sum (base64 -> base64)\n"); + + data = g_byte_array_new (); + g_byte_array_set_size (data, 256); + for (i = 0; i < data->len; i++) + data->data[i] = (char)(g_random_int_range (0, 256)); + + checksum = g_checksum_new (G_CHECKSUM_MD5); + g_checksum_update (checksum, data->data, data->len); + g_checksum_get_digest (checksum, digest, &digest_len); + g_checksum_free (checksum); + + ok = (do_xmlrpc ("md5sum", &retval, + SOUP_TYPE_BYTE_ARRAY, data, + G_TYPE_INVALID) && + check_xmlrpc (&retval, SOUP_TYPE_BYTE_ARRAY, &result)); + g_byte_array_free (data, TRUE); + if (!ok) + return; + + soup_assert_cmpmem (result->data, result->len, + digest, digest_len); + g_byte_array_free (result, TRUE); +} + +static void +test_dateChange (void) +{ + GHashTable *structval; + SoupDate *date, *result; + char *timestamp; + GValue retval; + gboolean ok; + + SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER; + + debug_printf (2, "dateChange (date, struct of ints -> time)\n"); + + date = soup_date_new (1970 + (g_random_int_range (0, 50)), + 1 + g_random_int_range (0, 12), + 1 + g_random_int_range (0, 28), + g_random_int_range (0, 24), + g_random_int_range (0, 60), + g_random_int_range (0, 60)); + if (debug_level >= 2) { + timestamp = soup_date_to_string (date, SOUP_DATE_ISO8601_XMLRPC); + debug_printf (2, "date: %s, {", timestamp); + g_free (timestamp); + } + + structval = soup_value_hash_new (); + +#define MAYBE (g_random_int_range (0, 3) != 0) + + if (MAYBE) { + date->year = 1970 + (g_random_int_range (0, 50)); + debug_printf (2, "tm_year: %d, ", date->year - 1900); + soup_value_hash_insert (structval, "tm_year", + G_TYPE_INT, date->year - 1900); + } + if (MAYBE) { + date->month = 1 + g_random_int_range (0, 12); + debug_printf (2, "tm_mon: %d, ", date->month - 1); + soup_value_hash_insert (structval, "tm_mon", + G_TYPE_INT, date->month - 1); + } + if (MAYBE) { + date->day = 1 + g_random_int_range (0, 28); + debug_printf (2, "tm_mday: %d, ", date->day); + soup_value_hash_insert (structval, "tm_mday", + G_TYPE_INT, date->day); + } + if (MAYBE) { + date->hour = g_random_int_range (0, 24); + debug_printf (2, "tm_hour: %d, ", date->hour); + soup_value_hash_insert (structval, "tm_hour", + G_TYPE_INT, date->hour); + } + if (MAYBE) { + date->minute = g_random_int_range (0, 60); + debug_printf (2, "tm_min: %d, ", date->minute); + soup_value_hash_insert (structval, "tm_min", + G_TYPE_INT, date->minute); + } + if (MAYBE) { + date->second = g_random_int_range (0, 60); + debug_printf (2, "tm_sec: %d, ", date->second); + soup_value_hash_insert (structval, "tm_sec", + G_TYPE_INT, date->second); + } + + debug_printf (2, "} -> "); + + ok = (do_xmlrpc ("dateChange", &retval, + SOUP_TYPE_DATE, date, + G_TYPE_HASH_TABLE, structval, + G_TYPE_INVALID) && + check_xmlrpc (&retval, SOUP_TYPE_DATE, &result)); + g_hash_table_destroy (structval); + if (!ok) { + soup_date_free (date); + return; + } + + if (debug_level >= 2) { + timestamp = soup_date_to_string (result, SOUP_DATE_ISO8601_XMLRPC); + debug_printf (2, "%s\n", timestamp); + g_free (timestamp); + } + + g_assert_cmpint (date->year, ==, result->year); + g_assert_cmpint (date->month, ==, result->month); + g_assert_cmpint (date->day, ==, result->day); + g_assert_cmpint (date->hour, ==, result->hour); + g_assert_cmpint (date->minute, ==, result->minute); + g_assert_cmpint (date->second, ==, result->second); + + soup_date_free (date); + soup_date_free (result); +} + +static const char *const echo_strings[] = { + "This is a test", + "& so is this", + "and so is ", + "& so is <this>" +}; +#define N_ECHO_STRINGS G_N_ELEMENTS (echo_strings) + +static void +test_echo (void) +{ + GValueArray *originals, *echoes; + GValue retval; + int i; + + SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER; + + debug_printf (2, "echo (array of string -> array of string):\n"); + + originals = g_value_array_new (N_ECHO_STRINGS); + for (i = 0; i < N_ECHO_STRINGS; i++) { + soup_value_array_append (originals, G_TYPE_STRING, echo_strings[i]); + debug_printf (2, "%s\"%s\"", i == 0 ? "[" : ", ", echo_strings[i]); + } + debug_printf (2, "] -> "); + + if (!(do_xmlrpc ("echo", &retval, + G_TYPE_VALUE_ARRAY, originals, + G_TYPE_INVALID) && + check_xmlrpc (&retval, G_TYPE_VALUE_ARRAY, &echoes))) { + g_value_array_free (originals); + return; + } + g_value_array_free (originals); + + if (debug_level >= 2) { + for (i = 0; i < echoes->n_values; i++) { + debug_printf (2, "%s\"%s\"", i == 0 ? "[" : ", ", + g_value_get_string (&echoes->values[i])); + } + debug_printf (2, "]\n"); + } + + g_assert_cmpint (echoes->n_values, ==, N_ECHO_STRINGS); + + for (i = 0; i < echoes->n_values; i++) + g_assert_cmpstr (echo_strings[i], ==, g_value_get_string (&echoes->values[i])); + + g_value_array_free (echoes); +} + +static void +test_ping (gconstpointer include_params) +{ + GValueArray *params; + GValue retval; + char *request; + char *out; + gboolean ret; + + g_test_bug ("671661"); + + SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER; + + debug_printf (2, "ping (void (%s) -> string)\n", + include_params ? "empty " : "no "); + + params = soup_value_array_new (); + request = soup_xmlrpc_build_method_call ("ping", params->values, + params->n_values); + g_value_array_free (params); + if (!request) + return; + + if (!include_params) { + char *params, *end; + + params = strstr (request, ""); + if (!params) { + soup_test_assert (FALSE, "ERROR: XML did not contain !"); + return; + } + end = params + strlen (""); + memmove (params, end, strlen (end) + 1); + } + + ret = send_xmlrpc (request, &retval); + g_free (request); + + if (!ret || !check_xmlrpc (&retval, G_TYPE_STRING, &out)) + return; + + g_assert_cmpstr (out, ==, "pong"); + + g_free (out); +} + +static void +do_bad_xmlrpc (const char *body) +{ + SoupMessage *msg; + GError *err = NULL; + GValue retval; + + msg = soup_message_new ("POST", uri); + soup_message_set_request (msg, "text/xml", SOUP_MEMORY_COPY, + body, strlen (body)); + soup_session_send_message (session, msg); + + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + + if (!soup_xmlrpc_parse_method_response (msg->response_body->data, + msg->response_body->length, + &retval, &err)) { + if (err) { + debug_printf (1, "FAULT: %d %s (OK!)\n", + err->code, err->message); + g_error_free (err); + g_object_unref (msg); + return; + } else + soup_test_assert (FALSE, "ERROR: could not parse response\n"); + } else + soup_test_assert (FALSE, "Unexpectedly got successful response!\n"); + + g_object_unref (msg); +} + +static void +test_fault_malformed (void) +{ + SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER; + + do_bad_xmlrpc (""); +} + +static void +test_fault_method (void) +{ + SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER; + + do_bad_xmlrpc ("no_such_method1"); +} + +static void +test_fault_args (void) +{ + SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER; + + do_bad_xmlrpc ("sum1"); +} + +static GOptionEntry xmlrpc_entries[] = { + { "uri", 'U', 0, G_OPTION_ARG_STRING, &uri, + "Alternate URI for server", NULL }, + { "server-test", 'S', 0, G_OPTION_ARG_NONE, &server_test, + "If this is being run from xmlrpc-old-server-test", NULL }, + { NULL } +}; + +int +main (int argc, char **argv) +{ + int ret; + + test_init (argc, argv, xmlrpc_entries); + + if (!uri && !server_test) { + apache_init (); + uri = default_uri; + } + + session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL); + + g_test_add_func ("/xmlrpc-old/sum", test_sum); + g_test_add_func ("/xmlrpc-old/countBools", test_countBools); + g_test_add_func ("/xmlrpc-old/md5sum", test_md5sum); + g_test_add_func ("/xmlrpc-old/dateChange", test_dateChange); + g_test_add_func ("/xmlrpc-old/echo", test_echo); + g_test_add_data_func ("/xmlrpc-old/ping/empty-params", GINT_TO_POINTER (TRUE), test_ping); + g_test_add_data_func ("/xmlrpc-old/ping/no-params", GINT_TO_POINTER (FALSE), test_ping); + g_test_add_func ("/xmlrpc-old/fault/malformed", test_fault_malformed); + g_test_add_func ("/xmlrpc-old/fault/method", test_fault_method); + g_test_add_func ("/xmlrpc-old/fault/args", test_fault_args); + + ret = g_test_run (); + + soup_test_session_abort_unref (session); + + test_cleanup (); + return ret; +} diff --git a/tests/xmlrpc-server-test.c b/tests/xmlrpc-server-test.c new file mode 100644 index 0000000..80f04ea --- /dev/null +++ b/tests/xmlrpc-server-test.c @@ -0,0 +1,374 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright 2008 Red Hat, Inc. + * Copyright 2015, Collabora ltd. + */ + +#include "test-utils.h" + +static char *uri; + +static GVariant * +parse_params (SoupMessage *msg, SoupXMLRPCParams *params, const char *signature) +{ + GVariant *args; + GError *error = NULL; + + args = soup_xmlrpc_params_parse (params, signature, &error); + if (!args) { + soup_xmlrpc_message_set_fault (msg, + SOUP_XMLRPC_FAULT_SERVER_ERROR_INVALID_METHOD_PARAMETERS, + "Wrong method signature: expected %s: %s", + signature, error->message); + } + + return args; +} + +static void +do_sum (SoupMessage *msg, SoupXMLRPCParams *params) +{ + GVariant *args; + GVariant *child; + GVariantIter iter; + double sum = 0.0, val; + + if (!(args = parse_params (msg, params, "(ad)"))) + return; + + child = g_variant_get_child_value (args, 0); + + g_variant_iter_init (&iter, child); + while (g_variant_iter_loop (&iter, "d", &val)) + sum += val; + + soup_xmlrpc_message_set_response (msg, g_variant_new_double (sum), NULL); + + g_variant_unref (args); + g_variant_unref (child); +} + +static void +do_countBools (SoupMessage *msg, SoupXMLRPCParams *params) +{ + GVariant *args; + GVariant *child; + GVariantIter iter; + gboolean val; + int trues = 0, falses = 0; + GVariantDict dict; + + if (!(args = parse_params (msg, params, "(ab)"))) + return; + + child = g_variant_get_child_value (args, 0); + + g_variant_iter_init (&iter, child); + while (g_variant_iter_loop (&iter, "b", &val)) { + if (val) + trues++; + else + falses++; + } + + g_variant_dict_init (&dict, NULL); + g_variant_dict_insert (&dict, "true", "i", trues); + g_variant_dict_insert (&dict, "false", "i", falses); + + soup_xmlrpc_message_set_response (msg, g_variant_dict_end (&dict), NULL); + + g_variant_unref (args); + g_variant_unref (child); +} + +static void +do_md5sum (SoupMessage *msg, SoupXMLRPCParams *params) +{ + GVariant *args; + GVariant *child; + GChecksum *checksum; + GByteArray *digest; + gsize digest_len = 16; + + if (!(args = parse_params (msg, params, "(ay)"))) + return; + + child = g_variant_get_child_value (args, 0); + + checksum = g_checksum_new (G_CHECKSUM_MD5); + g_checksum_update (checksum, + g_variant_get_data (child), + g_variant_get_size (child)); + digest = g_byte_array_new (); + g_byte_array_set_size (digest, digest_len); + g_checksum_get_digest (checksum, digest->data, &digest_len); + g_checksum_free (checksum); + + soup_xmlrpc_message_set_response (msg, + g_variant_new_from_data (G_VARIANT_TYPE_BYTESTRING, + digest->data, digest_len, + TRUE, NULL, NULL), + NULL); + g_byte_array_free (digest, TRUE); + g_variant_unref (child); + g_variant_unref (args); +} + + +static void +do_dateChange (SoupMessage *msg, SoupXMLRPCParams *params) +{ + GVariant *args; + GVariant *timestamp; + SoupDate *date; + GVariant *arg; + int val; + GError *error = NULL; + + if (!(args = parse_params (msg, params, "(va{si})"))) + return; + + g_variant_get (args, "(v@a{si})", ×tamp, &arg); + + date = soup_xmlrpc_variant_get_datetime (timestamp, &error); + if (!date) { + soup_xmlrpc_message_set_fault (msg, + SOUP_XMLRPC_FAULT_SERVER_ERROR_INVALID_METHOD_PARAMETERS, + "%s", error->message); + g_clear_error (&error); + goto fail; + } + + if (g_variant_lookup (arg, "tm_year", "i", &val)) + date->year = val + 1900; + if (g_variant_lookup (arg, "tm_mon", "i", &val)) + date->month = val + 1; + if (g_variant_lookup (arg, "tm_mday", "i", &val)) + date->day = val; + if (g_variant_lookup (arg, "tm_hour", "i", &val)) + date->hour = val; + if (g_variant_lookup (arg, "tm_min", "i", &val)) + date->minute = val; + if (g_variant_lookup (arg, "tm_sec", "i", &val)) + date->second = val; + + soup_xmlrpc_message_set_response (msg, + soup_xmlrpc_variant_new_datetime (date), + NULL); + + soup_date_free (date); + +fail: + g_variant_unref (args); + g_variant_unref (arg); + g_variant_unref (timestamp); +} + +static void +do_echo (SoupMessage *msg, SoupXMLRPCParams *params) +{ + GVariant *args; + GVariant *child; + + if (!(args = parse_params (msg, params, "(as)"))) + return; + + child = g_variant_get_child_value (args, 0); + soup_xmlrpc_message_set_response (msg, child, NULL); + g_variant_unref (args); + g_variant_unref (child); +} + +static void +do_ping (SoupMessage *msg, SoupXMLRPCParams *params) +{ + GVariant *args; + + if (!(args = parse_params (msg, params, "()"))) + return; + + soup_xmlrpc_message_set_response (msg, g_variant_new_string ("pong"), NULL); + g_variant_unref (args); +} + +static void +server_callback (SoupServer *server, SoupMessage *msg, + const char *path, GHashTable *query, + SoupClientContext *context, gpointer data) +{ + char *method_name; + SoupXMLRPCParams *params; + GError *error = NULL; + + if (msg->method != SOUP_METHOD_POST) { + soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED); + return; + } + + soup_message_set_status (msg, SOUP_STATUS_OK); + + method_name = soup_xmlrpc_parse_request (msg->request_body->data, + msg->request_body->length, + ¶ms, &error); + if (!method_name) { + soup_xmlrpc_message_set_fault (msg, SOUP_XMLRPC_FAULT_PARSE_ERROR_NOT_WELL_FORMED, + "Could not parse method call: %s", error->message); + g_clear_error (&error); + return; + } + + if (!strcmp (method_name, "sum")) + do_sum (msg, params); + else if (!strcmp (method_name, "countBools")) + do_countBools (msg, params); + else if (!strcmp (method_name, "md5sum")) + do_md5sum (msg, params); + else if (!strcmp (method_name, "dateChange")) + do_dateChange (msg, params); + else if (!strcmp (method_name, "echo")) + do_echo (msg, params); + else if (!strcmp (method_name, "ping")) + do_ping (msg, params); + else { + soup_xmlrpc_message_set_fault (msg, SOUP_XMLRPC_FAULT_SERVER_ERROR_REQUESTED_METHOD_NOT_FOUND, + "Unknown method %s", method_name); + } + + g_free (method_name); + soup_xmlrpc_params_free (params); +} + +static gboolean +run_xmlrpc_test (char **argv, + char **stdout_out, + char **stderr_out, + GError **error) +{ + gboolean ok; + int status; + + argv[0] = g_test_build_filename (G_TEST_BUILT, "xmlrpc-test", NULL); + ok = g_spawn_sync (NULL, argv, NULL, 0, NULL, NULL, + stdout_out, stderr_out, &status, + error); + g_free (argv[0]); + + if (!ok) + return FALSE; + + return g_spawn_check_exit_status (status, error); +} + +static void +do_one_xmlrpc_test (gconstpointer data) +{ + const char *path = data; + char *argv[12]; + char *stdout_out, *stderr_out; + GError *error = NULL; + int arg; + + argv[0] = NULL; + argv[1] = "-S"; + argv[2] = "-U"; + argv[3] = uri; + argv[4] = "-q"; + argv[5] = "-p"; + argv[6] = (char *) path; + + for (arg = 0; arg < debug_level && arg < 3; arg++) + argv[arg + 7] = "-d"; + argv[arg + 7] = NULL; + + run_xmlrpc_test (argv, &stdout_out, &stderr_out, &error); + if (stdout_out) { + g_print ("%s", stdout_out); + g_free (stdout_out); + } + if (stderr_out) { + g_printerr ("%s", stderr_out); + g_free (stderr_out); + } + + if ( g_error_matches (error, G_SPAWN_EXIT_ERROR, 1) + || g_error_matches (error, G_SPAWN_EXIT_ERROR, 77)) + g_test_fail (); + else + g_assert_no_error (error); + g_clear_error (&error); +} + +gboolean run_tests = TRUE; + +static GOptionEntry no_test_entry[] = { + { "no-tests", 'n', G_OPTION_FLAG_REVERSE, + G_OPTION_ARG_NONE, &run_tests, + "Don't run tests, just run the test server", NULL }, + { NULL } +}; + +int +main (int argc, char **argv) +{ + SoupServer *server; + SoupURI *server_uri; + int ret; + + test_init (argc, argv, no_test_entry); + + server = soup_test_server_new (run_tests ? SOUP_TEST_SERVER_IN_THREAD : SOUP_TEST_SERVER_DEFAULT); + soup_server_add_handler (server, "/xmlrpc-server.php", + server_callback, NULL, NULL); + server_uri = soup_test_server_get_uri (server, "http", NULL); + soup_uri_set_path (server_uri, "/xmlrpc-server.php"); + uri = soup_uri_to_string (server_uri, FALSE); + + if (run_tests) { + char *out, **tests, *path; + char *list_argv[4]; + GError *error = NULL; + int i; + + list_argv[0] = NULL; + list_argv[1] = "-S"; + list_argv[2] = "-l"; + list_argv[3] = NULL; + + if (!run_xmlrpc_test (list_argv, &out, NULL, &error)) { + g_printerr ("'xmlrpc-test -l' failed: %s\n", error->message); + g_error_free (error); + return 1; + } + + tests = g_strsplit (out, "\n", -1); + g_free (out); + + for (i = 0; tests[i] && *tests[i]; i++) { + g_assert_true (g_str_has_prefix (tests[i], "/xmlrpc/")); + path = g_strdup_printf ("/xmlrpc-server/%s", tests[i] + strlen ("/xmlrpc/")); + g_test_add_data_func (path, tests[i], do_one_xmlrpc_test); + g_free (path); + } + + ret = g_test_run (); + + g_strfreev (tests); + } else { + GMainLoop *loop; + + g_print ("Listening on port %d\n", server_uri->port); + + loop = g_main_loop_new (NULL, TRUE); + g_main_loop_run (loop); + g_main_loop_unref (loop); + + ret = 0; + } + + soup_test_server_quit_unref (server); + soup_uri_free (server_uri); + g_free (uri); + if (run_tests) + test_cleanup (); + return ret; +} diff --git a/tests/xmlrpc-server.php b/tests/xmlrpc-server.php new file mode 100644 index 0000000..f315b6d --- /dev/null +++ b/tests/xmlrpc-server.php @@ -0,0 +1,99 @@ + + $fault["faultCode"] = -32602; + $fault["faultString"] = "bad parameter"; + return $fault; +} + +# We only check the params in sum(), because that is the one that +# xmlrpc-test tests will fail if given bad args + +function sum ($method_name, $params, $app_data) +{ + if (xmlrpc_get_type ($params[0]) != "array") + return paramfault(); + + $sum = 0; + foreach ($params[0] as $val) { + if (xmlrpc_get_type ($val) != "double") + return paramfault(); + + $sum = $sum + $val; + } + return $sum; +} + +function countBools ($method_name, $params, $app_data) +{ + $counts["true"] = $counts["false"] = 0; + foreach ($params[0] as $val) { + if ($val) + $counts["true"] = $counts["true"] + 1; + else + $counts["false"] = $counts["false"] + 1; + } + return $counts; +} + +function md5sum ($method_name, $params, $app_data) +{ + $val = md5 ($params[0]->scalar, true); + xmlrpc_set_type ($val, "base64"); + return $val; +} + +function dateChange ($method_name, $params, $app_data) +{ + $date_str = $params[0]->scalar; + $date = strptime ($date_str, "%Y%m%dT%H:%M:%S"); + + foreach ($params[1] as $name => $val) { + if ($name == "date") + continue; + $date[$name] = $val; + } + + $ret = sprintf ("%04d%02d%02dT%02d:%02d:%02d", + $date["tm_year"] + 1900, $date["tm_mon"] + 1, + $date["tm_mday"], $date["tm_hour"], + $date["tm_min"], $date["tm_sec"]); + xmlrpc_set_type ($ret, "datetime"); + return $ret; +} + +function echo_ ($method_name, $params, $app_data) +{ + return $params[0]; +} + +function ping ($method_name, $params, $app_data) +{ + if (is_null ($params) or count ($params) == 0) + return "pong"; + else + return paramfault (); +} + +# Work around xmlrpc-php lossage; otherwise the datetime values +# we return will sometimes get a DST adjustment we do not want. +putenv ("TZ="); + +$xmlrpc_server = xmlrpc_server_create (); +xmlrpc_server_register_method($xmlrpc_server, "sum", "sum"); +xmlrpc_server_register_method($xmlrpc_server, "countBools", "countBools"); +xmlrpc_server_register_method($xmlrpc_server, "md5sum", "md5sum"); +xmlrpc_server_register_method($xmlrpc_server, "dateChange", "dateChange"); +xmlrpc_server_register_method($xmlrpc_server, "echo", "echo_"); +xmlrpc_server_register_method($xmlrpc_server, "ping", "ping"); + +$response = xmlrpc_server_call_method ($xmlrpc_server, + implode("\r\n", file('php://input')), + 0, array ("output_type" => "xml")); +echo ($response); + +xmlrpc_server_destroy ($xmlrpc_server); + +?> diff --git a/tests/xmlrpc-test.c b/tests/xmlrpc-test.c new file mode 100644 index 0000000..58d96ab --- /dev/null +++ b/tests/xmlrpc-test.c @@ -0,0 +1,738 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright 2001-2003, Ximian, Inc. + * Copyright 2015, Collabora ltd. + */ + +#include "test-utils.h" + +static SoupSession *session; +static const char *default_uri = "http://127.0.0.1:47524/xmlrpc-server.php"; +static const char *uri = NULL; +static gboolean server_test = FALSE; + +#ifdef HAVE_PHP_XMLRPC +#define SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER +#else +#define SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER \ + G_STMT_START { \ + if (!server_test) { \ + g_test_skip ("php-xmlrpc is not available"); \ + return; \ + } \ + } G_STMT_END +#endif + +static gboolean +send_xmlrpc (const char *body, const char *signature, GVariant **retval) +{ + SoupMessage *msg; + GError *err = NULL; + + msg = soup_message_new ("POST", uri); + soup_message_set_request (msg, "text/xml", SOUP_MEMORY_COPY, + body, strlen (body)); + soup_session_send_message (session, msg); + + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + + *retval = soup_xmlrpc_parse_response (msg->response_body->data, + msg->response_body->length, + signature, &err); + if (!*retval) { + if (err->domain == SOUP_XMLRPC_FAULT) + soup_test_assert (FALSE, "FAULT: %d %s\n", err->code, err->message); + else + soup_test_assert (FALSE, "ERROR: %s\n", err->message); + g_error_free (err); + g_object_unref (msg); + return FALSE; + } + + return TRUE; +} + +static gboolean +do_xmlrpc (const char *method, GVariant *args, const char *signature, GVariant **retval) +{ + gboolean ret; + char *body; + GError *error = NULL; + + body = soup_xmlrpc_build_request (method, args, &error); + g_assert_no_error (error); + if (!body) + return FALSE; + + ret = send_xmlrpc (body, signature, retval); + g_free (body); + + return ret; +} + +static void +test_sum (void) +{ + GVariantBuilder builder; + int i; + double val, sum, result; + GVariant *retval; + gboolean ok; + + SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER; + + debug_printf (2, "sum (array of double -> double): "); + + g_variant_builder_init (&builder, G_VARIANT_TYPE ("ad")); + for (i = sum = 0; i < 10; i++) { + val = g_random_int_range (0, 400) / 4.0; + debug_printf (2, "%s%.2f", i == 0 ? "[" : ", ", val); + g_variant_builder_add (&builder, "d", val); + sum += val; + } + debug_printf (2, "] -> "); + + ok = do_xmlrpc ("sum", + g_variant_new ("(@ad)", g_variant_builder_end (&builder)), + "d", &retval); + + if (!ok) + return; + + result = g_variant_get_double (retval); + debug_printf (2, "%.2f\n", result); + g_assert_cmpfloat (result, ==, sum); + + g_variant_unref (retval); +} + +static void +test_countBools (void) +{ + GVariantBuilder builder; + int i, trues, falses; + GVariant *retval; + int ret_trues, ret_falses; + gboolean val, ok; + + SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER; + + debug_printf (2, "countBools (array of boolean -> struct of ints): "); + + g_variant_builder_init (&builder, G_VARIANT_TYPE ("ab")); + for (i = trues = falses = 0; i < 10; i++) { + val = g_random_boolean (); + debug_printf (2, "%s%c", i == 0 ? "[" : ", ", val ? 'T' : 'F'); + g_variant_builder_add (&builder, "b", val); + if (val) + trues++; + else + falses++; + } + debug_printf (2, "] -> "); + + ok = do_xmlrpc ("countBools", + g_variant_new ("(@ab)", g_variant_builder_end (&builder)), + "a{si}", &retval); + if (!ok) + return; + + g_assert_true (g_variant_lookup (retval, "true", "i", &ret_trues)); + g_assert_true (g_variant_lookup (retval, "false", "i", &ret_falses)); + g_assert_cmpint (g_variant_n_children (retval), ==, 2); + g_variant_unref (retval); + + debug_printf (2, "{ true: %d, false: %d }\n", ret_trues, ret_falses); + g_assert_cmpint (trues, ==, ret_trues); + g_assert_cmpint (falses, ==, ret_falses); +} + +static void +test_md5sum (void) +{ + GByteArray *data; + int i; + GChecksum *checksum; + guchar digest[16]; + gsize digest_len = sizeof (digest); + GVariant *retval; + gboolean ok; + + SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER; + + debug_printf (2, "md5sum (base64 -> base64)\n"); + + data = g_byte_array_new (); + g_byte_array_set_size (data, 256); + for (i = 0; i < data->len; i++) + data->data[i] = (char)(g_random_int_range (0, 256)); + + checksum = g_checksum_new (G_CHECKSUM_MD5); + g_checksum_update (checksum, data->data, data->len); + g_checksum_get_digest (checksum, digest, &digest_len); + g_checksum_free (checksum); + + ok = do_xmlrpc ("md5sum", + g_variant_new ("(@ay)", + g_variant_new_from_data (G_VARIANT_TYPE_BYTESTRING, + data->data, data->len, + TRUE, NULL, NULL)), + "ay", &retval); + g_byte_array_free (data, TRUE); + if (!ok) + return; + + soup_assert_cmpmem (g_variant_get_data (retval), g_variant_get_size (retval), + digest, digest_len); + g_variant_unref (retval); +} + +static void +test_dateChange (void) +{ + GVariantDict structval; + SoupDate *date, *result; + char *timestamp; + GVariant *retval; + gboolean ok; + GError *error = NULL; + + SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER; + + debug_printf (2, "dateChange (date, struct of ints -> time)\n"); + + date = soup_date_new (1970 + (g_random_int_range (0, 50)), + 1 + g_random_int_range (0, 12), + 1 + g_random_int_range (0, 28), + g_random_int_range (0, 24), + g_random_int_range (0, 60), + g_random_int_range (0, 60)); + if (debug_level >= 2) { + char *tmp; + + tmp = soup_date_to_string (date, SOUP_DATE_ISO8601_XMLRPC); + debug_printf (2, "date: %s, {", tmp); + g_free (tmp); + } + + g_variant_dict_init (&structval, NULL); + +#define MAYBE (g_random_int_range (0, 3) != 0) + + if (MAYBE) { + date->year = 1970 + (g_random_int_range (0, 50)); + debug_printf (2, "tm_year: %d, ", date->year - 1900); + g_variant_dict_insert (&structval, "tm_year", + "i", date->year - 1900); + } + if (MAYBE) { + date->month = 1 + g_random_int_range (0, 12); + debug_printf (2, "tm_mon: %d, ", date->month - 1); + g_variant_dict_insert (&structval, "tm_mon", + "i", date->month - 1); + } + if (MAYBE) { + date->day = 1 + g_random_int_range (0, 28); + debug_printf (2, "tm_mday: %d, ", date->day); + g_variant_dict_insert (&structval, "tm_mday", + "i", date->day); + } + if (MAYBE) { + date->hour = g_random_int_range (0, 24); + debug_printf (2, "tm_hour: %d, ", date->hour); + g_variant_dict_insert (&structval, "tm_hour", + "i", date->hour); + } + if (MAYBE) { + date->minute = g_random_int_range (0, 60); + debug_printf (2, "tm_min: %d, ", date->minute); + g_variant_dict_insert (&structval, "tm_min", + "i", date->minute); + } + if (MAYBE) { + date->second = g_random_int_range (0, 60); + debug_printf (2, "tm_sec: %d, ", date->second); + g_variant_dict_insert (&structval, "tm_sec", + "i", date->second); + } + + debug_printf (2, "} -> "); + + ok = do_xmlrpc ("dateChange", + g_variant_new ("(vv)", + soup_xmlrpc_variant_new_datetime (date), + g_variant_dict_end (&structval)), + NULL, &retval); + if (!ok) { + soup_date_free (date); + return; + } + + result = soup_xmlrpc_variant_get_datetime (retval, &error); + g_assert_no_error (error); + + if (debug_level >= 2) { + timestamp = soup_date_to_string (result, SOUP_DATE_ISO8601_XMLRPC); + debug_printf (2, "%s\n", timestamp); + g_free (timestamp); + } + + g_assert_cmpint (date->year, ==, result->year); + g_assert_cmpint (date->month, ==, result->month); + g_assert_cmpint (date->day, ==, result->day); + g_assert_cmpint (date->hour, ==, result->hour); + g_assert_cmpint (date->minute, ==, result->minute); + g_assert_cmpint (date->second, ==, result->second); + + soup_date_free (date); + soup_date_free (result); + g_variant_unref (retval); +} + +static const char *const echo_strings[] = { + "This is a test", + "& so is this", + "and so is ", + "& so is <this>", + NULL +}; + +static void +test_echo (void) +{ + GVariant *originals; + GVariant *retval; + char *str; + + SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER; + + debug_printf (2, "echo (array of string -> array of string):\n"); + + originals = g_variant_new ("^as", echo_strings); + g_variant_ref_sink (originals); + str = g_variant_print (originals, TRUE); + debug_printf (2, "%s -> ", str); + g_free (str); + + if (!do_xmlrpc ("echo", + g_variant_new ("(@as)", originals), + "as", &retval)) { + g_variant_unref (originals); + return; + } + + str = g_variant_print (retval, TRUE); + debug_printf (2, "%s\n", str); + g_free (str); + + g_assert_true (g_variant_equal (originals, retval)); + + g_variant_unref (originals); + g_variant_unref (retval); +} + +static void +test_ping (gconstpointer include_params) +{ + GVariant *retval; + char *request; + gboolean ret; + GError *error = NULL; + + g_test_bug ("671661"); + + SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER; + + debug_printf (2, "ping (void (%s) -> string)\n", + include_params ? "empty " : "no "); + + request = soup_xmlrpc_build_request ("ping", g_variant_new ("()"), &error); + g_assert_no_error (error); + if (!request) + return; + + if (!include_params) { + char *params, *end; + + params = strstr (request, ""); + if (!params) { + soup_test_assert (FALSE, "ERROR: XML did not contain !"); + return; + } + end = params + strlen (""); + memmove (params, end, strlen (end) + 1); + } + + ret = send_xmlrpc (request, "s", &retval); + g_free (request); + + if (!ret) + return; + + g_assert_cmpstr (g_variant_get_string (retval, NULL), ==, "pong"); + g_variant_unref (retval); +} + +static void +do_bad_xmlrpc (const char *body) +{ + SoupMessage *msg; + GError *err = NULL; + + msg = soup_message_new ("POST", uri); + soup_message_set_request (msg, "text/xml", SOUP_MEMORY_COPY, + body, strlen (body)); + soup_session_send_message (session, msg); + + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + + if (!soup_xmlrpc_parse_response (msg->response_body->data, + msg->response_body->length, + "()", &err)) { + if (err->domain == SOUP_XMLRPC_FAULT) { + debug_printf (1, "FAULT: %d %s (OK!)\n", + err->code, err->message); + g_error_free (err); + g_object_unref (msg); + return; + } else + soup_test_assert (FALSE, "ERROR: could not parse response: %s\n", err->message); + } else + soup_test_assert (FALSE, "Unexpectedly got successful response!\n"); + + g_object_unref (msg); +} + +static void +test_fault_malformed (void) +{ + SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER; + + do_bad_xmlrpc (""); +} + +static void +test_fault_method (void) +{ + SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER; + + do_bad_xmlrpc ("no_such_method1"); +} + +static void +test_fault_args (void) +{ + SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER; + + do_bad_xmlrpc ("sum1"); +} + +#define BODY_PREFIX \ + "\n" \ + "MyMethod" +#define BODY_SUFFIX \ + "\n" + +static void +verify_serialization (GVariant *value, + const char *expected_params) +{ + char *debug; + char *body; + char *params; + GError *error = NULL; + + debug = g_variant_print (value, TRUE); + + body = soup_xmlrpc_build_request ("MyMethod", value, &error); + g_assert_no_error (error); + g_assert (g_str_has_prefix (body, BODY_PREFIX)); + g_assert (g_str_has_suffix (body, BODY_SUFFIX)); + + params = g_strndup (body + strlen (BODY_PREFIX), + strlen (body) - strlen (BODY_PREFIX) + - strlen (BODY_SUFFIX)); + + if (!g_str_equal (params, expected_params)) + g_error ("Failed to serialize '%s':\n" + " expected: %s\n" + " got: %s\n", + debug, expected_params, params); + + g_free (params); + g_free (body); + g_free (debug); +} + +static void +verify_serialization_fail (GVariant *value) +{ + char *body; + GError *error = NULL; + + body = soup_xmlrpc_build_request ("MyMethod", value, &error); + g_assert (body == NULL); + g_assert (error != NULL); +} + +static void +test_serializer (void) +{ + SoupDate *date; + + verify_serialization (g_variant_new_parsed ("()"), + ""); + verify_serialization (g_variant_new_parsed ("(1, 2)"), + "" + "1" + "2" + ""); + verify_serialization (g_variant_new_parsed ("((1, 2),)"), + "" + "1" + "2" + ""); + verify_serialization (g_variant_new_parsed ("({'one', 1},)"), + "" + "one1" + ""); + verify_serialization (g_variant_new_parsed ("([{'one', 1},{'two', 2}],)"), + "" + "one1" + "two2" + ""); + verify_serialization (g_variant_new ("(^ay)", "bytestring"), + "" + "Ynl0ZXN0cmluZwA=" + ""); + verify_serialization (g_variant_new ("(y)", 42), + "" + "42" + ""); + date = soup_date_new_from_time_t (1434161309); + verify_serialization (g_variant_new ("(v)", soup_xmlrpc_variant_new_datetime (date)), + "" + "20150613T02:08:29" + ""); + soup_date_free (date); + verify_serialization (g_variant_new ("(s)", "<>&"), + "" + "<>&" + ""); + verify_serialization (g_variant_new ("(u)", 0), + "" + "0" + ""); + + verify_serialization_fail (g_variant_new_parsed ("({1, 2},)")); + verify_serialization_fail (g_variant_new ("(mi)", NULL)); + verify_serialization_fail (g_variant_new ("(t)", 0)); +} + +static void +verify_deserialization (GVariant *expected_variant, + const char *signature, + const char *params) +{ + char *body; + char *method_name; + SoupXMLRPCParams *out_params = NULL; + GVariant *variant; + GError *error = NULL; + + body = g_strconcat (BODY_PREFIX, params, BODY_SUFFIX, NULL); + method_name = soup_xmlrpc_parse_request (body, strlen (body), + &out_params, + &error); + g_assert_no_error (error); + g_assert_cmpstr (method_name, ==, "MyMethod"); + + variant = soup_xmlrpc_params_parse (out_params, signature, &error); + g_assert_no_error (error); + + if (!g_variant_equal (variant, expected_variant)) { + char *str1, *str2; + + str1 = g_variant_print (expected_variant, TRUE); + str2 = g_variant_print (variant, TRUE); + g_error ("Failed to deserialize '%s':\n" + " expected: %s\n" + " got: %s\n", + params, str1, str2); + g_free (str1); + g_free (str2); + } + + soup_xmlrpc_params_free (out_params); + g_variant_unref (variant); + g_free (method_name); + g_free (body); +} + +static void +verify_deserialization_fail (const char *signature, + const char *params) +{ + char *body; + char *method_name; + SoupXMLRPCParams *out_params = NULL; + GVariant *variant; + GError *error = NULL; + + body = g_strconcat (BODY_PREFIX, params, BODY_SUFFIX, NULL); + method_name = soup_xmlrpc_parse_request (body, strlen (body), + &out_params, + &error); + g_assert_no_error (error); + g_assert_cmpstr (method_name, ==, "MyMethod"); + + variant = soup_xmlrpc_params_parse (out_params, signature, &error); + g_assert_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS); + g_assert (variant == NULL); + + g_free (body); + soup_xmlrpc_params_free (out_params); +} + +static void +test_deserializer (void) +{ + char *tmp; + SoupDate *date; + + verify_deserialization (g_variant_new_parsed ("@av []"), + NULL, + ""); + verify_deserialization (g_variant_new_parsed ("()"), + "()", + ""); + verify_deserialization (g_variant_new_parsed ("(@y 1,@n 2)"), + "(yn)", + "" + "1" + "2" + ""); + verify_deserialization (g_variant_new_parsed ("[<[{'one', <1>},{'two', <2>}]>]"), + NULL, + "" + "one1" + "two2" + ""); + verify_deserialization (g_variant_new_parsed ("([{'one', 1},{'two', 2}],)"), + "(a{si})", + "" + "one1" + "two2" + ""); + date = soup_date_new_from_time_t (1434146909); + verify_deserialization (g_variant_new_parsed ("[%v]", soup_xmlrpc_variant_new_datetime (date)), + NULL, + "" + "20150612T22:08:29" + ""); + soup_date_free (date); + verify_deserialization (g_variant_new_parsed ("[]"), + NULL, + "" + "Ynl0ZXN0cmluZwA=" + ""); + verify_deserialization (g_variant_new_parsed ("[<1>]"), + "av", + "1"); + verify_deserialization (g_variant_new_parsed ("[<%s>]", "<>&"), + NULL, + "" + "<>&" + ""); + verify_deserialization (g_variant_new_parsed ("(@y 255,)"), + "(y)", + "" + "255" + ""); + + tmp = g_strdup_printf ("" + "%"G_GUINT64_FORMAT"" + "", G_MAXUINT64); + verify_deserialization (g_variant_new ("(t)", G_MAXUINT64), + "(t)", tmp); + g_free (tmp); + + verify_deserialization_fail (NULL, + "" + "2" + ""); + verify_deserialization_fail ("(y)", + "" + "256" + ""); + verify_deserialization_fail ("(ii)", + "" + "1" + ""); + verify_deserialization_fail ("(i)", + "" + "1" + "2" + ""); +} + +static void +test_fault (void) +{ + char *body; + GVariant *reply; + GError *error = NULL; + + body = soup_xmlrpc_build_fault (1, "error: %s", "failed"); + reply = soup_xmlrpc_parse_response (body, strlen (body), NULL, &error); + g_assert_error (error, SOUP_XMLRPC_FAULT, 1); + g_assert_cmpstr (error->message, ==, "error: failed"); + g_assert (reply == NULL); + + g_free (body); + g_clear_error (&error); +} + +static GOptionEntry xmlrpc_entries[] = { + { "uri", 'U', 0, G_OPTION_ARG_STRING, &uri, + "Alternate URI for server", NULL }, + { "server-test", 'S', 0, G_OPTION_ARG_NONE, &server_test, + "If this is being run from xmlrpc-server-test", NULL }, + { NULL } +}; + +int +main (int argc, char **argv) +{ + int ret; + + test_init (argc, argv, xmlrpc_entries); + + if (!uri && !server_test) { + apache_init (); + uri = default_uri; + } + + session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL); + + g_test_add_func ("/xmlrpc/variant/serializer", test_serializer); + g_test_add_func ("/xmlrpc/variant/deserializer", test_deserializer); + g_test_add_func ("/xmlrpc/variant/fault", test_fault); + g_test_add_func ("/xmlrpc/variant/sum", test_sum); + g_test_add_func ("/xmlrpc/variant/countBools", test_countBools); + g_test_add_func ("/xmlrpc/variant/md5sum", test_md5sum); + g_test_add_func ("/xmlrpc/variant/dateChange", test_dateChange); + g_test_add_func ("/xmlrpc/variant/echo", test_echo); + g_test_add_data_func ("/xmlrpc/variant/ping/empty-params", GINT_TO_POINTER (TRUE), test_ping); + g_test_add_data_func ("/xmlrpc/variant/ping/no-params", GINT_TO_POINTER (FALSE), test_ping); + g_test_add_func ("/xmlrpc/variant/fault/malformed", test_fault_malformed); + g_test_add_func ("/xmlrpc/variant/fault/method", test_fault_method); + g_test_add_func ("/xmlrpc/variant/fault/args", test_fault_args); + + ret = g_test_run (); + + soup_test_session_abort_unref (session); + + test_cleanup (); + return ret; +} diff --git a/win32/Makefile-newvs.am b/win32/Makefile-newvs.am new file mode 100644 index 0000000..3a91862 --- /dev/null +++ b/win32/Makefile-newvs.am @@ -0,0 +1,55 @@ +# Centralized autotools file +# Create the Visual Studio 2012/2013/2015 project files +# from the Visual Studio 2010 project files + +# This autotools file, from GLib, can be used in other projects +# that have Visual Studio build support. + +# Author: Fan, Chun-wei +# November 05, 2012 + +# MSVC_BASE_VER: Baseline MSVC 201x version to copy/process project files from (100 for 2010, 120 for 2013) +# MSVC_BASE_VER_LONG: Long Version of baseline Visual Studio 201x version (2010, 2012, 2013, 14, 15) +# MSVC_BASE_TOOLSET: Use if baseline MSVC toolset is not in the form v$(MSVC_BASE_VER)0, meaning v$(MSVC_BASE_TOOLSET) +# MSVC_VER_LONG: Long Version of target Visual Studio (2012, 2013, 14 and so on) +# MSVC_VER: Short Version of target Visual Studio (110 for 2012, 120 for 2013, 140 for 2015, 141 for 2017) +# MSVC_TOOLSET: Use if target MSVC toolsett is not in the form v $(MSVC_VER)0, meaning v$(MSVC_TOOLSET) + +if MSVC_BASE_NO_TOOLSET_SET +MSVC_BASE_TOOLSET = $(MSVC_BASE_VER)0 +endif + +if MSVC_NO_TOOLSET_SET +MSVC_TOOLSET = $(MSVC_VER)0 +endif + +%.sln: + sed 's/11\.00/12\.00/g' < $(top_srcdir)/win32/vs$(MSVC_BASE_VER)/$@ > $(top_builddir)/win32/vs$(MSVC_VER)/$@.tmp + sed 's/$(MSVC_BASE_VER_LONG)/$(MSVC_VER_LONG)/g' < $(top_builddir)/win32/vs$(MSVC_VER)/$@.tmp > $(top_builddir)/win32/vs$(MSVC_VER)/$@ + rm $(top_builddir)/win32/vs$(MSVC_VER)/$@.tmp + +%.txt: + sed 's/vs$(MSVC_BASE_VER)/vs$(MSVC_VER)/g' < $(top_srcdir)/win32/vs$(MSVC_BASE_VER)/$@ > $(top_builddir)/win32/vs$(MSVC_VER)/$@.tmp + sed 's/VS$(MSVC_BASE_VER)/VS$(MSVC_VER)/g' < $(top_builddir)/win32/vs$(MSVC_VER)/$@.tmp > $(top_builddir)/win32/vs$(MSVC_VER)/$@ + rm $(top_builddir)/win32/vs$(MSVC_VER)/$@.tmp + +%.vcxproj: + if test -e $(top_srcdir)/win32/vs$(MSVC_BASE_VER)/$@; then \ + sed 's/v$(MSVC_BASE_TOOLSET)/v$(MSVC_TOOLSET)/g' < $(top_srcdir)/win32/vs$(MSVC_BASE_VER)/$@ > $(top_builddir)/win32/vs$(MSVC_VER)/$@; \ + else \ + sed 's/v$(MSVC_BASE_TOOLSET)/v$(MSVC_TOOLSET)/g' < $(top_builddir)/win32/vs$(MSVC_BASE_VER)/$@ > $(top_builddir)/win32/vs$(MSVC_VER)/$@; \ + fi + +%.props: $(top_builddir)/win32/vs$(MSVC_BASE_VER)/Makefile + if test -e $(top_srcdir)/win32/vs$(MSVC_BASE_VER)/$@; then \ + sed 's/$(MSVC_BASE_VER)<\/VSVer>/$(MSVC_VER)<\/VSVer>/g' < $(top_srcdir)/win32/vs$(MSVC_BASE_VER)/$@ > $(top_builddir)/win32/vs$(MSVC_VER)/$@; \ + else \ + sed 's/$(MSVC_BASE_VER)<\/VSVer>/$(MSVC_VER)<\/VSVer>/g' < $(top_builddir)/win32/vs$(MSVC_BASE_VER)/$@ > $(top_builddir)/win32/vs$(MSVC_VER)/$@; \ + fi + +%.vcxproj.filters: + if test -e $(top_srcdir)/win32/vs$(MSVC_BASE_VER)/$@; then \ + cp $(top_srcdir)/win32/vs$(MSVC_BASE_VER)/$@ $(top_builddir)/win32/vs$(MSVC_VER)/$@; \ + else \ + cp $(top_builddir)/win32/vs$(MSVC_BASE_VER)/$@ $(top_builddir)/win32/vs$(MSVC_VER)/$@; \ + fi diff --git a/win32/Makefile.am b/win32/Makefile.am new file mode 100644 index 0000000..e1d5759 --- /dev/null +++ b/win32/Makefile.am @@ -0,0 +1,35 @@ +SUBDIRS = vs9 vs10 vs11 vs12 vs14 vs15 + +if HAVE_INTROSPECTION +GENERATED_ITEMS = \ + introspection.body.mak \ + Soup_2_4_gir_list \ + SoupGNOME_2_4_gir_list + +MSVC_INTROSPECTION_INTERMEDIATE_FILES = Soup-2.4.gir.msvc.introspect SoupGNOME-2.4.gir.msvc.introspect + +introspection.body.mak: $(MSVC_INTROSPECTION_INTERMEDIATE_FILES) + -$(RM) introspection.body.mak + for F in `ls *.msvc.introspect`; do \ + case $$F in \ + *) cat $(top_builddir)/win32/$$F >>introspection.body.mak \ + ;; \ + esac; \ + done + $(RM) $(MSVC_INTROSPECTION_INTERMEDIATE_FILES) + +DISTCLEANFILES = $(GENERATED_ITEMS) + +else +GENERATED_ITEMS = +endif + +EXTRA_DIST = \ + pc_base.py \ + replace.py \ + souppc.py \ + soup_version_h.py \ + detectenv-msvc.mak \ + introspection-msvc.mak \ + soup-introspection-msvc.mak \ + $(GENERATED_ITEMS) diff --git a/win32/Makefile.in b/win32/Makefile.in new file mode 100644 index 0000000..17b3071 --- /dev/null +++ b/win32/Makefile.in @@ -0,0 +1,732 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = win32 +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_code_coverage.m4 \ + $(top_srcdir)/m4/glibtests.m4 $(top_srcdir)/m4/gtk-doc.m4 \ + $(top_srcdir)/m4/intltool.m4 $(top_srcdir)/m4/introspection.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/vapigen.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + distdir +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +ALL_LINGUAS = @ALL_LINGUAS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +APACHE_HTTPD = @APACHE_HTTPD@ +APACHE_MODULE_DIR = @APACHE_MODULE_DIR@ +APACHE_PHP_MODULE_DIR = @APACHE_PHP_MODULE_DIR@ +APACHE_SSL_MODULE_DIR = @APACHE_SSL_MODULE_DIR@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CODE_COVERAGE_CFLAGS = @CODE_COVERAGE_CFLAGS@ +CODE_COVERAGE_CPPFLAGS = @CODE_COVERAGE_CPPFLAGS@ +CODE_COVERAGE_CXXFLAGS = @CODE_COVERAGE_CXXFLAGS@ +CODE_COVERAGE_ENABLED = @CODE_COVERAGE_ENABLED@ +CODE_COVERAGE_LDFLAGS = @CODE_COVERAGE_LDFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CURL = @CURL@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GCOV = @GCOV@ +GENHTML = @GENHTML@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_COMPILE_RESOURCES = @GLIB_COMPILE_RESOURCES@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MAKEFILE = @GLIB_MAKEFILE@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GMSGFMT = @GMSGFMT@ +GOBJECT_QUERY = @GOBJECT_QUERY@ +GREP = @GREP@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +HAVE_GNOME = @HAVE_GNOME@ +HTML_DIR = @HTML_DIR@ +IF_HAVE_MOD_UNIXD = @IF_HAVE_MOD_UNIXD@ +IF_HAVE_PHP = @IF_HAVE_PHP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ +INTLTOOL_MERGE = @INTLTOOL_MERGE@ +INTLTOOL_PERL = @INTLTOOL_PERL@ +INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ +INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@ +INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@ +INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@ +INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LCOV = @LCOV@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PHP = @PHP@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOUP_AGE = @SOUP_AGE@ +SOUP_API_VERSION = @SOUP_API_VERSION@ +SOUP_CURRENT = @SOUP_CURRENT@ +SOUP_DEBUG_FLAGS = @SOUP_DEBUG_FLAGS@ +SOUP_HIDDEN_VISIBILITY_CFLAGS = @SOUP_HIDDEN_VISIBILITY_CFLAGS@ +SOUP_MAJOR_VERSION = @SOUP_MAJOR_VERSION@ +SOUP_MICRO_VERSION = @SOUP_MICRO_VERSION@ +SOUP_MINOR_VERSION = @SOUP_MINOR_VERSION@ +SOUP_REVISION = @SOUP_REVISION@ +SQLITE_CFLAGS = @SQLITE_CFLAGS@ +SQLITE_LIBS = @SQLITE_LIBS@ +STRIP = @STRIP@ +USE_NLS = @USE_NLS@ +VALAC = @VALAC@ +VAPIDIR = @VAPIDIR@ +VAPIGEN = @VAPIGEN@ +VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@ +VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@ +VERSION = @VERSION@ +XGETTEXT = @XGETTEXT@ +XML_CFLAGS = @XML_CFLAGS@ +XML_LIBS = @XML_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +installed_test_metadir = @installed_test_metadir@ +installed_testdir = @installed_testdir@ +intltool__v_merge_options_ = @intltool__v_merge_options_@ +intltool__v_merge_options_0 = @intltool__v_merge_options_0@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +ntlm_auth = @ntlm_auth@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = vs9 vs10 vs11 vs12 vs14 vs15 +@HAVE_INTROSPECTION_FALSE@GENERATED_ITEMS = +@HAVE_INTROSPECTION_TRUE@GENERATED_ITEMS = \ +@HAVE_INTROSPECTION_TRUE@ introspection.body.mak \ +@HAVE_INTROSPECTION_TRUE@ Soup_2_4_gir_list \ +@HAVE_INTROSPECTION_TRUE@ SoupGNOME_2_4_gir_list + +@HAVE_INTROSPECTION_TRUE@MSVC_INTROSPECTION_INTERMEDIATE_FILES = Soup-2.4.gir.msvc.introspect SoupGNOME-2.4.gir.msvc.introspect +@HAVE_INTROSPECTION_TRUE@DISTCLEANFILES = $(GENERATED_ITEMS) +EXTRA_DIST = \ + pc_base.py \ + replace.py \ + souppc.py \ + soup_version_h.py \ + detectenv-msvc.mak \ + introspection-msvc.mak \ + soup-introspection-msvc.mak \ + $(GENERATED_ITEMS) + +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign win32/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign win32/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(am__recursive_targets) install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ + check-am clean clean-generic clean-libtool cscopelist-am ctags \ + ctags-am distclean distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ + ps ps-am tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +@HAVE_INTROSPECTION_TRUE@introspection.body.mak: $(MSVC_INTROSPECTION_INTERMEDIATE_FILES) +@HAVE_INTROSPECTION_TRUE@ -$(RM) introspection.body.mak +@HAVE_INTROSPECTION_TRUE@ for F in `ls *.msvc.introspect`; do \ +@HAVE_INTROSPECTION_TRUE@ case $$F in \ +@HAVE_INTROSPECTION_TRUE@ *) cat $(top_builddir)/win32/$$F >>introspection.body.mak \ +@HAVE_INTROSPECTION_TRUE@ ;; \ +@HAVE_INTROSPECTION_TRUE@ esac; \ +@HAVE_INTROSPECTION_TRUE@ done +@HAVE_INTROSPECTION_TRUE@ $(RM) $(MSVC_INTROSPECTION_INTERMEDIATE_FILES) + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/win32/Makefile.msvc-introspection b/win32/Makefile.msvc-introspection new file mode 100644 index 0000000..1a244e0 --- /dev/null +++ b/win32/Makefile.msvc-introspection @@ -0,0 +1,129 @@ +# Author: Fan, Chun-wei +# Common autotools file for constructing the g-ir-scanner and +# g-ir-compiler command lines for Visual Studio builds. + +# This is copied from $(srcroot)/win32 from the gobject-introspection +# project, which may be included in projects that support both +# Visual Studio builds and introspection. + +# * Input variables: +# +# MSVC_INTROSPECT_GIRS - List of .gir's that should be built +# in the NMake Makefiles +# +# * Simple tutorial +# +# Add this to Makefile.am where your library/program is built: +# (Either YourLib_1_0_gir_MSVC_LIBS or YourLib_1_0_gir_MSVC_PROGRAM +# is required unless --headers-only is specified in +# YourLib_1_0_gir__MSVC_SCANNERFLAGS) +# +# include +# MSVC_INTROSPECT_GIRS = YourLib-1.0.gir +# YourLib_1_0_gir_NAMESPACE = YourLib # This is optional +# YourLib_1_0_gir_VERSION = 1.0 # This is optional +# YourLib_1_0_gir_MSVC_LIBS = yourlib-1.0 +# YourLib_1_0_gir_MSVC_FILES = $(libyourlib_1_0_SOURCES) +# YourLib_1_0_gir_MSVC_PROGRAM = YourProgram +# YourLib_1_0_gir_MSVC_PACKAGES = (Dependent .pc files) +# YourLib_1_0_gir_MSVC_INCLUDE_GIRS = (Dependent external .gir's) +# YourLib_1_0_gir_MSVC_EXPORT_PACKAGES = (Packages exported by this .gir) +# YourLib_1_0_gir_MSVC_C_INCLUDES = (List of public C headers which need to be included by +# consumers at compile time to make use of the API) + +# Private functions + +## Transform the MSVC project filename (no filename extensions) to something which can reference through a variable +## without automake/make complaining, eg Gtk-2.0 -> Gtk_2_0 +_gir_name=$(subst /,_,$(subst -,_,$(subst .,_,$(1)))) + +# Namespace and Version is either fetched from the gir filename +# or the _NAMESPACE/_VERSION variable combo +_gir_namespace_msvc = $(or $($(_gir_name)_NAMESPACE),$(firstword $(subst -, ,$(notdir $(1))))) +_gir_version_msvc = $(or $($(_gir_name)_VERSION),$(lastword $(subst -, ,$(1:.gir=)))) +_typelib_basename_msvc = $(_gir_namespace_msvc)'-'$(_gir_version_msvc) + +# _PROGRAM is an optional variable which needs its own --program argument +_gir_program_msvc = $(if $($(_gir_name)_MSVC_PROGRAM),--program=$($(_gir_name)_MSVC_PROGRAM)) + +# Deduce the sub-folder from $(srcroot) where the sources reside in +_gir_source_path_raw_msvc:=$(subst $(abs_top_srcdir),,$(abs_srcdir)) +_gir_source_path_msvc=$(subst /,\\,$(_gir_source_path_raw_msvc)) +_gir_source_subdir_int_msvc=$(subst \\\\,\\,\\$(_gir_source_path_msvc)\\) +_gir_source_subdir_msvc=$(subst \\.\\,\\,$(_gir_source_subdir_int_msvc)) + +_gir_files_raw_msvc=$(subst /,\\,$($(_gir_name)_MSVC_FILES)) +_gir_files_msvc=$(subst $(srcdir)\\,,$(subst $(builddir)\\,,$(subst $(top_builddir)\\$(_gir_source_path_msvc)\\,\\,$(_gir_files_raw_msvc)))) + +# Create a list of items for: +# - Libraries +# - Packages +# - GIRs to include +# - packages to export + +_gir_libraries_msvc = $(foreach lib,$($(_gir_name)_MSVC_LIBS),--library=$(lib)) +_gir_packages_msvc = $(foreach pkg,$($(_gir_name)_MSVC_PACKAGES),--pkg=$(pkg)) +_gir_includes_msvc = $(foreach include,$($(_gir_name)_MSVC_INCLUDE_GIRS),--include=$(include)) +_gir_export_packages_msvc = $(foreach pkg,$($(_gir_name)_MSVC_EXPORT_PACKAGES),--pkg-export=$(pkg)) +_gir_c_includes_msvc = $(foreach include,$($(_gir_name)_MSVC_C_INCLUDES),--c-include=$(include)) + +# +# Create NMake Makefile Sections for Building Introspection files +# from autotools files +# $(1) - File Name of the .gir that is to be generated +# + +define gir-nmake-builder + +# Basic sanity check, to make sure required variables are set +$(if $($(_gir_name)_MSVC_FILES),,$(error Need to define $(_gir_name)_MSVC_FILES)) +$(if $(or $(findstring --header-only,$($(_gir_name)_MSVC_SCANNERFLAGS)), + $($(_gir_name)_MSVC_LIBS), + $($(_gir_name)_MSVC_PROGRAM)),, + $(error Need to define $(_gir_name)_MSVC_LIBS or $(_gir_name)_MSVC_PROGRAM)) + +$(top_builddir)/win32/$(_gir_name)_list: + for F in $(_gir_files_msvc); do \ + case $$$$F in \ + *.c|*.cpp|*.cc|*.cxx|*.h|*.hpp|*.hh|*.hxx) \ + echo '..'$(_gir_source_subdir_msvc)$$$$F >>$(top_builddir)/win32/$(_gir_name)_list \ + ;; \ + esac; \ + done + +$(top_builddir)/win32/$(1).msvc.introspect: + -$(RM) $(top_builddir)/win32/$(1).msvc.introspect + +# Assemble the Command to Run g-ir-scanner + echo $(1)': '$(_gir_name)'_list '$($(_gir_name)_MSVC_GIR_DEPS)>>$(top_builddir)/win32/$(1).msvc.introspect + echo ' @-echo Generating $$$$@...'>>$(top_builddir)/win32/$(1).msvc.introspect + echo ' $$$$(PYTHON) $$$$(G_IR_SCANNER) \'>>$(top_builddir)/win32/$(1).msvc.introspect + echo ' --verbose -no-libtool \'>>$(top_builddir)/win32/$(1).msvc.introspect + echo ' --namespace='$(_gir_namespace_msvc)' \'>>$(top_builddir)/win32/$(1).msvc.introspect + echo ' --nsversion='$(_gir_version_msvc)' \'>>$(top_builddir)/win32/$(1).msvc.introspect + echo ' '$(_gir_packages_msvc)' \'>>$(top_builddir)/win32/$(1).msvc.introspect + echo ' '$(_gir_libraries_msvc)' \'>>$(top_builddir)/win32/$(1).msvc.introspect + echo ' '$(_gir_program_msvc)' \'>>$(top_builddir)/win32/$(1).msvc.introspect + echo ' --add-include-path=$$$$(G_IR_INCLUDEDIR) \'>>$(top_builddir)/win32/$(1).msvc.introspect + echo ' '$(_gir_includes_msvc)' \'>>$(top_builddir)/win32/$(1).msvc.introspect + echo ' '$(_gir_export_packages_msvc)' \'>>$(top_builddir)/win32/$(1).msvc.introspect + echo ' '$(_gir_c_includes_msvc)' \'>>$(top_builddir)/win32/$(1).msvc.introspect + echo ' --cflags-begin \'>>$(top_builddir)/win32/$(1).msvc.introspect + echo ' '$($(_gir_name)_MSVC_CFLAGS)' \'>>$(top_builddir)/win32/$(1).msvc.introspect + echo ' --cflags-end \'>>$(top_builddir)/win32/$(1).msvc.introspect + echo ' '$($(_gir_name)_MSVC_SCANNERFLAGS)' \'>>$(top_builddir)/win32/$(1).msvc.introspect + echo ' --filelist='$(_gir_name)'_list \'>>$(top_builddir)/win32/$(1).msvc.introspect + echo ' -o $$$$@'>>$(top_builddir)/win32/$(1).msvc.introspect + echo '' >>$(top_builddir)/win32/$(1).msvc.introspect + +# Finally Assemble the Command to Compile the generated .gir + echo '$(_typelib_basename_msvc).typelib: '$(_typelib_basename_msvc)'.gir'>>$(top_builddir)/win32/$(1).msvc.introspect + echo ' @-echo Compiling $$$$@...'>>$(top_builddir)/win32/$(1).msvc.introspect + echo ' $$$$(G_IR_COMPILER) \'>>$(top_builddir)/win32/$(1).msvc.introspect + echo ' --includedir=. --debug --verbose \'>>$(top_builddir)/win32/$(1).msvc.introspect + echo ' '$(1)' \'>>$(top_builddir)/win32/$(1).msvc.introspect + echo ' -o $$$$@'>>$(top_builddir)/win32/$(1).msvc.introspect + echo '' >>$(top_builddir)/win32/$(1).msvc.introspect +endef + +$(foreach gir,$(MSVC_INTROSPECT_GIRS),$(eval $(call gir-nmake-builder,$(gir)))) diff --git a/win32/Makefile.msvcproj b/win32/Makefile.msvcproj new file mode 100644 index 0000000..2e96e12 --- /dev/null +++ b/win32/Makefile.msvcproj @@ -0,0 +1,153 @@ +# Author: Fan, Chun-wei +# Common Autotools file used to generate Visual Studio 2008+ +# Projects from their templates + +# This autotools file, from GLib, can be used in other projects +# that have Visual Studio build support. + +# * Input variables: +# +# MSVCPROJS - List of Projects that should be generated +# +# * Simple tutorial +# +# Add this to Makefile.am where your library/program is built: +# include +# MSVCPROJS = YourProject (can be multiple projects in a single srcdir) +# YourProject_FILES = $(libyourlib_1_0_SOURCES) +# YourProject_EXCLUDES = ... # list of sources to exclude, separated by '|', wildcards allowed; use random unsed value if none +# (the following 3 lines if headers need to be installed) +# YourProject_HEADERS_DIR = $(libyourlibincludedir) +# YourProject_HEADERS_INST = $(libyourlib_1_0_HEADERS) +# YourProject_HEADERS_EXCLUDES = ... # +# +# dist-hook: \ # (or add to it if it is already there, note the vs9 items will also call the vs10 items in the process) +# $(top_builddir)/win32/vs9/YourProject.vcproj \ +# $(top_builddir)/win32/vs9/YourProject.headers # if headers need to be installed +# +# --or, if Visual Studio 2013 or later is required-- +# dist-hook: \ # (or add to it if it is already there, this does -not- call other vs items in the process) +# $(top_builddir)/win32/vs12/YourProject.vcxproj \ +# $(top_builddir)/win32/vs12/YourProject.vs12.headers # if headers need to be installed + +# Private functions + +## Transform the MSVC project filename (no filename extensions) to something which can reference through a variable +## without automake/make complaining, eg Gtk-2.0 -> Gtk_2_0 +_proj_name=$(subst /,_,$(subst -,_,$(subst .,_,$(1)))) +_proj_path_raw:=$(subst $(abs_top_srcdir),,$(abs_srcdir)) +_proj_path=$(subst /,\\,$(_proj_path_raw)) +_proj_subdir_int=$(subst \\\\,\\,\\$(_proj_path)\\) +_proj_subdir=$(subst \\.\\,\\,$(_proj_subdir_int)) + +_proj_files_raw=$(subst /,\\,$($(_proj_name)_FILES)) +_proj_files=$(subst $(srcdir)\\,,$(subst $(builddir)\\,,$(subst $(top_builddir)\\$(_proj_path)\\,\\,$(_proj_files_raw)))) +_proj_filters=$($(_proj_name)_EXCLUDES) + +_proj_headers_raw=$(subst /,\\,$($(_proj_name)_HEADERS_INST)) +_proj_headers=$(subst $(srcdir)\\,,$(subst $(builddir)\\,,$(subst $(top_builddir)\\$(_proj_path)\\,\\,$(_proj_headers_raw)))) +_proj_headers_excludes=$($(_proj_name)_HEADERS_EXCLUDES) + +_headers_dest_posix=$(subst $(includedir),,$($(_proj_name)_HEADERS_DIR)) +_headers_destdir=$(subst /,\\,$(_headers_dest_posix)) + +# +# Creates Visual Studio 2008/2010 projects from items passed in from autotools files +# $(1) - Base Name of the MSVC project files (outputs) +# + +define msvcproj-builder + +$(top_builddir)/win32/vs10/$(1).vcxproj: $(top_builddir)/win32/vs9/$(1).vcproj +$(top_builddir)/win32/vs10/$(1).vcxproj.filters: $(top_builddir)/win32/vs9/$(1).vcproj +$(1).sourcefiles: $(top_builddir)/win32/vs9/$(1).vcproj +$(1).vs10.sourcefiles: $(top_builddir)/win32/vs9/$(1).vcproj +$(1).vs10.sourcefiles.filters: $(top_builddir)/win32/vs9/$(1).vcproj + +$(top_builddir)/win32/vs9/$(1).vcproj: Makefile + -$(RM) $(top_builddir)/win32/vs9/$(1).vcproj + -$(RM) $(top_builddir)/win32/vs10/$(1).vcxproj + -$(RM) $(top_builddir)/win32/vs10/$(1).vcxproj.filters + -$(RM) $(top_builddir)/win32/vs11/$(1).vcxproj + -$(RM) $(top_builddir)/win32/vs11/$(1).vcxproj.filters + -$(RM) $(top_builddir)/win32/vs12/$(1).vcxproj + -$(RM) $(top_builddir)/win32/vs12/$(1).vcxproj.filters + -$(RM) $(top_builddir)/win32/vs14/$(1).vcxproj + -$(RM) $(top_builddir)/win32/vs14/$(1).vcxproj.filters + + + for F in $(_proj_files); do \ + case $$$$F in \ + $(_proj_filters)) \ + ;; \ + *.c|*.cpp|*.cc|*.cxx) \ + echo ' ' >>$(1).sourcefiles && \ + echo ' ' >>$(1).vs10.sourcefiles && \ + echo ' Source Files' >>$(1).vs10.sourcefiles.filters \ + ;; \ + esac; \ + done + + + $(CPP) -P - <$(top_srcdir)/win32/vs9/$(1).vcprojin >$(top_builddir)/win32/vs9/$(1).vcproj + $(CPP) -P - <$(top_srcdir)/win32/vs10/$(1).vcxprojin >$(top_builddir)/win32/vs10/$(1).vcxproj + $(CPP) -P - <$(top_srcdir)/win32/vs10/$(1).vcxproj.filtersin >$(top_builddir)/win32/vs10/$(1).vcxproj.filters + $(RM) $(1).sourcefiles + $(RM) $(1).vs10.sourcefiles + $(RM) $(1).vs10.sourcefiles.filters + +$(top_builddir)/win32/vs10/$(1).vs10.headers: $(top_builddir)/win32/vs9/$(1).headers + +$(top_builddir)/win32/vs9/$(1).headers: Makefile + -$(RM) $(top_builddir)/win32/vs9/$(1).headers + -$(RM) $(top_builddir)/win32/vs10/$(1).vs10.headers + + for F in $(_proj_headers); do \ + case $$$$F in \ + $(_proj_headers_excludes)) \ + ;; \ + *.h|*.hpp|*.hh|*.hxx) \ + echo 'copy ..\..'$(_proj_subdir)$$$$F' $$$$(CopyDir)\include'$(_headers_destdir)'\'$$$$F' ' >>$(top_builddir)/win32/vs9/$(1).headers && \ + echo 'copy ..\..'$(_proj_subdir)$$$$F' $$$$(CopyDir)\include'$(_headers_destdir)'\'$$$$F >>$(top_builddir)/win32/vs10/$(1).vs10.headers \ + ;; \ + esac; \ + done + +$(top_builddir)/win32/vs12/$(1).vcxproj.filters: $(top_builddir)/win32/vs12/$(1).vcxproj + +$(top_builddir)/win32/vs12/$(1).vcxproj: Makefile + -$(RM) $(top_builddir)/win32/vs14/$(1).vcxproj + -$(RM) $(top_builddir)/win32/vs14/$(1).vcxproj.filters + + for F in $(_proj_files); do \ + case $$$$F in \ + $(_proj_filters)) \ + ;; \ + *.c|*.cpp|*.cc|*.cxx) \ + echo ' ' >>$(1).vs12.sourcefiles && \ + echo ' Source Files' >>$(1).vs12.sourcefiles.filters \ + ;; \ + esac; \ + done + + $(CPP) -P - <$(top_srcdir)/win32/vs12/$(1).vcxprojin >$(top_builddir)/win32/vs12/$(1).vcxproj + $(CPP) -P - <$(top_srcdir)/win32/vs12/$(1).vcxproj.filtersin >$(top_builddir)/win32/vs12/$(1).vcxproj.filters + $(RM) $(1).vs12.sourcefiles + $(RM) $(1).vs12.sourcefiles.filters + +$(top_builddir)/win32/vs12/$(1).vs12.headers: Makefile + -$(RM) $(top_builddir)/win32/vs12/$(1).vs12.headers + + for F in $(_proj_headers); do \ + case $$$$F in \ + $(_proj_headers_excludes)) \ + ;; \ + *.h|*.hpp|*.hh|*.hxx) \ + echo 'copy ..\..'$(_proj_subdir)$$$$F' $$$$(CopyDir)\include'$(_headers_destdir)'\'$$$$F >>$(top_builddir)/win32/vs12/$(1).vs12.headers \ + ;; \ + esac; \ + done + +endef + +$(foreach proj,$(MSVCPROJS),$(eval $(call msvcproj-builder,$(proj)))) diff --git a/win32/SoupGNOME_2_4_gir_list b/win32/SoupGNOME_2_4_gir_list new file mode 100644 index 0000000..b5bab88 --- /dev/null +++ b/win32/SoupGNOME_2_4_gir_list @@ -0,0 +1,6 @@ +..\libsoup\soup-cookie-jar-sqlite.h +..\libsoup\soup-gnome-features.h +..\libsoup\soup-cookie-jar-sqlite.c +..\libsoup\soup-gnome-features.c +..\libsoup\soup-proxy-resolver-gnome.c +..\libsoup\soup-password-manager-gnome.c diff --git a/win32/Soup_2_4_gir_list b/win32/Soup_2_4_gir_list new file mode 100644 index 0000000..a382585 --- /dev/null +++ b/win32/Soup_2_4_gir_list @@ -0,0 +1,124 @@ +..\libsoup\soup-address.h +..\libsoup\soup-auth.h +..\libsoup\soup-auth-domain.h +..\libsoup\soup-auth-domain-basic.h +..\libsoup\soup-auth-domain-digest.h +..\libsoup\soup-auth-manager.h +..\libsoup\soup-autocleanups.h +..\libsoup\soup-cache.h +..\libsoup\soup-content-decoder.h +..\libsoup\soup-content-sniffer.h +..\libsoup\soup-cookie.h +..\libsoup\soup-cookie-jar.h +..\libsoup\soup-cookie-jar-db.h +..\libsoup\soup-cookie-jar-text.h +..\libsoup\soup-date.h +..\libsoup\soup-form.h +..\libsoup\soup-headers.h +..\libsoup\soup-logger.h +..\libsoup\soup-message.h +..\libsoup\soup-message-body.h +..\libsoup\soup-message-headers.h +..\libsoup\soup-method.h +..\libsoup\soup-misc.h +..\libsoup\soup-multipart.h +..\libsoup\soup-multipart-input-stream.h +..\libsoup\soup-password-manager.h +..\libsoup\soup-portability.h +..\libsoup\soup-proxy-resolver-default.h +..\libsoup\soup-proxy-uri-resolver.h +..\libsoup\soup-request.h +..\libsoup\soup-request-data.h +..\libsoup\soup-request-file.h +..\libsoup\soup-request-http.h +..\libsoup\soup-requester.h +..\libsoup\soup-server.h +..\libsoup\soup-session.h +..\libsoup\soup-session-async.h +..\libsoup\soup-session-feature.h +..\libsoup\soup-session-sync.h +..\libsoup\soup-socket.h +..\libsoup\soup-status.h +..\libsoup\soup-tld.h +..\libsoup\soup-types.h +..\libsoup\soup-uri.h +..\libsoup\soup-value-utils.h +..\libsoup\soup-websocket.h +..\libsoup\soup-websocket-connection.h +..\libsoup\soup-xmlrpc.h +..\libsoup\soup-xmlrpc-old.h +..\libsoup\soup-address.c +..\libsoup\soup-auth.c +..\libsoup\soup-auth-basic.c +..\libsoup\soup-auth-digest.c +..\libsoup\soup-auth-ntlm.c +..\libsoup\soup-auth-negotiate.c +..\libsoup\soup-auth-domain.c +..\libsoup\soup-auth-domain-basic.c +..\libsoup\soup-auth-domain-digest.c +..\libsoup\soup-auth-manager.c +..\libsoup\soup-body-input-stream.c +..\libsoup\soup-body-output-stream.c +..\libsoup\soup-cache.c +..\libsoup\soup-cache-client-input-stream.c +..\libsoup\soup-cache-input-stream.c +..\libsoup\soup-client-input-stream.c +..\libsoup\soup-connection.c +..\libsoup\soup-connection-auth.c +..\libsoup\soup-content-decoder.c +..\libsoup\soup-content-processor.c +..\libsoup\soup-content-sniffer.c +..\libsoup\soup-content-sniffer-stream.c +..\libsoup\soup-converter-wrapper.c +..\libsoup\soup-cookie.c +..\libsoup\soup-cookie-jar.c +..\libsoup\soup-cookie-jar-db.c +..\libsoup\soup-cookie-jar-text.c +..\libsoup\soup-date.c +..\libsoup\soup-directory-input-stream.c +..\libsoup\soup-filter-input-stream.c +..\libsoup\soup-form.c +..\libsoup\soup-headers.c +..\libsoup\soup-init.c +..\libsoup\soup-io-stream.c +..\libsoup\soup-logger.c +..\libsoup\soup-message.c +..\libsoup\soup-message-body.c +..\libsoup\soup-message-client-io.c +..\libsoup\soup-message-headers.c +..\libsoup\soup-message-io.c +..\libsoup\soup-message-queue.c +..\libsoup\soup-message-server-io.c +..\libsoup\soup-method.c +..\libsoup\soup-misc.c +..\libsoup\soup-multipart.c +..\libsoup\soup-multipart-input-stream.c +..\libsoup\soup-password-manager.c +..\libsoup\soup-path-map.c +..\libsoup\soup-proxy-resolver.c +..\libsoup\soup-proxy-resolver-default.c +..\libsoup\soup-proxy-resolver-wrapper.c +..\libsoup\soup-proxy-uri-resolver.c +..\libsoup\soup-request.c +..\libsoup\soup-request-data.c +..\libsoup\soup-request-file.c +..\libsoup\soup-request-http.c +..\libsoup\soup-requester.c +..\libsoup\soup-server.c +..\libsoup\soup-session.c +..\libsoup\soup-session-async.c +..\libsoup\soup-session-feature.c +..\libsoup\soup-session-sync.c +..\libsoup\soup-socket.c +..\libsoup\soup-socket-properties.c +..\libsoup\soup-status.c +..\libsoup\soup-tld.c +..\libsoup\soup-uri.c +..\libsoup\soup-value-utils.c +..\libsoup\soup-version.c +..\libsoup\soup-websocket.c +..\libsoup\soup-websocket-connection.c +..\libsoup\soup-xmlrpc.c +..\libsoup\soup-xmlrpc-old.c +..\libsoup\soup-enum-types.h +..\libsoup\soup-version.h diff --git a/win32/detectenv-msvc.mak b/win32/detectenv-msvc.mak new file mode 100644 index 0000000..6fd96cc --- /dev/null +++ b/win32/detectenv-msvc.mak @@ -0,0 +1,78 @@ +# Common NMake Makefile module for checking the build environment +# This can be copied from $(glib_srcroot)\build\win32 for GNOME items +# that support MSVC builds and introspection under MSVC, and can be used +# for building test programs as well. + +# Check to see we are configured to build with MSVC (MSDEVDIR, MSVCDIR or +# VCINSTALLDIR) or with the MS Platform SDK (MSSDK or WindowsSDKDir) +!if !defined(VCINSTALLDIR) && !defined(WINDOWSSDKDIR) +MSG = ^ +This Makefile is only for Visual Studio 2008 and later.^ +You need to ensure that the Visual Studio Environment is properly set up^ +before running this Makefile. +!error $(MSG) +!endif + +ERRNUL = 2>NUL +_HASH=^# + +!if ![echo VCVERSION=_MSC_VER > vercl.x] \ + && ![echo $(_HASH)if defined(_M_IX86) >> vercl.x] \ + && ![echo PLAT=Win32 >> vercl.x] \ + && ![echo $(_HASH)elif defined(_M_AMD64) >> vercl.x] \ + && ![echo PLAT=x64 >> vercl.x] \ + && ![echo $(_HASH)endif >> vercl.x] \ + && ![cl -nologo -TC -P vercl.x $(ERRNUL)] +!include vercl.i +!if ![echo VCVER= ^\> vercl.vc] \ + && ![set /a $(VCVERSION) / 100 - 6 >> vercl.vc] +!include vercl.vc +!endif +!endif +!if ![del $(ERRNUL) /q/f vercl.x vercl.i vercl.vc] +!endif + +!if $(VCVERSION) > 1499 && $(VCVERSION) < 1600 +VSVER = 9 +!elseif $(VCVERSION) > 1599 && $(VCVERSION) < 1700 +VSVER = 10 +!elseif $(VCVERSION) > 1699 && $(VCVERSION) < 1800 +VSVER = 11 +!elseif $(VCVERSION) > 1799 && $(VCVERSION) < 1900 +VSVER = 12 +!elseif $(VCVERSION) > 1899 && $(VCVERSION) < 1910 +VSVER = 14 +!elseif $(VCVERSION) > 1909 && $(VCVERSION) < 2000 +VSVER = 15 +!else +VSVER = 0 +!endif + +!if "$(VSVER)" == "0" +MSG = ^ +This NMake Makefile set supports Visual Studio^ +9 (2008) through 14 (2015). Your Visual Studio^ +version is not supported. +!error $(MSG) +!endif + +VALID_CFGSET = FALSE +!if "$(CFG)" == "release" || "$(CFG)" == "debug" || "$(CFG)" == "Release" || "$(CFG)" == "Debug" +VALID_CFGSET = TRUE +!endif + +# We want debugging symbols logged for all builds, +# using .pdb files for release builds +CFLAGS_BASE = /Zi + +!if "$(CFG)" == "release" || "$(CFG)" == "Release" +CFLAGS_ADD = /MD /O2 $(CFLAGS_BASE) +!else +CFLAGS_ADD = /MDd /Od $(CFLAGS_BASE) +!endif + +!if "$(PLAT)" == "x64" +LDFLAGS_ARCH = /machine:x64 +!else +LDFLAGS_ARCH = /machine:x86 +!endif diff --git a/win32/introspection-msvc.mak b/win32/introspection-msvc.mak new file mode 100644 index 0000000..26501f5 --- /dev/null +++ b/win32/introspection-msvc.mak @@ -0,0 +1,94 @@ +# Common NMake Makefile module for checking the build environment is sane +# for building introspection files under MSVC/NMake. +# This can be copied from $(gi_srcroot)\build\win32 for GNOME items +# that support MSVC builds and introspection under MSVC. + +# Can override with env vars as needed +# You will need to have built gobject-introspection for this to work. +# Change or pass in or set the following to suit your environment + +!if "$(PREFIX)" == "" +PREFIX = ..\..\vs$(VSVER)\$(PLAT) +!endif + +!if ![setlocal] && \ + ![set PFX=$(PREFIX)] && \ + ![for %P in (%PFX%) do @echo PREFIX_FULL=%~dpnfP > pfx.x] +!endif +!include pfx.x + +!if "$(PKG_CONFIG_PATH)" == "" +PKG_CONFIG_PATH=$(PREFIX_FULL)\lib\pkgconfig +!else +PKG_CONFIG_PATH=$(PREFIX_FULL)\lib\pkgconfig;$(PKG_CONFIG_PATH) +!endif + +!if ![del $(ERRNUL) /q/f pfx.x] +!endif + +# Note: The PYTHON must be the Python release series that was used to build +# the GObject-introspection scanner Python module! +# Either having python.exe your PATH will work or passing in +# PYTHON= will do + +# This is required, and gobject-introspection needs to be built +# before this can be successfully run. +!if "$(PYTHON)" == "" +PYTHON=python +!endif + +# Path to the pkg-config tool, if not already in the PATH +!if "$(PKG_CONFIG)" == "" +PKG_CONFIG=pkg-config +!endif + +# Don't change anything following this line! + +GIR_SUBDIR = share\gir-1.0 +GIR_TYPELIBDIR = lib\girepository-1.0 +G_IR_SCANNER = $(PREFIX)\bin\g-ir-scanner +G_IR_COMPILER = $(PREFIX)\bin\g-ir-compiler.exe +G_IR_INCLUDEDIR = $(PREFIX)\$(GIR_SUBDIR) +G_IR_TYPELIBDIR = $(PREFIX)\$(GIR_TYPELIBDIR) + +VALID_PKG_CONFIG_PATH = FALSE + +MSG_INVALID_PKGCONFIG = You must set or specifiy a valid PKG_CONFIG_PATH +MSG_INVALID_CFG = You need to specify or set CFG to be release or debug to use this Makefile to build the Introspection Files + +ERROR_MSG = + +BUILD_INTROSPECTION = TRUE + +!if ![set PKG_CONFIG_PATH=$(PKG_CONFIG_PATH)] \ + && ![$(PKG_CONFIG) --print-errors --errors-to-stdout $(CHECK_PACKAGE) > pkgconfig.x] \ + && ![setlocal] \ + && ![set file="pkgconfig.x"] \ + && ![FOR %A IN (%file%) DO @echo PKG_CHECK_SIZE=%~zA > pkgconfig.chksize] \ + && ![del $(ERRNUL) /q/f pkgconfig.x] +!endif + +!include pkgconfig.chksize +!if "$(PKG_CHECK_SIZE)" == "0" +VALID_PKG_CONFIG_PATH = TRUE +!else +VALID_PKG_CONFIG_PATH = FALSE +!endif + +!if ![del $(ERRNUL) /q/f pkgconfig.chksize] +!endif + +VALID_CFGSET = FALSE +!if "$(CFG)" == "release" || "$(CFG)" == "debug" || "$(CFG)" == "Release" || "$(CFG)" == "Debug" +VALID_CFGSET = TRUE +!endif + +!if "$(VALID_PKG_CONFIG_PATH)" != "TRUE" +BUILD_INTROSPECTION = FALSE +ERROR_MSG = $(MSG_INVALID_PKGCONFIG) +!endif + +!if "$(VALID_CFGSET)" != "TRUE" +BUILD_INTROSPECTION = FALSE +ERROR_MSG = $(MSG_INVALID_CFG) +!endif diff --git a/win32/introspection.body.mak b/win32/introspection.body.mak new file mode 100644 index 0000000..4bad419 --- /dev/null +++ b/win32/introspection.body.mak @@ -0,0 +1,54 @@ +Soup-2.4.gir: Soup_2_4_gir_list + @-echo Generating $@... + $(PYTHON) $(G_IR_SCANNER) \ + --verbose -no-libtool \ + --namespace=Soup \ + --nsversion=2.4 \ + \ + --library=soup-2.4 \ + \ + --add-include-path=$(G_IR_INCLUDEDIR) \ + --include=Gio-2.0 \ + --pkg-export=libsoup-2.4 \ + \ + --cflags-begin \ + -DG_LOG_DOMAIN="libsoup" -DLIBSOUP_COMPILATION -I.. -DLIBSOUP_USE_UNSTABLE_REQUEST_API \ + --cflags-end \ + --c-include "libsoup/soup.h" \ + --filelist=Soup_2_4_gir_list \ + -o $@ + +Soup-2.4.typelib: Soup-2.4.gir + @-echo Compiling $@... + $(G_IR_COMPILER) \ + --includedir=. --debug --verbose \ + Soup-2.4.gir \ + -o $@ + +SoupGNOME-2.4.gir: SoupGNOME_2_4_gir_list Soup-2.4.gir + @-echo Generating $@... + $(PYTHON) $(G_IR_SCANNER) \ + --verbose -no-libtool \ + --namespace=SoupGNOME \ + --nsversion=2.4 \ + \ + --library=soup-gnome-2.4 --library=soup-2.4 \ + \ + --add-include-path=$(G_IR_INCLUDEDIR) \ + \ + --pkg-export=libsoup-gnome-2.4 \ + \ + --cflags-begin \ + -DG_LOG_DOMAIN="libsoup" -DLIBSOUP_COMPILATION -I.. \ + --cflags-end \ + i --identifier-prefix=Soup --symbol-prefix=soup --c-include "libsoup/soup-gnome.h" --include-uninstalled=./Soup-2.4.gir \ + --filelist=SoupGNOME_2_4_gir_list \ + -o $@ + +SoupGNOME-2.4.typelib: SoupGNOME-2.4.gir + @-echo Compiling $@... + $(G_IR_COMPILER) \ + --includedir=. --debug --verbose \ + SoupGNOME-2.4.gir \ + -o $@ + diff --git a/win32/pc_base.py b/win32/pc_base.py new file mode 100644 index 0000000..f7976e8 --- /dev/null +++ b/win32/pc_base.py @@ -0,0 +1,124 @@ +#!/usr/bin/python +# +# Simple utility script to generate the basic info +# needed in a .pc (pkg-config) file, used especially +# for introspection purposes + +# This can be used in various projects where +# there is the need to generate .pc files, +# and is copied from GLib's $(srcroot)/win32 + +# Author: Fan, Chun-wei +# Date: March 10, 2016 + +import os +import sys +import argparse + +class BasePCItems: + def __init__(self): + self.base_replace_items = {} + self.exec_prefix = '' + self.includedir = '' + self.libdir = '' + self.prefix = '' + self.srcdir = os.path.dirname(__file__) + self.top_srcdir = self.srcdir + '\\..' + self.version = '' + + def setup(self, argv, parser=None): + if parser is None: + parser = argparse.ArgumentParser(description='Setup basic .pc file info') + parser.add_argument('--prefix', help='prefix of the installed library', + required=True) + parser.add_argument('--exec-prefix', + help='prefix of the installed programs, \ + if different from the prefix') + parser.add_argument('--includedir', + help='includedir of the installed library, \ + if different from ${prefix}/include') + parser.add_argument('--libdir', + help='libdir of the installed library, \ + if different from ${prefix}/lib') + parser.add_argument('--version', help='Version of the package', + required=True) + args = parser.parse_args() + + self.version = args.version + + # check whether the prefix and exec_prefix are valid + if not os.path.exists(args.prefix): + raise SystemExit('Specified prefix \'%s\' is invalid' % args.prefix) + + # use absolute paths for prefix + self.prefix = os.path.abspath(args.prefix).replace('\\','/') + + # check and setup the exec_prefix + if getattr(args, 'exec_prefix', None) is None: + exec_prefix_use_shorthand = True + self.exec_prefix = '${prefix}' + else: + if args.exec_prefix.startswith('${prefix}'): + exec_prefix_use_shorthand = True + input_exec_prefix = args.prefix + args.exec_prefix[len('${prefix}'):] + else: + exec_prefix_use_shorthand = False + input_exec_prefix = args.exec_prefix + if not os.path.exists(input_exec_prefix): + raise SystemExit('Specified exec_prefix \'%s\' is invalid' % + args.exec_prefix) + if exec_prefix_use_shorthand is True: + self.exec_prefix = args.exec_prefix.replace('\\','/') + else: + self.exec_prefix = os.path.abspath(input_exec_prefix).replace('\\','/') + + # check and setup the includedir + if getattr(args, 'includedir', None) is None: + self.includedir = '${prefix}/include' + else: + if args.includedir.startswith('${prefix}'): + includedir_use_shorthand = True + input_includedir = args.prefix + args.includedir[len('${prefix}'):] + else: + if args.includedir.startswith('${exec_prefix}'): + includedir_use_shorthand = True + input_includedir = input_exec_prefix + args.includedir[len('${exec_prefix}'):] + else: + includedir_use_shorthand = False + input_includedir = args.includedir + if not os.path.exists(input_includedir): + raise SystemExit('Specified includedir \'%s\' is invalid' % + args.includedir) + if includedir_use_shorthand is True: + self.includedir = args.includedir.replace('\\','/') + else: + self.includedir = os.path.abspath(input_includedir).replace('\\','/') + + # check and setup the libdir + if getattr(args, 'libdir', None) is None: + self.libdir = '${prefix}/lib' + else: + if args.libdir.startswith('${prefix}'): + libdir_use_shorthand = True + input_libdir = args.prefix + args.libdir[len('${prefix}'):] + else: + if args.libdir.startswith('${exec_prefix}'): + libdir_use_shorthand = True + input_libdir = input_exec_prefix + args.libdir[len('${exec_prefix}'):] + else: + libdir_use_shorthand = False + input_libdir = args.libdir + if not os.path.exists(input_libdir): + raise SystemExit('Specified libdir \'%s\' is invalid' % + args.libdir) + if libdir_use_shorthand is True: + self.libdir = args.libdir.replace('\\','/') + else: + self.libdir = os.path.abspath(input_libdir).replace('\\','/') + + # setup dictionary for replacing items in *.pc.in + self.base_replace_items.update({'@VERSION@': self.version}) + self.base_replace_items.update({'@prefix@': self.prefix}) + self.base_replace_items.update({'@exec_prefix@': self.exec_prefix}) + self.base_replace_items.update({'@libdir@': self.libdir}) + self.base_replace_items.update({'@includedir@': self.includedir}) diff --git a/win32/replace.py b/win32/replace.py new file mode 100644 index 0000000..3aeceb1 --- /dev/null +++ b/win32/replace.py @@ -0,0 +1,115 @@ +#!/usr/bin/python +# +# Simple utility script to manipulate +# certain types of strings in a file + +# This can be used in various projects where +# there is the need to replace strings in files, +# and is copied from GLib's $(srcroot)/win32 + +# Author: Fan, Chun-wei +# Date: September 03, 2014 + +import os +import sys +import re +import string +import argparse + +valid_actions = ['remove-prefix', + 'replace-var', + 'replace-str', + 'remove-str'] + +def open_file(filename, mode): + if sys.version_info[0] < 3: + return open(filename, mode=mode) + else: + return open(filename, mode=mode, encoding='utf-8') + +def replace_multi(src, dest, replace_items): + with open_file(src, 'r') as s: + with open_file(dest, 'w') as d: + for line in s: + replace_dict = dict((re.escape(key), value) \ + for key, value in replace_items.items()) + replace_pattern = re.compile("|".join(replace_dict.keys())) + d.write(replace_pattern.sub(lambda m: \ + replace_dict[re.escape(m.group(0))], line)) + +def replace(src, dest, instring, outstring): + replace_item = {instring: outstring} + replace_multi(src, dest, replace_item) + +def check_required_args(args, params): + for param in params: + if getattr(args, param, None) is None: + raise SystemExit('%s: error: --%s argument is required' % (__file__, param)) + +def warn_ignored_args(args, params): + for param in params: + if getattr(args, param, None) is not None: + print('%s: warning: --%s argument is ignored' % (__file__, param)) + +def main(argv): + + parser = argparse.ArgumentParser(description='Process strings in a file.') + parser.add_argument('-a', + '--action', + help='Action to carry out. Can be one of:\n' + 'remove-prefix\n' + 'replace-var\n' + 'replace-str\n' + 'remove-str', + choices=valid_actions) + parser.add_argument('-i', '--input', help='Input file') + parser.add_argument('-o', '--output', help='Output file') + parser.add_argument('--instring', help='String to replace or remove') + parser.add_argument('--var', help='Autotools variable name to replace') + parser.add_argument('--outstring', + help='New String to replace specified string or variable') + parser.add_argument('--removeprefix', help='Prefix of string to remove') + + args = parser.parse_args() + + input_string = '' + output_string = '' + + # We must have action, input, output for all operations + check_required_args(args, ['action','input','output']) + + # Build the arguments by the operation that is to be done, + # to be fed into replace() + + # Get rid of prefixes from a string + if args.action == 'remove-prefix': + check_required_args(args, ['instring','removeprefix']) + warn_ignored_args(args, ['outstring','var']) + input_string = args.removeprefix + args.instring + output_string = args.instring + + # Replace an m4-style variable (those surrounded by @...@) + if args.action == 'replace-var': + check_required_args(args, ['var','outstring']) + warn_ignored_args(args, ['instring','removeprefix']) + input_string = '@' + args.var + '@' + output_string = args.outstring + + # Replace a string + if args.action == 'replace-str': + check_required_args(args, ['instring','outstring']) + warn_ignored_args(args, ['var','removeprefix']) + input_string = args.instring + output_string = args.outstring + + # Remove a string + if args.action == 'remove-str': + check_required_args(args, ['instring']) + warn_ignored_args(args, ['var','outstring','removeprefix']) + input_string = args.instring + output_string = '' + + replace(args.input, args.output, input_string, output_string) + +if __name__ == '__main__': + sys.exit(main(sys.argv)) diff --git a/win32/soup-introspection-msvc.mak b/win32/soup-introspection-msvc.mak new file mode 100644 index 0000000..e1bbeb1 --- /dev/null +++ b/win32/soup-introspection-msvc.mak @@ -0,0 +1,37 @@ +# NMake Makefile to build Introspection Files for Pango + +!include detectenv-msvc.mak + +APIVERSION = 2.4 + +CHECK_PACKAGE = gio-2.0 + +!include introspection-msvc.mak + +!if "$(BUILD_INTROSPECTION)" == "TRUE" + +INTROSPECTION_TARGETS = Soup-$(APIVERSION).gir Soup-$(APIVERSION).typelib SoupGNOME-$(APIVERSION).gir SoupGNOME-$(APIVERSION).typelib + +all: setbuildenv $(INTROSPECTION_TARGETS) + +install-introspection: all + @-copy Soup-$(APIVERSION).gir $(G_IR_INCLUDEDIR) + @-copy /b Soup-$(APIVERSION).typelib $(G_IR_TYPELIBDIR) + @-copy SoupGNOME-$(APIVERSION).gir $(G_IR_INCLUDEDIR) + @-copy /b SoupGNOME-$(APIVERSION).typelib $(G_IR_TYPELIBDIR) + +setbuildenv: + @set PYTHONPATH=$(PREFIX)\lib\gobject-introspection + @set PATH=vs$(VSVER)\$(CFG)\$(PLAT)\bin;$(PREFIX)\bin;$(PATH) + @set PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) + @set LIB=vs$(VSVER)\$(CFG)\$(PLAT)\bin;$(PREFIX)\lib;$(LIB) + +!include introspection.body.mak + +!else +all: + @-echo $(ERROR_MSG) +!endif + +clean: + @-del /f/q $(INTROSPECTION_TARGETS) diff --git a/win32/soup_version_h.py b/win32/soup_version_h.py new file mode 100644 index 0000000..909db23 --- /dev/null +++ b/win32/soup_version_h.py @@ -0,0 +1,29 @@ +#!/usr/bin/python +# +# Simple utility script to generate soup-version.h + +import os +import sys +import argparse + +from replace import replace_multi + +def gen_version_h(argv): + top_srcdir = os.path.dirname(__file__) + "\\.." + parser = argparse.ArgumentParser(description='Generate soup-version.h') + parser.add_argument('--version', help='Version of the package', + required=True) + args = parser.parse_args() + version_info = args.version.split('.') + + version_h_replace_items = {'@SOUP_MAJOR_VERSION@': version_info[0], + '@SOUP_MINOR_VERSION@': version_info[1], + '@SOUP_MICRO_VERSION@': version_info[2]} + + # Generate soup-version.h + replace_multi(top_srcdir + '/libsoup/soup-version.h.in', + top_srcdir + '/libsoup/soup-version.h', + version_h_replace_items) + +if __name__ == '__main__': + sys.exit(gen_version_h(sys.argv)) \ No newline at end of file diff --git a/win32/souppc.py b/win32/souppc.py new file mode 100644 index 0000000..e5e85e8 --- /dev/null +++ b/win32/souppc.py @@ -0,0 +1,32 @@ +#!/usr/bin/python +# +# Utility script to generate .pc files for libsoup +# for Visual Studio builds, to be used for +# building introspection files + +# Author: Fan, Chun-wei +# Date: March 10, 2016 + +import os +import sys + +from replace import replace_multi +from pc_base import BasePCItems + +def main(argv): + base_pc = BasePCItems() + + base_pc.setup(argv) + + # Generate libsoup-2.4.pc + replace_multi(base_pc.top_srcdir + '/libsoup-2.4.pc.in', + base_pc.srcdir + '/libsoup-2.4.pc', + base_pc.base_replace_items) + + # Generate libsoup-gnome-2.4.pc + replace_multi(base_pc.top_srcdir + '/libsoup-gnome-2.4.pc.in', + base_pc.srcdir + '/libsoup-gnome-2.4.pc', + base_pc.base_replace_items) + +if __name__ == '__main__': + sys.exit(main(sys.argv)) diff --git a/win32/vs10/Makefile.am b/win32/vs10/Makefile.am new file mode 100644 index 0000000..78bd5f8 --- /dev/null +++ b/win32/vs10/Makefile.am @@ -0,0 +1,39 @@ +GENERATED_ITEMS = \ + soup.vcxproj \ + soup-gnome.vcxproj \ + soup.vcxproj.filters \ + soup-gnome.vcxproj.filters \ + soup-install.props + +MSVC_HEADERS_LIST = soup.vs10.headers soup-gnome.vs10.headers + +EXTRA_DIST = \ + libsoup.sln \ + get.vcxproj \ + simple-httpd.vcxproj \ + simple-proxy.vcxproj \ + soup-install.vcxproj \ + soup-install.vcxproj.filters \ + get.vcxproj.filters \ + simple-httpd.vcxproj.filters \ + simple-proxy.vcxproj.filters \ + soup-build-defines.props \ + soup-dll-build-defines.props \ + soup-gen-srcs.props \ + soup-version-paths.props \ + soup.vcxprojin \ + soup-gnome.vcxprojin \ + soup.vcxproj.filtersin \ + soup-gnome.vcxproj.filtersin \ + soup-install.propsin \ + $(GENERATED_ITEMS) + +soup-install.props: $(top_srcdir)/win32/vs10/soup-install.propsin $(MSVC_HEADERS_LIST) + -$(RM) $(top_builddir)/win32/vs11/soup-install.props + -$(RM) $(top_builddir)/win32/vs12/soup-install.props + -$(RM) $(top_builddir)/win32/vs14/soup-install.props + -$(RM) $(top_builddir)/win32/vs15/soup-install.props + $(CPP) -P - <$(top_srcdir)/win32/vs10/soup-install.propsin >$@ + rm $(MSVC_HEADERS_LIST) + +DISTCLEANFILES = $(GENERATED_ITEMS) diff --git a/win32/vs10/Makefile.in b/win32/vs10/Makefile.in new file mode 100644 index 0000000..21cd2ce --- /dev/null +++ b/win32/vs10/Makefile.in @@ -0,0 +1,564 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = win32/vs10 +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_code_coverage.m4 \ + $(top_srcdir)/m4/glibtests.m4 $(top_srcdir)/m4/gtk-doc.m4 \ + $(top_srcdir)/m4/intltool.m4 $(top_srcdir)/m4/introspection.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/vapigen.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = soup-version-paths.props +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +am__DIST_COMMON = $(srcdir)/Makefile.in \ + $(srcdir)/soup-version-paths.props.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALL_LINGUAS = @ALL_LINGUAS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +APACHE_HTTPD = @APACHE_HTTPD@ +APACHE_MODULE_DIR = @APACHE_MODULE_DIR@ +APACHE_PHP_MODULE_DIR = @APACHE_PHP_MODULE_DIR@ +APACHE_SSL_MODULE_DIR = @APACHE_SSL_MODULE_DIR@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CODE_COVERAGE_CFLAGS = @CODE_COVERAGE_CFLAGS@ +CODE_COVERAGE_CPPFLAGS = @CODE_COVERAGE_CPPFLAGS@ +CODE_COVERAGE_CXXFLAGS = @CODE_COVERAGE_CXXFLAGS@ +CODE_COVERAGE_ENABLED = @CODE_COVERAGE_ENABLED@ +CODE_COVERAGE_LDFLAGS = @CODE_COVERAGE_LDFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CURL = @CURL@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GCOV = @GCOV@ +GENHTML = @GENHTML@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_COMPILE_RESOURCES = @GLIB_COMPILE_RESOURCES@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MAKEFILE = @GLIB_MAKEFILE@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GMSGFMT = @GMSGFMT@ +GOBJECT_QUERY = @GOBJECT_QUERY@ +GREP = @GREP@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +HAVE_GNOME = @HAVE_GNOME@ +HTML_DIR = @HTML_DIR@ +IF_HAVE_MOD_UNIXD = @IF_HAVE_MOD_UNIXD@ +IF_HAVE_PHP = @IF_HAVE_PHP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ +INTLTOOL_MERGE = @INTLTOOL_MERGE@ +INTLTOOL_PERL = @INTLTOOL_PERL@ +INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ +INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@ +INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@ +INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@ +INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LCOV = @LCOV@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PHP = @PHP@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOUP_AGE = @SOUP_AGE@ +SOUP_API_VERSION = @SOUP_API_VERSION@ +SOUP_CURRENT = @SOUP_CURRENT@ +SOUP_DEBUG_FLAGS = @SOUP_DEBUG_FLAGS@ +SOUP_HIDDEN_VISIBILITY_CFLAGS = @SOUP_HIDDEN_VISIBILITY_CFLAGS@ +SOUP_MAJOR_VERSION = @SOUP_MAJOR_VERSION@ +SOUP_MICRO_VERSION = @SOUP_MICRO_VERSION@ +SOUP_MINOR_VERSION = @SOUP_MINOR_VERSION@ +SOUP_REVISION = @SOUP_REVISION@ +SQLITE_CFLAGS = @SQLITE_CFLAGS@ +SQLITE_LIBS = @SQLITE_LIBS@ +STRIP = @STRIP@ +USE_NLS = @USE_NLS@ +VALAC = @VALAC@ +VAPIDIR = @VAPIDIR@ +VAPIGEN = @VAPIGEN@ +VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@ +VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@ +VERSION = @VERSION@ +XGETTEXT = @XGETTEXT@ +XML_CFLAGS = @XML_CFLAGS@ +XML_LIBS = @XML_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +installed_test_metadir = @installed_test_metadir@ +installed_testdir = @installed_testdir@ +intltool__v_merge_options_ = @intltool__v_merge_options_@ +intltool__v_merge_options_0 = @intltool__v_merge_options_0@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +ntlm_auth = @ntlm_auth@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +GENERATED_ITEMS = \ + soup.vcxproj \ + soup-gnome.vcxproj \ + soup.vcxproj.filters \ + soup-gnome.vcxproj.filters \ + soup-install.props + +MSVC_HEADERS_LIST = soup.vs10.headers soup-gnome.vs10.headers +EXTRA_DIST = \ + libsoup.sln \ + get.vcxproj \ + simple-httpd.vcxproj \ + simple-proxy.vcxproj \ + soup-install.vcxproj \ + soup-install.vcxproj.filters \ + get.vcxproj.filters \ + simple-httpd.vcxproj.filters \ + simple-proxy.vcxproj.filters \ + soup-build-defines.props \ + soup-dll-build-defines.props \ + soup-gen-srcs.props \ + soup-version-paths.props \ + soup.vcxprojin \ + soup-gnome.vcxprojin \ + soup.vcxproj.filtersin \ + soup-gnome.vcxproj.filtersin \ + soup-install.propsin \ + $(GENERATED_ITEMS) + +DISTCLEANFILES = $(GENERATED_ITEMS) +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign win32/vs10/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign win32/vs10/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +soup-version-paths.props: $(top_builddir)/config.status $(srcdir)/soup-version-paths.props.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +tags TAGS: + +ctags CTAGS: + +cscope cscopelist: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic clean-libtool \ + cscopelist-am ctags-am distclean distclean-generic \ + distclean-libtool distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +soup-install.props: $(top_srcdir)/win32/vs10/soup-install.propsin $(MSVC_HEADERS_LIST) + -$(RM) $(top_builddir)/win32/vs11/soup-install.props + -$(RM) $(top_builddir)/win32/vs12/soup-install.props + -$(RM) $(top_builddir)/win32/vs14/soup-install.props + -$(RM) $(top_builddir)/win32/vs15/soup-install.props + $(CPP) -P - <$(top_srcdir)/win32/vs10/soup-install.propsin >$@ + rm $(MSVC_HEADERS_LIST) + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/win32/vs10/get.vcxproj b/win32/vs10/get.vcxproj new file mode 100644 index 0000000..1e2c09f --- /dev/null +++ b/win32/vs10/get.vcxproj @@ -0,0 +1,159 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {B24831C4-B8F2-41D6-AAF4-12192F71C623} + get + Win32Proj + + + + Application + Unicode + v100 + true + + + Application + Unicode + v100 + + + Application + Unicode + v100 + true + + + Application + Unicode + v100 + + + + + + + + + + + + + + + + + + + + + + true + false + + + Disabled + _DEBUG;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + EditAndContinue + + + true + Console + MachineX86 + + + + + MaxSpeed + true + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + true + Console + true + true + MachineX86 + + + + + X64 + + + Disabled + _DEBUG;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + ProgramDatabase + + + true + Console + MachineX64 + + + + + X64 + + + MaxSpeed + true + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + true + Console + true + true + MachineX64 + + + + + + + + {d83a3162-b14c-459c-af81-15bbfa90240d} + false + + + + + + diff --git a/win32/vs10/get.vcxproj.filters b/win32/vs10/get.vcxproj.filters new file mode 100644 index 0000000..9bc6fcf --- /dev/null +++ b/win32/vs10/get.vcxproj.filters @@ -0,0 +1,17 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav + + + Sources + + diff --git a/win32/vs10/libsoup.sln b/win32/vs10/libsoup.sln new file mode 100644 index 0000000..10d7824 --- /dev/null +++ b/win32/vs10/libsoup.sln @@ -0,0 +1,128 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "soup", "soup.vcxproj", "{D83A3162-B14C-459C-AF81-15BBFA90240D}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "soup-gnome", "soup-gnome.vcxproj", "{8C88A385-28C8-4B30-91A4-FBA381A5A46F}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "get", "get.vcxproj", "{B24831C4-B8F2-41D6-AAF4-12192F71C623}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "simple-httpd", "simple-httpd.vcxproj", "{80DC062E-2146-4CE8-A448-FD2205AB2CA4}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "simple-proxy", "simple-proxy.vcxproj", "{3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "soup-install", "soup-install.vcxproj", "{E0DCF460-914F-46F9-94D6-86D456CB53E9}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + Debug_MIT_GSSAPI|Win32 = Debug_MIT_GSSAPI|Win32 + Debug_MIT_GSSAPI|x64 = Debug_MIT_GSSAPI|x64 + Release_MIT_GSSAPI|Win32 = Release_MIT_GSSAPI|Win32 + Release_MIT_GSSAPI|x64 = Release_MIT_GSSAPI|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Debug|Win32.ActiveCfg = Debug|Win32 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Debug|Win32.Build.0 = Debug|Win32 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Debug|x64.ActiveCfg = Debug|x64 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Debug|x64.Build.0 = Debug|x64 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Release|Win32.ActiveCfg = Release|Win32 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Release|Win32.Build.0 = Release|Win32 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Release|x64.ActiveCfg = Release|x64 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Release|x64.Build.0 = Release|x64 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Debug_MIT_GSSAPI|Win32.ActiveCfg = Debug_MIT_GSSAPI|Win32 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Debug_MIT_GSSAPI|Win32.Build.0 = Debug_MIT_GSSAPI|Win32 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Debug_MIT_GSSAPI|x64.ActiveCfg = Debug_MIT_GSSAPI|x64 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Debug_MIT_GSSAPI|x64.Build.0 = Debug_MIT_GSSAPI|x64 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Release_MIT_GSSAPI|Win32.ActiveCfg = Release_MIT_GSSAPI|Win32 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Release_MIT_GSSAPI|Win32.Build.0 = Release_MIT_GSSAPI|Win32 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Release_MIT_GSSAPI|x64.ActiveCfg = Release_MIT_GSSAPI|x64 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Release_MIT_GSSAPI|x64.Build.0 = Release_MIT_GSSAPI|x64 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Debug|Win32.ActiveCfg = Debug|Win32 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Debug|Win32.Build.0 = Debug|Win32 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Debug|x64.ActiveCfg = Debug|x64 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Debug|x64.Build.0 = Debug|x64 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Release|Win32.ActiveCfg = Release|Win32 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Release|Win32.Build.0 = Release|Win32 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Release|x64.ActiveCfg = Release|x64 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Release|x64.Build.0 = Release|x64 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Debug_MIT_GSSAPI|Win32.ActiveCfg = Debug|Win32 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Debug_MIT_GSSAPI|Win32.Build.0 = Debug|Win32 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Debug_MIT_GSSAPI|x64.ActiveCfg = Debug|x64 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Debug_MIT_GSSAPI|x64.Build.0 = Debug|x64 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Release_MIT_GSSAPI|Win32.ActiveCfg = Release|Win32 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Release_MIT_GSSAPI|Win32.Build.0 = Release|Win32 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Release_MIT_GSSAPI|x64.ActiveCfg = Release|x64 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Release_MIT_GSSAPI|x64.Build.0 = Release|x64 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Debug|Win32.ActiveCfg = Debug|Win32 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Debug|Win32.Build.0 = Debug|Win32 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Debug|x64.ActiveCfg = Debug|x64 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Debug|x64.Build.0 = Debug|x64 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Release|Win32.ActiveCfg = Release|Win32 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Release|Win32.Build.0 = Release|Win32 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Release|x64.ActiveCfg = Release|x64 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Release|x64.Build.0 = Release|x64 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Debug_MIT_GSSAPI|Win32.ActiveCfg = Debug|Win32 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Debug_MIT_GSSAPI|Win32.Build.0 = Debug|Win32 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Debug_MIT_GSSAPI|x64.ActiveCfg = Debug|x64 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Debug_MIT_GSSAPI|x64.Build.0 = Debug|x64 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Release_MIT_GSSAPI|Win32.ActiveCfg = Release|Win32 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Release_MIT_GSSAPI|Win32.Build.0 = Release|Win32 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Release_MIT_GSSAPI|x64.ActiveCfg = Release|x64 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Release_MIT_GSSAPI|x64.Build.0 = Release|x64 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Debug|Win32.ActiveCfg = Debug|Win32 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Debug|Win32.Build.0 = Debug|Win32 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Debug|x64.ActiveCfg = Debug|x64 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Debug|x64.Build.0 = Debug|x64 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Release|Win32.ActiveCfg = Release|Win32 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Release|Win32.Build.0 = Release|Win32 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Release|x64.ActiveCfg = Release|x64 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Release|x64.Build.0 = Release|x64 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Debug_MIT_GSSAPI|Win32.ActiveCfg = Debug|Win32 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Debug_MIT_GSSAPI|Win32.Build.0 = Debug|Win32 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Debug_MIT_GSSAPI|x64.ActiveCfg = Debug|x64 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Debug_MIT_GSSAPI|x64.Build.0 = Debug|x64 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Release_MIT_GSSAPI|Win32.ActiveCfg = Release|Win32 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Release_MIT_GSSAPI|Win32.Build.0 = Release|Win32 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Release_MIT_GSSAPI|x64.ActiveCfg = Release|x64 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Release_MIT_GSSAPI|x64.Build.0 = Release|x64 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Debug|Win32.ActiveCfg = Debug|Win32 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Debug|Win32.Build.0 = Debug|Win32 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Debug|x64.ActiveCfg = Debug|x64 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Debug|x64.Build.0 = Debug|x64 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Release|Win32.ActiveCfg = Release|Win32 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Release|Win32.Build.0 = Release|Win32 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Release|x64.ActiveCfg = Release|x64 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Release|x64.Build.0 = Release|x64 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Debug_MIT_GSSAPI|Win32.ActiveCfg = Debug|Win32 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Debug_MIT_GSSAPI|Win32.Build.0 = Debug|Win32 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Debug_MIT_GSSAPI|x64.ActiveCfg = Debug|x64 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Debug_MIT_GSSAPI|x64.Build.0 = Debug|x64 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Release_MIT_GSSAPI|Win32.ActiveCfg = Release|Win32 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Release_MIT_GSSAPI|Win32.Build.0 = Release|Win32 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Release_MIT_GSSAPI|x64.ActiveCfg = Release|x64 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Release_MIT_GSSAPI|x64.Build.0 = Release|x64 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Debug|Win32.ActiveCfg = Debug|Win32 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Debug|Win32.Build.0 = Debug|Win32 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Debug|x64.ActiveCfg = Debug|x64 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Debug|x64.Build.0 = Debug|x64 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Release|Win32.ActiveCfg = Release|Win32 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Release|Win32.Build.0 = Release|Win32 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Release|x64.ActiveCfg = Release|x64 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Release|x64.Build.0 = Release|x64 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Debug_MIT_GSSAPI|Win32.ActiveCfg = Debug|Win32 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Debug_MIT_GSSAPI|Win32.Build.0 = Debug|Win32 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Debug_MIT_GSSAPI|x64.ActiveCfg = Debug|x64 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Debug_MIT_GSSAPI|x64.Build.0 = Debug|x64 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Release_MIT_GSSAPI|Win32.ActiveCfg = Release|Win32 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Release_MIT_GSSAPI|Win32.Build.0 = Release|Win32 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Release_MIT_GSSAPI|x64.ActiveCfg = Release|x64 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Release_MIT_GSSAPI|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/win32/vs10/simple-httpd.vcxproj b/win32/vs10/simple-httpd.vcxproj new file mode 100644 index 0000000..e381703 --- /dev/null +++ b/win32/vs10/simple-httpd.vcxproj @@ -0,0 +1,159 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {80DC062E-2146-4CE8-A448-FD2205AB2CA4} + simplehttpd + Win32Proj + + + + Application + Unicode + v100 + true + + + Application + Unicode + v100 + + + Application + Unicode + v100 + true + + + Application + Unicode + v100 + + + + + + + + + + + + + + + + + + + + + + true + false + + + Disabled + _DEBUG;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + EditAndContinue + + + true + Console + MachineX86 + + + + + MaxSpeed + true + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + true + Console + true + true + MachineX86 + + + + + X64 + + + Disabled + _DEBUG;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + ProgramDatabase + + + true + Console + MachineX64 + + + + + X64 + + + MaxSpeed + true + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + true + Console + true + true + MachineX64 + + + + + + + + {d83a3162-b14c-459c-af81-15bbfa90240d} + false + + + + + + diff --git a/win32/vs10/simple-httpd.vcxproj.filters b/win32/vs10/simple-httpd.vcxproj.filters new file mode 100644 index 0000000..14cf1d4 --- /dev/null +++ b/win32/vs10/simple-httpd.vcxproj.filters @@ -0,0 +1,17 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav + + + Sources + + diff --git a/win32/vs10/simple-proxy.vcxproj b/win32/vs10/simple-proxy.vcxproj new file mode 100644 index 0000000..8d5f2d3 --- /dev/null +++ b/win32/vs10/simple-proxy.vcxproj @@ -0,0 +1,159 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E} + simpleproxy + Win32Proj + + + + Application + Unicode + v100 + true + + + Application + Unicode + v100 + + + Application + Unicode + v100 + true + + + Application + Unicode + v100 + + + + + + + + + + + + + + + + + + + + + + true + false + + + Disabled + _DEBUG;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + EditAndContinue + + + true + Console + MachineX86 + + + + + MaxSpeed + true + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + true + Console + true + true + MachineX86 + + + + + X64 + + + Disabled + _DEBUG;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + ProgramDatabase + + + true + Console + MachineX64 + + + + + X64 + + + MaxSpeed + true + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + true + Console + true + true + MachineX64 + + + + + + + + {d83a3162-b14c-459c-af81-15bbfa90240d} + false + + + + + + diff --git a/win32/vs10/simple-proxy.vcxproj.filters b/win32/vs10/simple-proxy.vcxproj.filters new file mode 100644 index 0000000..4a7f2f2 --- /dev/null +++ b/win32/vs10/simple-proxy.vcxproj.filters @@ -0,0 +1,17 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav + + + Sources + + diff --git a/win32/vs10/soup-build-defines.props b/win32/vs10/soup-build-defines.props new file mode 100644 index 0000000..0c9b527 --- /dev/null +++ b/win32/vs10/soup-build-defines.props @@ -0,0 +1,29 @@ + + + + + + + + <_PropertySheetDisplayName>soupbuilddefinesprops + $(SolutionDir)$(Configuration)\$(PlatformName)\bin\ + $(SolutionDir)$(Configuration)\$(PlatformName)\obj\$(ProjectName)\ + + + + ..\..;$(GlibEtcInstallRoot)\include\gio-win32-2.0;$(GlibEtcInstallRoot)\include\glib-2.0;$(GlibEtcInstallRoot)\lib\glib-2.0\include;$(GlibEtcInstallRoot)\include\libxml2;$(GlibEtcInstallRoot)\include;%(AdditionalIncludeDirectories) + HAVE_CONFIG_H;%(PreprocessorDefinitions) + msvc_recommended_pragmas.h;%(ForcedIncludeFiles) + true + /d2Zi+ %(AdditionalOptions) + + + gio-2.0.lib;gobject-2.0.lib;glib-2.0.lib;%(AdditionalDependencies) + $(GlibEtcInstallRoot)\lib;%(AdditionalLibraryDirectories) + /HIGHENTROPYVA %(AdditionalOptions) + /HIGHENTROPYVA %(AdditionalOptions) + /HIGHENTROPYVA %(AdditionalOptions) + /HIGHENTROPYVA %(AdditionalOptions) + + + diff --git a/win32/vs10/soup-dll-build-defines.props b/win32/vs10/soup-dll-build-defines.props new file mode 100644 index 0000000..40591ff --- /dev/null +++ b/win32/vs10/soup-dll-build-defines.props @@ -0,0 +1,24 @@ + + + + + + + LIBSOUP_COMPILATION;DLL_EXPORT;G_LOG_DOMAIN="libsoup" + LIBSOUP_HAVE_GSSAPI + libxml2.lib;sqlite3.lib;intl.lib;ws2_32.lib + gssapi + 32.lib + 64.lib + + + <_PropertySheetDisplayName>soupdllbuilddefinesprops + + + + $(OutDir)$(SoupDllPrefix)$(ProjectName)$(SoupDllSuffix).dll + $(OutDir)$(SoupDllPrefix)$(ProjectName)$(SoupDllSuffix).pdb + $(OutDir)$(ProjectName)-$(ApiVersion).lib + + + diff --git a/win32/vs10/soup-gen-srcs.props b/win32/vs10/soup-gen-srcs.props new file mode 100644 index 0000000..760825c --- /dev/null +++ b/win32/vs10/soup-gen-srcs.props @@ -0,0 +1,26 @@ + + + + + + + copy ..\..\config.h.win32 ..\..\config.h + $(PythonPath)\python.exe ..\soup_version_h.py --version=$(SoupMajorVersion).$(SoupMinorVersion).$(SoupMicroVersion) + $(PythonPath)\python.exe ..\..\libsoup\tld-parser.py ..\..\data\effective_tld_names.dat ..\..\libsoup\tld_data.inc + + + <_PropertySheetDisplayName>soupgensrcsprops + + + + + $(CopyConfigH) + + + $(GenSoupVersionH) + + + $(GenTldDataInc) + + + diff --git a/win32/vs10/soup-gnome.vcxproj b/win32/vs10/soup-gnome.vcxproj new file mode 100644 index 0000000..1212aa6 --- /dev/null +++ b/win32/vs10/soup-gnome.vcxproj @@ -0,0 +1,164 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {8C88A385-28C8-4B30-91A4-FBA381A5A46F} + soupgnome + Win32Proj + + + + DynamicLibrary + Unicode + v100 + true + + + DynamicLibrary + Unicode + v100 + + + DynamicLibrary + Unicode + v100 + true + + + DynamicLibrary + Unicode + v100 + + + + + + + + + + + + + + + + + + + + + + true + false + + + Disabled + _DEBUG;$(SoupBuildDefines);%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + EditAndContinue + + + true + Windows + MachineX86 + + + + + MaxSpeed + true + $(SoupBuildDefines);%(PreprocessorDefinitions) + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + true + Windows + true + true + MachineX86 + + + + + X64 + + + Disabled + _DEBUG;$(SoupBuildDefines);%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + ProgramDatabase + + + true + Windows + MachineX64 + + + + + X64 + + + MaxSpeed + true + $(SoupBuildDefines);%(PreprocessorDefinitions) + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + true + Windows + true + true + MachineX64 + + + + + + + + + + + {d83a3162-b14c-459c-af81-15bbfa90240d} + false + + + + + + diff --git a/win32/vs10/soup-gnome.vcxproj.filters b/win32/vs10/soup-gnome.vcxproj.filters new file mode 100644 index 0000000..924bf66 --- /dev/null +++ b/win32/vs10/soup-gnome.vcxproj.filters @@ -0,0 +1,20 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav + + + Source Files + Source Files + Source Files + Source Files + + diff --git a/win32/vs10/soup-gnome.vcxproj.filtersin b/win32/vs10/soup-gnome.vcxproj.filtersin new file mode 100644 index 0000000..e6131d6 --- /dev/null +++ b/win32/vs10/soup-gnome.vcxproj.filtersin @@ -0,0 +1,17 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav + + +#include "soup-gnome.vs10.sourcefiles.filters" + + diff --git a/win32/vs10/soup-gnome.vcxprojin b/win32/vs10/soup-gnome.vcxprojin new file mode 100644 index 0000000..1fdc998 --- /dev/null +++ b/win32/vs10/soup-gnome.vcxprojin @@ -0,0 +1,161 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {8C88A385-28C8-4B30-91A4-FBA381A5A46F} + soupgnome + Win32Proj + + + + DynamicLibrary + Unicode + v100 + true + + + DynamicLibrary + Unicode + v100 + + + DynamicLibrary + Unicode + v100 + true + + + DynamicLibrary + Unicode + v100 + + + + + + + + + + + + + + + + + + + + + + true + false + + + Disabled + _DEBUG;$(SoupBuildDefines);%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + EditAndContinue + + + true + Windows + MachineX86 + + + + + MaxSpeed + true + $(SoupBuildDefines);%(PreprocessorDefinitions) + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + true + Windows + true + true + MachineX86 + + + + + X64 + + + Disabled + _DEBUG;$(SoupBuildDefines);%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + ProgramDatabase + + + true + Windows + MachineX64 + + + + + X64 + + + MaxSpeed + true + $(SoupBuildDefines);%(PreprocessorDefinitions) + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + true + Windows + true + true + MachineX64 + + + +#include "soup-gnome.vs10.sourcefiles" + + + + {d83a3162-b14c-459c-af81-15bbfa90240d} + false + + + + + + diff --git a/win32/vs10/soup-install.props b/win32/vs10/soup-install.props new file mode 100644 index 0000000..fb3240e --- /dev/null +++ b/win32/vs10/soup-install.props @@ -0,0 +1,101 @@ + + + + + + + +mkdir $(CopyDir)\bin +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\$(SoupDllPrefix)soup$(SoupDllSuffix).dll $(CopyDir)\bin +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\$(SoupDllPrefix)soup$(SoupDllSuffix).pdb $(CopyDir)\bin +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\$(SoupDllPrefix)soup-gnome$(SoupDllSuffix).dll $(CopyDir)\bin +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\$(SoupDllPrefix)soup-gnome$(SoupDllSuffix).pdb $(CopyDir)\bin +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\get.exe $(CopyDir)\bin +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\get.pdb $(CopyDir)\bin +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\simple-httpd.exe $(CopyDir)\bin +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\simple-httpd.pdb $(CopyDir)\bin +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\simple-proxy.exe $(CopyDir)\bin +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\simple-proxy.pdb $(CopyDir)\bin +mkdir $(CopyDir)\lib +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\soup-$(ApiVersion).lib $(CopyDir)\lib +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\soup-gnome-$(ApiVersion).lib $(CopyDir)\lib +copy ..\libsoup-$(ApiVersion).pc $(CopyDir)\lib\pkgconfig +copy ..\libsoup-gnome-$(ApiVersion).pc $(CopyDir)\lib\pkgconfig +mkdir $(CopyDir)\include\libsoup-$(ApiVersion)\libsoup +copy ..\..\libsoup\soup.h $(CopyDir)\include\libsoup-2.4\libsoup\soup.h +copy ..\..\libsoup\soup-address.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-address.h +copy ..\..\libsoup\soup-auth.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-auth.h +copy ..\..\libsoup\soup-auth-domain.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-auth-domain.h +copy ..\..\libsoup\soup-auth-domain-basic.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-auth-domain-basic.h +copy ..\..\libsoup\soup-auth-domain-digest.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-auth-domain-digest.h +copy ..\..\libsoup\soup-auth-manager.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-auth-manager.h +copy ..\..\libsoup\soup-autocleanups.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-autocleanups.h +copy ..\..\libsoup\soup-cache.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-cache.h +copy ..\..\libsoup\soup-content-decoder.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-content-decoder.h +copy ..\..\libsoup\soup-content-sniffer.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-content-sniffer.h +copy ..\..\libsoup\soup-cookie.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-cookie.h +copy ..\..\libsoup\soup-cookie-jar.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-cookie-jar.h +copy ..\..\libsoup\soup-cookie-jar-db.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-cookie-jar-db.h +copy ..\..\libsoup\soup-cookie-jar-text.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-cookie-jar-text.h +copy ..\..\libsoup\soup-date.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-date.h +copy ..\..\libsoup\soup-form.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-form.h +copy ..\..\libsoup\soup-headers.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-headers.h +copy ..\..\libsoup\soup-logger.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-logger.h +copy ..\..\libsoup\soup-message.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-message.h +copy ..\..\libsoup\soup-message-body.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-message-body.h +copy ..\..\libsoup\soup-message-headers.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-message-headers.h +copy ..\..\libsoup\soup-method.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-method.h +copy ..\..\libsoup\soup-misc.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-misc.h +copy ..\..\libsoup\soup-multipart.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-multipart.h +copy ..\..\libsoup\soup-multipart-input-stream.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-multipart-input-stream.h +copy ..\..\libsoup\soup-password-manager.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-password-manager.h +copy ..\..\libsoup\soup-portability.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-portability.h +copy ..\..\libsoup\soup-proxy-resolver.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-proxy-resolver.h +copy ..\..\libsoup\soup-proxy-resolver-default.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-proxy-resolver-default.h +copy ..\..\libsoup\soup-proxy-uri-resolver.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-proxy-uri-resolver.h +copy ..\..\libsoup\soup-request.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-request.h +copy ..\..\libsoup\soup-request-data.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-request-data.h +copy ..\..\libsoup\soup-request-file.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-request-file.h +copy ..\..\libsoup\soup-request-http.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-request-http.h +copy ..\..\libsoup\soup-requester.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-requester.h +copy ..\..\libsoup\soup-server.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-server.h +copy ..\..\libsoup\soup-session.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-session.h +copy ..\..\libsoup\soup-session-async.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-session-async.h +copy ..\..\libsoup\soup-session-feature.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-session-feature.h +copy ..\..\libsoup\soup-session-sync.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-session-sync.h +copy ..\..\libsoup\soup-socket.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-socket.h +copy ..\..\libsoup\soup-status.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-status.h +copy ..\..\libsoup\soup-tld.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-tld.h +copy ..\..\libsoup\soup-types.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-types.h +copy ..\..\libsoup\soup-uri.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-uri.h +copy ..\..\libsoup\soup-value-utils.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-value-utils.h +copy ..\..\libsoup\soup-websocket.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-websocket.h +copy ..\..\libsoup\soup-websocket-connection.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-websocket-connection.h +copy ..\..\libsoup\soup-xmlrpc.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-xmlrpc.h +copy ..\..\libsoup\soup-xmlrpc-old.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-xmlrpc-old.h +copy ..\..\libsoup\soup-enum-types.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-enum-types.h +copy ..\..\libsoup\soup-version.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-version.h +mkdir $(CopyDir)\include\libsoup-gnome-$(ApiVersion)\libsoup +copy ..\..\libsoup\soup-cookie-jar-sqlite.h $(CopyDir)\include\libsoup-gnome-2.4\libsoup\soup-cookie-jar-sqlite.h +copy ..\..\libsoup\soup-gnome.h $(CopyDir)\include\libsoup-gnome-2.4\libsoup\soup-gnome.h +copy ..\..\libsoup\soup-gnome-features.h $(CopyDir)\include\libsoup-gnome-2.4\libsoup\soup-gnome-features.h + + ..\libsoup-$(ApiVersion).pc;..\libsoup-gnome-$(ApiVersion).pc + (if not exist $(CopyDir)\lib\pkgconfig mkdir $(CopyDir)\lib\pkgconfig) & ($(PythonPath)\python.exe ..\souppc.py --prefix=$(CopyDir) --version=$(SoupMajorVersion).$(SoupMinorVersion).$(SoupMicroVersion)) + + + <_PropertySheetDisplayName>soupinstallprops + + + + + $(SoupDoInstall) + + + $(SoupPCFiles) + + + $(SoupGenPC) + + + diff --git a/win32/vs10/soup-install.propsin b/win32/vs10/soup-install.propsin new file mode 100644 index 0000000..1160892 --- /dev/null +++ b/win32/vs10/soup-install.propsin @@ -0,0 +1,51 @@ + + + + + + + +mkdir $(CopyDir)\bin + +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\$(SoupDllPrefix)soup$(SoupDllSuffix).dll $(CopyDir)\bin +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\$(SoupDllPrefix)soup$(SoupDllSuffix).pdb $(CopyDir)\bin +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\$(SoupDllPrefix)soup-gnome$(SoupDllSuffix).dll $(CopyDir)\bin +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\$(SoupDllPrefix)soup-gnome$(SoupDllSuffix).pdb $(CopyDir)\bin +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\get.exe $(CopyDir)\bin +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\get.pdb $(CopyDir)\bin +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\simple-httpd.exe $(CopyDir)\bin +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\simple-httpd.pdb $(CopyDir)\bin +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\simple-proxy.exe $(CopyDir)\bin +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\simple-proxy.pdb $(CopyDir)\bin + +mkdir $(CopyDir)\lib +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\soup-$(ApiVersion).lib $(CopyDir)\lib +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\soup-gnome-$(ApiVersion).lib $(CopyDir)\lib +copy ..\libsoup-$(ApiVersion).pc $(CopyDir)\lib\pkgconfig +copy ..\libsoup-gnome-$(ApiVersion).pc $(CopyDir)\lib\pkgconfig + +mkdir $(CopyDir)\include\libsoup-$(ApiVersion)\libsoup +#include "soup.vs10.headers" + +mkdir $(CopyDir)\include\libsoup-gnome-$(ApiVersion)\libsoup +#include "soup-gnome.vs10.headers" + + ..\libsoup-$(ApiVersion).pc;..\libsoup-gnome-$(ApiVersion).pc + (if not exist $(CopyDir)\lib\pkgconfig mkdir $(CopyDir)\lib\pkgconfig) & ($(PythonPath)\python.exe ..\souppc.py --prefix=$(CopyDir) --version=$(SoupMajorVersion).$(SoupMinorVersion).$(SoupMicroVersion)) + + + <_PropertySheetDisplayName>soupinstallprops + + + + + $(SoupDoInstall) + + + $(SoupPCFiles) + + + $(SoupGenPC) + + + diff --git a/win32/vs10/soup-install.vcxproj b/win32/vs10/soup-install.vcxproj new file mode 100644 index 0000000..07da506 --- /dev/null +++ b/win32/vs10/soup-install.vcxproj @@ -0,0 +1,121 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {E0DCF460-914F-46F9-94D6-86D456CB53E9} + soupinstall + + + + Utility + MultiByte + v100 + true + + + Utility + MultiByte + v100 + + + Utility + MultiByte + v100 + true + + + Utility + MultiByte + v100 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Copying build results... + $(SoupPCFiles) + $(SoupDoInstall) + some_file;%(Outputs) + Copying build results... + $(SoupPCFiles) + $(SoupDoInstall) + some_file;%(Outputs) + + + Generating .pc files... + $(SoupGenPC) + $(SoupPCFiles);%(Outputs) + Generating .pc files... + $(SoupGenPC) + $(SoupPCFiles);%(Outputs) + + + + + {b24831c4-b8f2-41d6-aaf4-12192f71c623} + false + + + {80dc062e-2146-4ce8-a448-fd2205ab2ca4} + false + + + {3ad0cb92-ee38-425e-83cb-e7b1cb1d305e} + false + + + {8c88a385-28c8-4b30-91a4-fba381a5a46f} + false + + + {d83a3162-b14c-459c-af81-15bbfa90240d} + false + + + + + + diff --git a/win32/vs10/soup-install.vcxproj.filters b/win32/vs10/soup-install.vcxproj.filters new file mode 100644 index 0000000..2627f42 --- /dev/null +++ b/win32/vs10/soup-install.vcxproj.filters @@ -0,0 +1,13 @@ + + + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav + + + + Resource Files + Resource Files + + diff --git a/win32/vs10/soup-version-paths.props b/win32/vs10/soup-version-paths.props new file mode 100644 index 0000000..d43c019 --- /dev/null +++ b/win32/vs10/soup-version-paths.props @@ -0,0 +1,69 @@ + + + + + + 10 + ..\..\..\vs$(VSVer)\$(Platform) + $(GlibEtcInstallRoot) + 2 + 62 + 3 + 2.4 + lib + -$(ApiVersion)-0 + + -$(ApiVersion)-vs$(VSVer) + $(SoupSeparateVSDllPrefix) + $(SoupSeparateVSDllSuffix) + c:\python34 + + + <_PropertySheetDisplayName>soupversionpathsprops + + + + + $(VSVer) + + + $(GlibEtcInstallRoot) + + + $(CopyDir) + + + $(SoupMajorVersion) + + + $(SoupMinorVersion) + + + $(SoupMicroVersion) + + + $(ApiVersion) + + + $(SoupLibtoolCompatibleDllPrefix) + + + $(SoupLibtoolCompatibleDllSuffix) + + + $(SoupSeparateVSDllPrefix) + + + $(SoupSeparateVSDllSuffix) + + + $(SoupDllPrefix) + + + $(SoupDllSuffix) + + + $(PythonPath) + + + diff --git a/win32/vs10/soup-version-paths.props.in b/win32/vs10/soup-version-paths.props.in new file mode 100644 index 0000000..7b259ce --- /dev/null +++ b/win32/vs10/soup-version-paths.props.in @@ -0,0 +1,69 @@ + + + + + + 10 + ..\..\..\vs$(VSVer)\$(Platform) + $(GlibEtcInstallRoot) + @SOUP_MAJOR_VERSION@ + @SOUP_MINOR_VERSION@ + @SOUP_MICRO_VERSION@ + 2.4 + lib + -$(ApiVersion)-0 + + -$(ApiVersion)-vs$(VSVer) + $(SoupSeparateVSDllPrefix) + $(SoupSeparateVSDllSuffix) + c:\python34 + + + <_PropertySheetDisplayName>soupversionpathsprops + + + + + $(VSVer) + + + $(GlibEtcInstallRoot) + + + $(CopyDir) + + + $(SoupMajorVersion) + + + $(SoupMinorVersion) + + + $(SoupMicroVersion) + + + $(ApiVersion) + + + $(SoupLibtoolCompatibleDllPrefix) + + + $(SoupLibtoolCompatibleDllSuffix) + + + $(SoupSeparateVSDllPrefix) + + + $(SoupSeparateVSDllSuffix) + + + $(SoupDllPrefix) + + + $(SoupDllSuffix) + + + $(PythonPath) + + + diff --git a/win32/vs10/soup.vcxproj b/win32/vs10/soup.vcxproj new file mode 100644 index 0000000..7c9e89f --- /dev/null +++ b/win32/vs10/soup.vcxproj @@ -0,0 +1,414 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + Debug_MIT_GSSAPI + Win32 + + + Debug_MIT_GSSAPI + x64 + + + Release_MIT_GSSAPI + Win32 + + + Release_MIT_GSSAPI + x64 + + + + {D83A3162-B14C-459C-AF81-15BBFA90240D} + soup + Win32Proj + + + + DynamicLibrary + Unicode + v100 + + + DynamicLibrary + Unicode + v100 + + + DynamicLibrary + Unicode + v100 + true + + + DynamicLibrary + Unicode + v100 + true + + + DynamicLibrary + Unicode + v100 + + + DynamicLibrary + Unicode + v100 + + + DynamicLibrary + Unicode + v100 + true + + + DynamicLibrary + Unicode + v100 + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + false + trueDebug\$(Platform)\bin\ + falseRelease\$(Platform)\bin\ + + + Disabled + _DEBUG;$(SoupBuildDefines);%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + EditAndContinue + + + $(SoupExtraDepLibs);%(AdditionalDependencies) + true + Windows + MachineX86 + + + + + Disabled + _DEBUG;$(SoupBuildDefines);$(SoupMITGSSAPIBuildDefines);%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + EditAndContinue + + + $(SoupExtraDepLibs);$(MITGSSAPILibBaseName)$(MITGSSAPILibNameSuffixX86);%(AdditionalDependencies) + true + Windows + MachineX86 + + + + + MaxSpeed + true + $(SoupBuildDefines);%(PreprocessorDefinitions) + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + $(SoupExtraDepLibs);%(AdditionalDependencies) + true + Windows + true + true + MachineX86 + + + + + MaxSpeed + true + $(SoupBuildDefines);$(SoupMITGSSAPIBuildDefines);%(PreprocessorDefinitions) + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + $(SoupExtraDepLibs);$(MITGSSAPILibBaseName)$(MITGSSAPILibNameSuffixX86);%(AdditionalDependencies) + true + Windows + true + true + MachineX86 + + + + + X64 + + + Disabled + _DEBUG;$(SoupBuildDefines);%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + ProgramDatabase + + + $(SoupExtraDepLibs);%(AdditionalDependencies) + true + Windows + MachineX64 + + + + + X64 + + + Disabled + _DEBUG;$(SoupBuildDefines);$(SoupMITGSSAPIBuildDefines);%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + ProgramDatabase + + + $(SoupExtraDepLibs);$(MITGSSAPILibBaseName)$(MITGSSAPILibNameSuffixX64);%(AdditionalDependencies) + true + Windows + MachineX64 + + + + + X64 + + + MaxSpeed + true + $(SoupBuildDefines);%(PreprocessorDefinitions) + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + $(SoupExtraDepLibs);%(AdditionalDependencies) + true + Windows + true + true + MachineX64 + + + + + X64 + + + MaxSpeed + true + $(SoupBuildDefines);$(SoupMITGSSAPIBuildDefines);%(PreprocessorDefinitions) + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + $(SoupExtraDepLibs);$(MITGSSAPILibBaseName)$(MITGSSAPILibNameSuffixX64);%(AdditionalDependencies) + true + Windows + true + true + MachineX64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Copying config.h from config.h.win32... + $(CopyConfigH) + ..\..\config.h;%(Outputs) + Copying config.h from config.h.win32... + $(CopyConfigH) + ..\..\config.h;%(Outputs) + Copying config.h from config.h.win32... + $(CopyConfigH) + ..\..\config.h;%(Outputs) + Copying config.h from config.h.win32... + $(CopyConfigH) + ..\..\config.h;%(Outputs) + + + Generating tld_data.inc... + $(GenTldDataInc) + ..\..\libsoup\tld_data.inc;%(Outputs) + Generating tld_data.inc... + $(GenTldDataInc) + ..\..\libsoup\tld_data.inc;%(Outputs) + Generating tld_data.inc... + $(GenTldDataInc) + ..\..\libsoup\tld_data.inc;%(Outputs) + Generating tld_data.inc... + $(GenTldDataInc) + ..\..\libsoup\tld_data.inc;%(Outputs) + + + Generating soup-version.h... + $(GenSoupVersionH) + ..\..\libsoup\soup-version.h;%(Outputs) + Generating soup-version.h... + $(GenSoupVersionH) + ..\..\libsoup\soup-version.h;%(Outputs) + Generating soup-version.h... + $(GenSoupVersionH) + ..\..\libsoup\soup-version.h;%(Outputs) + Generating soup-version.h... + $(GenSoupVersionH) + ..\..\libsoup\soup-version.h;%(Outputs) + + + + + + diff --git a/win32/vs10/soup.vcxproj.filters b/win32/vs10/soup.vcxproj.filters new file mode 100644 index 0000000..71eb5a6 --- /dev/null +++ b/win32/vs10/soup.vcxproj.filters @@ -0,0 +1,95 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav + + + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + + + Resource Files + Resource Files + Resource Files + + diff --git a/win32/vs10/soup.vcxproj.filtersin b/win32/vs10/soup.vcxproj.filtersin new file mode 100644 index 0000000..d18b142 --- /dev/null +++ b/win32/vs10/soup.vcxproj.filtersin @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav + + +#include "soup.vs10.sourcefiles.filters" + + + Resource Files + Resource Files + Resource Files + + diff --git a/win32/vs10/soup.vcxprojin b/win32/vs10/soup.vcxprojin new file mode 100644 index 0000000..047ff28 --- /dev/null +++ b/win32/vs10/soup.vcxprojin @@ -0,0 +1,341 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + Debug_MIT_GSSAPI + Win32 + + + Debug_MIT_GSSAPI + x64 + + + Release_MIT_GSSAPI + Win32 + + + Release_MIT_GSSAPI + x64 + + + + {D83A3162-B14C-459C-AF81-15BBFA90240D} + soup + Win32Proj + + + + DynamicLibrary + Unicode + v100 + + + DynamicLibrary + Unicode + v100 + + + DynamicLibrary + Unicode + v100 + true + + + DynamicLibrary + Unicode + v100 + true + + + DynamicLibrary + Unicode + v100 + + + DynamicLibrary + Unicode + v100 + + + DynamicLibrary + Unicode + v100 + true + + + DynamicLibrary + Unicode + v100 + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + false + trueDebug\$(Platform)\bin\ + falseRelease\$(Platform)\bin\ + + + Disabled + _DEBUG;$(SoupBuildDefines);%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + EditAndContinue + + + $(SoupExtraDepLibs);%(AdditionalDependencies) + true + Windows + MachineX86 + + + + + Disabled + _DEBUG;$(SoupBuildDefines);$(SoupMITGSSAPIBuildDefines);%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + EditAndContinue + + + $(SoupExtraDepLibs);$(MITGSSAPILibBaseName)$(MITGSSAPILibNameSuffixX86);%(AdditionalDependencies) + true + Windows + MachineX86 + + + + + MaxSpeed + true + $(SoupBuildDefines);%(PreprocessorDefinitions) + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + $(SoupExtraDepLibs);%(AdditionalDependencies) + true + Windows + true + true + MachineX86 + + + + + MaxSpeed + true + $(SoupBuildDefines);$(SoupMITGSSAPIBuildDefines);%(PreprocessorDefinitions) + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + $(SoupExtraDepLibs);$(MITGSSAPILibBaseName)$(MITGSSAPILibNameSuffixX86);%(AdditionalDependencies) + true + Windows + true + true + MachineX86 + + + + + X64 + + + Disabled + _DEBUG;$(SoupBuildDefines);%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + ProgramDatabase + + + $(SoupExtraDepLibs);%(AdditionalDependencies) + true + Windows + MachineX64 + + + + + X64 + + + Disabled + _DEBUG;$(SoupBuildDefines);$(SoupMITGSSAPIBuildDefines);%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + ProgramDatabase + + + $(SoupExtraDepLibs);$(MITGSSAPILibBaseName)$(MITGSSAPILibNameSuffixX64);%(AdditionalDependencies) + true + Windows + MachineX64 + + + + + X64 + + + MaxSpeed + true + $(SoupBuildDefines);%(PreprocessorDefinitions) + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + $(SoupExtraDepLibs);%(AdditionalDependencies) + true + Windows + true + true + MachineX64 + + + + + X64 + + + MaxSpeed + true + $(SoupBuildDefines);$(SoupMITGSSAPIBuildDefines);%(PreprocessorDefinitions) + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + $(SoupExtraDepLibs);$(MITGSSAPILibBaseName)$(MITGSSAPILibNameSuffixX64);%(AdditionalDependencies) + true + Windows + true + true + MachineX64 + + + +#include "soup.vs10.sourcefiles" + + + + Copying config.h from config.h.win32... + $(CopyConfigH) + ..\..\config.h;%(Outputs) + Copying config.h from config.h.win32... + $(CopyConfigH) + ..\..\config.h;%(Outputs) + Copying config.h from config.h.win32... + $(CopyConfigH) + ..\..\config.h;%(Outputs) + Copying config.h from config.h.win32... + $(CopyConfigH) + ..\..\config.h;%(Outputs) + + + Generating tld_data.inc... + $(GenTldDataInc) + ..\..\libsoup\tld_data.inc;%(Outputs) + Generating tld_data.inc... + $(GenTldDataInc) + ..\..\libsoup\tld_data.inc;%(Outputs) + Generating tld_data.inc... + $(GenTldDataInc) + ..\..\libsoup\tld_data.inc;%(Outputs) + Generating tld_data.inc... + $(GenTldDataInc) + ..\..\libsoup\tld_data.inc;%(Outputs) + + + Generating soup-version.h... + $(GenSoupVersionH) + ..\..\libsoup\soup-version.h;%(Outputs) + Generating soup-version.h... + $(GenSoupVersionH) + ..\..\libsoup\soup-version.h;%(Outputs) + Generating soup-version.h... + $(GenSoupVersionH) + ..\..\libsoup\soup-version.h;%(Outputs) + Generating soup-version.h... + $(GenSoupVersionH) + ..\..\libsoup\soup-version.h;%(Outputs) + + + + + + diff --git a/win32/vs11/Makefile.am b/win32/vs11/Makefile.am new file mode 100644 index 0000000..3f913e6 --- /dev/null +++ b/win32/vs11/Makefile.am @@ -0,0 +1,28 @@ +EXTRA_DIST = \ + libsoup.sln \ + get.vcxproj \ + simple-httpd.vcxproj \ + simple-proxy.vcxproj \ + soup-install.vcxproj \ + soup-install.vcxproj.filters \ + get.vcxproj.filters \ + simple-httpd.vcxproj.filters \ + simple-proxy.vcxproj.filters \ + soup-build-defines.props \ + soup-dll-build-defines.props \ + soup-gen-srcs.props \ + soup-version-paths.props \ + soup.vcxproj \ + soup-gnome.vcxproj \ + soup.vcxproj.filters \ + soup-gnome.vcxproj.filters \ + soup-install.props + +DISTCLEANFILES = $(EXTRA_DIST) + +MSVC_BASE_VER = 10 +MSVC_BASE_VER_LONG = 2010 +MSVC_VER = 11 +MSVC_VER_LONG = 2012 + +include $(top_srcdir)/win32/Makefile-newvs.am diff --git a/win32/vs11/Makefile.in b/win32/vs11/Makefile.in new file mode 100644 index 0000000..759bf3d --- /dev/null +++ b/win32/vs11/Makefile.in @@ -0,0 +1,600 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Centralized autotools file +# Create the Visual Studio 2012/2013/2015 project files +# from the Visual Studio 2010 project files + +# This autotools file, from GLib, can be used in other projects +# that have Visual Studio build support. + +# Author: Fan, Chun-wei +# November 05, 2012 + +# MSVC_BASE_VER: Baseline MSVC 201x version to copy/process project files from (100 for 2010, 120 for 2013) +# MSVC_BASE_VER_LONG: Long Version of baseline Visual Studio 201x version (2010, 2012, 2013, 14, 15) +# MSVC_BASE_TOOLSET: Use if baseline MSVC toolset is not in the form v$(MSVC_BASE_VER)0, meaning v$(MSVC_BASE_TOOLSET) +# MSVC_VER_LONG: Long Version of target Visual Studio (2012, 2013, 14 and so on) +# MSVC_VER: Short Version of target Visual Studio (110 for 2012, 120 for 2013, 140 for 2015, 141 for 2017) +# MSVC_TOOLSET: Use if target MSVC toolsett is not in the form v $(MSVC_VER)0, meaning v$(MSVC_TOOLSET) +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = win32/vs11 +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_code_coverage.m4 \ + $(top_srcdir)/m4/glibtests.m4 $(top_srcdir)/m4/gtk-doc.m4 \ + $(top_srcdir)/m4/intltool.m4 $(top_srcdir)/m4/introspection.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/vapigen.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +am__DIST_COMMON = $(srcdir)/Makefile.in \ + $(top_srcdir)/win32/Makefile-newvs.am +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALL_LINGUAS = @ALL_LINGUAS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +APACHE_HTTPD = @APACHE_HTTPD@ +APACHE_MODULE_DIR = @APACHE_MODULE_DIR@ +APACHE_PHP_MODULE_DIR = @APACHE_PHP_MODULE_DIR@ +APACHE_SSL_MODULE_DIR = @APACHE_SSL_MODULE_DIR@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CODE_COVERAGE_CFLAGS = @CODE_COVERAGE_CFLAGS@ +CODE_COVERAGE_CPPFLAGS = @CODE_COVERAGE_CPPFLAGS@ +CODE_COVERAGE_CXXFLAGS = @CODE_COVERAGE_CXXFLAGS@ +CODE_COVERAGE_ENABLED = @CODE_COVERAGE_ENABLED@ +CODE_COVERAGE_LDFLAGS = @CODE_COVERAGE_LDFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CURL = @CURL@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GCOV = @GCOV@ +GENHTML = @GENHTML@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_COMPILE_RESOURCES = @GLIB_COMPILE_RESOURCES@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MAKEFILE = @GLIB_MAKEFILE@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GMSGFMT = @GMSGFMT@ +GOBJECT_QUERY = @GOBJECT_QUERY@ +GREP = @GREP@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +HAVE_GNOME = @HAVE_GNOME@ +HTML_DIR = @HTML_DIR@ +IF_HAVE_MOD_UNIXD = @IF_HAVE_MOD_UNIXD@ +IF_HAVE_PHP = @IF_HAVE_PHP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ +INTLTOOL_MERGE = @INTLTOOL_MERGE@ +INTLTOOL_PERL = @INTLTOOL_PERL@ +INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ +INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@ +INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@ +INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@ +INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LCOV = @LCOV@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PHP = @PHP@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOUP_AGE = @SOUP_AGE@ +SOUP_API_VERSION = @SOUP_API_VERSION@ +SOUP_CURRENT = @SOUP_CURRENT@ +SOUP_DEBUG_FLAGS = @SOUP_DEBUG_FLAGS@ +SOUP_HIDDEN_VISIBILITY_CFLAGS = @SOUP_HIDDEN_VISIBILITY_CFLAGS@ +SOUP_MAJOR_VERSION = @SOUP_MAJOR_VERSION@ +SOUP_MICRO_VERSION = @SOUP_MICRO_VERSION@ +SOUP_MINOR_VERSION = @SOUP_MINOR_VERSION@ +SOUP_REVISION = @SOUP_REVISION@ +SQLITE_CFLAGS = @SQLITE_CFLAGS@ +SQLITE_LIBS = @SQLITE_LIBS@ +STRIP = @STRIP@ +USE_NLS = @USE_NLS@ +VALAC = @VALAC@ +VAPIDIR = @VAPIDIR@ +VAPIGEN = @VAPIGEN@ +VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@ +VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@ +VERSION = @VERSION@ +XGETTEXT = @XGETTEXT@ +XML_CFLAGS = @XML_CFLAGS@ +XML_LIBS = @XML_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +installed_test_metadir = @installed_test_metadir@ +installed_testdir = @installed_testdir@ +intltool__v_merge_options_ = @intltool__v_merge_options_@ +intltool__v_merge_options_0 = @intltool__v_merge_options_0@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +ntlm_auth = @ntlm_auth@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +EXTRA_DIST = \ + libsoup.sln \ + get.vcxproj \ + simple-httpd.vcxproj \ + simple-proxy.vcxproj \ + soup-install.vcxproj \ + soup-install.vcxproj.filters \ + get.vcxproj.filters \ + simple-httpd.vcxproj.filters \ + simple-proxy.vcxproj.filters \ + soup-build-defines.props \ + soup-dll-build-defines.props \ + soup-gen-srcs.props \ + soup-version-paths.props \ + soup.vcxproj \ + soup-gnome.vcxproj \ + soup.vcxproj.filters \ + soup-gnome.vcxproj.filters \ + soup-install.props + +DISTCLEANFILES = $(EXTRA_DIST) +MSVC_BASE_VER = 10 +MSVC_BASE_VER_LONG = 2010 +MSVC_VER = 11 +MSVC_VER_LONG = 2012 +@MSVC_BASE_NO_TOOLSET_SET_TRUE@MSVC_BASE_TOOLSET = $(MSVC_BASE_VER)0 +@MSVC_NO_TOOLSET_SET_TRUE@MSVC_TOOLSET = $(MSVC_VER)0 +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/win32/Makefile-newvs.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign win32/vs11/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign win32/vs11/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; +$(top_srcdir)/win32/Makefile-newvs.am $(am__empty): + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +tags TAGS: + +ctags CTAGS: + +cscope cscopelist: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic clean-libtool \ + cscopelist-am ctags-am distclean distclean-generic \ + distclean-libtool distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +%.sln: + sed 's/11\.00/12\.00/g' < $(top_srcdir)/win32/vs$(MSVC_BASE_VER)/$@ > $(top_builddir)/win32/vs$(MSVC_VER)/$@.tmp + sed 's/$(MSVC_BASE_VER_LONG)/$(MSVC_VER_LONG)/g' < $(top_builddir)/win32/vs$(MSVC_VER)/$@.tmp > $(top_builddir)/win32/vs$(MSVC_VER)/$@ + rm $(top_builddir)/win32/vs$(MSVC_VER)/$@.tmp + +%.txt: + sed 's/vs$(MSVC_BASE_VER)/vs$(MSVC_VER)/g' < $(top_srcdir)/win32/vs$(MSVC_BASE_VER)/$@ > $(top_builddir)/win32/vs$(MSVC_VER)/$@.tmp + sed 's/VS$(MSVC_BASE_VER)/VS$(MSVC_VER)/g' < $(top_builddir)/win32/vs$(MSVC_VER)/$@.tmp > $(top_builddir)/win32/vs$(MSVC_VER)/$@ + rm $(top_builddir)/win32/vs$(MSVC_VER)/$@.tmp + +%.vcxproj: + if test -e $(top_srcdir)/win32/vs$(MSVC_BASE_VER)/$@; then \ + sed 's/v$(MSVC_BASE_TOOLSET)/v$(MSVC_TOOLSET)/g' < $(top_srcdir)/win32/vs$(MSVC_BASE_VER)/$@ > $(top_builddir)/win32/vs$(MSVC_VER)/$@; \ + else \ + sed 's/v$(MSVC_BASE_TOOLSET)/v$(MSVC_TOOLSET)/g' < $(top_builddir)/win32/vs$(MSVC_BASE_VER)/$@ > $(top_builddir)/win32/vs$(MSVC_VER)/$@; \ + fi + +%.props: $(top_builddir)/win32/vs$(MSVC_BASE_VER)/Makefile + if test -e $(top_srcdir)/win32/vs$(MSVC_BASE_VER)/$@; then \ + sed 's/$(MSVC_BASE_VER)<\/VSVer>/$(MSVC_VER)<\/VSVer>/g' < $(top_srcdir)/win32/vs$(MSVC_BASE_VER)/$@ > $(top_builddir)/win32/vs$(MSVC_VER)/$@; \ + else \ + sed 's/$(MSVC_BASE_VER)<\/VSVer>/$(MSVC_VER)<\/VSVer>/g' < $(top_builddir)/win32/vs$(MSVC_BASE_VER)/$@ > $(top_builddir)/win32/vs$(MSVC_VER)/$@; \ + fi + +%.vcxproj.filters: + if test -e $(top_srcdir)/win32/vs$(MSVC_BASE_VER)/$@; then \ + cp $(top_srcdir)/win32/vs$(MSVC_BASE_VER)/$@ $(top_builddir)/win32/vs$(MSVC_VER)/$@; \ + else \ + cp $(top_builddir)/win32/vs$(MSVC_BASE_VER)/$@ $(top_builddir)/win32/vs$(MSVC_VER)/$@; \ + fi + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/win32/vs11/get.vcxproj b/win32/vs11/get.vcxproj new file mode 100644 index 0000000..2cb7899 --- /dev/null +++ b/win32/vs11/get.vcxproj @@ -0,0 +1,159 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {B24831C4-B8F2-41D6-AAF4-12192F71C623} + get + Win32Proj + + + + Application + Unicode + v110 + true + + + Application + Unicode + v110 + + + Application + Unicode + v110 + true + + + Application + Unicode + v110 + + + + + + + + + + + + + + + + + + + + + + true + false + + + Disabled + _DEBUG;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + EditAndContinue + + + true + Console + MachineX86 + + + + + MaxSpeed + true + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + true + Console + true + true + MachineX86 + + + + + X64 + + + Disabled + _DEBUG;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + ProgramDatabase + + + true + Console + MachineX64 + + + + + X64 + + + MaxSpeed + true + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + true + Console + true + true + MachineX64 + + + + + + + + {d83a3162-b14c-459c-af81-15bbfa90240d} + false + + + + + + diff --git a/win32/vs11/get.vcxproj.filters b/win32/vs11/get.vcxproj.filters new file mode 100644 index 0000000..9bc6fcf --- /dev/null +++ b/win32/vs11/get.vcxproj.filters @@ -0,0 +1,17 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav + + + Sources + + diff --git a/win32/vs11/libsoup.sln b/win32/vs11/libsoup.sln new file mode 100644 index 0000000..67cd7b5 --- /dev/null +++ b/win32/vs11/libsoup.sln @@ -0,0 +1,128 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "soup", "soup.vcxproj", "{D83A3162-B14C-459C-AF81-15BBFA90240D}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "soup-gnome", "soup-gnome.vcxproj", "{8C88A385-28C8-4B30-91A4-FBA381A5A46F}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "get", "get.vcxproj", "{B24831C4-B8F2-41D6-AAF4-12192F71C623}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "simple-httpd", "simple-httpd.vcxproj", "{80DC062E-2146-4CE8-A448-FD2205AB2CA4}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "simple-proxy", "simple-proxy.vcxproj", "{3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "soup-install", "soup-install.vcxproj", "{E0DCF460-914F-46F9-94D6-86D456CB53E9}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + Debug_MIT_GSSAPI|Win32 = Debug_MIT_GSSAPI|Win32 + Debug_MIT_GSSAPI|x64 = Debug_MIT_GSSAPI|x64 + Release_MIT_GSSAPI|Win32 = Release_MIT_GSSAPI|Win32 + Release_MIT_GSSAPI|x64 = Release_MIT_GSSAPI|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Debug|Win32.ActiveCfg = Debug|Win32 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Debug|Win32.Build.0 = Debug|Win32 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Debug|x64.ActiveCfg = Debug|x64 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Debug|x64.Build.0 = Debug|x64 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Release|Win32.ActiveCfg = Release|Win32 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Release|Win32.Build.0 = Release|Win32 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Release|x64.ActiveCfg = Release|x64 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Release|x64.Build.0 = Release|x64 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Debug_MIT_GSSAPI|Win32.ActiveCfg = Debug_MIT_GSSAPI|Win32 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Debug_MIT_GSSAPI|Win32.Build.0 = Debug_MIT_GSSAPI|Win32 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Debug_MIT_GSSAPI|x64.ActiveCfg = Debug_MIT_GSSAPI|x64 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Debug_MIT_GSSAPI|x64.Build.0 = Debug_MIT_GSSAPI|x64 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Release_MIT_GSSAPI|Win32.ActiveCfg = Release_MIT_GSSAPI|Win32 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Release_MIT_GSSAPI|Win32.Build.0 = Release_MIT_GSSAPI|Win32 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Release_MIT_GSSAPI|x64.ActiveCfg = Release_MIT_GSSAPI|x64 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Release_MIT_GSSAPI|x64.Build.0 = Release_MIT_GSSAPI|x64 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Debug|Win32.ActiveCfg = Debug|Win32 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Debug|Win32.Build.0 = Debug|Win32 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Debug|x64.ActiveCfg = Debug|x64 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Debug|x64.Build.0 = Debug|x64 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Release|Win32.ActiveCfg = Release|Win32 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Release|Win32.Build.0 = Release|Win32 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Release|x64.ActiveCfg = Release|x64 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Release|x64.Build.0 = Release|x64 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Debug_MIT_GSSAPI|Win32.ActiveCfg = Debug|Win32 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Debug_MIT_GSSAPI|Win32.Build.0 = Debug|Win32 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Debug_MIT_GSSAPI|x64.ActiveCfg = Debug|x64 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Debug_MIT_GSSAPI|x64.Build.0 = Debug|x64 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Release_MIT_GSSAPI|Win32.ActiveCfg = Release|Win32 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Release_MIT_GSSAPI|Win32.Build.0 = Release|Win32 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Release_MIT_GSSAPI|x64.ActiveCfg = Release|x64 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Release_MIT_GSSAPI|x64.Build.0 = Release|x64 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Debug|Win32.ActiveCfg = Debug|Win32 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Debug|Win32.Build.0 = Debug|Win32 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Debug|x64.ActiveCfg = Debug|x64 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Debug|x64.Build.0 = Debug|x64 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Release|Win32.ActiveCfg = Release|Win32 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Release|Win32.Build.0 = Release|Win32 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Release|x64.ActiveCfg = Release|x64 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Release|x64.Build.0 = Release|x64 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Debug_MIT_GSSAPI|Win32.ActiveCfg = Debug|Win32 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Debug_MIT_GSSAPI|Win32.Build.0 = Debug|Win32 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Debug_MIT_GSSAPI|x64.ActiveCfg = Debug|x64 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Debug_MIT_GSSAPI|x64.Build.0 = Debug|x64 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Release_MIT_GSSAPI|Win32.ActiveCfg = Release|Win32 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Release_MIT_GSSAPI|Win32.Build.0 = Release|Win32 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Release_MIT_GSSAPI|x64.ActiveCfg = Release|x64 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Release_MIT_GSSAPI|x64.Build.0 = Release|x64 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Debug|Win32.ActiveCfg = Debug|Win32 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Debug|Win32.Build.0 = Debug|Win32 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Debug|x64.ActiveCfg = Debug|x64 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Debug|x64.Build.0 = Debug|x64 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Release|Win32.ActiveCfg = Release|Win32 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Release|Win32.Build.0 = Release|Win32 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Release|x64.ActiveCfg = Release|x64 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Release|x64.Build.0 = Release|x64 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Debug_MIT_GSSAPI|Win32.ActiveCfg = Debug|Win32 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Debug_MIT_GSSAPI|Win32.Build.0 = Debug|Win32 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Debug_MIT_GSSAPI|x64.ActiveCfg = Debug|x64 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Debug_MIT_GSSAPI|x64.Build.0 = Debug|x64 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Release_MIT_GSSAPI|Win32.ActiveCfg = Release|Win32 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Release_MIT_GSSAPI|Win32.Build.0 = Release|Win32 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Release_MIT_GSSAPI|x64.ActiveCfg = Release|x64 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Release_MIT_GSSAPI|x64.Build.0 = Release|x64 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Debug|Win32.ActiveCfg = Debug|Win32 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Debug|Win32.Build.0 = Debug|Win32 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Debug|x64.ActiveCfg = Debug|x64 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Debug|x64.Build.0 = Debug|x64 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Release|Win32.ActiveCfg = Release|Win32 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Release|Win32.Build.0 = Release|Win32 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Release|x64.ActiveCfg = Release|x64 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Release|x64.Build.0 = Release|x64 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Debug_MIT_GSSAPI|Win32.ActiveCfg = Debug|Win32 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Debug_MIT_GSSAPI|Win32.Build.0 = Debug|Win32 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Debug_MIT_GSSAPI|x64.ActiveCfg = Debug|x64 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Debug_MIT_GSSAPI|x64.Build.0 = Debug|x64 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Release_MIT_GSSAPI|Win32.ActiveCfg = Release|Win32 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Release_MIT_GSSAPI|Win32.Build.0 = Release|Win32 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Release_MIT_GSSAPI|x64.ActiveCfg = Release|x64 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Release_MIT_GSSAPI|x64.Build.0 = Release|x64 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Debug|Win32.ActiveCfg = Debug|Win32 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Debug|Win32.Build.0 = Debug|Win32 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Debug|x64.ActiveCfg = Debug|x64 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Debug|x64.Build.0 = Debug|x64 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Release|Win32.ActiveCfg = Release|Win32 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Release|Win32.Build.0 = Release|Win32 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Release|x64.ActiveCfg = Release|x64 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Release|x64.Build.0 = Release|x64 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Debug_MIT_GSSAPI|Win32.ActiveCfg = Debug|Win32 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Debug_MIT_GSSAPI|Win32.Build.0 = Debug|Win32 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Debug_MIT_GSSAPI|x64.ActiveCfg = Debug|x64 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Debug_MIT_GSSAPI|x64.Build.0 = Debug|x64 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Release_MIT_GSSAPI|Win32.ActiveCfg = Release|Win32 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Release_MIT_GSSAPI|Win32.Build.0 = Release|Win32 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Release_MIT_GSSAPI|x64.ActiveCfg = Release|x64 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Release_MIT_GSSAPI|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/win32/vs11/simple-httpd.vcxproj b/win32/vs11/simple-httpd.vcxproj new file mode 100644 index 0000000..1c93bf0 --- /dev/null +++ b/win32/vs11/simple-httpd.vcxproj @@ -0,0 +1,159 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {80DC062E-2146-4CE8-A448-FD2205AB2CA4} + simplehttpd + Win32Proj + + + + Application + Unicode + v110 + true + + + Application + Unicode + v110 + + + Application + Unicode + v110 + true + + + Application + Unicode + v110 + + + + + + + + + + + + + + + + + + + + + + true + false + + + Disabled + _DEBUG;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + EditAndContinue + + + true + Console + MachineX86 + + + + + MaxSpeed + true + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + true + Console + true + true + MachineX86 + + + + + X64 + + + Disabled + _DEBUG;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + ProgramDatabase + + + true + Console + MachineX64 + + + + + X64 + + + MaxSpeed + true + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + true + Console + true + true + MachineX64 + + + + + + + + {d83a3162-b14c-459c-af81-15bbfa90240d} + false + + + + + + diff --git a/win32/vs11/simple-httpd.vcxproj.filters b/win32/vs11/simple-httpd.vcxproj.filters new file mode 100644 index 0000000..14cf1d4 --- /dev/null +++ b/win32/vs11/simple-httpd.vcxproj.filters @@ -0,0 +1,17 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav + + + Sources + + diff --git a/win32/vs11/simple-proxy.vcxproj b/win32/vs11/simple-proxy.vcxproj new file mode 100644 index 0000000..04f595f --- /dev/null +++ b/win32/vs11/simple-proxy.vcxproj @@ -0,0 +1,159 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E} + simpleproxy + Win32Proj + + + + Application + Unicode + v110 + true + + + Application + Unicode + v110 + + + Application + Unicode + v110 + true + + + Application + Unicode + v110 + + + + + + + + + + + + + + + + + + + + + + true + false + + + Disabled + _DEBUG;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + EditAndContinue + + + true + Console + MachineX86 + + + + + MaxSpeed + true + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + true + Console + true + true + MachineX86 + + + + + X64 + + + Disabled + _DEBUG;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + ProgramDatabase + + + true + Console + MachineX64 + + + + + X64 + + + MaxSpeed + true + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + true + Console + true + true + MachineX64 + + + + + + + + {d83a3162-b14c-459c-af81-15bbfa90240d} + false + + + + + + diff --git a/win32/vs11/simple-proxy.vcxproj.filters b/win32/vs11/simple-proxy.vcxproj.filters new file mode 100644 index 0000000..4a7f2f2 --- /dev/null +++ b/win32/vs11/simple-proxy.vcxproj.filters @@ -0,0 +1,17 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav + + + Sources + + diff --git a/win32/vs11/soup-build-defines.props b/win32/vs11/soup-build-defines.props new file mode 100644 index 0000000..0c9b527 --- /dev/null +++ b/win32/vs11/soup-build-defines.props @@ -0,0 +1,29 @@ + + + + + + + + <_PropertySheetDisplayName>soupbuilddefinesprops + $(SolutionDir)$(Configuration)\$(PlatformName)\bin\ + $(SolutionDir)$(Configuration)\$(PlatformName)\obj\$(ProjectName)\ + + + + ..\..;$(GlibEtcInstallRoot)\include\gio-win32-2.0;$(GlibEtcInstallRoot)\include\glib-2.0;$(GlibEtcInstallRoot)\lib\glib-2.0\include;$(GlibEtcInstallRoot)\include\libxml2;$(GlibEtcInstallRoot)\include;%(AdditionalIncludeDirectories) + HAVE_CONFIG_H;%(PreprocessorDefinitions) + msvc_recommended_pragmas.h;%(ForcedIncludeFiles) + true + /d2Zi+ %(AdditionalOptions) + + + gio-2.0.lib;gobject-2.0.lib;glib-2.0.lib;%(AdditionalDependencies) + $(GlibEtcInstallRoot)\lib;%(AdditionalLibraryDirectories) + /HIGHENTROPYVA %(AdditionalOptions) + /HIGHENTROPYVA %(AdditionalOptions) + /HIGHENTROPYVA %(AdditionalOptions) + /HIGHENTROPYVA %(AdditionalOptions) + + + diff --git a/win32/vs11/soup-dll-build-defines.props b/win32/vs11/soup-dll-build-defines.props new file mode 100644 index 0000000..40591ff --- /dev/null +++ b/win32/vs11/soup-dll-build-defines.props @@ -0,0 +1,24 @@ + + + + + + + LIBSOUP_COMPILATION;DLL_EXPORT;G_LOG_DOMAIN="libsoup" + LIBSOUP_HAVE_GSSAPI + libxml2.lib;sqlite3.lib;intl.lib;ws2_32.lib + gssapi + 32.lib + 64.lib + + + <_PropertySheetDisplayName>soupdllbuilddefinesprops + + + + $(OutDir)$(SoupDllPrefix)$(ProjectName)$(SoupDllSuffix).dll + $(OutDir)$(SoupDllPrefix)$(ProjectName)$(SoupDllSuffix).pdb + $(OutDir)$(ProjectName)-$(ApiVersion).lib + + + diff --git a/win32/vs11/soup-gen-srcs.props b/win32/vs11/soup-gen-srcs.props new file mode 100644 index 0000000..760825c --- /dev/null +++ b/win32/vs11/soup-gen-srcs.props @@ -0,0 +1,26 @@ + + + + + + + copy ..\..\config.h.win32 ..\..\config.h + $(PythonPath)\python.exe ..\soup_version_h.py --version=$(SoupMajorVersion).$(SoupMinorVersion).$(SoupMicroVersion) + $(PythonPath)\python.exe ..\..\libsoup\tld-parser.py ..\..\data\effective_tld_names.dat ..\..\libsoup\tld_data.inc + + + <_PropertySheetDisplayName>soupgensrcsprops + + + + + $(CopyConfigH) + + + $(GenSoupVersionH) + + + $(GenTldDataInc) + + + diff --git a/win32/vs11/soup-gnome.vcxproj b/win32/vs11/soup-gnome.vcxproj new file mode 100644 index 0000000..1d97e83 --- /dev/null +++ b/win32/vs11/soup-gnome.vcxproj @@ -0,0 +1,164 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {8C88A385-28C8-4B30-91A4-FBA381A5A46F} + soupgnome + Win32Proj + + + + DynamicLibrary + Unicode + v110 + true + + + DynamicLibrary + Unicode + v110 + + + DynamicLibrary + Unicode + v110 + true + + + DynamicLibrary + Unicode + v110 + + + + + + + + + + + + + + + + + + + + + + true + false + + + Disabled + _DEBUG;$(SoupBuildDefines);%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + EditAndContinue + + + true + Windows + MachineX86 + + + + + MaxSpeed + true + $(SoupBuildDefines);%(PreprocessorDefinitions) + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + true + Windows + true + true + MachineX86 + + + + + X64 + + + Disabled + _DEBUG;$(SoupBuildDefines);%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + ProgramDatabase + + + true + Windows + MachineX64 + + + + + X64 + + + MaxSpeed + true + $(SoupBuildDefines);%(PreprocessorDefinitions) + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + true + Windows + true + true + MachineX64 + + + + + + + + + + + {d83a3162-b14c-459c-af81-15bbfa90240d} + false + + + + + + diff --git a/win32/vs11/soup-gnome.vcxproj.filters b/win32/vs11/soup-gnome.vcxproj.filters new file mode 100644 index 0000000..924bf66 --- /dev/null +++ b/win32/vs11/soup-gnome.vcxproj.filters @@ -0,0 +1,20 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav + + + Source Files + Source Files + Source Files + Source Files + + diff --git a/win32/vs11/soup-install.props b/win32/vs11/soup-install.props new file mode 100644 index 0000000..fb3240e --- /dev/null +++ b/win32/vs11/soup-install.props @@ -0,0 +1,101 @@ + + + + + + + +mkdir $(CopyDir)\bin +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\$(SoupDllPrefix)soup$(SoupDllSuffix).dll $(CopyDir)\bin +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\$(SoupDllPrefix)soup$(SoupDllSuffix).pdb $(CopyDir)\bin +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\$(SoupDllPrefix)soup-gnome$(SoupDllSuffix).dll $(CopyDir)\bin +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\$(SoupDllPrefix)soup-gnome$(SoupDllSuffix).pdb $(CopyDir)\bin +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\get.exe $(CopyDir)\bin +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\get.pdb $(CopyDir)\bin +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\simple-httpd.exe $(CopyDir)\bin +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\simple-httpd.pdb $(CopyDir)\bin +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\simple-proxy.exe $(CopyDir)\bin +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\simple-proxy.pdb $(CopyDir)\bin +mkdir $(CopyDir)\lib +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\soup-$(ApiVersion).lib $(CopyDir)\lib +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\soup-gnome-$(ApiVersion).lib $(CopyDir)\lib +copy ..\libsoup-$(ApiVersion).pc $(CopyDir)\lib\pkgconfig +copy ..\libsoup-gnome-$(ApiVersion).pc $(CopyDir)\lib\pkgconfig +mkdir $(CopyDir)\include\libsoup-$(ApiVersion)\libsoup +copy ..\..\libsoup\soup.h $(CopyDir)\include\libsoup-2.4\libsoup\soup.h +copy ..\..\libsoup\soup-address.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-address.h +copy ..\..\libsoup\soup-auth.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-auth.h +copy ..\..\libsoup\soup-auth-domain.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-auth-domain.h +copy ..\..\libsoup\soup-auth-domain-basic.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-auth-domain-basic.h +copy ..\..\libsoup\soup-auth-domain-digest.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-auth-domain-digest.h +copy ..\..\libsoup\soup-auth-manager.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-auth-manager.h +copy ..\..\libsoup\soup-autocleanups.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-autocleanups.h +copy ..\..\libsoup\soup-cache.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-cache.h +copy ..\..\libsoup\soup-content-decoder.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-content-decoder.h +copy ..\..\libsoup\soup-content-sniffer.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-content-sniffer.h +copy ..\..\libsoup\soup-cookie.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-cookie.h +copy ..\..\libsoup\soup-cookie-jar.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-cookie-jar.h +copy ..\..\libsoup\soup-cookie-jar-db.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-cookie-jar-db.h +copy ..\..\libsoup\soup-cookie-jar-text.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-cookie-jar-text.h +copy ..\..\libsoup\soup-date.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-date.h +copy ..\..\libsoup\soup-form.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-form.h +copy ..\..\libsoup\soup-headers.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-headers.h +copy ..\..\libsoup\soup-logger.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-logger.h +copy ..\..\libsoup\soup-message.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-message.h +copy ..\..\libsoup\soup-message-body.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-message-body.h +copy ..\..\libsoup\soup-message-headers.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-message-headers.h +copy ..\..\libsoup\soup-method.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-method.h +copy ..\..\libsoup\soup-misc.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-misc.h +copy ..\..\libsoup\soup-multipart.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-multipart.h +copy ..\..\libsoup\soup-multipart-input-stream.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-multipart-input-stream.h +copy ..\..\libsoup\soup-password-manager.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-password-manager.h +copy ..\..\libsoup\soup-portability.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-portability.h +copy ..\..\libsoup\soup-proxy-resolver.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-proxy-resolver.h +copy ..\..\libsoup\soup-proxy-resolver-default.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-proxy-resolver-default.h +copy ..\..\libsoup\soup-proxy-uri-resolver.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-proxy-uri-resolver.h +copy ..\..\libsoup\soup-request.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-request.h +copy ..\..\libsoup\soup-request-data.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-request-data.h +copy ..\..\libsoup\soup-request-file.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-request-file.h +copy ..\..\libsoup\soup-request-http.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-request-http.h +copy ..\..\libsoup\soup-requester.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-requester.h +copy ..\..\libsoup\soup-server.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-server.h +copy ..\..\libsoup\soup-session.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-session.h +copy ..\..\libsoup\soup-session-async.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-session-async.h +copy ..\..\libsoup\soup-session-feature.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-session-feature.h +copy ..\..\libsoup\soup-session-sync.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-session-sync.h +copy ..\..\libsoup\soup-socket.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-socket.h +copy ..\..\libsoup\soup-status.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-status.h +copy ..\..\libsoup\soup-tld.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-tld.h +copy ..\..\libsoup\soup-types.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-types.h +copy ..\..\libsoup\soup-uri.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-uri.h +copy ..\..\libsoup\soup-value-utils.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-value-utils.h +copy ..\..\libsoup\soup-websocket.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-websocket.h +copy ..\..\libsoup\soup-websocket-connection.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-websocket-connection.h +copy ..\..\libsoup\soup-xmlrpc.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-xmlrpc.h +copy ..\..\libsoup\soup-xmlrpc-old.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-xmlrpc-old.h +copy ..\..\libsoup\soup-enum-types.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-enum-types.h +copy ..\..\libsoup\soup-version.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-version.h +mkdir $(CopyDir)\include\libsoup-gnome-$(ApiVersion)\libsoup +copy ..\..\libsoup\soup-cookie-jar-sqlite.h $(CopyDir)\include\libsoup-gnome-2.4\libsoup\soup-cookie-jar-sqlite.h +copy ..\..\libsoup\soup-gnome.h $(CopyDir)\include\libsoup-gnome-2.4\libsoup\soup-gnome.h +copy ..\..\libsoup\soup-gnome-features.h $(CopyDir)\include\libsoup-gnome-2.4\libsoup\soup-gnome-features.h + + ..\libsoup-$(ApiVersion).pc;..\libsoup-gnome-$(ApiVersion).pc + (if not exist $(CopyDir)\lib\pkgconfig mkdir $(CopyDir)\lib\pkgconfig) & ($(PythonPath)\python.exe ..\souppc.py --prefix=$(CopyDir) --version=$(SoupMajorVersion).$(SoupMinorVersion).$(SoupMicroVersion)) + + + <_PropertySheetDisplayName>soupinstallprops + + + + + $(SoupDoInstall) + + + $(SoupPCFiles) + + + $(SoupGenPC) + + + diff --git a/win32/vs11/soup-install.vcxproj b/win32/vs11/soup-install.vcxproj new file mode 100644 index 0000000..cbd1537 --- /dev/null +++ b/win32/vs11/soup-install.vcxproj @@ -0,0 +1,121 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {E0DCF460-914F-46F9-94D6-86D456CB53E9} + soupinstall + + + + Utility + MultiByte + v110 + true + + + Utility + MultiByte + v110 + + + Utility + MultiByte + v110 + true + + + Utility + MultiByte + v110 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Copying build results... + $(SoupPCFiles) + $(SoupDoInstall) + some_file;%(Outputs) + Copying build results... + $(SoupPCFiles) + $(SoupDoInstall) + some_file;%(Outputs) + + + Generating .pc files... + $(SoupGenPC) + $(SoupPCFiles);%(Outputs) + Generating .pc files... + $(SoupGenPC) + $(SoupPCFiles);%(Outputs) + + + + + {b24831c4-b8f2-41d6-aaf4-12192f71c623} + false + + + {80dc062e-2146-4ce8-a448-fd2205ab2ca4} + false + + + {3ad0cb92-ee38-425e-83cb-e7b1cb1d305e} + false + + + {8c88a385-28c8-4b30-91a4-fba381a5a46f} + false + + + {d83a3162-b14c-459c-af81-15bbfa90240d} + false + + + + + + diff --git a/win32/vs11/soup-install.vcxproj.filters b/win32/vs11/soup-install.vcxproj.filters new file mode 100644 index 0000000..2627f42 --- /dev/null +++ b/win32/vs11/soup-install.vcxproj.filters @@ -0,0 +1,13 @@ + + + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav + + + + Resource Files + Resource Files + + diff --git a/win32/vs11/soup-version-paths.props b/win32/vs11/soup-version-paths.props new file mode 100644 index 0000000..ceab09a --- /dev/null +++ b/win32/vs11/soup-version-paths.props @@ -0,0 +1,69 @@ + + + + + + 11 + ..\..\..\vs$(VSVer)\$(Platform) + $(GlibEtcInstallRoot) + 2 + 62 + 3 + 2.4 + lib + -$(ApiVersion)-0 + + -$(ApiVersion)-vs$(VSVer) + $(SoupSeparateVSDllPrefix) + $(SoupSeparateVSDllSuffix) + c:\python34 + + + <_PropertySheetDisplayName>soupversionpathsprops + + + + + $(VSVer) + + + $(GlibEtcInstallRoot) + + + $(CopyDir) + + + $(SoupMajorVersion) + + + $(SoupMinorVersion) + + + $(SoupMicroVersion) + + + $(ApiVersion) + + + $(SoupLibtoolCompatibleDllPrefix) + + + $(SoupLibtoolCompatibleDllSuffix) + + + $(SoupSeparateVSDllPrefix) + + + $(SoupSeparateVSDllSuffix) + + + $(SoupDllPrefix) + + + $(SoupDllSuffix) + + + $(PythonPath) + + + diff --git a/win32/vs11/soup.vcxproj b/win32/vs11/soup.vcxproj new file mode 100644 index 0000000..f7c57a4 --- /dev/null +++ b/win32/vs11/soup.vcxproj @@ -0,0 +1,414 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + Debug_MIT_GSSAPI + Win32 + + + Debug_MIT_GSSAPI + x64 + + + Release_MIT_GSSAPI + Win32 + + + Release_MIT_GSSAPI + x64 + + + + {D83A3162-B14C-459C-AF81-15BBFA90240D} + soup + Win32Proj + + + + DynamicLibrary + Unicode + v110 + + + DynamicLibrary + Unicode + v110 + + + DynamicLibrary + Unicode + v110 + true + + + DynamicLibrary + Unicode + v110 + true + + + DynamicLibrary + Unicode + v110 + + + DynamicLibrary + Unicode + v110 + + + DynamicLibrary + Unicode + v110 + true + + + DynamicLibrary + Unicode + v110 + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + false + trueDebug\$(Platform)\bin\ + falseRelease\$(Platform)\bin\ + + + Disabled + _DEBUG;$(SoupBuildDefines);%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + EditAndContinue + + + $(SoupExtraDepLibs);%(AdditionalDependencies) + true + Windows + MachineX86 + + + + + Disabled + _DEBUG;$(SoupBuildDefines);$(SoupMITGSSAPIBuildDefines);%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + EditAndContinue + + + $(SoupExtraDepLibs);$(MITGSSAPILibBaseName)$(MITGSSAPILibNameSuffixX86);%(AdditionalDependencies) + true + Windows + MachineX86 + + + + + MaxSpeed + true + $(SoupBuildDefines);%(PreprocessorDefinitions) + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + $(SoupExtraDepLibs);%(AdditionalDependencies) + true + Windows + true + true + MachineX86 + + + + + MaxSpeed + true + $(SoupBuildDefines);$(SoupMITGSSAPIBuildDefines);%(PreprocessorDefinitions) + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + $(SoupExtraDepLibs);$(MITGSSAPILibBaseName)$(MITGSSAPILibNameSuffixX86);%(AdditionalDependencies) + true + Windows + true + true + MachineX86 + + + + + X64 + + + Disabled + _DEBUG;$(SoupBuildDefines);%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + ProgramDatabase + + + $(SoupExtraDepLibs);%(AdditionalDependencies) + true + Windows + MachineX64 + + + + + X64 + + + Disabled + _DEBUG;$(SoupBuildDefines);$(SoupMITGSSAPIBuildDefines);%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + ProgramDatabase + + + $(SoupExtraDepLibs);$(MITGSSAPILibBaseName)$(MITGSSAPILibNameSuffixX64);%(AdditionalDependencies) + true + Windows + MachineX64 + + + + + X64 + + + MaxSpeed + true + $(SoupBuildDefines);%(PreprocessorDefinitions) + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + $(SoupExtraDepLibs);%(AdditionalDependencies) + true + Windows + true + true + MachineX64 + + + + + X64 + + + MaxSpeed + true + $(SoupBuildDefines);$(SoupMITGSSAPIBuildDefines);%(PreprocessorDefinitions) + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + $(SoupExtraDepLibs);$(MITGSSAPILibBaseName)$(MITGSSAPILibNameSuffixX64);%(AdditionalDependencies) + true + Windows + true + true + MachineX64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Copying config.h from config.h.win32... + $(CopyConfigH) + ..\..\config.h;%(Outputs) + Copying config.h from config.h.win32... + $(CopyConfigH) + ..\..\config.h;%(Outputs) + Copying config.h from config.h.win32... + $(CopyConfigH) + ..\..\config.h;%(Outputs) + Copying config.h from config.h.win32... + $(CopyConfigH) + ..\..\config.h;%(Outputs) + + + Generating tld_data.inc... + $(GenTldDataInc) + ..\..\libsoup\tld_data.inc;%(Outputs) + Generating tld_data.inc... + $(GenTldDataInc) + ..\..\libsoup\tld_data.inc;%(Outputs) + Generating tld_data.inc... + $(GenTldDataInc) + ..\..\libsoup\tld_data.inc;%(Outputs) + Generating tld_data.inc... + $(GenTldDataInc) + ..\..\libsoup\tld_data.inc;%(Outputs) + + + Generating soup-version.h... + $(GenSoupVersionH) + ..\..\libsoup\soup-version.h;%(Outputs) + Generating soup-version.h... + $(GenSoupVersionH) + ..\..\libsoup\soup-version.h;%(Outputs) + Generating soup-version.h... + $(GenSoupVersionH) + ..\..\libsoup\soup-version.h;%(Outputs) + Generating soup-version.h... + $(GenSoupVersionH) + ..\..\libsoup\soup-version.h;%(Outputs) + + + + + + diff --git a/win32/vs11/soup.vcxproj.filters b/win32/vs11/soup.vcxproj.filters new file mode 100644 index 0000000..71eb5a6 --- /dev/null +++ b/win32/vs11/soup.vcxproj.filters @@ -0,0 +1,95 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav + + + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + + + Resource Files + Resource Files + Resource Files + + diff --git a/win32/vs12/Makefile.am b/win32/vs12/Makefile.am new file mode 100644 index 0000000..a86d179 --- /dev/null +++ b/win32/vs12/Makefile.am @@ -0,0 +1,28 @@ +EXTRA_DIST = \ + libsoup.sln \ + get.vcxproj \ + simple-httpd.vcxproj \ + simple-proxy.vcxproj \ + soup-install.vcxproj \ + soup-install.vcxproj.filters \ + get.vcxproj.filters \ + simple-httpd.vcxproj.filters \ + simple-proxy.vcxproj.filters \ + soup-build-defines.props \ + soup-dll-build-defines.props \ + soup-gen-srcs.props \ + soup-version-paths.props \ + soup.vcxproj \ + soup-gnome.vcxproj \ + soup.vcxproj.filters \ + soup-gnome.vcxproj.filters \ + soup-install.props + +DISTCLEANFILES = $(EXTRA_DIST) + +MSVC_BASE_VER = 10 +MSVC_BASE_VER_LONG = 2010 +MSVC_VER = 12 +MSVC_VER_LONG = 2013 + +include $(top_srcdir)/win32/Makefile-newvs.am diff --git a/win32/vs12/Makefile.in b/win32/vs12/Makefile.in new file mode 100644 index 0000000..d29a41e --- /dev/null +++ b/win32/vs12/Makefile.in @@ -0,0 +1,600 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Centralized autotools file +# Create the Visual Studio 2012/2013/2015 project files +# from the Visual Studio 2010 project files + +# This autotools file, from GLib, can be used in other projects +# that have Visual Studio build support. + +# Author: Fan, Chun-wei +# November 05, 2012 + +# MSVC_BASE_VER: Baseline MSVC 201x version to copy/process project files from (100 for 2010, 120 for 2013) +# MSVC_BASE_VER_LONG: Long Version of baseline Visual Studio 201x version (2010, 2012, 2013, 14, 15) +# MSVC_BASE_TOOLSET: Use if baseline MSVC toolset is not in the form v$(MSVC_BASE_VER)0, meaning v$(MSVC_BASE_TOOLSET) +# MSVC_VER_LONG: Long Version of target Visual Studio (2012, 2013, 14 and so on) +# MSVC_VER: Short Version of target Visual Studio (110 for 2012, 120 for 2013, 140 for 2015, 141 for 2017) +# MSVC_TOOLSET: Use if target MSVC toolsett is not in the form v $(MSVC_VER)0, meaning v$(MSVC_TOOLSET) +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = win32/vs12 +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_code_coverage.m4 \ + $(top_srcdir)/m4/glibtests.m4 $(top_srcdir)/m4/gtk-doc.m4 \ + $(top_srcdir)/m4/intltool.m4 $(top_srcdir)/m4/introspection.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/vapigen.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +am__DIST_COMMON = $(srcdir)/Makefile.in \ + $(top_srcdir)/win32/Makefile-newvs.am +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALL_LINGUAS = @ALL_LINGUAS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +APACHE_HTTPD = @APACHE_HTTPD@ +APACHE_MODULE_DIR = @APACHE_MODULE_DIR@ +APACHE_PHP_MODULE_DIR = @APACHE_PHP_MODULE_DIR@ +APACHE_SSL_MODULE_DIR = @APACHE_SSL_MODULE_DIR@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CODE_COVERAGE_CFLAGS = @CODE_COVERAGE_CFLAGS@ +CODE_COVERAGE_CPPFLAGS = @CODE_COVERAGE_CPPFLAGS@ +CODE_COVERAGE_CXXFLAGS = @CODE_COVERAGE_CXXFLAGS@ +CODE_COVERAGE_ENABLED = @CODE_COVERAGE_ENABLED@ +CODE_COVERAGE_LDFLAGS = @CODE_COVERAGE_LDFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CURL = @CURL@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GCOV = @GCOV@ +GENHTML = @GENHTML@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_COMPILE_RESOURCES = @GLIB_COMPILE_RESOURCES@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MAKEFILE = @GLIB_MAKEFILE@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GMSGFMT = @GMSGFMT@ +GOBJECT_QUERY = @GOBJECT_QUERY@ +GREP = @GREP@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +HAVE_GNOME = @HAVE_GNOME@ +HTML_DIR = @HTML_DIR@ +IF_HAVE_MOD_UNIXD = @IF_HAVE_MOD_UNIXD@ +IF_HAVE_PHP = @IF_HAVE_PHP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ +INTLTOOL_MERGE = @INTLTOOL_MERGE@ +INTLTOOL_PERL = @INTLTOOL_PERL@ +INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ +INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@ +INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@ +INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@ +INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LCOV = @LCOV@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PHP = @PHP@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOUP_AGE = @SOUP_AGE@ +SOUP_API_VERSION = @SOUP_API_VERSION@ +SOUP_CURRENT = @SOUP_CURRENT@ +SOUP_DEBUG_FLAGS = @SOUP_DEBUG_FLAGS@ +SOUP_HIDDEN_VISIBILITY_CFLAGS = @SOUP_HIDDEN_VISIBILITY_CFLAGS@ +SOUP_MAJOR_VERSION = @SOUP_MAJOR_VERSION@ +SOUP_MICRO_VERSION = @SOUP_MICRO_VERSION@ +SOUP_MINOR_VERSION = @SOUP_MINOR_VERSION@ +SOUP_REVISION = @SOUP_REVISION@ +SQLITE_CFLAGS = @SQLITE_CFLAGS@ +SQLITE_LIBS = @SQLITE_LIBS@ +STRIP = @STRIP@ +USE_NLS = @USE_NLS@ +VALAC = @VALAC@ +VAPIDIR = @VAPIDIR@ +VAPIGEN = @VAPIGEN@ +VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@ +VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@ +VERSION = @VERSION@ +XGETTEXT = @XGETTEXT@ +XML_CFLAGS = @XML_CFLAGS@ +XML_LIBS = @XML_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +installed_test_metadir = @installed_test_metadir@ +installed_testdir = @installed_testdir@ +intltool__v_merge_options_ = @intltool__v_merge_options_@ +intltool__v_merge_options_0 = @intltool__v_merge_options_0@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +ntlm_auth = @ntlm_auth@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +EXTRA_DIST = \ + libsoup.sln \ + get.vcxproj \ + simple-httpd.vcxproj \ + simple-proxy.vcxproj \ + soup-install.vcxproj \ + soup-install.vcxproj.filters \ + get.vcxproj.filters \ + simple-httpd.vcxproj.filters \ + simple-proxy.vcxproj.filters \ + soup-build-defines.props \ + soup-dll-build-defines.props \ + soup-gen-srcs.props \ + soup-version-paths.props \ + soup.vcxproj \ + soup-gnome.vcxproj \ + soup.vcxproj.filters \ + soup-gnome.vcxproj.filters \ + soup-install.props + +DISTCLEANFILES = $(EXTRA_DIST) +MSVC_BASE_VER = 10 +MSVC_BASE_VER_LONG = 2010 +MSVC_VER = 12 +MSVC_VER_LONG = 2013 +@MSVC_BASE_NO_TOOLSET_SET_TRUE@MSVC_BASE_TOOLSET = $(MSVC_BASE_VER)0 +@MSVC_NO_TOOLSET_SET_TRUE@MSVC_TOOLSET = $(MSVC_VER)0 +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/win32/Makefile-newvs.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign win32/vs12/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign win32/vs12/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; +$(top_srcdir)/win32/Makefile-newvs.am $(am__empty): + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +tags TAGS: + +ctags CTAGS: + +cscope cscopelist: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic clean-libtool \ + cscopelist-am ctags-am distclean distclean-generic \ + distclean-libtool distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +%.sln: + sed 's/11\.00/12\.00/g' < $(top_srcdir)/win32/vs$(MSVC_BASE_VER)/$@ > $(top_builddir)/win32/vs$(MSVC_VER)/$@.tmp + sed 's/$(MSVC_BASE_VER_LONG)/$(MSVC_VER_LONG)/g' < $(top_builddir)/win32/vs$(MSVC_VER)/$@.tmp > $(top_builddir)/win32/vs$(MSVC_VER)/$@ + rm $(top_builddir)/win32/vs$(MSVC_VER)/$@.tmp + +%.txt: + sed 's/vs$(MSVC_BASE_VER)/vs$(MSVC_VER)/g' < $(top_srcdir)/win32/vs$(MSVC_BASE_VER)/$@ > $(top_builddir)/win32/vs$(MSVC_VER)/$@.tmp + sed 's/VS$(MSVC_BASE_VER)/VS$(MSVC_VER)/g' < $(top_builddir)/win32/vs$(MSVC_VER)/$@.tmp > $(top_builddir)/win32/vs$(MSVC_VER)/$@ + rm $(top_builddir)/win32/vs$(MSVC_VER)/$@.tmp + +%.vcxproj: + if test -e $(top_srcdir)/win32/vs$(MSVC_BASE_VER)/$@; then \ + sed 's/v$(MSVC_BASE_TOOLSET)/v$(MSVC_TOOLSET)/g' < $(top_srcdir)/win32/vs$(MSVC_BASE_VER)/$@ > $(top_builddir)/win32/vs$(MSVC_VER)/$@; \ + else \ + sed 's/v$(MSVC_BASE_TOOLSET)/v$(MSVC_TOOLSET)/g' < $(top_builddir)/win32/vs$(MSVC_BASE_VER)/$@ > $(top_builddir)/win32/vs$(MSVC_VER)/$@; \ + fi + +%.props: $(top_builddir)/win32/vs$(MSVC_BASE_VER)/Makefile + if test -e $(top_srcdir)/win32/vs$(MSVC_BASE_VER)/$@; then \ + sed 's/$(MSVC_BASE_VER)<\/VSVer>/$(MSVC_VER)<\/VSVer>/g' < $(top_srcdir)/win32/vs$(MSVC_BASE_VER)/$@ > $(top_builddir)/win32/vs$(MSVC_VER)/$@; \ + else \ + sed 's/$(MSVC_BASE_VER)<\/VSVer>/$(MSVC_VER)<\/VSVer>/g' < $(top_builddir)/win32/vs$(MSVC_BASE_VER)/$@ > $(top_builddir)/win32/vs$(MSVC_VER)/$@; \ + fi + +%.vcxproj.filters: + if test -e $(top_srcdir)/win32/vs$(MSVC_BASE_VER)/$@; then \ + cp $(top_srcdir)/win32/vs$(MSVC_BASE_VER)/$@ $(top_builddir)/win32/vs$(MSVC_VER)/$@; \ + else \ + cp $(top_builddir)/win32/vs$(MSVC_BASE_VER)/$@ $(top_builddir)/win32/vs$(MSVC_VER)/$@; \ + fi + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/win32/vs12/get.vcxproj b/win32/vs12/get.vcxproj new file mode 100644 index 0000000..01ecefd --- /dev/null +++ b/win32/vs12/get.vcxproj @@ -0,0 +1,159 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {B24831C4-B8F2-41D6-AAF4-12192F71C623} + get + Win32Proj + + + + Application + Unicode + v120 + true + + + Application + Unicode + v120 + + + Application + Unicode + v120 + true + + + Application + Unicode + v120 + + + + + + + + + + + + + + + + + + + + + + true + false + + + Disabled + _DEBUG;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + EditAndContinue + + + true + Console + MachineX86 + + + + + MaxSpeed + true + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + true + Console + true + true + MachineX86 + + + + + X64 + + + Disabled + _DEBUG;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + ProgramDatabase + + + true + Console + MachineX64 + + + + + X64 + + + MaxSpeed + true + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + true + Console + true + true + MachineX64 + + + + + + + + {d83a3162-b14c-459c-af81-15bbfa90240d} + false + + + + + + diff --git a/win32/vs12/get.vcxproj.filters b/win32/vs12/get.vcxproj.filters new file mode 100644 index 0000000..9bc6fcf --- /dev/null +++ b/win32/vs12/get.vcxproj.filters @@ -0,0 +1,17 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav + + + Sources + + diff --git a/win32/vs12/libsoup.sln b/win32/vs12/libsoup.sln new file mode 100644 index 0000000..945b046 --- /dev/null +++ b/win32/vs12/libsoup.sln @@ -0,0 +1,128 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "soup", "soup.vcxproj", "{D83A3162-B14C-459C-AF81-15BBFA90240D}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "soup-gnome", "soup-gnome.vcxproj", "{8C88A385-28C8-4B30-91A4-FBA381A5A46F}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "get", "get.vcxproj", "{B24831C4-B8F2-41D6-AAF4-12192F71C623}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "simple-httpd", "simple-httpd.vcxproj", "{80DC062E-2146-4CE8-A448-FD2205AB2CA4}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "simple-proxy", "simple-proxy.vcxproj", "{3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "soup-install", "soup-install.vcxproj", "{E0DCF460-914F-46F9-94D6-86D456CB53E9}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + Debug_MIT_GSSAPI|Win32 = Debug_MIT_GSSAPI|Win32 + Debug_MIT_GSSAPI|x64 = Debug_MIT_GSSAPI|x64 + Release_MIT_GSSAPI|Win32 = Release_MIT_GSSAPI|Win32 + Release_MIT_GSSAPI|x64 = Release_MIT_GSSAPI|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Debug|Win32.ActiveCfg = Debug|Win32 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Debug|Win32.Build.0 = Debug|Win32 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Debug|x64.ActiveCfg = Debug|x64 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Debug|x64.Build.0 = Debug|x64 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Release|Win32.ActiveCfg = Release|Win32 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Release|Win32.Build.0 = Release|Win32 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Release|x64.ActiveCfg = Release|x64 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Release|x64.Build.0 = Release|x64 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Debug_MIT_GSSAPI|Win32.ActiveCfg = Debug_MIT_GSSAPI|Win32 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Debug_MIT_GSSAPI|Win32.Build.0 = Debug_MIT_GSSAPI|Win32 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Debug_MIT_GSSAPI|x64.ActiveCfg = Debug_MIT_GSSAPI|x64 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Debug_MIT_GSSAPI|x64.Build.0 = Debug_MIT_GSSAPI|x64 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Release_MIT_GSSAPI|Win32.ActiveCfg = Release_MIT_GSSAPI|Win32 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Release_MIT_GSSAPI|Win32.Build.0 = Release_MIT_GSSAPI|Win32 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Release_MIT_GSSAPI|x64.ActiveCfg = Release_MIT_GSSAPI|x64 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Release_MIT_GSSAPI|x64.Build.0 = Release_MIT_GSSAPI|x64 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Debug|Win32.ActiveCfg = Debug|Win32 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Debug|Win32.Build.0 = Debug|Win32 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Debug|x64.ActiveCfg = Debug|x64 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Debug|x64.Build.0 = Debug|x64 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Release|Win32.ActiveCfg = Release|Win32 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Release|Win32.Build.0 = Release|Win32 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Release|x64.ActiveCfg = Release|x64 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Release|x64.Build.0 = Release|x64 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Debug_MIT_GSSAPI|Win32.ActiveCfg = Debug|Win32 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Debug_MIT_GSSAPI|Win32.Build.0 = Debug|Win32 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Debug_MIT_GSSAPI|x64.ActiveCfg = Debug|x64 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Debug_MIT_GSSAPI|x64.Build.0 = Debug|x64 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Release_MIT_GSSAPI|Win32.ActiveCfg = Release|Win32 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Release_MIT_GSSAPI|Win32.Build.0 = Release|Win32 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Release_MIT_GSSAPI|x64.ActiveCfg = Release|x64 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Release_MIT_GSSAPI|x64.Build.0 = Release|x64 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Debug|Win32.ActiveCfg = Debug|Win32 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Debug|Win32.Build.0 = Debug|Win32 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Debug|x64.ActiveCfg = Debug|x64 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Debug|x64.Build.0 = Debug|x64 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Release|Win32.ActiveCfg = Release|Win32 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Release|Win32.Build.0 = Release|Win32 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Release|x64.ActiveCfg = Release|x64 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Release|x64.Build.0 = Release|x64 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Debug_MIT_GSSAPI|Win32.ActiveCfg = Debug|Win32 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Debug_MIT_GSSAPI|Win32.Build.0 = Debug|Win32 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Debug_MIT_GSSAPI|x64.ActiveCfg = Debug|x64 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Debug_MIT_GSSAPI|x64.Build.0 = Debug|x64 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Release_MIT_GSSAPI|Win32.ActiveCfg = Release|Win32 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Release_MIT_GSSAPI|Win32.Build.0 = Release|Win32 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Release_MIT_GSSAPI|x64.ActiveCfg = Release|x64 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Release_MIT_GSSAPI|x64.Build.0 = Release|x64 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Debug|Win32.ActiveCfg = Debug|Win32 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Debug|Win32.Build.0 = Debug|Win32 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Debug|x64.ActiveCfg = Debug|x64 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Debug|x64.Build.0 = Debug|x64 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Release|Win32.ActiveCfg = Release|Win32 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Release|Win32.Build.0 = Release|Win32 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Release|x64.ActiveCfg = Release|x64 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Release|x64.Build.0 = Release|x64 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Debug_MIT_GSSAPI|Win32.ActiveCfg = Debug|Win32 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Debug_MIT_GSSAPI|Win32.Build.0 = Debug|Win32 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Debug_MIT_GSSAPI|x64.ActiveCfg = Debug|x64 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Debug_MIT_GSSAPI|x64.Build.0 = Debug|x64 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Release_MIT_GSSAPI|Win32.ActiveCfg = Release|Win32 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Release_MIT_GSSAPI|Win32.Build.0 = Release|Win32 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Release_MIT_GSSAPI|x64.ActiveCfg = Release|x64 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Release_MIT_GSSAPI|x64.Build.0 = Release|x64 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Debug|Win32.ActiveCfg = Debug|Win32 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Debug|Win32.Build.0 = Debug|Win32 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Debug|x64.ActiveCfg = Debug|x64 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Debug|x64.Build.0 = Debug|x64 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Release|Win32.ActiveCfg = Release|Win32 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Release|Win32.Build.0 = Release|Win32 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Release|x64.ActiveCfg = Release|x64 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Release|x64.Build.0 = Release|x64 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Debug_MIT_GSSAPI|Win32.ActiveCfg = Debug|Win32 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Debug_MIT_GSSAPI|Win32.Build.0 = Debug|Win32 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Debug_MIT_GSSAPI|x64.ActiveCfg = Debug|x64 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Debug_MIT_GSSAPI|x64.Build.0 = Debug|x64 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Release_MIT_GSSAPI|Win32.ActiveCfg = Release|Win32 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Release_MIT_GSSAPI|Win32.Build.0 = Release|Win32 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Release_MIT_GSSAPI|x64.ActiveCfg = Release|x64 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Release_MIT_GSSAPI|x64.Build.0 = Release|x64 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Debug|Win32.ActiveCfg = Debug|Win32 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Debug|Win32.Build.0 = Debug|Win32 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Debug|x64.ActiveCfg = Debug|x64 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Debug|x64.Build.0 = Debug|x64 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Release|Win32.ActiveCfg = Release|Win32 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Release|Win32.Build.0 = Release|Win32 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Release|x64.ActiveCfg = Release|x64 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Release|x64.Build.0 = Release|x64 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Debug_MIT_GSSAPI|Win32.ActiveCfg = Debug|Win32 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Debug_MIT_GSSAPI|Win32.Build.0 = Debug|Win32 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Debug_MIT_GSSAPI|x64.ActiveCfg = Debug|x64 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Debug_MIT_GSSAPI|x64.Build.0 = Debug|x64 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Release_MIT_GSSAPI|Win32.ActiveCfg = Release|Win32 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Release_MIT_GSSAPI|Win32.Build.0 = Release|Win32 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Release_MIT_GSSAPI|x64.ActiveCfg = Release|x64 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Release_MIT_GSSAPI|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/win32/vs12/simple-httpd.vcxproj b/win32/vs12/simple-httpd.vcxproj new file mode 100644 index 0000000..fd1f564 --- /dev/null +++ b/win32/vs12/simple-httpd.vcxproj @@ -0,0 +1,159 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {80DC062E-2146-4CE8-A448-FD2205AB2CA4} + simplehttpd + Win32Proj + + + + Application + Unicode + v120 + true + + + Application + Unicode + v120 + + + Application + Unicode + v120 + true + + + Application + Unicode + v120 + + + + + + + + + + + + + + + + + + + + + + true + false + + + Disabled + _DEBUG;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + EditAndContinue + + + true + Console + MachineX86 + + + + + MaxSpeed + true + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + true + Console + true + true + MachineX86 + + + + + X64 + + + Disabled + _DEBUG;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + ProgramDatabase + + + true + Console + MachineX64 + + + + + X64 + + + MaxSpeed + true + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + true + Console + true + true + MachineX64 + + + + + + + + {d83a3162-b14c-459c-af81-15bbfa90240d} + false + + + + + + diff --git a/win32/vs12/simple-httpd.vcxproj.filters b/win32/vs12/simple-httpd.vcxproj.filters new file mode 100644 index 0000000..14cf1d4 --- /dev/null +++ b/win32/vs12/simple-httpd.vcxproj.filters @@ -0,0 +1,17 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav + + + Sources + + diff --git a/win32/vs12/simple-proxy.vcxproj b/win32/vs12/simple-proxy.vcxproj new file mode 100644 index 0000000..0071cbd --- /dev/null +++ b/win32/vs12/simple-proxy.vcxproj @@ -0,0 +1,159 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E} + simpleproxy + Win32Proj + + + + Application + Unicode + v120 + true + + + Application + Unicode + v120 + + + Application + Unicode + v120 + true + + + Application + Unicode + v120 + + + + + + + + + + + + + + + + + + + + + + true + false + + + Disabled + _DEBUG;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + EditAndContinue + + + true + Console + MachineX86 + + + + + MaxSpeed + true + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + true + Console + true + true + MachineX86 + + + + + X64 + + + Disabled + _DEBUG;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + ProgramDatabase + + + true + Console + MachineX64 + + + + + X64 + + + MaxSpeed + true + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + true + Console + true + true + MachineX64 + + + + + + + + {d83a3162-b14c-459c-af81-15bbfa90240d} + false + + + + + + diff --git a/win32/vs12/simple-proxy.vcxproj.filters b/win32/vs12/simple-proxy.vcxproj.filters new file mode 100644 index 0000000..4a7f2f2 --- /dev/null +++ b/win32/vs12/simple-proxy.vcxproj.filters @@ -0,0 +1,17 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav + + + Sources + + diff --git a/win32/vs12/soup-build-defines.props b/win32/vs12/soup-build-defines.props new file mode 100644 index 0000000..0c9b527 --- /dev/null +++ b/win32/vs12/soup-build-defines.props @@ -0,0 +1,29 @@ + + + + + + + + <_PropertySheetDisplayName>soupbuilddefinesprops + $(SolutionDir)$(Configuration)\$(PlatformName)\bin\ + $(SolutionDir)$(Configuration)\$(PlatformName)\obj\$(ProjectName)\ + + + + ..\..;$(GlibEtcInstallRoot)\include\gio-win32-2.0;$(GlibEtcInstallRoot)\include\glib-2.0;$(GlibEtcInstallRoot)\lib\glib-2.0\include;$(GlibEtcInstallRoot)\include\libxml2;$(GlibEtcInstallRoot)\include;%(AdditionalIncludeDirectories) + HAVE_CONFIG_H;%(PreprocessorDefinitions) + msvc_recommended_pragmas.h;%(ForcedIncludeFiles) + true + /d2Zi+ %(AdditionalOptions) + + + gio-2.0.lib;gobject-2.0.lib;glib-2.0.lib;%(AdditionalDependencies) + $(GlibEtcInstallRoot)\lib;%(AdditionalLibraryDirectories) + /HIGHENTROPYVA %(AdditionalOptions) + /HIGHENTROPYVA %(AdditionalOptions) + /HIGHENTROPYVA %(AdditionalOptions) + /HIGHENTROPYVA %(AdditionalOptions) + + + diff --git a/win32/vs12/soup-dll-build-defines.props b/win32/vs12/soup-dll-build-defines.props new file mode 100644 index 0000000..40591ff --- /dev/null +++ b/win32/vs12/soup-dll-build-defines.props @@ -0,0 +1,24 @@ + + + + + + + LIBSOUP_COMPILATION;DLL_EXPORT;G_LOG_DOMAIN="libsoup" + LIBSOUP_HAVE_GSSAPI + libxml2.lib;sqlite3.lib;intl.lib;ws2_32.lib + gssapi + 32.lib + 64.lib + + + <_PropertySheetDisplayName>soupdllbuilddefinesprops + + + + $(OutDir)$(SoupDllPrefix)$(ProjectName)$(SoupDllSuffix).dll + $(OutDir)$(SoupDllPrefix)$(ProjectName)$(SoupDllSuffix).pdb + $(OutDir)$(ProjectName)-$(ApiVersion).lib + + + diff --git a/win32/vs12/soup-gen-srcs.props b/win32/vs12/soup-gen-srcs.props new file mode 100644 index 0000000..760825c --- /dev/null +++ b/win32/vs12/soup-gen-srcs.props @@ -0,0 +1,26 @@ + + + + + + + copy ..\..\config.h.win32 ..\..\config.h + $(PythonPath)\python.exe ..\soup_version_h.py --version=$(SoupMajorVersion).$(SoupMinorVersion).$(SoupMicroVersion) + $(PythonPath)\python.exe ..\..\libsoup\tld-parser.py ..\..\data\effective_tld_names.dat ..\..\libsoup\tld_data.inc + + + <_PropertySheetDisplayName>soupgensrcsprops + + + + + $(CopyConfigH) + + + $(GenSoupVersionH) + + + $(GenTldDataInc) + + + diff --git a/win32/vs12/soup-gnome.vcxproj b/win32/vs12/soup-gnome.vcxproj new file mode 100644 index 0000000..5020928 --- /dev/null +++ b/win32/vs12/soup-gnome.vcxproj @@ -0,0 +1,164 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {8C88A385-28C8-4B30-91A4-FBA381A5A46F} + soupgnome + Win32Proj + + + + DynamicLibrary + Unicode + v120 + true + + + DynamicLibrary + Unicode + v120 + + + DynamicLibrary + Unicode + v120 + true + + + DynamicLibrary + Unicode + v120 + + + + + + + + + + + + + + + + + + + + + + true + false + + + Disabled + _DEBUG;$(SoupBuildDefines);%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + EditAndContinue + + + true + Windows + MachineX86 + + + + + MaxSpeed + true + $(SoupBuildDefines);%(PreprocessorDefinitions) + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + true + Windows + true + true + MachineX86 + + + + + X64 + + + Disabled + _DEBUG;$(SoupBuildDefines);%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + ProgramDatabase + + + true + Windows + MachineX64 + + + + + X64 + + + MaxSpeed + true + $(SoupBuildDefines);%(PreprocessorDefinitions) + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + true + Windows + true + true + MachineX64 + + + + + + + + + + + {d83a3162-b14c-459c-af81-15bbfa90240d} + false + + + + + + diff --git a/win32/vs12/soup-gnome.vcxproj.filters b/win32/vs12/soup-gnome.vcxproj.filters new file mode 100644 index 0000000..924bf66 --- /dev/null +++ b/win32/vs12/soup-gnome.vcxproj.filters @@ -0,0 +1,20 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav + + + Source Files + Source Files + Source Files + Source Files + + diff --git a/win32/vs12/soup-install.props b/win32/vs12/soup-install.props new file mode 100644 index 0000000..fb3240e --- /dev/null +++ b/win32/vs12/soup-install.props @@ -0,0 +1,101 @@ + + + + + + + +mkdir $(CopyDir)\bin +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\$(SoupDllPrefix)soup$(SoupDllSuffix).dll $(CopyDir)\bin +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\$(SoupDllPrefix)soup$(SoupDllSuffix).pdb $(CopyDir)\bin +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\$(SoupDllPrefix)soup-gnome$(SoupDllSuffix).dll $(CopyDir)\bin +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\$(SoupDllPrefix)soup-gnome$(SoupDllSuffix).pdb $(CopyDir)\bin +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\get.exe $(CopyDir)\bin +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\get.pdb $(CopyDir)\bin +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\simple-httpd.exe $(CopyDir)\bin +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\simple-httpd.pdb $(CopyDir)\bin +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\simple-proxy.exe $(CopyDir)\bin +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\simple-proxy.pdb $(CopyDir)\bin +mkdir $(CopyDir)\lib +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\soup-$(ApiVersion).lib $(CopyDir)\lib +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\soup-gnome-$(ApiVersion).lib $(CopyDir)\lib +copy ..\libsoup-$(ApiVersion).pc $(CopyDir)\lib\pkgconfig +copy ..\libsoup-gnome-$(ApiVersion).pc $(CopyDir)\lib\pkgconfig +mkdir $(CopyDir)\include\libsoup-$(ApiVersion)\libsoup +copy ..\..\libsoup\soup.h $(CopyDir)\include\libsoup-2.4\libsoup\soup.h +copy ..\..\libsoup\soup-address.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-address.h +copy ..\..\libsoup\soup-auth.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-auth.h +copy ..\..\libsoup\soup-auth-domain.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-auth-domain.h +copy ..\..\libsoup\soup-auth-domain-basic.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-auth-domain-basic.h +copy ..\..\libsoup\soup-auth-domain-digest.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-auth-domain-digest.h +copy ..\..\libsoup\soup-auth-manager.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-auth-manager.h +copy ..\..\libsoup\soup-autocleanups.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-autocleanups.h +copy ..\..\libsoup\soup-cache.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-cache.h +copy ..\..\libsoup\soup-content-decoder.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-content-decoder.h +copy ..\..\libsoup\soup-content-sniffer.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-content-sniffer.h +copy ..\..\libsoup\soup-cookie.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-cookie.h +copy ..\..\libsoup\soup-cookie-jar.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-cookie-jar.h +copy ..\..\libsoup\soup-cookie-jar-db.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-cookie-jar-db.h +copy ..\..\libsoup\soup-cookie-jar-text.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-cookie-jar-text.h +copy ..\..\libsoup\soup-date.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-date.h +copy ..\..\libsoup\soup-form.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-form.h +copy ..\..\libsoup\soup-headers.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-headers.h +copy ..\..\libsoup\soup-logger.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-logger.h +copy ..\..\libsoup\soup-message.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-message.h +copy ..\..\libsoup\soup-message-body.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-message-body.h +copy ..\..\libsoup\soup-message-headers.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-message-headers.h +copy ..\..\libsoup\soup-method.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-method.h +copy ..\..\libsoup\soup-misc.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-misc.h +copy ..\..\libsoup\soup-multipart.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-multipart.h +copy ..\..\libsoup\soup-multipart-input-stream.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-multipart-input-stream.h +copy ..\..\libsoup\soup-password-manager.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-password-manager.h +copy ..\..\libsoup\soup-portability.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-portability.h +copy ..\..\libsoup\soup-proxy-resolver.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-proxy-resolver.h +copy ..\..\libsoup\soup-proxy-resolver-default.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-proxy-resolver-default.h +copy ..\..\libsoup\soup-proxy-uri-resolver.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-proxy-uri-resolver.h +copy ..\..\libsoup\soup-request.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-request.h +copy ..\..\libsoup\soup-request-data.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-request-data.h +copy ..\..\libsoup\soup-request-file.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-request-file.h +copy ..\..\libsoup\soup-request-http.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-request-http.h +copy ..\..\libsoup\soup-requester.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-requester.h +copy ..\..\libsoup\soup-server.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-server.h +copy ..\..\libsoup\soup-session.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-session.h +copy ..\..\libsoup\soup-session-async.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-session-async.h +copy ..\..\libsoup\soup-session-feature.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-session-feature.h +copy ..\..\libsoup\soup-session-sync.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-session-sync.h +copy ..\..\libsoup\soup-socket.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-socket.h +copy ..\..\libsoup\soup-status.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-status.h +copy ..\..\libsoup\soup-tld.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-tld.h +copy ..\..\libsoup\soup-types.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-types.h +copy ..\..\libsoup\soup-uri.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-uri.h +copy ..\..\libsoup\soup-value-utils.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-value-utils.h +copy ..\..\libsoup\soup-websocket.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-websocket.h +copy ..\..\libsoup\soup-websocket-connection.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-websocket-connection.h +copy ..\..\libsoup\soup-xmlrpc.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-xmlrpc.h +copy ..\..\libsoup\soup-xmlrpc-old.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-xmlrpc-old.h +copy ..\..\libsoup\soup-enum-types.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-enum-types.h +copy ..\..\libsoup\soup-version.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-version.h +mkdir $(CopyDir)\include\libsoup-gnome-$(ApiVersion)\libsoup +copy ..\..\libsoup\soup-cookie-jar-sqlite.h $(CopyDir)\include\libsoup-gnome-2.4\libsoup\soup-cookie-jar-sqlite.h +copy ..\..\libsoup\soup-gnome.h $(CopyDir)\include\libsoup-gnome-2.4\libsoup\soup-gnome.h +copy ..\..\libsoup\soup-gnome-features.h $(CopyDir)\include\libsoup-gnome-2.4\libsoup\soup-gnome-features.h + + ..\libsoup-$(ApiVersion).pc;..\libsoup-gnome-$(ApiVersion).pc + (if not exist $(CopyDir)\lib\pkgconfig mkdir $(CopyDir)\lib\pkgconfig) & ($(PythonPath)\python.exe ..\souppc.py --prefix=$(CopyDir) --version=$(SoupMajorVersion).$(SoupMinorVersion).$(SoupMicroVersion)) + + + <_PropertySheetDisplayName>soupinstallprops + + + + + $(SoupDoInstall) + + + $(SoupPCFiles) + + + $(SoupGenPC) + + + diff --git a/win32/vs12/soup-install.vcxproj b/win32/vs12/soup-install.vcxproj new file mode 100644 index 0000000..03a6acd --- /dev/null +++ b/win32/vs12/soup-install.vcxproj @@ -0,0 +1,121 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {E0DCF460-914F-46F9-94D6-86D456CB53E9} + soupinstall + + + + Utility + MultiByte + v120 + true + + + Utility + MultiByte + v120 + + + Utility + MultiByte + v120 + true + + + Utility + MultiByte + v120 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Copying build results... + $(SoupPCFiles) + $(SoupDoInstall) + some_file;%(Outputs) + Copying build results... + $(SoupPCFiles) + $(SoupDoInstall) + some_file;%(Outputs) + + + Generating .pc files... + $(SoupGenPC) + $(SoupPCFiles);%(Outputs) + Generating .pc files... + $(SoupGenPC) + $(SoupPCFiles);%(Outputs) + + + + + {b24831c4-b8f2-41d6-aaf4-12192f71c623} + false + + + {80dc062e-2146-4ce8-a448-fd2205ab2ca4} + false + + + {3ad0cb92-ee38-425e-83cb-e7b1cb1d305e} + false + + + {8c88a385-28c8-4b30-91a4-fba381a5a46f} + false + + + {d83a3162-b14c-459c-af81-15bbfa90240d} + false + + + + + + diff --git a/win32/vs12/soup-install.vcxproj.filters b/win32/vs12/soup-install.vcxproj.filters new file mode 100644 index 0000000..2627f42 --- /dev/null +++ b/win32/vs12/soup-install.vcxproj.filters @@ -0,0 +1,13 @@ + + + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav + + + + Resource Files + Resource Files + + diff --git a/win32/vs12/soup-version-paths.props b/win32/vs12/soup-version-paths.props new file mode 100644 index 0000000..9a9a083 --- /dev/null +++ b/win32/vs12/soup-version-paths.props @@ -0,0 +1,69 @@ + + + + + + 12 + ..\..\..\vs$(VSVer)\$(Platform) + $(GlibEtcInstallRoot) + 2 + 62 + 3 + 2.4 + lib + -$(ApiVersion)-0 + + -$(ApiVersion)-vs$(VSVer) + $(SoupSeparateVSDllPrefix) + $(SoupSeparateVSDllSuffix) + c:\python34 + + + <_PropertySheetDisplayName>soupversionpathsprops + + + + + $(VSVer) + + + $(GlibEtcInstallRoot) + + + $(CopyDir) + + + $(SoupMajorVersion) + + + $(SoupMinorVersion) + + + $(SoupMicroVersion) + + + $(ApiVersion) + + + $(SoupLibtoolCompatibleDllPrefix) + + + $(SoupLibtoolCompatibleDllSuffix) + + + $(SoupSeparateVSDllPrefix) + + + $(SoupSeparateVSDllSuffix) + + + $(SoupDllPrefix) + + + $(SoupDllSuffix) + + + $(PythonPath) + + + diff --git a/win32/vs12/soup.vcxproj b/win32/vs12/soup.vcxproj new file mode 100644 index 0000000..e49c437 --- /dev/null +++ b/win32/vs12/soup.vcxproj @@ -0,0 +1,414 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + Debug_MIT_GSSAPI + Win32 + + + Debug_MIT_GSSAPI + x64 + + + Release_MIT_GSSAPI + Win32 + + + Release_MIT_GSSAPI + x64 + + + + {D83A3162-B14C-459C-AF81-15BBFA90240D} + soup + Win32Proj + + + + DynamicLibrary + Unicode + v120 + + + DynamicLibrary + Unicode + v120 + + + DynamicLibrary + Unicode + v120 + true + + + DynamicLibrary + Unicode + v120 + true + + + DynamicLibrary + Unicode + v120 + + + DynamicLibrary + Unicode + v120 + + + DynamicLibrary + Unicode + v120 + true + + + DynamicLibrary + Unicode + v120 + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + false + trueDebug\$(Platform)\bin\ + falseRelease\$(Platform)\bin\ + + + Disabled + _DEBUG;$(SoupBuildDefines);%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + EditAndContinue + + + $(SoupExtraDepLibs);%(AdditionalDependencies) + true + Windows + MachineX86 + + + + + Disabled + _DEBUG;$(SoupBuildDefines);$(SoupMITGSSAPIBuildDefines);%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + EditAndContinue + + + $(SoupExtraDepLibs);$(MITGSSAPILibBaseName)$(MITGSSAPILibNameSuffixX86);%(AdditionalDependencies) + true + Windows + MachineX86 + + + + + MaxSpeed + true + $(SoupBuildDefines);%(PreprocessorDefinitions) + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + $(SoupExtraDepLibs);%(AdditionalDependencies) + true + Windows + true + true + MachineX86 + + + + + MaxSpeed + true + $(SoupBuildDefines);$(SoupMITGSSAPIBuildDefines);%(PreprocessorDefinitions) + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + $(SoupExtraDepLibs);$(MITGSSAPILibBaseName)$(MITGSSAPILibNameSuffixX86);%(AdditionalDependencies) + true + Windows + true + true + MachineX86 + + + + + X64 + + + Disabled + _DEBUG;$(SoupBuildDefines);%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + ProgramDatabase + + + $(SoupExtraDepLibs);%(AdditionalDependencies) + true + Windows + MachineX64 + + + + + X64 + + + Disabled + _DEBUG;$(SoupBuildDefines);$(SoupMITGSSAPIBuildDefines);%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + ProgramDatabase + + + $(SoupExtraDepLibs);$(MITGSSAPILibBaseName)$(MITGSSAPILibNameSuffixX64);%(AdditionalDependencies) + true + Windows + MachineX64 + + + + + X64 + + + MaxSpeed + true + $(SoupBuildDefines);%(PreprocessorDefinitions) + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + $(SoupExtraDepLibs);%(AdditionalDependencies) + true + Windows + true + true + MachineX64 + + + + + X64 + + + MaxSpeed + true + $(SoupBuildDefines);$(SoupMITGSSAPIBuildDefines);%(PreprocessorDefinitions) + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + $(SoupExtraDepLibs);$(MITGSSAPILibBaseName)$(MITGSSAPILibNameSuffixX64);%(AdditionalDependencies) + true + Windows + true + true + MachineX64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Copying config.h from config.h.win32... + $(CopyConfigH) + ..\..\config.h;%(Outputs) + Copying config.h from config.h.win32... + $(CopyConfigH) + ..\..\config.h;%(Outputs) + Copying config.h from config.h.win32... + $(CopyConfigH) + ..\..\config.h;%(Outputs) + Copying config.h from config.h.win32... + $(CopyConfigH) + ..\..\config.h;%(Outputs) + + + Generating tld_data.inc... + $(GenTldDataInc) + ..\..\libsoup\tld_data.inc;%(Outputs) + Generating tld_data.inc... + $(GenTldDataInc) + ..\..\libsoup\tld_data.inc;%(Outputs) + Generating tld_data.inc... + $(GenTldDataInc) + ..\..\libsoup\tld_data.inc;%(Outputs) + Generating tld_data.inc... + $(GenTldDataInc) + ..\..\libsoup\tld_data.inc;%(Outputs) + + + Generating soup-version.h... + $(GenSoupVersionH) + ..\..\libsoup\soup-version.h;%(Outputs) + Generating soup-version.h... + $(GenSoupVersionH) + ..\..\libsoup\soup-version.h;%(Outputs) + Generating soup-version.h... + $(GenSoupVersionH) + ..\..\libsoup\soup-version.h;%(Outputs) + Generating soup-version.h... + $(GenSoupVersionH) + ..\..\libsoup\soup-version.h;%(Outputs) + + + + + + diff --git a/win32/vs12/soup.vcxproj.filters b/win32/vs12/soup.vcxproj.filters new file mode 100644 index 0000000..71eb5a6 --- /dev/null +++ b/win32/vs12/soup.vcxproj.filters @@ -0,0 +1,95 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav + + + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + + + Resource Files + Resource Files + Resource Files + + diff --git a/win32/vs14/Makefile.am b/win32/vs14/Makefile.am new file mode 100644 index 0000000..43db09d --- /dev/null +++ b/win32/vs14/Makefile.am @@ -0,0 +1,28 @@ +EXTRA_DIST = \ + libsoup.sln \ + get.vcxproj \ + simple-httpd.vcxproj \ + simple-proxy.vcxproj \ + get.vcxproj.filters \ + soup-install.vcxproj \ + soup-install.vcxproj.filters \ + simple-httpd.vcxproj.filters \ + simple-proxy.vcxproj.filters \ + soup-build-defines.props \ + soup-dll-build-defines.props \ + soup-gen-srcs.props \ + soup-version-paths.props \ + soup.vcxproj \ + soup-gnome.vcxproj \ + soup.vcxproj.filters \ + soup-gnome.vcxproj.filters \ + soup-install.props + +DISTCLEANFILES = $(EXTRA_DIST) + +MSVC_BASE_VER = 10 +MSVC_BASE_VER_LONG = 2010 +MSVC_VER = 14 +MSVC_VER_LONG = 14 + +include $(top_srcdir)/win32/Makefile-newvs.am diff --git a/win32/vs14/Makefile.in b/win32/vs14/Makefile.in new file mode 100644 index 0000000..5ed552b --- /dev/null +++ b/win32/vs14/Makefile.in @@ -0,0 +1,600 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Centralized autotools file +# Create the Visual Studio 2012/2013/2015 project files +# from the Visual Studio 2010 project files + +# This autotools file, from GLib, can be used in other projects +# that have Visual Studio build support. + +# Author: Fan, Chun-wei +# November 05, 2012 + +# MSVC_BASE_VER: Baseline MSVC 201x version to copy/process project files from (100 for 2010, 120 for 2013) +# MSVC_BASE_VER_LONG: Long Version of baseline Visual Studio 201x version (2010, 2012, 2013, 14, 15) +# MSVC_BASE_TOOLSET: Use if baseline MSVC toolset is not in the form v$(MSVC_BASE_VER)0, meaning v$(MSVC_BASE_TOOLSET) +# MSVC_VER_LONG: Long Version of target Visual Studio (2012, 2013, 14 and so on) +# MSVC_VER: Short Version of target Visual Studio (110 for 2012, 120 for 2013, 140 for 2015, 141 for 2017) +# MSVC_TOOLSET: Use if target MSVC toolsett is not in the form v $(MSVC_VER)0, meaning v$(MSVC_TOOLSET) +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = win32/vs14 +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_code_coverage.m4 \ + $(top_srcdir)/m4/glibtests.m4 $(top_srcdir)/m4/gtk-doc.m4 \ + $(top_srcdir)/m4/intltool.m4 $(top_srcdir)/m4/introspection.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/vapigen.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +am__DIST_COMMON = $(srcdir)/Makefile.in \ + $(top_srcdir)/win32/Makefile-newvs.am +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALL_LINGUAS = @ALL_LINGUAS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +APACHE_HTTPD = @APACHE_HTTPD@ +APACHE_MODULE_DIR = @APACHE_MODULE_DIR@ +APACHE_PHP_MODULE_DIR = @APACHE_PHP_MODULE_DIR@ +APACHE_SSL_MODULE_DIR = @APACHE_SSL_MODULE_DIR@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CODE_COVERAGE_CFLAGS = @CODE_COVERAGE_CFLAGS@ +CODE_COVERAGE_CPPFLAGS = @CODE_COVERAGE_CPPFLAGS@ +CODE_COVERAGE_CXXFLAGS = @CODE_COVERAGE_CXXFLAGS@ +CODE_COVERAGE_ENABLED = @CODE_COVERAGE_ENABLED@ +CODE_COVERAGE_LDFLAGS = @CODE_COVERAGE_LDFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CURL = @CURL@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GCOV = @GCOV@ +GENHTML = @GENHTML@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_COMPILE_RESOURCES = @GLIB_COMPILE_RESOURCES@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MAKEFILE = @GLIB_MAKEFILE@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GMSGFMT = @GMSGFMT@ +GOBJECT_QUERY = @GOBJECT_QUERY@ +GREP = @GREP@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +HAVE_GNOME = @HAVE_GNOME@ +HTML_DIR = @HTML_DIR@ +IF_HAVE_MOD_UNIXD = @IF_HAVE_MOD_UNIXD@ +IF_HAVE_PHP = @IF_HAVE_PHP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ +INTLTOOL_MERGE = @INTLTOOL_MERGE@ +INTLTOOL_PERL = @INTLTOOL_PERL@ +INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ +INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@ +INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@ +INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@ +INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LCOV = @LCOV@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PHP = @PHP@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOUP_AGE = @SOUP_AGE@ +SOUP_API_VERSION = @SOUP_API_VERSION@ +SOUP_CURRENT = @SOUP_CURRENT@ +SOUP_DEBUG_FLAGS = @SOUP_DEBUG_FLAGS@ +SOUP_HIDDEN_VISIBILITY_CFLAGS = @SOUP_HIDDEN_VISIBILITY_CFLAGS@ +SOUP_MAJOR_VERSION = @SOUP_MAJOR_VERSION@ +SOUP_MICRO_VERSION = @SOUP_MICRO_VERSION@ +SOUP_MINOR_VERSION = @SOUP_MINOR_VERSION@ +SOUP_REVISION = @SOUP_REVISION@ +SQLITE_CFLAGS = @SQLITE_CFLAGS@ +SQLITE_LIBS = @SQLITE_LIBS@ +STRIP = @STRIP@ +USE_NLS = @USE_NLS@ +VALAC = @VALAC@ +VAPIDIR = @VAPIDIR@ +VAPIGEN = @VAPIGEN@ +VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@ +VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@ +VERSION = @VERSION@ +XGETTEXT = @XGETTEXT@ +XML_CFLAGS = @XML_CFLAGS@ +XML_LIBS = @XML_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +installed_test_metadir = @installed_test_metadir@ +installed_testdir = @installed_testdir@ +intltool__v_merge_options_ = @intltool__v_merge_options_@ +intltool__v_merge_options_0 = @intltool__v_merge_options_0@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +ntlm_auth = @ntlm_auth@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +EXTRA_DIST = \ + libsoup.sln \ + get.vcxproj \ + simple-httpd.vcxproj \ + simple-proxy.vcxproj \ + get.vcxproj.filters \ + soup-install.vcxproj \ + soup-install.vcxproj.filters \ + simple-httpd.vcxproj.filters \ + simple-proxy.vcxproj.filters \ + soup-build-defines.props \ + soup-dll-build-defines.props \ + soup-gen-srcs.props \ + soup-version-paths.props \ + soup.vcxproj \ + soup-gnome.vcxproj \ + soup.vcxproj.filters \ + soup-gnome.vcxproj.filters \ + soup-install.props + +DISTCLEANFILES = $(EXTRA_DIST) +MSVC_BASE_VER = 10 +MSVC_BASE_VER_LONG = 2010 +MSVC_VER = 14 +MSVC_VER_LONG = 14 +@MSVC_BASE_NO_TOOLSET_SET_TRUE@MSVC_BASE_TOOLSET = $(MSVC_BASE_VER)0 +@MSVC_NO_TOOLSET_SET_TRUE@MSVC_TOOLSET = $(MSVC_VER)0 +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/win32/Makefile-newvs.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign win32/vs14/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign win32/vs14/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; +$(top_srcdir)/win32/Makefile-newvs.am $(am__empty): + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +tags TAGS: + +ctags CTAGS: + +cscope cscopelist: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic clean-libtool \ + cscopelist-am ctags-am distclean distclean-generic \ + distclean-libtool distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +%.sln: + sed 's/11\.00/12\.00/g' < $(top_srcdir)/win32/vs$(MSVC_BASE_VER)/$@ > $(top_builddir)/win32/vs$(MSVC_VER)/$@.tmp + sed 's/$(MSVC_BASE_VER_LONG)/$(MSVC_VER_LONG)/g' < $(top_builddir)/win32/vs$(MSVC_VER)/$@.tmp > $(top_builddir)/win32/vs$(MSVC_VER)/$@ + rm $(top_builddir)/win32/vs$(MSVC_VER)/$@.tmp + +%.txt: + sed 's/vs$(MSVC_BASE_VER)/vs$(MSVC_VER)/g' < $(top_srcdir)/win32/vs$(MSVC_BASE_VER)/$@ > $(top_builddir)/win32/vs$(MSVC_VER)/$@.tmp + sed 's/VS$(MSVC_BASE_VER)/VS$(MSVC_VER)/g' < $(top_builddir)/win32/vs$(MSVC_VER)/$@.tmp > $(top_builddir)/win32/vs$(MSVC_VER)/$@ + rm $(top_builddir)/win32/vs$(MSVC_VER)/$@.tmp + +%.vcxproj: + if test -e $(top_srcdir)/win32/vs$(MSVC_BASE_VER)/$@; then \ + sed 's/v$(MSVC_BASE_TOOLSET)/v$(MSVC_TOOLSET)/g' < $(top_srcdir)/win32/vs$(MSVC_BASE_VER)/$@ > $(top_builddir)/win32/vs$(MSVC_VER)/$@; \ + else \ + sed 's/v$(MSVC_BASE_TOOLSET)/v$(MSVC_TOOLSET)/g' < $(top_builddir)/win32/vs$(MSVC_BASE_VER)/$@ > $(top_builddir)/win32/vs$(MSVC_VER)/$@; \ + fi + +%.props: $(top_builddir)/win32/vs$(MSVC_BASE_VER)/Makefile + if test -e $(top_srcdir)/win32/vs$(MSVC_BASE_VER)/$@; then \ + sed 's/$(MSVC_BASE_VER)<\/VSVer>/$(MSVC_VER)<\/VSVer>/g' < $(top_srcdir)/win32/vs$(MSVC_BASE_VER)/$@ > $(top_builddir)/win32/vs$(MSVC_VER)/$@; \ + else \ + sed 's/$(MSVC_BASE_VER)<\/VSVer>/$(MSVC_VER)<\/VSVer>/g' < $(top_builddir)/win32/vs$(MSVC_BASE_VER)/$@ > $(top_builddir)/win32/vs$(MSVC_VER)/$@; \ + fi + +%.vcxproj.filters: + if test -e $(top_srcdir)/win32/vs$(MSVC_BASE_VER)/$@; then \ + cp $(top_srcdir)/win32/vs$(MSVC_BASE_VER)/$@ $(top_builddir)/win32/vs$(MSVC_VER)/$@; \ + else \ + cp $(top_builddir)/win32/vs$(MSVC_BASE_VER)/$@ $(top_builddir)/win32/vs$(MSVC_VER)/$@; \ + fi + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/win32/vs14/get.vcxproj b/win32/vs14/get.vcxproj new file mode 100644 index 0000000..3b6bfb7 --- /dev/null +++ b/win32/vs14/get.vcxproj @@ -0,0 +1,159 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {B24831C4-B8F2-41D6-AAF4-12192F71C623} + get + Win32Proj + + + + Application + Unicode + v140 + true + + + Application + Unicode + v140 + + + Application + Unicode + v140 + true + + + Application + Unicode + v140 + + + + + + + + + + + + + + + + + + + + + + true + false + + + Disabled + _DEBUG;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + EditAndContinue + + + true + Console + MachineX86 + + + + + MaxSpeed + true + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + true + Console + true + true + MachineX86 + + + + + X64 + + + Disabled + _DEBUG;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + ProgramDatabase + + + true + Console + MachineX64 + + + + + X64 + + + MaxSpeed + true + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + true + Console + true + true + MachineX64 + + + + + + + + {d83a3162-b14c-459c-af81-15bbfa90240d} + false + + + + + + diff --git a/win32/vs14/get.vcxproj.filters b/win32/vs14/get.vcxproj.filters new file mode 100644 index 0000000..9bc6fcf --- /dev/null +++ b/win32/vs14/get.vcxproj.filters @@ -0,0 +1,17 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav + + + Sources + + diff --git a/win32/vs14/libsoup.sln b/win32/vs14/libsoup.sln new file mode 100644 index 0000000..ca11fce --- /dev/null +++ b/win32/vs14/libsoup.sln @@ -0,0 +1,128 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "soup", "soup.vcxproj", "{D83A3162-B14C-459C-AF81-15BBFA90240D}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "soup-gnome", "soup-gnome.vcxproj", "{8C88A385-28C8-4B30-91A4-FBA381A5A46F}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "get", "get.vcxproj", "{B24831C4-B8F2-41D6-AAF4-12192F71C623}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "simple-httpd", "simple-httpd.vcxproj", "{80DC062E-2146-4CE8-A448-FD2205AB2CA4}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "simple-proxy", "simple-proxy.vcxproj", "{3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "soup-install", "soup-install.vcxproj", "{E0DCF460-914F-46F9-94D6-86D456CB53E9}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + Debug_MIT_GSSAPI|Win32 = Debug_MIT_GSSAPI|Win32 + Debug_MIT_GSSAPI|x64 = Debug_MIT_GSSAPI|x64 + Release_MIT_GSSAPI|Win32 = Release_MIT_GSSAPI|Win32 + Release_MIT_GSSAPI|x64 = Release_MIT_GSSAPI|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Debug|Win32.ActiveCfg = Debug|Win32 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Debug|Win32.Build.0 = Debug|Win32 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Debug|x64.ActiveCfg = Debug|x64 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Debug|x64.Build.0 = Debug|x64 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Release|Win32.ActiveCfg = Release|Win32 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Release|Win32.Build.0 = Release|Win32 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Release|x64.ActiveCfg = Release|x64 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Release|x64.Build.0 = Release|x64 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Debug_MIT_GSSAPI|Win32.ActiveCfg = Debug_MIT_GSSAPI|Win32 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Debug_MIT_GSSAPI|Win32.Build.0 = Debug_MIT_GSSAPI|Win32 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Debug_MIT_GSSAPI|x64.ActiveCfg = Debug_MIT_GSSAPI|x64 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Debug_MIT_GSSAPI|x64.Build.0 = Debug_MIT_GSSAPI|x64 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Release_MIT_GSSAPI|Win32.ActiveCfg = Release_MIT_GSSAPI|Win32 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Release_MIT_GSSAPI|Win32.Build.0 = Release_MIT_GSSAPI|Win32 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Release_MIT_GSSAPI|x64.ActiveCfg = Release_MIT_GSSAPI|x64 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Release_MIT_GSSAPI|x64.Build.0 = Release_MIT_GSSAPI|x64 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Debug|Win32.ActiveCfg = Debug|Win32 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Debug|Win32.Build.0 = Debug|Win32 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Debug|x64.ActiveCfg = Debug|x64 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Debug|x64.Build.0 = Debug|x64 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Release|Win32.ActiveCfg = Release|Win32 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Release|Win32.Build.0 = Release|Win32 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Release|x64.ActiveCfg = Release|x64 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Release|x64.Build.0 = Release|x64 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Debug_MIT_GSSAPI|Win32.ActiveCfg = Debug|Win32 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Debug_MIT_GSSAPI|Win32.Build.0 = Debug|Win32 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Debug_MIT_GSSAPI|x64.ActiveCfg = Debug|x64 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Debug_MIT_GSSAPI|x64.Build.0 = Debug|x64 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Release_MIT_GSSAPI|Win32.ActiveCfg = Release|Win32 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Release_MIT_GSSAPI|Win32.Build.0 = Release|Win32 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Release_MIT_GSSAPI|x64.ActiveCfg = Release|x64 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Release_MIT_GSSAPI|x64.Build.0 = Release|x64 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Debug|Win32.ActiveCfg = Debug|Win32 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Debug|Win32.Build.0 = Debug|Win32 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Debug|x64.ActiveCfg = Debug|x64 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Debug|x64.Build.0 = Debug|x64 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Release|Win32.ActiveCfg = Release|Win32 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Release|Win32.Build.0 = Release|Win32 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Release|x64.ActiveCfg = Release|x64 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Release|x64.Build.0 = Release|x64 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Debug_MIT_GSSAPI|Win32.ActiveCfg = Debug|Win32 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Debug_MIT_GSSAPI|Win32.Build.0 = Debug|Win32 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Debug_MIT_GSSAPI|x64.ActiveCfg = Debug|x64 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Debug_MIT_GSSAPI|x64.Build.0 = Debug|x64 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Release_MIT_GSSAPI|Win32.ActiveCfg = Release|Win32 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Release_MIT_GSSAPI|Win32.Build.0 = Release|Win32 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Release_MIT_GSSAPI|x64.ActiveCfg = Release|x64 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Release_MIT_GSSAPI|x64.Build.0 = Release|x64 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Debug|Win32.ActiveCfg = Debug|Win32 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Debug|Win32.Build.0 = Debug|Win32 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Debug|x64.ActiveCfg = Debug|x64 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Debug|x64.Build.0 = Debug|x64 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Release|Win32.ActiveCfg = Release|Win32 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Release|Win32.Build.0 = Release|Win32 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Release|x64.ActiveCfg = Release|x64 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Release|x64.Build.0 = Release|x64 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Debug_MIT_GSSAPI|Win32.ActiveCfg = Debug|Win32 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Debug_MIT_GSSAPI|Win32.Build.0 = Debug|Win32 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Debug_MIT_GSSAPI|x64.ActiveCfg = Debug|x64 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Debug_MIT_GSSAPI|x64.Build.0 = Debug|x64 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Release_MIT_GSSAPI|Win32.ActiveCfg = Release|Win32 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Release_MIT_GSSAPI|Win32.Build.0 = Release|Win32 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Release_MIT_GSSAPI|x64.ActiveCfg = Release|x64 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Release_MIT_GSSAPI|x64.Build.0 = Release|x64 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Debug|Win32.ActiveCfg = Debug|Win32 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Debug|Win32.Build.0 = Debug|Win32 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Debug|x64.ActiveCfg = Debug|x64 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Debug|x64.Build.0 = Debug|x64 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Release|Win32.ActiveCfg = Release|Win32 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Release|Win32.Build.0 = Release|Win32 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Release|x64.ActiveCfg = Release|x64 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Release|x64.Build.0 = Release|x64 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Debug_MIT_GSSAPI|Win32.ActiveCfg = Debug|Win32 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Debug_MIT_GSSAPI|Win32.Build.0 = Debug|Win32 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Debug_MIT_GSSAPI|x64.ActiveCfg = Debug|x64 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Debug_MIT_GSSAPI|x64.Build.0 = Debug|x64 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Release_MIT_GSSAPI|Win32.ActiveCfg = Release|Win32 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Release_MIT_GSSAPI|Win32.Build.0 = Release|Win32 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Release_MIT_GSSAPI|x64.ActiveCfg = Release|x64 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Release_MIT_GSSAPI|x64.Build.0 = Release|x64 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Debug|Win32.ActiveCfg = Debug|Win32 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Debug|Win32.Build.0 = Debug|Win32 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Debug|x64.ActiveCfg = Debug|x64 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Debug|x64.Build.0 = Debug|x64 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Release|Win32.ActiveCfg = Release|Win32 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Release|Win32.Build.0 = Release|Win32 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Release|x64.ActiveCfg = Release|x64 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Release|x64.Build.0 = Release|x64 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Debug_MIT_GSSAPI|Win32.ActiveCfg = Debug|Win32 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Debug_MIT_GSSAPI|Win32.Build.0 = Debug|Win32 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Debug_MIT_GSSAPI|x64.ActiveCfg = Debug|x64 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Debug_MIT_GSSAPI|x64.Build.0 = Debug|x64 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Release_MIT_GSSAPI|Win32.ActiveCfg = Release|Win32 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Release_MIT_GSSAPI|Win32.Build.0 = Release|Win32 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Release_MIT_GSSAPI|x64.ActiveCfg = Release|x64 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Release_MIT_GSSAPI|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/win32/vs14/simple-httpd.vcxproj b/win32/vs14/simple-httpd.vcxproj new file mode 100644 index 0000000..13740e1 --- /dev/null +++ b/win32/vs14/simple-httpd.vcxproj @@ -0,0 +1,159 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {80DC062E-2146-4CE8-A448-FD2205AB2CA4} + simplehttpd + Win32Proj + + + + Application + Unicode + v140 + true + + + Application + Unicode + v140 + + + Application + Unicode + v140 + true + + + Application + Unicode + v140 + + + + + + + + + + + + + + + + + + + + + + true + false + + + Disabled + _DEBUG;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + EditAndContinue + + + true + Console + MachineX86 + + + + + MaxSpeed + true + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + true + Console + true + true + MachineX86 + + + + + X64 + + + Disabled + _DEBUG;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + ProgramDatabase + + + true + Console + MachineX64 + + + + + X64 + + + MaxSpeed + true + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + true + Console + true + true + MachineX64 + + + + + + + + {d83a3162-b14c-459c-af81-15bbfa90240d} + false + + + + + + diff --git a/win32/vs14/simple-httpd.vcxproj.filters b/win32/vs14/simple-httpd.vcxproj.filters new file mode 100644 index 0000000..14cf1d4 --- /dev/null +++ b/win32/vs14/simple-httpd.vcxproj.filters @@ -0,0 +1,17 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav + + + Sources + + diff --git a/win32/vs14/simple-proxy.vcxproj b/win32/vs14/simple-proxy.vcxproj new file mode 100644 index 0000000..fa5cbfa --- /dev/null +++ b/win32/vs14/simple-proxy.vcxproj @@ -0,0 +1,159 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E} + simpleproxy + Win32Proj + + + + Application + Unicode + v140 + true + + + Application + Unicode + v140 + + + Application + Unicode + v140 + true + + + Application + Unicode + v140 + + + + + + + + + + + + + + + + + + + + + + true + false + + + Disabled + _DEBUG;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + EditAndContinue + + + true + Console + MachineX86 + + + + + MaxSpeed + true + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + true + Console + true + true + MachineX86 + + + + + X64 + + + Disabled + _DEBUG;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + ProgramDatabase + + + true + Console + MachineX64 + + + + + X64 + + + MaxSpeed + true + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + true + Console + true + true + MachineX64 + + + + + + + + {d83a3162-b14c-459c-af81-15bbfa90240d} + false + + + + + + diff --git a/win32/vs14/simple-proxy.vcxproj.filters b/win32/vs14/simple-proxy.vcxproj.filters new file mode 100644 index 0000000..4a7f2f2 --- /dev/null +++ b/win32/vs14/simple-proxy.vcxproj.filters @@ -0,0 +1,17 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav + + + Sources + + diff --git a/win32/vs14/soup-build-defines.props b/win32/vs14/soup-build-defines.props new file mode 100644 index 0000000..0c9b527 --- /dev/null +++ b/win32/vs14/soup-build-defines.props @@ -0,0 +1,29 @@ + + + + + + + + <_PropertySheetDisplayName>soupbuilddefinesprops + $(SolutionDir)$(Configuration)\$(PlatformName)\bin\ + $(SolutionDir)$(Configuration)\$(PlatformName)\obj\$(ProjectName)\ + + + + ..\..;$(GlibEtcInstallRoot)\include\gio-win32-2.0;$(GlibEtcInstallRoot)\include\glib-2.0;$(GlibEtcInstallRoot)\lib\glib-2.0\include;$(GlibEtcInstallRoot)\include\libxml2;$(GlibEtcInstallRoot)\include;%(AdditionalIncludeDirectories) + HAVE_CONFIG_H;%(PreprocessorDefinitions) + msvc_recommended_pragmas.h;%(ForcedIncludeFiles) + true + /d2Zi+ %(AdditionalOptions) + + + gio-2.0.lib;gobject-2.0.lib;glib-2.0.lib;%(AdditionalDependencies) + $(GlibEtcInstallRoot)\lib;%(AdditionalLibraryDirectories) + /HIGHENTROPYVA %(AdditionalOptions) + /HIGHENTROPYVA %(AdditionalOptions) + /HIGHENTROPYVA %(AdditionalOptions) + /HIGHENTROPYVA %(AdditionalOptions) + + + diff --git a/win32/vs14/soup-dll-build-defines.props b/win32/vs14/soup-dll-build-defines.props new file mode 100644 index 0000000..40591ff --- /dev/null +++ b/win32/vs14/soup-dll-build-defines.props @@ -0,0 +1,24 @@ + + + + + + + LIBSOUP_COMPILATION;DLL_EXPORT;G_LOG_DOMAIN="libsoup" + LIBSOUP_HAVE_GSSAPI + libxml2.lib;sqlite3.lib;intl.lib;ws2_32.lib + gssapi + 32.lib + 64.lib + + + <_PropertySheetDisplayName>soupdllbuilddefinesprops + + + + $(OutDir)$(SoupDllPrefix)$(ProjectName)$(SoupDllSuffix).dll + $(OutDir)$(SoupDllPrefix)$(ProjectName)$(SoupDllSuffix).pdb + $(OutDir)$(ProjectName)-$(ApiVersion).lib + + + diff --git a/win32/vs14/soup-gen-srcs.props b/win32/vs14/soup-gen-srcs.props new file mode 100644 index 0000000..760825c --- /dev/null +++ b/win32/vs14/soup-gen-srcs.props @@ -0,0 +1,26 @@ + + + + + + + copy ..\..\config.h.win32 ..\..\config.h + $(PythonPath)\python.exe ..\soup_version_h.py --version=$(SoupMajorVersion).$(SoupMinorVersion).$(SoupMicroVersion) + $(PythonPath)\python.exe ..\..\libsoup\tld-parser.py ..\..\data\effective_tld_names.dat ..\..\libsoup\tld_data.inc + + + <_PropertySheetDisplayName>soupgensrcsprops + + + + + $(CopyConfigH) + + + $(GenSoupVersionH) + + + $(GenTldDataInc) + + + diff --git a/win32/vs14/soup-gnome.vcxproj b/win32/vs14/soup-gnome.vcxproj new file mode 100644 index 0000000..d220c10 --- /dev/null +++ b/win32/vs14/soup-gnome.vcxproj @@ -0,0 +1,164 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {8C88A385-28C8-4B30-91A4-FBA381A5A46F} + soupgnome + Win32Proj + + + + DynamicLibrary + Unicode + v140 + true + + + DynamicLibrary + Unicode + v140 + + + DynamicLibrary + Unicode + v140 + true + + + DynamicLibrary + Unicode + v140 + + + + + + + + + + + + + + + + + + + + + + true + false + + + Disabled + _DEBUG;$(SoupBuildDefines);%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + EditAndContinue + + + true + Windows + MachineX86 + + + + + MaxSpeed + true + $(SoupBuildDefines);%(PreprocessorDefinitions) + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + true + Windows + true + true + MachineX86 + + + + + X64 + + + Disabled + _DEBUG;$(SoupBuildDefines);%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + ProgramDatabase + + + true + Windows + MachineX64 + + + + + X64 + + + MaxSpeed + true + $(SoupBuildDefines);%(PreprocessorDefinitions) + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + true + Windows + true + true + MachineX64 + + + + + + + + + + + {d83a3162-b14c-459c-af81-15bbfa90240d} + false + + + + + + diff --git a/win32/vs14/soup-gnome.vcxproj.filters b/win32/vs14/soup-gnome.vcxproj.filters new file mode 100644 index 0000000..924bf66 --- /dev/null +++ b/win32/vs14/soup-gnome.vcxproj.filters @@ -0,0 +1,20 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav + + + Source Files + Source Files + Source Files + Source Files + + diff --git a/win32/vs14/soup-install.props b/win32/vs14/soup-install.props new file mode 100644 index 0000000..fb3240e --- /dev/null +++ b/win32/vs14/soup-install.props @@ -0,0 +1,101 @@ + + + + + + + +mkdir $(CopyDir)\bin +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\$(SoupDllPrefix)soup$(SoupDllSuffix).dll $(CopyDir)\bin +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\$(SoupDllPrefix)soup$(SoupDllSuffix).pdb $(CopyDir)\bin +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\$(SoupDllPrefix)soup-gnome$(SoupDllSuffix).dll $(CopyDir)\bin +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\$(SoupDllPrefix)soup-gnome$(SoupDllSuffix).pdb $(CopyDir)\bin +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\get.exe $(CopyDir)\bin +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\get.pdb $(CopyDir)\bin +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\simple-httpd.exe $(CopyDir)\bin +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\simple-httpd.pdb $(CopyDir)\bin +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\simple-proxy.exe $(CopyDir)\bin +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\simple-proxy.pdb $(CopyDir)\bin +mkdir $(CopyDir)\lib +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\soup-$(ApiVersion).lib $(CopyDir)\lib +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\soup-gnome-$(ApiVersion).lib $(CopyDir)\lib +copy ..\libsoup-$(ApiVersion).pc $(CopyDir)\lib\pkgconfig +copy ..\libsoup-gnome-$(ApiVersion).pc $(CopyDir)\lib\pkgconfig +mkdir $(CopyDir)\include\libsoup-$(ApiVersion)\libsoup +copy ..\..\libsoup\soup.h $(CopyDir)\include\libsoup-2.4\libsoup\soup.h +copy ..\..\libsoup\soup-address.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-address.h +copy ..\..\libsoup\soup-auth.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-auth.h +copy ..\..\libsoup\soup-auth-domain.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-auth-domain.h +copy ..\..\libsoup\soup-auth-domain-basic.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-auth-domain-basic.h +copy ..\..\libsoup\soup-auth-domain-digest.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-auth-domain-digest.h +copy ..\..\libsoup\soup-auth-manager.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-auth-manager.h +copy ..\..\libsoup\soup-autocleanups.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-autocleanups.h +copy ..\..\libsoup\soup-cache.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-cache.h +copy ..\..\libsoup\soup-content-decoder.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-content-decoder.h +copy ..\..\libsoup\soup-content-sniffer.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-content-sniffer.h +copy ..\..\libsoup\soup-cookie.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-cookie.h +copy ..\..\libsoup\soup-cookie-jar.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-cookie-jar.h +copy ..\..\libsoup\soup-cookie-jar-db.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-cookie-jar-db.h +copy ..\..\libsoup\soup-cookie-jar-text.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-cookie-jar-text.h +copy ..\..\libsoup\soup-date.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-date.h +copy ..\..\libsoup\soup-form.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-form.h +copy ..\..\libsoup\soup-headers.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-headers.h +copy ..\..\libsoup\soup-logger.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-logger.h +copy ..\..\libsoup\soup-message.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-message.h +copy ..\..\libsoup\soup-message-body.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-message-body.h +copy ..\..\libsoup\soup-message-headers.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-message-headers.h +copy ..\..\libsoup\soup-method.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-method.h +copy ..\..\libsoup\soup-misc.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-misc.h +copy ..\..\libsoup\soup-multipart.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-multipart.h +copy ..\..\libsoup\soup-multipart-input-stream.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-multipart-input-stream.h +copy ..\..\libsoup\soup-password-manager.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-password-manager.h +copy ..\..\libsoup\soup-portability.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-portability.h +copy ..\..\libsoup\soup-proxy-resolver.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-proxy-resolver.h +copy ..\..\libsoup\soup-proxy-resolver-default.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-proxy-resolver-default.h +copy ..\..\libsoup\soup-proxy-uri-resolver.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-proxy-uri-resolver.h +copy ..\..\libsoup\soup-request.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-request.h +copy ..\..\libsoup\soup-request-data.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-request-data.h +copy ..\..\libsoup\soup-request-file.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-request-file.h +copy ..\..\libsoup\soup-request-http.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-request-http.h +copy ..\..\libsoup\soup-requester.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-requester.h +copy ..\..\libsoup\soup-server.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-server.h +copy ..\..\libsoup\soup-session.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-session.h +copy ..\..\libsoup\soup-session-async.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-session-async.h +copy ..\..\libsoup\soup-session-feature.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-session-feature.h +copy ..\..\libsoup\soup-session-sync.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-session-sync.h +copy ..\..\libsoup\soup-socket.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-socket.h +copy ..\..\libsoup\soup-status.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-status.h +copy ..\..\libsoup\soup-tld.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-tld.h +copy ..\..\libsoup\soup-types.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-types.h +copy ..\..\libsoup\soup-uri.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-uri.h +copy ..\..\libsoup\soup-value-utils.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-value-utils.h +copy ..\..\libsoup\soup-websocket.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-websocket.h +copy ..\..\libsoup\soup-websocket-connection.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-websocket-connection.h +copy ..\..\libsoup\soup-xmlrpc.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-xmlrpc.h +copy ..\..\libsoup\soup-xmlrpc-old.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-xmlrpc-old.h +copy ..\..\libsoup\soup-enum-types.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-enum-types.h +copy ..\..\libsoup\soup-version.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-version.h +mkdir $(CopyDir)\include\libsoup-gnome-$(ApiVersion)\libsoup +copy ..\..\libsoup\soup-cookie-jar-sqlite.h $(CopyDir)\include\libsoup-gnome-2.4\libsoup\soup-cookie-jar-sqlite.h +copy ..\..\libsoup\soup-gnome.h $(CopyDir)\include\libsoup-gnome-2.4\libsoup\soup-gnome.h +copy ..\..\libsoup\soup-gnome-features.h $(CopyDir)\include\libsoup-gnome-2.4\libsoup\soup-gnome-features.h + + ..\libsoup-$(ApiVersion).pc;..\libsoup-gnome-$(ApiVersion).pc + (if not exist $(CopyDir)\lib\pkgconfig mkdir $(CopyDir)\lib\pkgconfig) & ($(PythonPath)\python.exe ..\souppc.py --prefix=$(CopyDir) --version=$(SoupMajorVersion).$(SoupMinorVersion).$(SoupMicroVersion)) + + + <_PropertySheetDisplayName>soupinstallprops + + + + + $(SoupDoInstall) + + + $(SoupPCFiles) + + + $(SoupGenPC) + + + diff --git a/win32/vs14/soup-install.vcxproj b/win32/vs14/soup-install.vcxproj new file mode 100644 index 0000000..7064d08 --- /dev/null +++ b/win32/vs14/soup-install.vcxproj @@ -0,0 +1,121 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {E0DCF460-914F-46F9-94D6-86D456CB53E9} + soupinstall + + + + Utility + MultiByte + v140 + true + + + Utility + MultiByte + v140 + + + Utility + MultiByte + v140 + true + + + Utility + MultiByte + v140 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Copying build results... + $(SoupPCFiles) + $(SoupDoInstall) + some_file;%(Outputs) + Copying build results... + $(SoupPCFiles) + $(SoupDoInstall) + some_file;%(Outputs) + + + Generating .pc files... + $(SoupGenPC) + $(SoupPCFiles);%(Outputs) + Generating .pc files... + $(SoupGenPC) + $(SoupPCFiles);%(Outputs) + + + + + {b24831c4-b8f2-41d6-aaf4-12192f71c623} + false + + + {80dc062e-2146-4ce8-a448-fd2205ab2ca4} + false + + + {3ad0cb92-ee38-425e-83cb-e7b1cb1d305e} + false + + + {8c88a385-28c8-4b30-91a4-fba381a5a46f} + false + + + {d83a3162-b14c-459c-af81-15bbfa90240d} + false + + + + + + diff --git a/win32/vs14/soup-install.vcxproj.filters b/win32/vs14/soup-install.vcxproj.filters new file mode 100644 index 0000000..2627f42 --- /dev/null +++ b/win32/vs14/soup-install.vcxproj.filters @@ -0,0 +1,13 @@ + + + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav + + + + Resource Files + Resource Files + + diff --git a/win32/vs14/soup-version-paths.props b/win32/vs14/soup-version-paths.props new file mode 100644 index 0000000..4332de3 --- /dev/null +++ b/win32/vs14/soup-version-paths.props @@ -0,0 +1,69 @@ + + + + + + 14 + ..\..\..\vs$(VSVer)\$(Platform) + $(GlibEtcInstallRoot) + 2 + 62 + 3 + 2.4 + lib + -$(ApiVersion)-0 + + -$(ApiVersion)-vs$(VSVer) + $(SoupSeparateVSDllPrefix) + $(SoupSeparateVSDllSuffix) + c:\python34 + + + <_PropertySheetDisplayName>soupversionpathsprops + + + + + $(VSVer) + + + $(GlibEtcInstallRoot) + + + $(CopyDir) + + + $(SoupMajorVersion) + + + $(SoupMinorVersion) + + + $(SoupMicroVersion) + + + $(ApiVersion) + + + $(SoupLibtoolCompatibleDllPrefix) + + + $(SoupLibtoolCompatibleDllSuffix) + + + $(SoupSeparateVSDllPrefix) + + + $(SoupSeparateVSDllSuffix) + + + $(SoupDllPrefix) + + + $(SoupDllSuffix) + + + $(PythonPath) + + + diff --git a/win32/vs14/soup.vcxproj b/win32/vs14/soup.vcxproj new file mode 100644 index 0000000..5611b13 --- /dev/null +++ b/win32/vs14/soup.vcxproj @@ -0,0 +1,414 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + Debug_MIT_GSSAPI + Win32 + + + Debug_MIT_GSSAPI + x64 + + + Release_MIT_GSSAPI + Win32 + + + Release_MIT_GSSAPI + x64 + + + + {D83A3162-B14C-459C-AF81-15BBFA90240D} + soup + Win32Proj + + + + DynamicLibrary + Unicode + v140 + + + DynamicLibrary + Unicode + v140 + + + DynamicLibrary + Unicode + v140 + true + + + DynamicLibrary + Unicode + v140 + true + + + DynamicLibrary + Unicode + v140 + + + DynamicLibrary + Unicode + v140 + + + DynamicLibrary + Unicode + v140 + true + + + DynamicLibrary + Unicode + v140 + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + false + trueDebug\$(Platform)\bin\ + falseRelease\$(Platform)\bin\ + + + Disabled + _DEBUG;$(SoupBuildDefines);%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + EditAndContinue + + + $(SoupExtraDepLibs);%(AdditionalDependencies) + true + Windows + MachineX86 + + + + + Disabled + _DEBUG;$(SoupBuildDefines);$(SoupMITGSSAPIBuildDefines);%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + EditAndContinue + + + $(SoupExtraDepLibs);$(MITGSSAPILibBaseName)$(MITGSSAPILibNameSuffixX86);%(AdditionalDependencies) + true + Windows + MachineX86 + + + + + MaxSpeed + true + $(SoupBuildDefines);%(PreprocessorDefinitions) + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + $(SoupExtraDepLibs);%(AdditionalDependencies) + true + Windows + true + true + MachineX86 + + + + + MaxSpeed + true + $(SoupBuildDefines);$(SoupMITGSSAPIBuildDefines);%(PreprocessorDefinitions) + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + $(SoupExtraDepLibs);$(MITGSSAPILibBaseName)$(MITGSSAPILibNameSuffixX86);%(AdditionalDependencies) + true + Windows + true + true + MachineX86 + + + + + X64 + + + Disabled + _DEBUG;$(SoupBuildDefines);%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + ProgramDatabase + + + $(SoupExtraDepLibs);%(AdditionalDependencies) + true + Windows + MachineX64 + + + + + X64 + + + Disabled + _DEBUG;$(SoupBuildDefines);$(SoupMITGSSAPIBuildDefines);%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + ProgramDatabase + + + $(SoupExtraDepLibs);$(MITGSSAPILibBaseName)$(MITGSSAPILibNameSuffixX64);%(AdditionalDependencies) + true + Windows + MachineX64 + + + + + X64 + + + MaxSpeed + true + $(SoupBuildDefines);%(PreprocessorDefinitions) + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + $(SoupExtraDepLibs);%(AdditionalDependencies) + true + Windows + true + true + MachineX64 + + + + + X64 + + + MaxSpeed + true + $(SoupBuildDefines);$(SoupMITGSSAPIBuildDefines);%(PreprocessorDefinitions) + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + $(SoupExtraDepLibs);$(MITGSSAPILibBaseName)$(MITGSSAPILibNameSuffixX64);%(AdditionalDependencies) + true + Windows + true + true + MachineX64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Copying config.h from config.h.win32... + $(CopyConfigH) + ..\..\config.h;%(Outputs) + Copying config.h from config.h.win32... + $(CopyConfigH) + ..\..\config.h;%(Outputs) + Copying config.h from config.h.win32... + $(CopyConfigH) + ..\..\config.h;%(Outputs) + Copying config.h from config.h.win32... + $(CopyConfigH) + ..\..\config.h;%(Outputs) + + + Generating tld_data.inc... + $(GenTldDataInc) + ..\..\libsoup\tld_data.inc;%(Outputs) + Generating tld_data.inc... + $(GenTldDataInc) + ..\..\libsoup\tld_data.inc;%(Outputs) + Generating tld_data.inc... + $(GenTldDataInc) + ..\..\libsoup\tld_data.inc;%(Outputs) + Generating tld_data.inc... + $(GenTldDataInc) + ..\..\libsoup\tld_data.inc;%(Outputs) + + + Generating soup-version.h... + $(GenSoupVersionH) + ..\..\libsoup\soup-version.h;%(Outputs) + Generating soup-version.h... + $(GenSoupVersionH) + ..\..\libsoup\soup-version.h;%(Outputs) + Generating soup-version.h... + $(GenSoupVersionH) + ..\..\libsoup\soup-version.h;%(Outputs) + Generating soup-version.h... + $(GenSoupVersionH) + ..\..\libsoup\soup-version.h;%(Outputs) + + + + + + diff --git a/win32/vs14/soup.vcxproj.filters b/win32/vs14/soup.vcxproj.filters new file mode 100644 index 0000000..71eb5a6 --- /dev/null +++ b/win32/vs14/soup.vcxproj.filters @@ -0,0 +1,95 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav + + + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + + + Resource Files + Resource Files + Resource Files + + diff --git a/win32/vs15/Makefile.am b/win32/vs15/Makefile.am new file mode 100644 index 0000000..efb3c88 --- /dev/null +++ b/win32/vs15/Makefile.am @@ -0,0 +1,29 @@ +EXTRA_DIST = \ + libsoup.sln \ + get.vcxproj \ + simple-httpd.vcxproj \ + simple-proxy.vcxproj \ + get.vcxproj.filters \ + soup-install.vcxproj \ + soup-install.vcxproj.filters \ + simple-httpd.vcxproj.filters \ + simple-proxy.vcxproj.filters \ + soup-build-defines.props \ + soup-dll-build-defines.props \ + soup-gen-srcs.props \ + soup-version-paths.props \ + soup.vcxproj \ + soup-gnome.vcxproj \ + soup.vcxproj.filters \ + soup-gnome.vcxproj.filters \ + soup-install.props + +DISTCLEANFILES = $(EXTRA_DIST) + +MSVC_BASE_VER = 10 +MSVC_BASE_VER_LONG = 2010 +MSVC_VER = 15 +MSVC_VER_LONG = 15 +MSVC_TOOLSET = 141 + +include $(top_srcdir)/win32/Makefile-newvs.am diff --git a/win32/vs15/Makefile.in b/win32/vs15/Makefile.in new file mode 100644 index 0000000..87c5789 --- /dev/null +++ b/win32/vs15/Makefile.in @@ -0,0 +1,601 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Centralized autotools file +# Create the Visual Studio 2012/2013/2015 project files +# from the Visual Studio 2010 project files + +# This autotools file, from GLib, can be used in other projects +# that have Visual Studio build support. + +# Author: Fan, Chun-wei +# November 05, 2012 + +# MSVC_BASE_VER: Baseline MSVC 201x version to copy/process project files from (100 for 2010, 120 for 2013) +# MSVC_BASE_VER_LONG: Long Version of baseline Visual Studio 201x version (2010, 2012, 2013, 14, 15) +# MSVC_BASE_TOOLSET: Use if baseline MSVC toolset is not in the form v$(MSVC_BASE_VER)0, meaning v$(MSVC_BASE_TOOLSET) +# MSVC_VER_LONG: Long Version of target Visual Studio (2012, 2013, 14 and so on) +# MSVC_VER: Short Version of target Visual Studio (110 for 2012, 120 for 2013, 140 for 2015, 141 for 2017) +# MSVC_TOOLSET: Use if target MSVC toolsett is not in the form v $(MSVC_VER)0, meaning v$(MSVC_TOOLSET) +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = win32/vs15 +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_code_coverage.m4 \ + $(top_srcdir)/m4/glibtests.m4 $(top_srcdir)/m4/gtk-doc.m4 \ + $(top_srcdir)/m4/intltool.m4 $(top_srcdir)/m4/introspection.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/vapigen.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +am__DIST_COMMON = $(srcdir)/Makefile.in \ + $(top_srcdir)/win32/Makefile-newvs.am +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALL_LINGUAS = @ALL_LINGUAS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +APACHE_HTTPD = @APACHE_HTTPD@ +APACHE_MODULE_DIR = @APACHE_MODULE_DIR@ +APACHE_PHP_MODULE_DIR = @APACHE_PHP_MODULE_DIR@ +APACHE_SSL_MODULE_DIR = @APACHE_SSL_MODULE_DIR@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CODE_COVERAGE_CFLAGS = @CODE_COVERAGE_CFLAGS@ +CODE_COVERAGE_CPPFLAGS = @CODE_COVERAGE_CPPFLAGS@ +CODE_COVERAGE_CXXFLAGS = @CODE_COVERAGE_CXXFLAGS@ +CODE_COVERAGE_ENABLED = @CODE_COVERAGE_ENABLED@ +CODE_COVERAGE_LDFLAGS = @CODE_COVERAGE_LDFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CURL = @CURL@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GCOV = @GCOV@ +GENHTML = @GENHTML@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_COMPILE_RESOURCES = @GLIB_COMPILE_RESOURCES@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MAKEFILE = @GLIB_MAKEFILE@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GMSGFMT = @GMSGFMT@ +GOBJECT_QUERY = @GOBJECT_QUERY@ +GREP = @GREP@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +HAVE_GNOME = @HAVE_GNOME@ +HTML_DIR = @HTML_DIR@ +IF_HAVE_MOD_UNIXD = @IF_HAVE_MOD_UNIXD@ +IF_HAVE_PHP = @IF_HAVE_PHP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ +INTLTOOL_MERGE = @INTLTOOL_MERGE@ +INTLTOOL_PERL = @INTLTOOL_PERL@ +INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ +INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@ +INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@ +INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@ +INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LCOV = @LCOV@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PHP = @PHP@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOUP_AGE = @SOUP_AGE@ +SOUP_API_VERSION = @SOUP_API_VERSION@ +SOUP_CURRENT = @SOUP_CURRENT@ +SOUP_DEBUG_FLAGS = @SOUP_DEBUG_FLAGS@ +SOUP_HIDDEN_VISIBILITY_CFLAGS = @SOUP_HIDDEN_VISIBILITY_CFLAGS@ +SOUP_MAJOR_VERSION = @SOUP_MAJOR_VERSION@ +SOUP_MICRO_VERSION = @SOUP_MICRO_VERSION@ +SOUP_MINOR_VERSION = @SOUP_MINOR_VERSION@ +SOUP_REVISION = @SOUP_REVISION@ +SQLITE_CFLAGS = @SQLITE_CFLAGS@ +SQLITE_LIBS = @SQLITE_LIBS@ +STRIP = @STRIP@ +USE_NLS = @USE_NLS@ +VALAC = @VALAC@ +VAPIDIR = @VAPIDIR@ +VAPIGEN = @VAPIGEN@ +VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@ +VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@ +VERSION = @VERSION@ +XGETTEXT = @XGETTEXT@ +XML_CFLAGS = @XML_CFLAGS@ +XML_LIBS = @XML_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +installed_test_metadir = @installed_test_metadir@ +installed_testdir = @installed_testdir@ +intltool__v_merge_options_ = @intltool__v_merge_options_@ +intltool__v_merge_options_0 = @intltool__v_merge_options_0@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +ntlm_auth = @ntlm_auth@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +EXTRA_DIST = \ + libsoup.sln \ + get.vcxproj \ + simple-httpd.vcxproj \ + simple-proxy.vcxproj \ + get.vcxproj.filters \ + soup-install.vcxproj \ + soup-install.vcxproj.filters \ + simple-httpd.vcxproj.filters \ + simple-proxy.vcxproj.filters \ + soup-build-defines.props \ + soup-dll-build-defines.props \ + soup-gen-srcs.props \ + soup-version-paths.props \ + soup.vcxproj \ + soup-gnome.vcxproj \ + soup.vcxproj.filters \ + soup-gnome.vcxproj.filters \ + soup-install.props + +DISTCLEANFILES = $(EXTRA_DIST) +MSVC_BASE_VER = 10 +MSVC_BASE_VER_LONG = 2010 +MSVC_VER = 15 +MSVC_VER_LONG = 15 +@MSVC_NO_TOOLSET_SET_TRUE@MSVC_TOOLSET = $(MSVC_VER)0 +MSVC_TOOLSET = 141 +@MSVC_BASE_NO_TOOLSET_SET_TRUE@MSVC_BASE_TOOLSET = $(MSVC_BASE_VER)0 +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/win32/Makefile-newvs.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign win32/vs15/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign win32/vs15/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; +$(top_srcdir)/win32/Makefile-newvs.am $(am__empty): + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +tags TAGS: + +ctags CTAGS: + +cscope cscopelist: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic clean-libtool \ + cscopelist-am ctags-am distclean distclean-generic \ + distclean-libtool distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +%.sln: + sed 's/11\.00/12\.00/g' < $(top_srcdir)/win32/vs$(MSVC_BASE_VER)/$@ > $(top_builddir)/win32/vs$(MSVC_VER)/$@.tmp + sed 's/$(MSVC_BASE_VER_LONG)/$(MSVC_VER_LONG)/g' < $(top_builddir)/win32/vs$(MSVC_VER)/$@.tmp > $(top_builddir)/win32/vs$(MSVC_VER)/$@ + rm $(top_builddir)/win32/vs$(MSVC_VER)/$@.tmp + +%.txt: + sed 's/vs$(MSVC_BASE_VER)/vs$(MSVC_VER)/g' < $(top_srcdir)/win32/vs$(MSVC_BASE_VER)/$@ > $(top_builddir)/win32/vs$(MSVC_VER)/$@.tmp + sed 's/VS$(MSVC_BASE_VER)/VS$(MSVC_VER)/g' < $(top_builddir)/win32/vs$(MSVC_VER)/$@.tmp > $(top_builddir)/win32/vs$(MSVC_VER)/$@ + rm $(top_builddir)/win32/vs$(MSVC_VER)/$@.tmp + +%.vcxproj: + if test -e $(top_srcdir)/win32/vs$(MSVC_BASE_VER)/$@; then \ + sed 's/v$(MSVC_BASE_TOOLSET)/v$(MSVC_TOOLSET)/g' < $(top_srcdir)/win32/vs$(MSVC_BASE_VER)/$@ > $(top_builddir)/win32/vs$(MSVC_VER)/$@; \ + else \ + sed 's/v$(MSVC_BASE_TOOLSET)/v$(MSVC_TOOLSET)/g' < $(top_builddir)/win32/vs$(MSVC_BASE_VER)/$@ > $(top_builddir)/win32/vs$(MSVC_VER)/$@; \ + fi + +%.props: $(top_builddir)/win32/vs$(MSVC_BASE_VER)/Makefile + if test -e $(top_srcdir)/win32/vs$(MSVC_BASE_VER)/$@; then \ + sed 's/$(MSVC_BASE_VER)<\/VSVer>/$(MSVC_VER)<\/VSVer>/g' < $(top_srcdir)/win32/vs$(MSVC_BASE_VER)/$@ > $(top_builddir)/win32/vs$(MSVC_VER)/$@; \ + else \ + sed 's/$(MSVC_BASE_VER)<\/VSVer>/$(MSVC_VER)<\/VSVer>/g' < $(top_builddir)/win32/vs$(MSVC_BASE_VER)/$@ > $(top_builddir)/win32/vs$(MSVC_VER)/$@; \ + fi + +%.vcxproj.filters: + if test -e $(top_srcdir)/win32/vs$(MSVC_BASE_VER)/$@; then \ + cp $(top_srcdir)/win32/vs$(MSVC_BASE_VER)/$@ $(top_builddir)/win32/vs$(MSVC_VER)/$@; \ + else \ + cp $(top_builddir)/win32/vs$(MSVC_BASE_VER)/$@ $(top_builddir)/win32/vs$(MSVC_VER)/$@; \ + fi + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/win32/vs15/get.vcxproj b/win32/vs15/get.vcxproj new file mode 100644 index 0000000..78cd315 --- /dev/null +++ b/win32/vs15/get.vcxproj @@ -0,0 +1,159 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {B24831C4-B8F2-41D6-AAF4-12192F71C623} + get + Win32Proj + + + + Application + Unicode + v141 + true + + + Application + Unicode + v141 + + + Application + Unicode + v141 + true + + + Application + Unicode + v141 + + + + + + + + + + + + + + + + + + + + + + true + false + + + Disabled + _DEBUG;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + EditAndContinue + + + true + Console + MachineX86 + + + + + MaxSpeed + true + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + true + Console + true + true + MachineX86 + + + + + X64 + + + Disabled + _DEBUG;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + ProgramDatabase + + + true + Console + MachineX64 + + + + + X64 + + + MaxSpeed + true + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + true + Console + true + true + MachineX64 + + + + + + + + {d83a3162-b14c-459c-af81-15bbfa90240d} + false + + + + + + diff --git a/win32/vs15/get.vcxproj.filters b/win32/vs15/get.vcxproj.filters new file mode 100644 index 0000000..9bc6fcf --- /dev/null +++ b/win32/vs15/get.vcxproj.filters @@ -0,0 +1,17 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav + + + Sources + + diff --git a/win32/vs15/libsoup.sln b/win32/vs15/libsoup.sln new file mode 100644 index 0000000..ec1df45 --- /dev/null +++ b/win32/vs15/libsoup.sln @@ -0,0 +1,128 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "soup", "soup.vcxproj", "{D83A3162-B14C-459C-AF81-15BBFA90240D}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "soup-gnome", "soup-gnome.vcxproj", "{8C88A385-28C8-4B30-91A4-FBA381A5A46F}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "get", "get.vcxproj", "{B24831C4-B8F2-41D6-AAF4-12192F71C623}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "simple-httpd", "simple-httpd.vcxproj", "{80DC062E-2146-4CE8-A448-FD2205AB2CA4}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "simple-proxy", "simple-proxy.vcxproj", "{3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "soup-install", "soup-install.vcxproj", "{E0DCF460-914F-46F9-94D6-86D456CB53E9}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + Debug_MIT_GSSAPI|Win32 = Debug_MIT_GSSAPI|Win32 + Debug_MIT_GSSAPI|x64 = Debug_MIT_GSSAPI|x64 + Release_MIT_GSSAPI|Win32 = Release_MIT_GSSAPI|Win32 + Release_MIT_GSSAPI|x64 = Release_MIT_GSSAPI|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Debug|Win32.ActiveCfg = Debug|Win32 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Debug|Win32.Build.0 = Debug|Win32 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Debug|x64.ActiveCfg = Debug|x64 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Debug|x64.Build.0 = Debug|x64 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Release|Win32.ActiveCfg = Release|Win32 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Release|Win32.Build.0 = Release|Win32 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Release|x64.ActiveCfg = Release|x64 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Release|x64.Build.0 = Release|x64 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Debug_MIT_GSSAPI|Win32.ActiveCfg = Debug_MIT_GSSAPI|Win32 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Debug_MIT_GSSAPI|Win32.Build.0 = Debug_MIT_GSSAPI|Win32 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Debug_MIT_GSSAPI|x64.ActiveCfg = Debug_MIT_GSSAPI|x64 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Debug_MIT_GSSAPI|x64.Build.0 = Debug_MIT_GSSAPI|x64 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Release_MIT_GSSAPI|Win32.ActiveCfg = Release_MIT_GSSAPI|Win32 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Release_MIT_GSSAPI|Win32.Build.0 = Release_MIT_GSSAPI|Win32 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Release_MIT_GSSAPI|x64.ActiveCfg = Release_MIT_GSSAPI|x64 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Release_MIT_GSSAPI|x64.Build.0 = Release_MIT_GSSAPI|x64 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Debug|Win32.ActiveCfg = Debug|Win32 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Debug|Win32.Build.0 = Debug|Win32 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Debug|x64.ActiveCfg = Debug|x64 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Debug|x64.Build.0 = Debug|x64 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Release|Win32.ActiveCfg = Release|Win32 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Release|Win32.Build.0 = Release|Win32 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Release|x64.ActiveCfg = Release|x64 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Release|x64.Build.0 = Release|x64 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Debug_MIT_GSSAPI|Win32.ActiveCfg = Debug|Win32 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Debug_MIT_GSSAPI|Win32.Build.0 = Debug|Win32 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Debug_MIT_GSSAPI|x64.ActiveCfg = Debug|x64 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Debug_MIT_GSSAPI|x64.Build.0 = Debug|x64 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Release_MIT_GSSAPI|Win32.ActiveCfg = Release|Win32 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Release_MIT_GSSAPI|Win32.Build.0 = Release|Win32 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Release_MIT_GSSAPI|x64.ActiveCfg = Release|x64 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Release_MIT_GSSAPI|x64.Build.0 = Release|x64 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Debug|Win32.ActiveCfg = Debug|Win32 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Debug|Win32.Build.0 = Debug|Win32 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Debug|x64.ActiveCfg = Debug|x64 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Debug|x64.Build.0 = Debug|x64 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Release|Win32.ActiveCfg = Release|Win32 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Release|Win32.Build.0 = Release|Win32 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Release|x64.ActiveCfg = Release|x64 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Release|x64.Build.0 = Release|x64 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Debug_MIT_GSSAPI|Win32.ActiveCfg = Debug|Win32 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Debug_MIT_GSSAPI|Win32.Build.0 = Debug|Win32 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Debug_MIT_GSSAPI|x64.ActiveCfg = Debug|x64 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Debug_MIT_GSSAPI|x64.Build.0 = Debug|x64 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Release_MIT_GSSAPI|Win32.ActiveCfg = Release|Win32 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Release_MIT_GSSAPI|Win32.Build.0 = Release|Win32 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Release_MIT_GSSAPI|x64.ActiveCfg = Release|x64 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Release_MIT_GSSAPI|x64.Build.0 = Release|x64 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Debug|Win32.ActiveCfg = Debug|Win32 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Debug|Win32.Build.0 = Debug|Win32 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Debug|x64.ActiveCfg = Debug|x64 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Debug|x64.Build.0 = Debug|x64 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Release|Win32.ActiveCfg = Release|Win32 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Release|Win32.Build.0 = Release|Win32 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Release|x64.ActiveCfg = Release|x64 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Release|x64.Build.0 = Release|x64 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Debug_MIT_GSSAPI|Win32.ActiveCfg = Debug|Win32 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Debug_MIT_GSSAPI|Win32.Build.0 = Debug|Win32 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Debug_MIT_GSSAPI|x64.ActiveCfg = Debug|x64 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Debug_MIT_GSSAPI|x64.Build.0 = Debug|x64 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Release_MIT_GSSAPI|Win32.ActiveCfg = Release|Win32 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Release_MIT_GSSAPI|Win32.Build.0 = Release|Win32 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Release_MIT_GSSAPI|x64.ActiveCfg = Release|x64 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Release_MIT_GSSAPI|x64.Build.0 = Release|x64 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Debug|Win32.ActiveCfg = Debug|Win32 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Debug|Win32.Build.0 = Debug|Win32 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Debug|x64.ActiveCfg = Debug|x64 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Debug|x64.Build.0 = Debug|x64 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Release|Win32.ActiveCfg = Release|Win32 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Release|Win32.Build.0 = Release|Win32 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Release|x64.ActiveCfg = Release|x64 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Release|x64.Build.0 = Release|x64 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Debug_MIT_GSSAPI|Win32.ActiveCfg = Debug|Win32 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Debug_MIT_GSSAPI|Win32.Build.0 = Debug|Win32 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Debug_MIT_GSSAPI|x64.ActiveCfg = Debug|x64 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Debug_MIT_GSSAPI|x64.Build.0 = Debug|x64 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Release_MIT_GSSAPI|Win32.ActiveCfg = Release|Win32 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Release_MIT_GSSAPI|Win32.Build.0 = Release|Win32 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Release_MIT_GSSAPI|x64.ActiveCfg = Release|x64 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Release_MIT_GSSAPI|x64.Build.0 = Release|x64 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Debug|Win32.ActiveCfg = Debug|Win32 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Debug|Win32.Build.0 = Debug|Win32 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Debug|x64.ActiveCfg = Debug|x64 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Debug|x64.Build.0 = Debug|x64 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Release|Win32.ActiveCfg = Release|Win32 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Release|Win32.Build.0 = Release|Win32 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Release|x64.ActiveCfg = Release|x64 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Release|x64.Build.0 = Release|x64 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Debug_MIT_GSSAPI|Win32.ActiveCfg = Debug|Win32 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Debug_MIT_GSSAPI|Win32.Build.0 = Debug|Win32 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Debug_MIT_GSSAPI|x64.ActiveCfg = Debug|x64 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Debug_MIT_GSSAPI|x64.Build.0 = Debug|x64 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Release_MIT_GSSAPI|Win32.ActiveCfg = Release|Win32 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Release_MIT_GSSAPI|Win32.Build.0 = Release|Win32 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Release_MIT_GSSAPI|x64.ActiveCfg = Release|x64 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Release_MIT_GSSAPI|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/win32/vs15/simple-httpd.vcxproj b/win32/vs15/simple-httpd.vcxproj new file mode 100644 index 0000000..86c4901 --- /dev/null +++ b/win32/vs15/simple-httpd.vcxproj @@ -0,0 +1,159 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {80DC062E-2146-4CE8-A448-FD2205AB2CA4} + simplehttpd + Win32Proj + + + + Application + Unicode + v141 + true + + + Application + Unicode + v141 + + + Application + Unicode + v141 + true + + + Application + Unicode + v141 + + + + + + + + + + + + + + + + + + + + + + true + false + + + Disabled + _DEBUG;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + EditAndContinue + + + true + Console + MachineX86 + + + + + MaxSpeed + true + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + true + Console + true + true + MachineX86 + + + + + X64 + + + Disabled + _DEBUG;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + ProgramDatabase + + + true + Console + MachineX64 + + + + + X64 + + + MaxSpeed + true + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + true + Console + true + true + MachineX64 + + + + + + + + {d83a3162-b14c-459c-af81-15bbfa90240d} + false + + + + + + diff --git a/win32/vs15/simple-httpd.vcxproj.filters b/win32/vs15/simple-httpd.vcxproj.filters new file mode 100644 index 0000000..14cf1d4 --- /dev/null +++ b/win32/vs15/simple-httpd.vcxproj.filters @@ -0,0 +1,17 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav + + + Sources + + diff --git a/win32/vs15/simple-proxy.vcxproj b/win32/vs15/simple-proxy.vcxproj new file mode 100644 index 0000000..1a90b30 --- /dev/null +++ b/win32/vs15/simple-proxy.vcxproj @@ -0,0 +1,159 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E} + simpleproxy + Win32Proj + + + + Application + Unicode + v141 + true + + + Application + Unicode + v141 + + + Application + Unicode + v141 + true + + + Application + Unicode + v141 + + + + + + + + + + + + + + + + + + + + + + true + false + + + Disabled + _DEBUG;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + EditAndContinue + + + true + Console + MachineX86 + + + + + MaxSpeed + true + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + true + Console + true + true + MachineX86 + + + + + X64 + + + Disabled + _DEBUG;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + ProgramDatabase + + + true + Console + MachineX64 + + + + + X64 + + + MaxSpeed + true + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + true + Console + true + true + MachineX64 + + + + + + + + {d83a3162-b14c-459c-af81-15bbfa90240d} + false + + + + + + diff --git a/win32/vs15/simple-proxy.vcxproj.filters b/win32/vs15/simple-proxy.vcxproj.filters new file mode 100644 index 0000000..4a7f2f2 --- /dev/null +++ b/win32/vs15/simple-proxy.vcxproj.filters @@ -0,0 +1,17 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav + + + Sources + + diff --git a/win32/vs15/soup-build-defines.props b/win32/vs15/soup-build-defines.props new file mode 100644 index 0000000..0c9b527 --- /dev/null +++ b/win32/vs15/soup-build-defines.props @@ -0,0 +1,29 @@ + + + + + + + + <_PropertySheetDisplayName>soupbuilddefinesprops + $(SolutionDir)$(Configuration)\$(PlatformName)\bin\ + $(SolutionDir)$(Configuration)\$(PlatformName)\obj\$(ProjectName)\ + + + + ..\..;$(GlibEtcInstallRoot)\include\gio-win32-2.0;$(GlibEtcInstallRoot)\include\glib-2.0;$(GlibEtcInstallRoot)\lib\glib-2.0\include;$(GlibEtcInstallRoot)\include\libxml2;$(GlibEtcInstallRoot)\include;%(AdditionalIncludeDirectories) + HAVE_CONFIG_H;%(PreprocessorDefinitions) + msvc_recommended_pragmas.h;%(ForcedIncludeFiles) + true + /d2Zi+ %(AdditionalOptions) + + + gio-2.0.lib;gobject-2.0.lib;glib-2.0.lib;%(AdditionalDependencies) + $(GlibEtcInstallRoot)\lib;%(AdditionalLibraryDirectories) + /HIGHENTROPYVA %(AdditionalOptions) + /HIGHENTROPYVA %(AdditionalOptions) + /HIGHENTROPYVA %(AdditionalOptions) + /HIGHENTROPYVA %(AdditionalOptions) + + + diff --git a/win32/vs15/soup-dll-build-defines.props b/win32/vs15/soup-dll-build-defines.props new file mode 100644 index 0000000..40591ff --- /dev/null +++ b/win32/vs15/soup-dll-build-defines.props @@ -0,0 +1,24 @@ + + + + + + + LIBSOUP_COMPILATION;DLL_EXPORT;G_LOG_DOMAIN="libsoup" + LIBSOUP_HAVE_GSSAPI + libxml2.lib;sqlite3.lib;intl.lib;ws2_32.lib + gssapi + 32.lib + 64.lib + + + <_PropertySheetDisplayName>soupdllbuilddefinesprops + + + + $(OutDir)$(SoupDllPrefix)$(ProjectName)$(SoupDllSuffix).dll + $(OutDir)$(SoupDllPrefix)$(ProjectName)$(SoupDllSuffix).pdb + $(OutDir)$(ProjectName)-$(ApiVersion).lib + + + diff --git a/win32/vs15/soup-gen-srcs.props b/win32/vs15/soup-gen-srcs.props new file mode 100644 index 0000000..760825c --- /dev/null +++ b/win32/vs15/soup-gen-srcs.props @@ -0,0 +1,26 @@ + + + + + + + copy ..\..\config.h.win32 ..\..\config.h + $(PythonPath)\python.exe ..\soup_version_h.py --version=$(SoupMajorVersion).$(SoupMinorVersion).$(SoupMicroVersion) + $(PythonPath)\python.exe ..\..\libsoup\tld-parser.py ..\..\data\effective_tld_names.dat ..\..\libsoup\tld_data.inc + + + <_PropertySheetDisplayName>soupgensrcsprops + + + + + $(CopyConfigH) + + + $(GenSoupVersionH) + + + $(GenTldDataInc) + + + diff --git a/win32/vs15/soup-gnome.vcxproj b/win32/vs15/soup-gnome.vcxproj new file mode 100644 index 0000000..b5da2d3 --- /dev/null +++ b/win32/vs15/soup-gnome.vcxproj @@ -0,0 +1,164 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {8C88A385-28C8-4B30-91A4-FBA381A5A46F} + soupgnome + Win32Proj + + + + DynamicLibrary + Unicode + v141 + true + + + DynamicLibrary + Unicode + v141 + + + DynamicLibrary + Unicode + v141 + true + + + DynamicLibrary + Unicode + v141 + + + + + + + + + + + + + + + + + + + + + + true + false + + + Disabled + _DEBUG;$(SoupBuildDefines);%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + EditAndContinue + + + true + Windows + MachineX86 + + + + + MaxSpeed + true + $(SoupBuildDefines);%(PreprocessorDefinitions) + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + true + Windows + true + true + MachineX86 + + + + + X64 + + + Disabled + _DEBUG;$(SoupBuildDefines);%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + ProgramDatabase + + + true + Windows + MachineX64 + + + + + X64 + + + MaxSpeed + true + $(SoupBuildDefines);%(PreprocessorDefinitions) + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + true + Windows + true + true + MachineX64 + + + + + + + + + + + {d83a3162-b14c-459c-af81-15bbfa90240d} + false + + + + + + diff --git a/win32/vs15/soup-gnome.vcxproj.filters b/win32/vs15/soup-gnome.vcxproj.filters new file mode 100644 index 0000000..924bf66 --- /dev/null +++ b/win32/vs15/soup-gnome.vcxproj.filters @@ -0,0 +1,20 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav + + + Source Files + Source Files + Source Files + Source Files + + diff --git a/win32/vs15/soup-install.props b/win32/vs15/soup-install.props new file mode 100644 index 0000000..fb3240e --- /dev/null +++ b/win32/vs15/soup-install.props @@ -0,0 +1,101 @@ + + + + + + + +mkdir $(CopyDir)\bin +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\$(SoupDllPrefix)soup$(SoupDllSuffix).dll $(CopyDir)\bin +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\$(SoupDllPrefix)soup$(SoupDllSuffix).pdb $(CopyDir)\bin +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\$(SoupDllPrefix)soup-gnome$(SoupDllSuffix).dll $(CopyDir)\bin +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\$(SoupDllPrefix)soup-gnome$(SoupDllSuffix).pdb $(CopyDir)\bin +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\get.exe $(CopyDir)\bin +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\get.pdb $(CopyDir)\bin +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\simple-httpd.exe $(CopyDir)\bin +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\simple-httpd.pdb $(CopyDir)\bin +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\simple-proxy.exe $(CopyDir)\bin +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\simple-proxy.pdb $(CopyDir)\bin +mkdir $(CopyDir)\lib +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\soup-$(ApiVersion).lib $(CopyDir)\lib +copy $(SolutionDir)\$(Configuration)\$(Platform)\bin\soup-gnome-$(ApiVersion).lib $(CopyDir)\lib +copy ..\libsoup-$(ApiVersion).pc $(CopyDir)\lib\pkgconfig +copy ..\libsoup-gnome-$(ApiVersion).pc $(CopyDir)\lib\pkgconfig +mkdir $(CopyDir)\include\libsoup-$(ApiVersion)\libsoup +copy ..\..\libsoup\soup.h $(CopyDir)\include\libsoup-2.4\libsoup\soup.h +copy ..\..\libsoup\soup-address.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-address.h +copy ..\..\libsoup\soup-auth.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-auth.h +copy ..\..\libsoup\soup-auth-domain.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-auth-domain.h +copy ..\..\libsoup\soup-auth-domain-basic.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-auth-domain-basic.h +copy ..\..\libsoup\soup-auth-domain-digest.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-auth-domain-digest.h +copy ..\..\libsoup\soup-auth-manager.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-auth-manager.h +copy ..\..\libsoup\soup-autocleanups.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-autocleanups.h +copy ..\..\libsoup\soup-cache.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-cache.h +copy ..\..\libsoup\soup-content-decoder.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-content-decoder.h +copy ..\..\libsoup\soup-content-sniffer.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-content-sniffer.h +copy ..\..\libsoup\soup-cookie.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-cookie.h +copy ..\..\libsoup\soup-cookie-jar.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-cookie-jar.h +copy ..\..\libsoup\soup-cookie-jar-db.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-cookie-jar-db.h +copy ..\..\libsoup\soup-cookie-jar-text.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-cookie-jar-text.h +copy ..\..\libsoup\soup-date.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-date.h +copy ..\..\libsoup\soup-form.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-form.h +copy ..\..\libsoup\soup-headers.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-headers.h +copy ..\..\libsoup\soup-logger.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-logger.h +copy ..\..\libsoup\soup-message.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-message.h +copy ..\..\libsoup\soup-message-body.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-message-body.h +copy ..\..\libsoup\soup-message-headers.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-message-headers.h +copy ..\..\libsoup\soup-method.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-method.h +copy ..\..\libsoup\soup-misc.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-misc.h +copy ..\..\libsoup\soup-multipart.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-multipart.h +copy ..\..\libsoup\soup-multipart-input-stream.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-multipart-input-stream.h +copy ..\..\libsoup\soup-password-manager.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-password-manager.h +copy ..\..\libsoup\soup-portability.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-portability.h +copy ..\..\libsoup\soup-proxy-resolver.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-proxy-resolver.h +copy ..\..\libsoup\soup-proxy-resolver-default.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-proxy-resolver-default.h +copy ..\..\libsoup\soup-proxy-uri-resolver.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-proxy-uri-resolver.h +copy ..\..\libsoup\soup-request.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-request.h +copy ..\..\libsoup\soup-request-data.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-request-data.h +copy ..\..\libsoup\soup-request-file.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-request-file.h +copy ..\..\libsoup\soup-request-http.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-request-http.h +copy ..\..\libsoup\soup-requester.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-requester.h +copy ..\..\libsoup\soup-server.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-server.h +copy ..\..\libsoup\soup-session.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-session.h +copy ..\..\libsoup\soup-session-async.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-session-async.h +copy ..\..\libsoup\soup-session-feature.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-session-feature.h +copy ..\..\libsoup\soup-session-sync.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-session-sync.h +copy ..\..\libsoup\soup-socket.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-socket.h +copy ..\..\libsoup\soup-status.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-status.h +copy ..\..\libsoup\soup-tld.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-tld.h +copy ..\..\libsoup\soup-types.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-types.h +copy ..\..\libsoup\soup-uri.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-uri.h +copy ..\..\libsoup\soup-value-utils.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-value-utils.h +copy ..\..\libsoup\soup-websocket.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-websocket.h +copy ..\..\libsoup\soup-websocket-connection.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-websocket-connection.h +copy ..\..\libsoup\soup-xmlrpc.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-xmlrpc.h +copy ..\..\libsoup\soup-xmlrpc-old.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-xmlrpc-old.h +copy ..\..\libsoup\soup-enum-types.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-enum-types.h +copy ..\..\libsoup\soup-version.h $(CopyDir)\include\libsoup-2.4\libsoup\soup-version.h +mkdir $(CopyDir)\include\libsoup-gnome-$(ApiVersion)\libsoup +copy ..\..\libsoup\soup-cookie-jar-sqlite.h $(CopyDir)\include\libsoup-gnome-2.4\libsoup\soup-cookie-jar-sqlite.h +copy ..\..\libsoup\soup-gnome.h $(CopyDir)\include\libsoup-gnome-2.4\libsoup\soup-gnome.h +copy ..\..\libsoup\soup-gnome-features.h $(CopyDir)\include\libsoup-gnome-2.4\libsoup\soup-gnome-features.h + + ..\libsoup-$(ApiVersion).pc;..\libsoup-gnome-$(ApiVersion).pc + (if not exist $(CopyDir)\lib\pkgconfig mkdir $(CopyDir)\lib\pkgconfig) & ($(PythonPath)\python.exe ..\souppc.py --prefix=$(CopyDir) --version=$(SoupMajorVersion).$(SoupMinorVersion).$(SoupMicroVersion)) + + + <_PropertySheetDisplayName>soupinstallprops + + + + + $(SoupDoInstall) + + + $(SoupPCFiles) + + + $(SoupGenPC) + + + diff --git a/win32/vs15/soup-install.vcxproj b/win32/vs15/soup-install.vcxproj new file mode 100644 index 0000000..d6de8a7 --- /dev/null +++ b/win32/vs15/soup-install.vcxproj @@ -0,0 +1,121 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {E0DCF460-914F-46F9-94D6-86D456CB53E9} + soupinstall + + + + Utility + MultiByte + v141 + true + + + Utility + MultiByte + v141 + + + Utility + MultiByte + v141 + true + + + Utility + MultiByte + v141 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Copying build results... + $(SoupPCFiles) + $(SoupDoInstall) + some_file;%(Outputs) + Copying build results... + $(SoupPCFiles) + $(SoupDoInstall) + some_file;%(Outputs) + + + Generating .pc files... + $(SoupGenPC) + $(SoupPCFiles);%(Outputs) + Generating .pc files... + $(SoupGenPC) + $(SoupPCFiles);%(Outputs) + + + + + {b24831c4-b8f2-41d6-aaf4-12192f71c623} + false + + + {80dc062e-2146-4ce8-a448-fd2205ab2ca4} + false + + + {3ad0cb92-ee38-425e-83cb-e7b1cb1d305e} + false + + + {8c88a385-28c8-4b30-91a4-fba381a5a46f} + false + + + {d83a3162-b14c-459c-af81-15bbfa90240d} + false + + + + + + diff --git a/win32/vs15/soup-install.vcxproj.filters b/win32/vs15/soup-install.vcxproj.filters new file mode 100644 index 0000000..2627f42 --- /dev/null +++ b/win32/vs15/soup-install.vcxproj.filters @@ -0,0 +1,13 @@ + + + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav + + + + Resource Files + Resource Files + + diff --git a/win32/vs15/soup-version-paths.props b/win32/vs15/soup-version-paths.props new file mode 100644 index 0000000..f04f39e --- /dev/null +++ b/win32/vs15/soup-version-paths.props @@ -0,0 +1,69 @@ + + + + + + 15 + ..\..\..\vs$(VSVer)\$(Platform) + $(GlibEtcInstallRoot) + 2 + 62 + 3 + 2.4 + lib + -$(ApiVersion)-0 + + -$(ApiVersion)-vs$(VSVer) + $(SoupSeparateVSDllPrefix) + $(SoupSeparateVSDllSuffix) + c:\python34 + + + <_PropertySheetDisplayName>soupversionpathsprops + + + + + $(VSVer) + + + $(GlibEtcInstallRoot) + + + $(CopyDir) + + + $(SoupMajorVersion) + + + $(SoupMinorVersion) + + + $(SoupMicroVersion) + + + $(ApiVersion) + + + $(SoupLibtoolCompatibleDllPrefix) + + + $(SoupLibtoolCompatibleDllSuffix) + + + $(SoupSeparateVSDllPrefix) + + + $(SoupSeparateVSDllSuffix) + + + $(SoupDllPrefix) + + + $(SoupDllSuffix) + + + $(PythonPath) + + + diff --git a/win32/vs15/soup.vcxproj b/win32/vs15/soup.vcxproj new file mode 100644 index 0000000..65effc4 --- /dev/null +++ b/win32/vs15/soup.vcxproj @@ -0,0 +1,414 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + Debug_MIT_GSSAPI + Win32 + + + Debug_MIT_GSSAPI + x64 + + + Release_MIT_GSSAPI + Win32 + + + Release_MIT_GSSAPI + x64 + + + + {D83A3162-B14C-459C-AF81-15BBFA90240D} + soup + Win32Proj + + + + DynamicLibrary + Unicode + v141 + + + DynamicLibrary + Unicode + v141 + + + DynamicLibrary + Unicode + v141 + true + + + DynamicLibrary + Unicode + v141 + true + + + DynamicLibrary + Unicode + v141 + + + DynamicLibrary + Unicode + v141 + + + DynamicLibrary + Unicode + v141 + true + + + DynamicLibrary + Unicode + v141 + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + false + trueDebug\$(Platform)\bin\ + falseRelease\$(Platform)\bin\ + + + Disabled + _DEBUG;$(SoupBuildDefines);%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + EditAndContinue + + + $(SoupExtraDepLibs);%(AdditionalDependencies) + true + Windows + MachineX86 + + + + + Disabled + _DEBUG;$(SoupBuildDefines);$(SoupMITGSSAPIBuildDefines);%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + EditAndContinue + + + $(SoupExtraDepLibs);$(MITGSSAPILibBaseName)$(MITGSSAPILibNameSuffixX86);%(AdditionalDependencies) + true + Windows + MachineX86 + + + + + MaxSpeed + true + $(SoupBuildDefines);%(PreprocessorDefinitions) + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + $(SoupExtraDepLibs);%(AdditionalDependencies) + true + Windows + true + true + MachineX86 + + + + + MaxSpeed + true + $(SoupBuildDefines);$(SoupMITGSSAPIBuildDefines);%(PreprocessorDefinitions) + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + $(SoupExtraDepLibs);$(MITGSSAPILibBaseName)$(MITGSSAPILibNameSuffixX86);%(AdditionalDependencies) + true + Windows + true + true + MachineX86 + + + + + X64 + + + Disabled + _DEBUG;$(SoupBuildDefines);%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + ProgramDatabase + + + $(SoupExtraDepLibs);%(AdditionalDependencies) + true + Windows + MachineX64 + + + + + X64 + + + Disabled + _DEBUG;$(SoupBuildDefines);$(SoupMITGSSAPIBuildDefines);%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + ProgramDatabase + + + $(SoupExtraDepLibs);$(MITGSSAPILibBaseName)$(MITGSSAPILibNameSuffixX64);%(AdditionalDependencies) + true + Windows + MachineX64 + + + + + X64 + + + MaxSpeed + true + $(SoupBuildDefines);%(PreprocessorDefinitions) + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + $(SoupExtraDepLibs);%(AdditionalDependencies) + true + Windows + true + true + MachineX64 + + + + + X64 + + + MaxSpeed + true + $(SoupBuildDefines);$(SoupMITGSSAPIBuildDefines);%(PreprocessorDefinitions) + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + $(SoupExtraDepLibs);$(MITGSSAPILibBaseName)$(MITGSSAPILibNameSuffixX64);%(AdditionalDependencies) + true + Windows + true + true + MachineX64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Copying config.h from config.h.win32... + $(CopyConfigH) + ..\..\config.h;%(Outputs) + Copying config.h from config.h.win32... + $(CopyConfigH) + ..\..\config.h;%(Outputs) + Copying config.h from config.h.win32... + $(CopyConfigH) + ..\..\config.h;%(Outputs) + Copying config.h from config.h.win32... + $(CopyConfigH) + ..\..\config.h;%(Outputs) + + + Generating tld_data.inc... + $(GenTldDataInc) + ..\..\libsoup\tld_data.inc;%(Outputs) + Generating tld_data.inc... + $(GenTldDataInc) + ..\..\libsoup\tld_data.inc;%(Outputs) + Generating tld_data.inc... + $(GenTldDataInc) + ..\..\libsoup\tld_data.inc;%(Outputs) + Generating tld_data.inc... + $(GenTldDataInc) + ..\..\libsoup\tld_data.inc;%(Outputs) + + + Generating soup-version.h... + $(GenSoupVersionH) + ..\..\libsoup\soup-version.h;%(Outputs) + Generating soup-version.h... + $(GenSoupVersionH) + ..\..\libsoup\soup-version.h;%(Outputs) + Generating soup-version.h... + $(GenSoupVersionH) + ..\..\libsoup\soup-version.h;%(Outputs) + Generating soup-version.h... + $(GenSoupVersionH) + ..\..\libsoup\soup-version.h;%(Outputs) + + + + + + diff --git a/win32/vs15/soup.vcxproj.filters b/win32/vs15/soup.vcxproj.filters new file mode 100644 index 0000000..71eb5a6 --- /dev/null +++ b/win32/vs15/soup.vcxproj.filters @@ -0,0 +1,95 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav + + + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + Source Files + + + Resource Files + Resource Files + Resource Files + + diff --git a/win32/vs9/Makefile.am b/win32/vs9/Makefile.am new file mode 100644 index 0000000..62f77fa --- /dev/null +++ b/win32/vs9/Makefile.am @@ -0,0 +1,27 @@ +GENERATED_ITEMS = \ + soup.vcproj \ + soup-gnome.vcproj \ + soup-install.vsprops + +MSVC_HEADERS_LIST = soup.headers soup-gnome.headers + +EXTRA_DIST = \ + libsoup.sln \ + get.vcproj \ + simple-httpd.vcproj \ + simple-proxy.vcproj \ + soup-install.vcproj \ + soup-build-defines.vsprops \ + soup-dll-build-defines.vsprops \ + soup-gen-srcs.vsprops \ + soup-version-paths.vsprops \ + soup.vcprojin \ + soup-gnome.vcprojin \ + soup-install.vspropsin \ + $(GENERATED_ITEMS) + +soup-install.vsprops: $(top_srcdir)/win32/vs9/soup-install.vspropsin $(MSVC_HEADERS_LIST) + $(CPP) -P - <$(top_srcdir)/win32/vs9/soup-install.vspropsin >$@ + rm $(MSVC_HEADERS_LIST) + +DISTCLEANFILES = $(GENERATED_ITEMS) diff --git a/win32/vs9/Makefile.in b/win32/vs9/Makefile.in new file mode 100644 index 0000000..23ca1ac --- /dev/null +++ b/win32/vs9/Makefile.in @@ -0,0 +1,552 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = win32/vs9 +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_code_coverage.m4 \ + $(top_srcdir)/m4/glibtests.m4 $(top_srcdir)/m4/gtk-doc.m4 \ + $(top_srcdir)/m4/intltool.m4 $(top_srcdir)/m4/introspection.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/vapigen.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = soup-version-paths.vsprops +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +am__DIST_COMMON = $(srcdir)/Makefile.in \ + $(srcdir)/soup-version-paths.vsprops.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALL_LINGUAS = @ALL_LINGUAS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +APACHE_HTTPD = @APACHE_HTTPD@ +APACHE_MODULE_DIR = @APACHE_MODULE_DIR@ +APACHE_PHP_MODULE_DIR = @APACHE_PHP_MODULE_DIR@ +APACHE_SSL_MODULE_DIR = @APACHE_SSL_MODULE_DIR@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CODE_COVERAGE_CFLAGS = @CODE_COVERAGE_CFLAGS@ +CODE_COVERAGE_CPPFLAGS = @CODE_COVERAGE_CPPFLAGS@ +CODE_COVERAGE_CXXFLAGS = @CODE_COVERAGE_CXXFLAGS@ +CODE_COVERAGE_ENABLED = @CODE_COVERAGE_ENABLED@ +CODE_COVERAGE_LDFLAGS = @CODE_COVERAGE_LDFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CURL = @CURL@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GCOV = @GCOV@ +GENHTML = @GENHTML@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_COMPILE_RESOURCES = @GLIB_COMPILE_RESOURCES@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MAKEFILE = @GLIB_MAKEFILE@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GMSGFMT = @GMSGFMT@ +GOBJECT_QUERY = @GOBJECT_QUERY@ +GREP = @GREP@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +HAVE_GNOME = @HAVE_GNOME@ +HTML_DIR = @HTML_DIR@ +IF_HAVE_MOD_UNIXD = @IF_HAVE_MOD_UNIXD@ +IF_HAVE_PHP = @IF_HAVE_PHP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ +INTLTOOL_MERGE = @INTLTOOL_MERGE@ +INTLTOOL_PERL = @INTLTOOL_PERL@ +INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ +INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@ +INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@ +INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@ +INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LCOV = @LCOV@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PHP = @PHP@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOUP_AGE = @SOUP_AGE@ +SOUP_API_VERSION = @SOUP_API_VERSION@ +SOUP_CURRENT = @SOUP_CURRENT@ +SOUP_DEBUG_FLAGS = @SOUP_DEBUG_FLAGS@ +SOUP_HIDDEN_VISIBILITY_CFLAGS = @SOUP_HIDDEN_VISIBILITY_CFLAGS@ +SOUP_MAJOR_VERSION = @SOUP_MAJOR_VERSION@ +SOUP_MICRO_VERSION = @SOUP_MICRO_VERSION@ +SOUP_MINOR_VERSION = @SOUP_MINOR_VERSION@ +SOUP_REVISION = @SOUP_REVISION@ +SQLITE_CFLAGS = @SQLITE_CFLAGS@ +SQLITE_LIBS = @SQLITE_LIBS@ +STRIP = @STRIP@ +USE_NLS = @USE_NLS@ +VALAC = @VALAC@ +VAPIDIR = @VAPIDIR@ +VAPIGEN = @VAPIGEN@ +VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@ +VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@ +VERSION = @VERSION@ +XGETTEXT = @XGETTEXT@ +XML_CFLAGS = @XML_CFLAGS@ +XML_LIBS = @XML_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +installed_test_metadir = @installed_test_metadir@ +installed_testdir = @installed_testdir@ +intltool__v_merge_options_ = @intltool__v_merge_options_@ +intltool__v_merge_options_0 = @intltool__v_merge_options_0@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +ntlm_auth = @ntlm_auth@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +GENERATED_ITEMS = \ + soup.vcproj \ + soup-gnome.vcproj \ + soup-install.vsprops + +MSVC_HEADERS_LIST = soup.headers soup-gnome.headers +EXTRA_DIST = \ + libsoup.sln \ + get.vcproj \ + simple-httpd.vcproj \ + simple-proxy.vcproj \ + soup-install.vcproj \ + soup-build-defines.vsprops \ + soup-dll-build-defines.vsprops \ + soup-gen-srcs.vsprops \ + soup-version-paths.vsprops \ + soup.vcprojin \ + soup-gnome.vcprojin \ + soup-install.vspropsin \ + $(GENERATED_ITEMS) + +DISTCLEANFILES = $(GENERATED_ITEMS) +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign win32/vs9/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign win32/vs9/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +soup-version-paths.vsprops: $(top_builddir)/config.status $(srcdir)/soup-version-paths.vsprops.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +tags TAGS: + +ctags CTAGS: + +cscope cscopelist: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic clean-libtool \ + cscopelist-am ctags-am distclean distclean-generic \ + distclean-libtool distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +soup-install.vsprops: $(top_srcdir)/win32/vs9/soup-install.vspropsin $(MSVC_HEADERS_LIST) + $(CPP) -P - <$(top_srcdir)/win32/vs9/soup-install.vspropsin >$@ + rm $(MSVC_HEADERS_LIST) + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/win32/vs9/get.vcproj b/win32/vs9/get.vcproj new file mode 100644 index 0000000..7c3f998 --- /dev/null +++ b/win32/vs9/get.vcproj @@ -0,0 +1,162 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/win32/vs9/libsoup.sln b/win32/vs9/libsoup.sln new file mode 100644 index 0000000..d738f8e --- /dev/null +++ b/win32/vs9/libsoup.sln @@ -0,0 +1,147 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "soup", "soup.vcproj", "{D83A3162-B14C-459C-AF81-15BBFA90240D}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "soup-gnome", "soup-gnome.vcproj", "{8C88A385-28C8-4B30-91A4-FBA381A5A46F}" + ProjectSection(ProjectDependencies) = postProject + {D83A3162-B14C-459C-AF81-15BBFA90240D} = {D83A3162-B14C-459C-AF81-15BBFA90240D} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "get", "get.vcproj", "{B24831C4-B8F2-41D6-AAF4-12192F71C623}" + ProjectSection(ProjectDependencies) = postProject + {D83A3162-B14C-459C-AF81-15BBFA90240D} = {D83A3162-B14C-459C-AF81-15BBFA90240D} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "simple-httpd", "simple-httpd.vcproj", "{80DC062E-2146-4CE8-A448-FD2205AB2CA4}" + ProjectSection(ProjectDependencies) = postProject + {D83A3162-B14C-459C-AF81-15BBFA90240D} = {D83A3162-B14C-459C-AF81-15BBFA90240D} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "simple-proxy", "simple-proxy.vcproj", "{3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}" + ProjectSection(ProjectDependencies) = postProject + {D83A3162-B14C-459C-AF81-15BBFA90240D} = {D83A3162-B14C-459C-AF81-15BBFA90240D} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "soup-install", "soup-install.vcproj", "{E0DCF460-914F-46F9-94D6-86D456CB53E9}" + ProjectSection(ProjectDependencies) = postProject + {80DC062E-2146-4CE8-A448-FD2205AB2CA4} = {80DC062E-2146-4CE8-A448-FD2205AB2CA4} + {D83A3162-B14C-459C-AF81-15BBFA90240D} = {D83A3162-B14C-459C-AF81-15BBFA90240D} + {8C88A385-28C8-4B30-91A4-FBA381A5A46F} = {8C88A385-28C8-4B30-91A4-FBA381A5A46F} + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E} = {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E} + {B24831C4-B8F2-41D6-AAF4-12192F71C623} = {B24831C4-B8F2-41D6-AAF4-12192F71C623} + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + Debug_MIT_GSSAPI|Win32 = Debug_MIT_GSSAPI|Win32 + Debug_MIT_GSSAPI|x64 = Debug_MIT_GSSAPI|x64 + Release_MIT_GSSAPI|Win32 = Release_MIT_GSSAPI|Win32 + Release_MIT_GSSAPI|x64 = Release_MIT_GSSAPI|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Debug|Win32.ActiveCfg = Debug|Win32 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Debug|Win32.Build.0 = Debug|Win32 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Debug|x64.ActiveCfg = Debug|x64 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Debug|x64.Build.0 = Debug|x64 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Release|Win32.ActiveCfg = Release|Win32 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Release|Win32.Build.0 = Release|Win32 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Release|x64.ActiveCfg = Release|x64 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Release|x64.Build.0 = Release|x64 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Debug_MIT_GSSAPI|Win32.ActiveCfg = Debug_MIT_GSSAPI|Win32 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Debug_MIT_GSSAPI|Win32.Build.0 = Debug_MIT_GSSAPI|Win32 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Debug_MIT_GSSAPI|x64.ActiveCfg = Debug_MIT_GSSAPI|x64 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Debug_MIT_GSSAPI|x64.Build.0 = Debug_MIT_GSSAPI|x64 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Release_MIT_GSSAPI|Win32.ActiveCfg = Release_MIT_GSSAPI|Win32 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Release_MIT_GSSAPI|Win32.Build.0 = Release_MIT_GSSAPI|Win32 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Release_MIT_GSSAPI|x64.ActiveCfg = Release_MIT_GSSAPI|x64 + {D83A3162-B14C-459C-AF81-15BBFA90240D}.Release_MIT_GSSAPI|x64.Build.0 = Release_MIT_GSSAPI|x64 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Debug|Win32.ActiveCfg = Debug|Win32 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Debug|Win32.Build.0 = Debug|Win32 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Debug|x64.ActiveCfg = Debug|x64 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Debug|x64.Build.0 = Debug|x64 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Release|Win32.ActiveCfg = Release|Win32 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Release|Win32.Build.0 = Release|Win32 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Release|x64.ActiveCfg = Release|x64 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Release|x64.Build.0 = Release|x64 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Debug_MIT_GSSAPI|Win32.ActiveCfg = Debug|Win32 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Debug_MIT_GSSAPI|Win32.Build.0 = Debug|Win32 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Debug_MIT_GSSAPI|x64.ActiveCfg = Debug|x64 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Debug_MIT_GSSAPI|x64.Build.0 = Debug|x64 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Release_MIT_GSSAPI|Win32.ActiveCfg = Release|Win32 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Release_MIT_GSSAPI|Win32.Build.0 = Release|Win32 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Release_MIT_GSSAPI|x64.ActiveCfg = Release|x64 + {8C88A385-28C8-4B30-91A4-FBA381A5A46F}.Release_MIT_GSSAPI|x64.Build.0 = Release|x64 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Debug|Win32.ActiveCfg = Debug|Win32 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Debug|Win32.Build.0 = Debug|Win32 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Debug|x64.ActiveCfg = Debug|x64 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Debug|x64.Build.0 = Debug|x64 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Release|Win32.ActiveCfg = Release|Win32 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Release|Win32.Build.0 = Release|Win32 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Release|x64.ActiveCfg = Release|x64 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Release|x64.Build.0 = Release|x64 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Debug_MIT_GSSAPI|Win32.ActiveCfg = Debug|Win32 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Debug_MIT_GSSAPI|Win32.Build.0 = Debug|Win32 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Debug_MIT_GSSAPI|x64.ActiveCfg = Debug|x64 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Debug_MIT_GSSAPI|x64.Build.0 = Debug|x64 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Release_MIT_GSSAPI|Win32.ActiveCfg = Release|Win32 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Release_MIT_GSSAPI|Win32.Build.0 = Release|Win32 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Release_MIT_GSSAPI|x64.ActiveCfg = Release|x64 + {B24831C4-B8F2-41D6-AAF4-12192F71C623}.Release_MIT_GSSAPI|x64.Build.0 = Release|x64 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Debug|Win32.ActiveCfg = Debug|Win32 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Debug|Win32.Build.0 = Debug|Win32 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Debug|x64.ActiveCfg = Debug|x64 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Debug|x64.Build.0 = Debug|x64 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Release|Win32.ActiveCfg = Release|Win32 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Release|Win32.Build.0 = Release|Win32 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Release|x64.ActiveCfg = Release|x64 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Release|x64.Build.0 = Release|x64 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Debug_MIT_GSSAPI|Win32.ActiveCfg = Debug|Win32 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Debug_MIT_GSSAPI|Win32.Build.0 = Debug|Win32 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Debug_MIT_GSSAPI|x64.ActiveCfg = Debug|x64 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Debug_MIT_GSSAPI|x64.Build.0 = Debug|x64 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Release_MIT_GSSAPI|Win32.ActiveCfg = Release|Win32 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Release_MIT_GSSAPI|Win32.Build.0 = Release|Win32 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Release_MIT_GSSAPI|x64.ActiveCfg = Release|x64 + {80DC062E-2146-4CE8-A448-FD2205AB2CA4}.Release_MIT_GSSAPI|x64.Build.0 = Release|x64 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Debug|Win32.ActiveCfg = Debug|Win32 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Debug|Win32.Build.0 = Debug|Win32 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Debug|x64.ActiveCfg = Debug|x64 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Debug|x64.Build.0 = Debug|x64 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Release|Win32.ActiveCfg = Release|Win32 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Release|Win32.Build.0 = Release|Win32 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Release|x64.ActiveCfg = Release|x64 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Release|x64.Build.0 = Release|x64 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Debug_MIT_GSSAPI|Win32.ActiveCfg = Debug|Win32 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Debug_MIT_GSSAPI|Win32.Build.0 = Debug|Win32 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Debug_MIT_GSSAPI|x64.ActiveCfg = Debug|x64 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Debug_MIT_GSSAPI|x64.Build.0 = Debug|x64 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Release_MIT_GSSAPI|Win32.ActiveCfg = Release|Win32 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Release_MIT_GSSAPI|Win32.Build.0 = Release|Win32 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Release_MIT_GSSAPI|x64.ActiveCfg = Release|x64 + {3AD0CB92-EE38-425E-83CB-E7B1CB1D305E}.Release_MIT_GSSAPI|x64.Build.0 = Release|x64 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Debug|Win32.ActiveCfg = Debug|Win32 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Debug|Win32.Build.0 = Debug|Win32 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Debug|x64.ActiveCfg = Debug|x64 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Debug|x64.Build.0 = Debug|x64 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Release|Win32.ActiveCfg = Release|Win32 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Release|Win32.Build.0 = Release|Win32 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Release|x64.ActiveCfg = Release|x64 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Release|x64.Build.0 = Release|x64 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Debug_MIT_GSSAPI|Win32.ActiveCfg = Debug|Win32 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Debug_MIT_GSSAPI|Win32.Build.0 = Debug|Win32 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Debug_MIT_GSSAPI|x64.ActiveCfg = Debug|x64 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Debug_MIT_GSSAPI|x64.Build.0 = Debug|x64 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Release_MIT_GSSAPI|Win32.ActiveCfg = Release|Win32 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Release_MIT_GSSAPI|Win32.Build.0 = Release|Win32 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Release_MIT_GSSAPI|x64.ActiveCfg = Release|x64 + {E0DCF460-914F-46F9-94D6-86D456CB53E9}.Release_MIT_GSSAPI|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/win32/vs9/simple-httpd.vcproj b/win32/vs9/simple-httpd.vcproj new file mode 100644 index 0000000..217306e --- /dev/null +++ b/win32/vs9/simple-httpd.vcproj @@ -0,0 +1,162 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/win32/vs9/simple-proxy.vcproj b/win32/vs9/simple-proxy.vcproj new file mode 100644 index 0000000..cd3582d --- /dev/null +++ b/win32/vs9/simple-proxy.vcproj @@ -0,0 +1,162 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/win32/vs9/soup-build-defines.vsprops b/win32/vs9/soup-build-defines.vsprops new file mode 100644 index 0000000..095d568 --- /dev/null +++ b/win32/vs9/soup-build-defines.vsprops @@ -0,0 +1,22 @@ + + + + + diff --git a/win32/vs9/soup-dll-build-defines.vsprops b/win32/vs9/soup-dll-build-defines.vsprops new file mode 100644 index 0000000..02d0547 --- /dev/null +++ b/win32/vs9/soup-dll-build-defines.vsprops @@ -0,0 +1,38 @@ + + + + + + + + + + diff --git a/win32/vs9/soup-gen-srcs.vsprops b/win32/vs9/soup-gen-srcs.vsprops new file mode 100644 index 0000000..d897efa --- /dev/null +++ b/win32/vs9/soup-gen-srcs.vsprops @@ -0,0 +1,20 @@ + + + + + + diff --git a/win32/vs9/soup-gnome.vcproj b/win32/vs9/soup-gnome.vcproj new file mode 100644 index 0000000..cbeb14c --- /dev/null +++ b/win32/vs9/soup-gnome.vcproj @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/win32/vs9/soup-gnome.vcprojin b/win32/vs9/soup-gnome.vcprojin new file mode 100644 index 0000000..8e13232 --- /dev/null +++ b/win32/vs9/soup-gnome.vcprojin @@ -0,0 +1,162 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +#include "soup-gnome.sourcefiles" + + + + + + + + + diff --git a/win32/vs9/soup-install.vcproj b/win32/vs9/soup-install.vcproj new file mode 100644 index 0000000..665b91a --- /dev/null +++ b/win32/vs9/soup-install.vcproj @@ -0,0 +1,114 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/win32/vs9/soup-install.vsprops b/win32/vs9/soup-install.vsprops new file mode 100644 index 0000000..4a03756 --- /dev/null +++ b/win32/vs9/soup-install.vsprops @@ -0,0 +1,91 @@ + + + + + diff --git a/win32/vs9/soup-install.vspropsin b/win32/vs9/soup-install.vspropsin new file mode 100644 index 0000000..5948d77 --- /dev/null +++ b/win32/vs9/soup-install.vspropsin @@ -0,0 +1,40 @@ + + + + + diff --git a/win32/vs9/soup-version-paths.vsprops b/win32/vs9/soup-version-paths.vsprops new file mode 100644 index 0000000..8a562d0 --- /dev/null +++ b/win32/vs9/soup-version-paths.vsprops @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + diff --git a/win32/vs9/soup-version-paths.vsprops.in b/win32/vs9/soup-version-paths.vsprops.in new file mode 100644 index 0000000..cde608e --- /dev/null +++ b/win32/vs9/soup-version-paths.vsprops.in @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + diff --git a/win32/vs9/soup.vcproj b/win32/vs9/soup.vcproj new file mode 100644 index 0000000..f791b4a --- /dev/null +++ b/win32/vs9/soup.vcproj @@ -0,0 +1,391 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/win32/vs9/soup.vcprojin b/win32/vs9/soup.vcprojin new file mode 100644 index 0000000..58f4baa --- /dev/null +++ b/win32/vs9/soup.vcprojin @@ -0,0 +1,318 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +#include "soup.sourcefiles" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +