35 files changed, 2505 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..87771db --- a/dev/null +++ b/.gitignore | |||
@@ -0,0 +1,21 @@ | |||
1 | configure | ||
2 | Makefile.in | ||
3 | Doxyfile | ||
4 | config.log | ||
5 | depcomp | ||
6 | config.guess | ||
7 | config.h | ||
8 | config.sub | ||
9 | ltmain.sh | ||
10 | INSTALL | ||
11 | NEWS | ||
12 | Makefile | ||
13 | config.status | ||
14 | stamp-h1 | ||
15 | config.h.in | ||
16 | libtool | ||
17 | autom4te.cache | ||
18 | libopkele.pc | ||
19 | missing | ||
20 | aclocal.m4 | ||
21 | install-sh | ||
@@ -0,0 +1,3 @@ | |||
1 | Klever dissected: | ||
2 | Michael 'hacker' Krelin <hacker@klever.net> | ||
3 | Leonid Ivanov <kamel@klever.net> | ||
@@ -0,0 +1,19 @@ | |||
1 | Copyright (c) 2005 Klever Group (http://www.klever.net/) | ||
2 | |||
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of | ||
4 | this software and associated documentation files (the "Software"), to deal in | ||
5 | the Software without restriction, including without limitation the rights to | ||
6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies | ||
7 | of the Software, and to permit persons to whom the Software is furnished to do | ||
8 | so, subject to the following conditions: | ||
9 | |||
10 | The above copyright notice and this permission notice shall be included in all | ||
11 | copies or substantial portions of the Software. | ||
12 | |||
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
19 | SOFTWARE. | ||
diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..e69de29 --- a/dev/null +++ b/ChangeLog | |||
diff --git a/Doxyfile.in b/Doxyfile.in new file mode 100644 index 0000000..fac9a29 --- a/dev/null +++ b/Doxyfile.in | |||
@@ -0,0 +1,247 @@ | |||
1 | # Doxyfile 1.3.9.1 | ||
2 | |||
3 | #--------------------------------------------------------------------------- | ||
4 | # Project related configuration options | ||
5 | #--------------------------------------------------------------------------- | ||
6 | PROJECT_NAME = @PACKAGE@ | ||
7 | PROJECT_NUMBER = @VERSION@ | ||
8 | OUTPUT_DIRECTORY = @builddir@/doxydox | ||
9 | CREATE_SUBDIRS = NO | ||
10 | OUTPUT_LANGUAGE = English | ||
11 | USE_WINDOWS_ENCODING = NO | ||
12 | BRIEF_MEMBER_DESC = YES | ||
13 | REPEAT_BRIEF = YES | ||
14 | ABBREVIATE_BRIEF = | ||
15 | ALWAYS_DETAILED_SEC = NO | ||
16 | INLINE_INHERITED_MEMB = NO | ||
17 | FULL_PATH_NAMES = YES | ||
18 | STRIP_FROM_PATH = include | ||
19 | STRIP_FROM_INC_PATH = include | ||
20 | SHORT_NAMES = NO | ||
21 | JAVADOC_AUTOBRIEF = NO | ||
22 | MULTILINE_CPP_IS_BRIEF = NO | ||
23 | DETAILS_AT_TOP = NO | ||
24 | INHERIT_DOCS = YES | ||
25 | DISTRIBUTE_GROUP_DOC = NO | ||
26 | TAB_SIZE = 8 | ||
27 | ALIASES = | ||
28 | OPTIMIZE_OUTPUT_FOR_C = NO | ||
29 | OPTIMIZE_OUTPUT_JAVA = NO | ||
30 | SUBGROUPING = YES | ||
31 | |||
32 | #--------------------------------------------------------------------------- | ||
33 | # Build related configuration options | ||
34 | #--------------------------------------------------------------------------- | ||
35 | |||
36 | EXTRACT_ALL = NO | ||
37 | EXTRACT_PRIVATE = NO | ||
38 | EXTRACT_STATIC = NO | ||
39 | EXTRACT_LOCAL_CLASSES = YES | ||
40 | EXTRACT_LOCAL_METHODS = NO | ||
41 | HIDE_UNDOC_MEMBERS = NO | ||
42 | HIDE_UNDOC_CLASSES = NO | ||
43 | HIDE_FRIEND_COMPOUNDS = NO | ||
44 | HIDE_IN_BODY_DOCS = NO | ||
45 | INTERNAL_DOCS = NO | ||
46 | CASE_SENSE_NAMES = YES | ||
47 | HIDE_SCOPE_NAMES = NO | ||
48 | SHOW_INCLUDE_FILES = NO | ||
49 | INLINE_INFO = YES | ||
50 | SORT_MEMBER_DOCS = YES | ||
51 | SORT_BRIEF_DOCS = NO | ||
52 | SORT_BY_SCOPE_NAME = YES | ||
53 | GENERATE_TODOLIST = YES | ||
54 | GENERATE_TESTLIST = YES | ||
55 | GENERATE_BUGLIST = YES | ||
56 | GENERATE_DEPRECATEDLIST= YES | ||
57 | ENABLED_SECTIONS = | ||
58 | MAX_INITIALIZER_LINES = 30 | ||
59 | SHOW_USED_FILES = NO | ||
60 | SHOW_DIRECTORIES = YES | ||
61 | |||
62 | #--------------------------------------------------------------------------- | ||
63 | # configuration options related to warning and progress messages | ||
64 | #--------------------------------------------------------------------------- | ||
65 | |||
66 | QUIET = NO | ||
67 | WARNINGS = YES | ||
68 | WARN_IF_UNDOCUMENTED = YES | ||
69 | WARN_IF_DOC_ERROR = YES | ||
70 | WARN_FORMAT = "$file:$line: $text" | ||
71 | WARN_LOGFILE = | ||
72 | |||
73 | #--------------------------------------------------------------------------- | ||
74 | # configuration options related to the input files | ||
75 | #--------------------------------------------------------------------------- | ||
76 | |||
77 | INPUT = \ | ||
78 | @srcdir@/include/opkele/ | ||
79 | FILE_PATTERNS = *.h | ||
80 | RECURSIVE = NO | ||
81 | EXCLUDE = | ||
82 | EXCLUDE_SYMLINKS = NO | ||
83 | EXCLUDE_PATTERNS = | ||
84 | EXAMPLE_PATH = | ||
85 | EXAMPLE_PATTERNS = | ||
86 | EXAMPLE_RECURSIVE = NO | ||
87 | IMAGE_PATH = | ||
88 | INPUT_FILTER = | ||
89 | FILTER_PATTERNS = | ||
90 | FILTER_SOURCE_FILES = NO | ||
91 | |||
92 | #--------------------------------------------------------------------------- | ||
93 | # configuration options related to source browsing | ||
94 | #--------------------------------------------------------------------------- | ||
95 | |||
96 | SOURCE_BROWSER = NO | ||
97 | INLINE_SOURCES = NO | ||
98 | STRIP_CODE_COMMENTS = YES | ||
99 | REFERENCED_BY_RELATION = YES | ||
100 | REFERENCES_RELATION = YES | ||
101 | VERBATIM_HEADERS = YES | ||
102 | |||
103 | #--------------------------------------------------------------------------- | ||
104 | # configuration options related to the alphabetical class index | ||
105 | #--------------------------------------------------------------------------- | ||
106 | |||
107 | ALPHABETICAL_INDEX = YES | ||
108 | COLS_IN_ALPHA_INDEX = 2 | ||
109 | IGNORE_PREFIX = | ||
110 | |||
111 | #--------------------------------------------------------------------------- | ||
112 | # configuration options related to the HTML output | ||
113 | #--------------------------------------------------------------------------- | ||
114 | |||
115 | GENERATE_HTML = YES | ||
116 | HTML_OUTPUT = html | ||
117 | HTML_FILE_EXTENSION = .html | ||
118 | HTML_HEADER = | ||
119 | HTML_FOOTER = | ||
120 | HTML_STYLESHEET = | ||
121 | HTML_ALIGN_MEMBERS = YES | ||
122 | GENERATE_HTMLHELP = NO | ||
123 | CHM_FILE = | ||
124 | HHC_LOCATION = | ||
125 | GENERATE_CHI = NO | ||
126 | BINARY_TOC = NO | ||
127 | TOC_EXPAND = NO | ||
128 | DISABLE_INDEX = NO | ||
129 | ENUM_VALUES_PER_LINE = 4 | ||
130 | GENERATE_TREEVIEW = NO | ||
131 | TREEVIEW_WIDTH = 250 | ||
132 | |||
133 | #--------------------------------------------------------------------------- | ||
134 | # configuration options related to the LaTeX output | ||
135 | #--------------------------------------------------------------------------- | ||
136 | |||
137 | GENERATE_LATEX = NO | ||
138 | LATEX_OUTPUT = latex | ||
139 | LATEX_CMD_NAME = latex | ||
140 | MAKEINDEX_CMD_NAME = makeindex | ||
141 | COMPACT_LATEX = NO | ||
142 | PAPER_TYPE = a4wide | ||
143 | EXTRA_PACKAGES = | ||
144 | LATEX_HEADER = | ||
145 | PDF_HYPERLINKS = NO | ||
146 | USE_PDFLATEX = NO | ||
147 | LATEX_BATCHMODE = NO | ||
148 | LATEX_HIDE_INDICES = NO | ||
149 | |||
150 | #--------------------------------------------------------------------------- | ||
151 | # configuration options related to the RTF output | ||
152 | #--------------------------------------------------------------------------- | ||
153 | |||
154 | GENERATE_RTF = NO | ||
155 | RTF_OUTPUT = rtf | ||
156 | COMPACT_RTF = NO | ||
157 | RTF_HYPERLINKS = NO | ||
158 | RTF_STYLESHEET_FILE = | ||
159 | RTF_EXTENSIONS_FILE = | ||
160 | |||
161 | #--------------------------------------------------------------------------- | ||
162 | # configuration options related to the man page output | ||
163 | #--------------------------------------------------------------------------- | ||
164 | |||
165 | GENERATE_MAN = NO | ||
166 | MAN_OUTPUT = man | ||
167 | MAN_EXTENSION = .3 | ||
168 | MAN_LINKS = YES | ||
169 | |||
170 | #--------------------------------------------------------------------------- | ||
171 | # configuration options related to the XML output | ||
172 | #--------------------------------------------------------------------------- | ||
173 | |||
174 | GENERATE_XML = YES | ||
175 | XML_OUTPUT = xml | ||
176 | XML_SCHEMA = | ||
177 | XML_DTD = | ||
178 | XML_PROGRAMLISTING = YES | ||
179 | |||
180 | #--------------------------------------------------------------------------- | ||
181 | # configuration options for the AutoGen Definitions output | ||
182 | #--------------------------------------------------------------------------- | ||
183 | |||
184 | GENERATE_AUTOGEN_DEF = NO | ||
185 | |||
186 | #--------------------------------------------------------------------------- | ||
187 | # configuration options related to the Perl module output | ||
188 | #--------------------------------------------------------------------------- | ||
189 | |||
190 | GENERATE_PERLMOD = NO | ||
191 | PERLMOD_LATEX = NO | ||
192 | PERLMOD_PRETTY = YES | ||
193 | PERLMOD_MAKEVAR_PREFIX = | ||
194 | |||
195 | #--------------------------------------------------------------------------- | ||
196 | # Configuration options related to the preprocessor | ||
197 | #--------------------------------------------------------------------------- | ||
198 | |||
199 | ENABLE_PREPROCESSING = YES | ||
200 | MACRO_EXPANSION = NO | ||
201 | EXPAND_ONLY_PREDEF = NO | ||
202 | SEARCH_INCLUDES = YES | ||
203 | INCLUDE_PATH = | ||
204 | INCLUDE_FILE_PATTERNS = | ||
205 | PREDEFINED = | ||
206 | EXPAND_AS_DEFINED = | ||
207 | SKIP_FUNCTION_MACROS = YES | ||
208 | |||
209 | #--------------------------------------------------------------------------- | ||
210 | # Configuration::additions related to external references | ||
211 | #--------------------------------------------------------------------------- | ||
212 | |||
213 | TAGFILES = | ||
214 | GENERATE_TAGFILE = | ||
215 | ALLEXTERNALS = NO | ||
216 | EXTERNAL_GROUPS = YES | ||
217 | PERL_PATH = /usr/bin/perl | ||
218 | |||
219 | #--------------------------------------------------------------------------- | ||
220 | # Configuration options related to the dot tool | ||
221 | #--------------------------------------------------------------------------- | ||
222 | |||
223 | CLASS_DIAGRAMS = YES | ||
224 | HIDE_UNDOC_RELATIONS = YES | ||
225 | HAVE_DOT = @HAVE_DOT@ | ||
226 | CLASS_GRAPH = YES | ||
227 | COLLABORATION_GRAPH = YES | ||
228 | UML_LOOK = NO | ||
229 | TEMPLATE_RELATIONS = YES | ||
230 | INCLUDE_GRAPH = YES | ||
231 | INCLUDED_BY_GRAPH = YES | ||
232 | CALL_GRAPH = NO | ||
233 | GRAPHICAL_HIERARCHY = YES | ||
234 | DOT_IMAGE_FORMAT = png | ||
235 | DOT_PATH = @DOT@ | ||
236 | DOTFILE_DIRS = | ||
237 | MAX_DOT_GRAPH_WIDTH = 1024 | ||
238 | MAX_DOT_GRAPH_HEIGHT = 1024 | ||
239 | MAX_DOT_GRAPH_DEPTH = 0 | ||
240 | GENERATE_LEGEND = YES | ||
241 | DOT_CLEANUP = YES | ||
242 | |||
243 | #--------------------------------------------------------------------------- | ||
244 | # Configuration::additions related to the search engine | ||
245 | #--------------------------------------------------------------------------- | ||
246 | |||
247 | SEARCHENGINE = NO | ||
diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..c577ef8 --- a/dev/null +++ b/Makefile.am | |||
@@ -0,0 +1,23 @@ | |||
1 | |||
2 | SUBDIRS=include lib | ||
3 | EXTRA_DIST= NEWS NEWS.xml NEWS.xsl | ||
4 | |||
5 | DISTCHECK_CONFIGURE_FLAGS=--with-pkgconfigdir=$${dc_install_base}/lib/pkgconfig | ||
6 | if HAVE_PKGCONFIG | ||
7 | pkgconfigdir=@PKGCONFIG_DIR@ | ||
8 | pkgconfig_DATA=libopkele.pc | ||
9 | endif | ||
10 | |||
11 | all-local: NEWS | ||
12 | if HAVE_DOXYGEN | ||
13 | clean-local: | ||
14 | rm -rf doxydox | ||
15 | endif | ||
16 | |||
17 | NEWS: NEWS.xsl NEWS.xml | ||
18 | ${XSLTPROC} -o $@ NEWS.xsl NEWS.xml | ||
19 | |||
20 | if HAVE_DOXYGEN | ||
21 | dox: Doxyfile | ||
22 | ${DOXYGEN} | ||
23 | endif | ||
diff --git a/NEWS.xml b/NEWS.xml new file mode 100644 index 0000000..f8f3331 --- a/dev/null +++ b/NEWS.xml | |||
@@ -0,0 +1,6 @@ | |||
1 | <?xml version="1.0" encoding="us-ascii"?> | ||
2 | <news> | ||
3 | <version version="0.0" date="July 16th, 2005"> | ||
4 | <ni>Initial release</ni> | ||
5 | </version> | ||
6 | </news> | ||
diff --git a/NEWS.xsl b/NEWS.xsl new file mode 100644 index 0000000..7c71307 --- a/dev/null +++ b/NEWS.xsl | |||
@@ -0,0 +1,24 @@ | |||
1 | <?xml version="1.0" encoding="us-ascii"?> | ||
2 | <xsl:stylesheet version="1.0" | ||
3 | xmlns:xsl="http://www.w3.org/1999/XSL/Transform" | ||
4 | > | ||
5 | <xsl:output | ||
6 | method="text" | ||
7 | encoding="us-ascii" | ||
8 | media-type="text/plain" /> | ||
9 | |||
10 | <xsl:template match="news"> | ||
11 | <xsl:apply-templates/> | ||
12 | </xsl:template> | ||
13 | <xsl:template match="version"> | ||
14 | <xsl:value-of select="concat(@version,' (',@date,')
')"/> | ||
15 | <xsl:apply-templates/> | ||
16 | </xsl:template> | ||
17 | <xsl:template match="ni"> | ||
18 | <xsl:text> - </xsl:text> | ||
19 | <xsl:apply-templates mode="text"/> | ||
20 | <xsl:text>
</xsl:text> | ||
21 | </xsl:template> | ||
22 | <xsl:template match="*|text()"/> | ||
23 | |||
24 | </xsl:stylesheet> | ||
diff --git a/acinclude.d/libcurl.m4 b/acinclude.d/libcurl.m4 new file mode 100644 index 0000000..e80c206 --- a/dev/null +++ b/acinclude.d/libcurl.m4 | |||
@@ -0,0 +1,209 @@ | |||
1 | # LIBCURL_CHECK_CONFIG ([DEFAULT-ACTION], [MINIMUM-VERSION], | ||
2 | # [ACTION-IF-YES], [ACTION-IF-NO]) | ||
3 | # ---------------------------------------------------------- | ||
4 | # David Shaw <dshaw@jabberwocky.com> Jan-23-2005 | ||
5 | # | ||
6 | # Checks for libcurl. DEFAULT-ACTION is the string yes or no to | ||
7 | # specify whether to default to --with-libcurl or --without-libcurl. | ||
8 | # If not supplied, DEFAULT-ACTION is yes. MINIMUM-VERSION is the | ||
9 | # minimum version of libcurl to accept. Pass the version as a regular | ||
10 | # version number like 7.10.1. If not supplied, any version is | ||
11 | # accepted. ACTION-IF-YES is a list of shell commands to run if | ||
12 | # libcurl was successfully found and passed the various tests. | ||
13 | # ACTION-IF-NO is a list of shell commands that are run otherwise. | ||
14 | # Note that using --without-libcurl does run ACTION-IF-NO. | ||
15 | # | ||
16 | # This macro defines HAVE_LIBCURL if a working libcurl setup is found, | ||
17 | # and sets @LIBCURL@ and @LIBCURL_CPPFLAGS@ to the necessary values. | ||
18 | # Other useful defines are LIBCURL_FEATURE_xxx where xxx are the | ||
19 | # various features supported by libcurl, and LIBCURL_PROTOCOL_yyy | ||
20 | # where yyy are the various protocols supported by libcurl. Both xxx | ||
21 | # and yyy are capitalized. See the list of AH_TEMPLATEs at the top of | ||
22 | # the macro for the complete list of possible defines. Shell | ||
23 | # variables $libcurl_feature_xxx and $libcurl_protocol_yyy are also | ||
24 | # defined to 'yes' for those features and protocols that were found. | ||
25 | # Note that xxx and yyy keep the same capitalization as in the | ||
26 | # curl-config list (e.g. it's "HTTP" and not "http"). | ||
27 | # | ||
28 | # Users may override the detected values by doing something like: | ||
29 | # LIBCURL="-lcurl" LIBCURL_CPPFLAGS="-I/usr/myinclude" ./configure | ||
30 | # | ||
31 | # For the sake of sanity, this macro assumes that any libcurl that is | ||
32 | # found is after version 7.7.2, the first version that included the | ||
33 | # curl-config script. Note that it is very important for people | ||
34 | # packaging binary versions of libcurl to include this script! | ||
35 | # Without curl-config, we can only make educated guesses as to what | ||
36 | # protocols are available. Specifically, we assume that all of HTTP, | ||
37 | # FTP, GOPHER, FILE, TELNET, LDAP, and DICT exist, and (if SSL exists) | ||
38 | # HTTPS is present. All of these protocols existed when libcurl was | ||
39 | # first created in version 7, so this is a safe assumption. If the | ||
40 | # version is 7.11.0 or later, FTPS is assumed to be present as well. | ||
41 | # FTPS existed before then, but was not yet fully standards compliant. | ||
42 | |||
43 | AC_DEFUN([LIBCURL_CHECK_CONFIG], | ||
44 | [ | ||
45 | AH_TEMPLATE([LIBCURL_FEATURE_SSL],[Defined if libcurl supports SSL]) | ||
46 | AH_TEMPLATE([LIBCURL_FEATURE_KRB4],[Defined if libcurl supports KRB4]) | ||
47 | AH_TEMPLATE([LIBCURL_FEATURE_IPV6],[Defined if libcurl supports IPv6]) | ||
48 | AH_TEMPLATE([LIBCURL_FEATURE_LIBZ],[Defined if libcurl supports libz]) | ||
49 | AH_TEMPLATE([LIBCURL_FEATURE_ASYNCHDNS],[Defined if libcurl supports AsynchDNS]) | ||
50 | |||
51 | AH_TEMPLATE([LIBCURL_PROTOCOL_HTTP],[Defined if libcurl supports HTTP]) | ||
52 | AH_TEMPLATE([LIBCURL_PROTOCOL_HTTPS],[Defined if libcurl supports HTTPS]) | ||
53 | AH_TEMPLATE([LIBCURL_PROTOCOL_FTP],[Defined if libcurl supports FTP]) | ||
54 | AH_TEMPLATE([LIBCURL_PROTOCOL_FTPS],[Defined if libcurl supports FTPS]) | ||
55 | AH_TEMPLATE([LIBCURL_PROTOCOL_GOPHER],[Defined if libcurl supports GOPHER]) | ||
56 | AH_TEMPLATE([LIBCURL_PROTOCOL_FILE],[Defined if libcurl supports FILE]) | ||
57 | AH_TEMPLATE([LIBCURL_PROTOCOL_TELNET],[Defined if libcurl supports TELNET]) | ||
58 | AH_TEMPLATE([LIBCURL_PROTOCOL_LDAP],[Defined if libcurl supports LDAP]) | ||
59 | AH_TEMPLATE([LIBCURL_PROTOCOL_DICT],[Defined if libcurl supports DICT]) | ||
60 | |||
61 | AC_ARG_WITH(libcurl, | ||
62 | AC_HELP_STRING([--with-libcurl=DIR],[look for the curl library in DIR]), | ||
63 | [_libcurl_with=$withval],[_libcurl_with=ifelse([$1],,[yes],[$1])]) | ||
64 | |||
65 | if test "$_libcurl_with" != "no" ; then | ||
66 | |||
67 | AC_PROG_AWK | ||
68 | |||
69 | _libcurl_version_parse="eval $AWK '{split(\$NF,A,\".\"); X=256*256*A[[1]]+256*A[[2]]+A[[3]]; print X;}'" | ||
70 | |||
71 | _libcurl_try_link=yes | ||
72 | |||
73 | if test -d "$_libcurl_with" ; then | ||
74 | CPPFLAGS="${CPPFLAGS} -I$withval/include" | ||
75 | LDFLAGS="${LDFLAGS} -L$withval/lib" | ||
76 | fi | ||
77 | |||
78 | AC_PATH_PROG([_libcurl_config],[curl-config]) | ||
79 | |||
80 | if test x$_libcurl_config != "x" ; then | ||
81 | AC_CACHE_CHECK([for the version of libcurl], | ||
82 | [libcurl_cv_lib_curl_version], | ||
83 | [libcurl_cv_lib_curl_version=`$_libcurl_config --version | $AWK '{print $[]2}'`]) | ||
84 | |||
85 | _libcurl_version=`echo $libcurl_cv_lib_curl_version | $_libcurl_version_parse` | ||
86 | _libcurl_wanted=`echo ifelse([$2],,[0],[$2]) | $_libcurl_version_parse` | ||
87 | |||
88 | if test $_libcurl_wanted -gt 0 ; then | ||
89 | AC_CACHE_CHECK([for libcurl >= version $2], | ||
90 | [libcurl_cv_lib_version_ok], | ||
91 | [ | ||
92 | if test $_libcurl_version -ge $_libcurl_wanted ; then | ||
93 | libcurl_cv_lib_version_ok=yes | ||
94 | else | ||
95 | libcurl_cv_lib_version_ok=no | ||
96 | fi | ||
97 | ]) | ||
98 | fi | ||
99 | |||
100 | if test $_libcurl_wanted -eq 0 || test x$libcurl_cv_lib_version_ok = xyes ; then | ||
101 | if test x"$LIBCURL_CPPFLAGS" = "x" ; then | ||
102 | LIBCURL_CPPFLAGS=`$_libcurl_config --cflags` | ||
103 | fi | ||
104 | if test x"$LIBCURL" = "x" ; then | ||
105 | LIBCURL=`$_libcurl_config --libs` | ||
106 | fi | ||
107 | |||
108 | # All curl-config scripts support --feature | ||
109 | _libcurl_features=`$_libcurl_config --feature` | ||
110 | |||
111 | # Is it modern enough to have --protocols? (7.12.4) | ||
112 | if test $_libcurl_version -ge 461828 ; then | ||
113 | _libcurl_protocols=`$_libcurl_config --protocols` | ||
114 | fi | ||
115 | else | ||
116 | _libcurl_try_link=no | ||
117 | fi | ||
118 | |||
119 | unset _libcurl_wanted | ||
120 | fi | ||
121 | |||
122 | if test $_libcurl_try_link = yes ; then | ||
123 | |||
124 | # we didn't find curl-config, so let's see if the user-supplied | ||
125 | # link line (or failing that, "-lcurl") is enough. | ||
126 | LIBCURL=${LIBCURL-"-lcurl"} | ||
127 | |||
128 | AC_CACHE_CHECK([whether libcurl is usable], | ||
129 | [libcurl_cv_lib_curl_usable], | ||
130 | [ | ||
131 | _libcurl_save_cppflags=$CPPFLAGS | ||
132 | CPPFLAGS="$CPPFLAGS $LIBCURL_CPPFLAGS" | ||
133 | _libcurl_save_ldflags=$LDFLAGS | ||
134 | LDFLAGS="$LDFLAGS $LIBCURL" | ||
135 | |||
136 | AC_LINK_IFELSE(AC_LANG_PROGRAM([#include <curl/curl.h>],[ | ||
137 | /* Try and use a few common options to force a failure if we are | ||
138 | missing symbols or can't link. */ | ||
139 | int x; | ||
140 | curl_easy_setopt(NULL,CURLOPT_URL,NULL); | ||
141 | x=CURL_ERROR_SIZE; | ||
142 | x=CURLOPT_WRITEFUNCTION; | ||
143 | x=CURLOPT_FILE; | ||
144 | x=CURLOPT_ERRORBUFFER; | ||
145 | x=CURLOPT_STDERR; | ||
146 | x=CURLOPT_VERBOSE; | ||
147 | ]),libcurl_cv_lib_curl_usable=yes,libcurl_cv_lib_curl_usable=no) | ||
148 | |||
149 | CPPFLAGS=$_libcurl_save_cppflags | ||
150 | LDFLAGS=$_libcurl_save_ldflags | ||
151 | unset _libcurl_save_cppflags | ||
152 | unset _libcurl_save_ldflags | ||
153 | ]) | ||
154 | |||
155 | if test $libcurl_cv_lib_curl_usable = yes ; then | ||
156 | AC_DEFINE(HAVE_LIBCURL,1, | ||
157 | [Define to 1 if you have a functional curl library.]) | ||
158 | AC_SUBST(LIBCURL_CPPFLAGS) | ||
159 | AC_SUBST(LIBCURL) | ||
160 | |||
161 | for _libcurl_feature in $_libcurl_features ; do | ||
162 | AC_DEFINE_UNQUOTED(AS_TR_CPP(libcurl_feature_$_libcurl_feature),[1]) | ||
163 | eval AS_TR_SH(libcurl_feature_$_libcurl_feature)=yes | ||
164 | done | ||
165 | |||
166 | if test "x$_libcurl_protocols" = "x" ; then | ||
167 | |||
168 | # We don't have --protocols, so just assume that all | ||
169 | # protocols are available | ||
170 | _libcurl_protocols="HTTP FTP GOPHER FILE TELNET LDAP DICT" | ||
171 | |||
172 | if test x$libcurl_feature_SSL = xyes ; then | ||
173 | _libcurl_protocols="$_libcurl_protocols HTTPS" | ||
174 | |||
175 | # FTPS wasn't standards-compliant until version | ||
176 | # 7.11.0 | ||
177 | if test $_libcurl_version -ge 461568; then | ||
178 | _libcurl_protocols="$_libcurl_protocols FTPS" | ||
179 | fi | ||
180 | fi | ||
181 | fi | ||
182 | |||
183 | for _libcurl_protocol in $_libcurl_protocols ; do | ||
184 | AC_DEFINE_UNQUOTED(AS_TR_CPP(libcurl_protocol_$_libcurl_protocol),[1]) | ||
185 | eval AS_TR_SH(libcurl_protocol_$_libcurl_protocol)=yes | ||
186 | done | ||
187 | fi | ||
188 | fi | ||
189 | |||
190 | unset _libcurl_try_link | ||
191 | unset _libcurl_version_parse | ||
192 | unset _libcurl_config | ||
193 | unset _libcurl_feature | ||
194 | unset _libcurl_features | ||
195 | unset _libcurl_protocol | ||
196 | unset _libcurl_protocols | ||
197 | unset _libcurl_version | ||
198 | fi | ||
199 | |||
200 | if test x$_libcurl_with = xno || test x$libcurl_cv_lib_curl_usable != xyes ; then | ||
201 | # This is the IF-NO path | ||
202 | ifelse([$4],,:,[$4]) | ||
203 | else | ||
204 | # This is the IF-YES path | ||
205 | ifelse([$3],,:,[$3]) | ||
206 | fi | ||
207 | |||
208 | unset _libcurl_with | ||
209 | ])dnl | ||
diff --git a/acinclude.m4 b/acinclude.m4 new file mode 100644 index 0000000..9c9f945 --- a/dev/null +++ b/acinclude.m4 | |||
@@ -0,0 +1,213 @@ | |||
1 | dnl AC_WITH_PKGCONFIG([ACTION-IF-FOUND[,ACTION-IF-NOT-FOUND]]) | ||
2 | dnl Outputs: | ||
3 | dnl AC_SUBST: PKGCONFIG_PKGCONFIG PKGCONFIG_DIR | ||
4 | dnl AM_CONDTIONAL: HAVE_PKGCONFIG | ||
5 | AC_DEFUN([AC_WITH_PKGCONFIG],[ | ||
6 | PKGCONFIG_PKGCONFIG="" | ||
7 | PKGCONFIG_DIR="" | ||
8 | HAVE_PKGCONFIG="no" | ||
9 | EXPLICIT_PKGCONFIGDIR="no" | ||
10 | test -z "${WANT_PKGCONFIG}" && WANT_PKGCONFIG="" | ||
11 | AC_PATH_PROG([PKGCONFIG_PKGCONFIG],[pkg-config],[false]) | ||
12 | if test "${PKGCONFIG_PKGCONFIG}" != "false" ; then | ||
13 | AC_ARG_WITH([pkgconfigdir], | ||
14 | AC_HELP_STRING([--with-pkgconfigdir=dir],[Specify pkgconfig directory]), | ||
15 | [ | ||
16 | if test "${withval}" = "no" ; then | ||
17 | WANT_PKGCONFIG="no" | ||
18 | else | ||
19 | PKGCONFIG_DIR="${withval}" | ||
20 | EXPLICIT_PKGCONFIGDIR="yes" | ||
21 | fi | ||
22 | ],[ | ||
23 | AC_MSG_CHECKING([for pkgconfig directory]) | ||
24 | PKGCONFIG_DIR="`${PKGCONFIG_PKGCONFIG} --debug 2>&1 | grep '^Scanning'| head -n 1 | cut -d\' -f2-|cut -d\' -f1`" | ||
25 | AC_MSG_RESULT([${PKGCONFIG_DIR}]) | ||
26 | ] | ||
27 | ) | ||
28 | if test -d "${PKGCONFIG_DIR}" ; then | ||
29 | HAVE_PKGCONFIG=yes | ||
30 | AC_SUBST([PKGCONFIG_PKGCONFIG]) | ||
31 | AC_SUBST([PKGCONFIG_DIR]) | ||
32 | else | ||
33 | AC_MSG_NOTICE([unexistent pkgconfig directory: ${PKGCONFIG_DIR}]) | ||
34 | if test "${EXPLICIT_PKGCONFIGDIR}" = "yes" ; then | ||
35 | HAVE_PKGCONFIG=yes | ||
36 | AC_SUBST([PKGCONFIG_PKGCONFIG]) | ||
37 | AC_SUBST([PKGCONFIG_DIR]) | ||
38 | else | ||
39 | ifelse([$2], , :, [$2]) | ||
40 | fi | ||
41 | fi | ||
42 | fi | ||
43 | AM_CONDITIONAL([HAVE_PKGCONFIG],[test "${HAVE_PKGCONFIG}" = "yes"]) | ||
44 | ]) | ||
45 | |||
46 | dnl AC_WITH_DOXYGEN([ACTION-IF-FOUND[,ACTION-IF-NOT-FOUND]]) | ||
47 | dnl Outputs: | ||
48 | dnl AC_SUBST: DOXYGEN HAVE_DOXYGEN | ||
49 | dnl AM_CONDTIONAL: HAVE_DOXYGEN | ||
50 | AC_DEFUN([AC_WITH_DOXYGEN],[ | ||
51 | HAVE_DOXYGEN="no" | ||
52 | AC_PATH_PROG([DOXYGEN],[doxygen],[false]) | ||
53 | if test "${DOXYGEN}" = "false" ; then | ||
54 | ifelse([$2], , :, [$2]) | ||
55 | else | ||
56 | HAVE_DOXYGEN="yes" | ||
57 | AC_SUBST([DOXYGEN]) | ||
58 | $1 | ||
59 | fi | ||
60 | AC_SUBST([HAVE_DOXYGEN]) | ||
61 | AM_CONDITIONAL([HAVE_DOXYGEN],[test "${HAVE_DOXYGEN}" = "yes"]) | ||
62 | ]) | ||
63 | |||
64 | dnl AC_WITH_DOT([ACTION-IF-FOUND[,ACTION-IF-NOT-FOUND]]) | ||
65 | dnl Outputs: | ||
66 | dnl AC_SUBST: DOT HAVE_DOT | ||
67 | dnl AM_CONDITIONAL: HAVE_DOT | ||
68 | AC_DEFUN([AC_WITH_DOT],[ | ||
69 | HAVE_DOT="no" | ||
70 | AC_PATH_PROG([DOT],[dot],[false]) | ||
71 | if test "${DOT}" = "false" ; then | ||
72 | ifelse([$2], , :, [$2]) | ||
73 | else | ||
74 | HAVE_DOT="yes" | ||
75 | AC_SUBST([DOT]) | ||
76 | $1 | ||
77 | fi | ||
78 | AC_SUBST([HAVE_DOT]) | ||
79 | AM_CONDITIONAL([HAVE_DOT],[test "${HAVE_DOT}" = "yes"]) | ||
80 | ]) | ||
81 | |||
82 | dnl AC_WITH_PCRE([ACTION-IF-FOUND[,ACTION-IF-NOT-FOUND]]) | ||
83 | dnl Outputs: | ||
84 | dnl AC_SUBST: PCRE_CONFIG PCRE_PREFIX PCRE_EXEC_PREFIX | ||
85 | dnl PCRE_VERSION PCRE_CFLAGS PCRE_LIBS | ||
86 | dnl PCRE_LIBS_POSIX PCRE_CFLAGS_POSIX | ||
87 | dnl AM_CONDITIONAL: HAVE_PCRE | ||
88 | dnl AC_DEFINE: HAVE_PCRE PCRE_VERSION | ||
89 | AC_DEFUN([AC_WITH_PCRE],[ | ||
90 | HAVE_PCRE="no" | ||
91 | PCRE_CONFIG="" | ||
92 | PCRE_PREFIX="" | ||
93 | PCRE_EXEC_PREFIX="" | ||
94 | PCRE_VERSION="" | ||
95 | PCRE_CFLAGS="" | ||
96 | PCRE_LIBS="" | ||
97 | PCRE_LOCATIONS="${PATH}:/usr/local/bin:/usr/bin" | ||
98 | test -z "$WANT_PCRE" && WANT_PCRE="" | ||
99 | AC_ARG_WITH([pcre], | ||
100 | AC_HELP_STRING([--with-pcre=location],[Look for pcre in specified locations]), | ||
101 | [ | ||
102 | if test "${withval}" = "no" ; then | ||
103 | WANT_PCRE="no" | ||
104 | else | ||
105 | if test -x "${withval}" ; then | ||
106 | PCRE_CONFIG="${withval}" | ||
107 | elif test -x "${withval}/pcre-config" ; then | ||
108 | PCRE_CONFIG="${withval}/pcre-config" | ||
109 | elif test -x "${withval}/bin/pcre-config" ; then | ||
110 | PCRE_CONFIG="${withval}/bin/pcre-config" | ||
111 | fi | ||
112 | fi | ||
113 | ] | ||
114 | ) | ||
115 | if test "${WANT_PCRE}" = "no" ; then | ||
116 | ifelse([$2], , :, [$2]) | ||
117 | else | ||
118 | if test -z "${PCRE_CONFIG}" ; then | ||
119 | AC_PATH_PROG(PCRE_CONFIG,[pcre-config],false,[${PCRE_LOCATIONS}]) | ||
120 | if test "${PCRE_CONFIG}" = "false" ; then | ||
121 | ifelse([$2], , :, [$2]) | ||
122 | else | ||
123 | HAVE_PCRE="yes" | ||
124 | PCRE_PREFIX="`${PCRE_CONFIG} --prefix`" | ||
125 | PCRE_EXEC_PREFIX="`${PCRE_CONFIG} --exec-prefix`" | ||
126 | PCRE_VERSION="`${PCRE_CONFIG} --version`" | ||
127 | PCRE_CFLAGS="`${PCRE_CONFIG} --cflags`" | ||
128 | PCRE_LIBS="`${PCRE_CONFIG} --libs`" | ||
129 | PCRE_CFLAGS_POSIX="`${PCRE_CONFIG} --cflags-posix`" | ||
130 | PCRE_LIBS_POSIX="`${PCRE_CONFIG} --libs-posix`" | ||
131 | AC_SUBST([PCRE_CONFIG]) | ||
132 | AC_SUBST([PCRE_PREFIX]) | ||
133 | AC_SUBST([PCRE_EXEC_PREFIX]) | ||
134 | AC_SUBST([PCRE_VERSION]) | ||
135 | AC_SUBST([PCRE_CFLAGS]) | ||
136 | AC_SUBST([PCRE_LIBS]) | ||
137 | AC_SUBST([PCRE_CFLAGS_POSIX]) | ||
138 | AC_SUBST([PCRE_LIBS_POSIX]) | ||
139 | AC_DEFINE([HAVE_PCRE],,[pcre support]) | ||
140 | AC_DEFINE_UNQUOTED([PCRE_VERSION],["${PCRE_VERSION}"],[pcre version]) | ||
141 | $1 | ||
142 | fi | ||
143 | fi | ||
144 | fi | ||
145 | AM_CONDITIONAL([HAVE_PCRE],[test "${HAVE_PCRE}" = "yes"]) | ||
146 | ]) | ||
147 | |||
148 | dnl AC_WITH_PCREPP([ACTION-IF-FOUND[,ACTION-IF-NOT-FOUND]]) | ||
149 | dnl Outputs: | ||
150 | dnl AC_SUBST: PCREPP_CONFIG PCREPP_PREFIX PCREPP_EXEC_PREFIX | ||
151 | dnl PCREPP_VERSION PCREPP_CFLAGS PCREPP_LIBS | ||
152 | dnl AM_CONDITIONAL: HAVE_PCREPP | ||
153 | dnl AC_DEFINE: HAVE_PCREPP PCREPP_VERSION | ||
154 | AC_DEFUN([AC_WITH_PCREPP],[ | ||
155 | HAVE_PCREPP="no" | ||
156 | PCREPP_CONFIG="" | ||
157 | PCREPP_PREFIX="" | ||
158 | PCREPP_EXEC_PREFIX="" | ||
159 | PCREPP_VERSION="" | ||
160 | PCREPP_CFLAGS="" | ||
161 | PCREPP_LIBS="" | ||
162 | PCREPP_LOCATIONS="${PATH}:/usr/local/bin:/usr/bin" | ||
163 | test -z "$WANT_PCREPP" && WANT_PCREPP="" | ||
164 | AC_ARG_WITH([pcre++], | ||
165 | AC_HELP_STRING([--with-pcre++=location],[Look for pcre++ in specified locations]), | ||
166 | [ | ||
167 | if test "${withval}" = "no" ; then | ||
168 | WANT_PCREPP="no" | ||
169 | else | ||
170 | if test -x "${withval}" ; then | ||
171 | PCREPP_CONFIG="${withval}" | ||
172 | elif test -x "${withval}/pcre++-config" ; then | ||
173 | PCREPP_CONFIG="${withval}/pcre++-config" | ||
174 | elif test -x "${withval}/bin/pcre++-config" ; then | ||
175 | PCREPP_CONFIG="${withval}/bin/pcre++-config" | ||
176 | fi | ||
177 | fi | ||
178 | ] | ||
179 | ) | ||
180 | if test "${WANT_PCREPP}" = "no" ; then | ||
181 | ifelse([$2], , :, [$2]) | ||
182 | else | ||
183 | if test "${HAVE_PCRE}" != "yes" ; then | ||
184 | ifelse([$2], , :, [$2]) | ||
185 | else | ||
186 | if test -z "${PCREPP_CONFIG}" ; then | ||
187 | AC_PATH_PROG([PCREPP_CONFIG],[pcre++-config],false,[${PCREPP_LOCATIONS}]) | ||
188 | if test "${PCREPP_CONFIG}" = "false" ; then | ||
189 | ifelse([$2], , :, [$2]) | ||
190 | else | ||
191 | HAVE_PCREPP="yes" | ||
192 | PCREPP_PREFIX="`${PCREPP_CONFIG} --prefix`" | ||
193 | PCREPP_EXEC_PREFIX="`${PCREPP_CONFIG} --exec-prefix`" | ||
194 | PCREPP_VERSION="`${PCREPP_CONFIG} --version`" | ||
195 | PCREPP_CFLAGS="`${PCREPP_CONFIG} --cflags` ${PCRE_CFLAGS}" | ||
196 | PCREPP_LIBS="`${PCREPP_CONFIG} --libs` ${PCRE_LIBS}" | ||
197 | AC_SUBST([PCREPP_CONFIG]) | ||
198 | AC_SUBST([PCREPP_PREFIX]) | ||
199 | AC_SUBST([PCREPP_EXEC_PREFIX]) | ||
200 | AC_SUBST([PCREPP_VERSION]) | ||
201 | AC_SUBST([PCREPP_CFLAGS]) | ||
202 | AC_SUBST([PCREPP_LIBS]) | ||
203 | AC_DEFINE([HAVE_PCREPP],,[pcre++ support]) | ||
204 | AC_DEFINE_UNQUOTED([PCREPP_VERSION],["${PCREPP_VERSION}"],[pcre++ version]) | ||
205 | $1 | ||
206 | fi | ||
207 | fi | ||
208 | fi | ||
209 | fi | ||
210 | AM_CONDITIONAL([HAVE_PCREPP],[test "${HAVE_PCREPP}" = "yes"]) | ||
211 | ]) | ||
212 | |||
213 | m4_include([acinclude.d/libcurl.m4]) | ||
diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 0000000..ba27501 --- a/dev/null +++ b/autogen.sh | |||
@@ -0,0 +1,9 @@ | |||
1 | #!/bin/sh | ||
2 | WANT_AUTOMAKE=1.8 | ||
3 | export WANT_AUTOMAKE | ||
4 | libtoolize -f \ | ||
5 | && aclocal \ | ||
6 | && autoheader \ | ||
7 | && automake -a \ | ||
8 | && autoconf \ | ||
9 | && ./configure "$@" | ||
diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..a31f5b1 --- a/dev/null +++ b/configure.ac | |||
@@ -0,0 +1,87 @@ | |||
1 | AC_INIT([libopkele], [0.0], [libopkele-bugs@klever.net]) | ||
2 | AC_CONFIG_SRCDIR([include/opkele/opkele-config.h]) | ||
3 | AC_CONFIG_HEADERS([config.h include/opkele/acconfig.h]) | ||
4 | AM_INIT_AUTOMAKE([dist-bzip2]) | ||
5 | |||
6 | AC_PROG_INSTALL | ||
7 | AC_PROG_CXX | ||
8 | AC_PROG_CC | ||
9 | AC_PROG_LIBTOOL | ||
10 | |||
11 | AC_HEADER_STDC | ||
12 | |||
13 | AC_PATH_PROG([XSLTPROC],[xsltproc],[true]) | ||
14 | AC_WITH_PKGCONFIG | ||
15 | |||
16 | PKG_CHECK_MODULES([OPENSSL],[openssl],[ | ||
17 | AC_MSG_RESULT([yes]) | ||
18 | ],[ | ||
19 | AC_MSG_ERROR([no openssl library found. get one from http://www.openssl.org/]) | ||
20 | ] | ||
21 | ) | ||
22 | |||
23 | WANT_KONFORKA="yes" | ||
24 | AC_ARG_ENABLE([konforka], | ||
25 | AC_HELP_STRING([--disable-konforka],[do not use konforka library (default: use if found)]), | ||
26 | [ | ||
27 | test "${enableval}" = "no" && WANT_KONFORKA="no" | ||
28 | ] | ||
29 | ) | ||
30 | if test "${WANT_KONFORKA}" = "yes" ; then | ||
31 | PKG_CHECK_MODULES([KONFORKA],[konforka],[ | ||
32 | AC_MSG_RESULT([yes]) | ||
33 | AC_SUBST([KONFORKA_CFLAGS]) | ||
34 | AC_SUBST([KONFORKA_LIBS]) | ||
35 | AC_DEFINE([HAVE_KONFORKA],,[defined in presence of konforka library]) | ||
36 | AC_DEFINE([OPKELE_HAVE_KONFORKA],,[defined in presence of konforka library]) | ||
37 | AC_SUBST([KONFORKA_KONFORKA],[konforka]) | ||
38 | ] | ||
39 | ) | ||
40 | fi | ||
41 | |||
42 | AC_LANG_PUSH([C++]) | ||
43 | AC_CHECK_LIB([mimetic],[main],[ | ||
44 | MIMETIC_LIBS=-lmimetic | ||
45 | AC_SUBST([MIMETIC_CFLAGS]) | ||
46 | AC_SUBST([MIMETIC_LIBS]) | ||
47 | ],[ | ||
48 | AC_MSG_ERROR([no mimetic library found. get one from http://codesink.org/mimetic_mime_library.html]) | ||
49 | ] | ||
50 | ) | ||
51 | AC_LANG_POP([C++]) | ||
52 | |||
53 | WANT_DOXYGEN="yes" | ||
54 | AC_ARG_ENABLE([doxygen], | ||
55 | AC_HELP_STRING([--disable-doxygen],[do not generate documentation]), | ||
56 | [ | ||
57 | test "${enableval}" = "no" && WANT_DOXYGEN="no" | ||
58 | ] | ||
59 | ) | ||
60 | if test "${WANT_DOXYGEN}" = "yes" ; then | ||
61 | AC_WITH_DOXYGEN | ||
62 | AC_WITH_DOT | ||
63 | else | ||
64 | AM_CONDITIONAL([HAVE_DOXYGEN],[false]) | ||
65 | AM_CONDITIONAL([HAVE_DOT],[false]) | ||
66 | fi | ||
67 | |||
68 | LIBCURL_CHECK_CONFIG(,,,[ | ||
69 | AC_MSG_ERROR([no required libcurl library. get one from http://curl.haxx.se/]) | ||
70 | ]) | ||
71 | AC_WITH_PCRE([ | ||
72 | AC_WITH_PCREPP(,[ | ||
73 | AC_MSG_ERROR([no pcre++ library found. get one at http://www.daemon.de/PCRE]) | ||
74 | ]) | ||
75 | ],[ | ||
76 | AC_MSG_ERROR([no pcre library found. get one at http://www.pcre.org/]) | ||
77 | ] | ||
78 | ) | ||
79 | |||
80 | AC_CONFIG_FILES([ | ||
81 | Makefile | ||
82 | libopkele.pc | ||
83 | Doxyfile | ||
84 | include/Makefile | ||
85 | lib/Makefile | ||
86 | ]) | ||
87 | AC_OUTPUT | ||
diff --git a/include/.gitignore b/include/.gitignore new file mode 100644 index 0000000..3dda729 --- a/dev/null +++ b/include/.gitignore | |||
@@ -0,0 +1,2 @@ | |||
1 | Makefile.in | ||
2 | Makefile | ||
diff --git a/include/Makefile.am b/include/Makefile.am new file mode 100644 index 0000000..b014752 --- a/dev/null +++ b/include/Makefile.am | |||
@@ -0,0 +1,11 @@ | |||
1 | nobase_include_HEADERS = \ | ||
2 | opkele/acconfig.h \ | ||
3 | opkele/opkele-config.h \ | ||
4 | opkele/types.h \ | ||
5 | opkele/association.h \ | ||
6 | opkele/exception.h \ | ||
7 | opkele/server.h \ | ||
8 | opkele/consumer.h | ||
9 | EXTRA_DIST = \ | ||
10 | opkele/data.h \ | ||
11 | opkele/util.h | ||
diff --git a/include/opkele/.gitignore b/include/opkele/.gitignore new file mode 100644 index 0000000..ffa24dc --- a/dev/null +++ b/include/opkele/.gitignore | |||
@@ -0,0 +1,2 @@ | |||
1 | acconfig.h | ||
2 | stamp-h2 | ||
diff --git a/include/opkele/acconfig.h.in b/include/opkele/acconfig.h.in new file mode 100644 index 0000000..d56a1cd --- a/dev/null +++ b/include/opkele/acconfig.h.in | |||
@@ -0,0 +1,3 @@ | |||
1 | |||
2 | /* defined in presence of konforka library */ | ||
3 | #undef OPKELE_HAVE_KONFORKA | ||
diff --git a/include/opkele/association.h b/include/opkele/association.h new file mode 100644 index 0000000..5eb1cc3 --- a/dev/null +++ b/include/opkele/association.h | |||
@@ -0,0 +1,89 @@ | |||
1 | #ifndef __OPKELE_ASSOCIATION_H | ||
2 | #define __OPKELE_ASSOCIATION_H | ||
3 | |||
4 | #include <time.h> | ||
5 | #include <opkele/types.h> | ||
6 | |||
7 | /** | ||
8 | * @file | ||
9 | * @brief reference implementation of association_t | ||
10 | */ | ||
11 | |||
12 | /** | ||
13 | * @brief the main opkele namespace | ||
14 | */ | ||
15 | namespace opkele { | ||
16 | |||
17 | /** | ||
18 | * reference implementation of association_t class. | ||
19 | */ | ||
20 | class association : public association_t { | ||
21 | public: | ||
22 | /** | ||
23 | * OpenID server name | ||
24 | */ | ||
25 | string _server; | ||
26 | /** | ||
27 | * association handle | ||
28 | */ | ||
29 | string _handle; | ||
30 | /** | ||
31 | * association type | ||
32 | */ | ||
33 | string _assoc_type; | ||
34 | /** | ||
35 | * the secret | ||
36 | */ | ||
37 | secret_t _secret; | ||
38 | /** | ||
39 | * expiration time | ||
40 | */ | ||
41 | time_t _expires; | ||
42 | /** | ||
43 | * statelessness of the assoc_handle | ||
44 | */ | ||
45 | bool _stateless; | ||
46 | |||
47 | /** | ||
48 | * @param __server the server name | ||
49 | * @param __handle association handle | ||
50 | * @param __assoc_type association type | ||
51 | * @param __secret the secret | ||
52 | * @param __expires expiration time | ||
53 | * @param __stateless statelessness of the assoc_handle | ||
54 | */ | ||
55 | association(const string& __server, const string& __handle, | ||
56 | const string& __assoc_type, const secret_t& __secret, | ||
57 | time_t __expires, bool __stateless) | ||
58 | : _server(__server), _handle(__handle), _assoc_type(__assoc_type), | ||
59 | _secret(__secret), _expires(__expires), _stateless(__stateless) { } | ||
60 | |||
61 | /** | ||
62 | * @overload association_t::server() | ||
63 | */ | ||
64 | virtual string server() const { return _server; } | ||
65 | /** | ||
66 | * @overload association_t::handle() | ||
67 | */ | ||
68 | virtual string handle() const { return _handle; } | ||
69 | /** | ||
70 | * @overload association_t::assoc_type() | ||
71 | */ | ||
72 | virtual string assoc_type() const { return _assoc_type; } | ||
73 | /** | ||
74 | * @overload association_t::secret() | ||
75 | */ | ||
76 | virtual secret_t secret() const { return _secret; } | ||
77 | /** | ||
78 | * @overload association_t::expires_in() | ||
79 | */ | ||
80 | virtual int expires_in() const { return _expires-time(0); } | ||
81 | /** | ||
82 | * @overload associationn_t::stateless() | ||
83 | */ | ||
84 | virtual bool stateless() const { return _stateless; } | ||
85 | }; | ||
86 | |||
87 | } | ||
88 | |||
89 | #endif /* __OPKELE_ASSOCIATION_H */ | ||
diff --git a/include/opkele/consumer.h b/include/opkele/consumer.h new file mode 100644 index 0000000..b9c29bd --- a/dev/null +++ b/include/opkele/consumer.h | |||
@@ -0,0 +1,135 @@ | |||
1 | #ifndef __OPKELE_CONSUMER_H | ||
2 | #define __OPKELE_CONSUMER_H | ||
3 | |||
4 | #include <opkele/types.h> | ||
5 | |||
6 | /** | ||
7 | * @file | ||
8 | * @brief OpenID consumer-side functionality | ||
9 | */ | ||
10 | |||
11 | /** | ||
12 | * @brief the main opkele namespace | ||
13 | */ | ||
14 | namespace opkele { | ||
15 | |||
16 | /** | ||
17 | * implementation of basic consumer functionality | ||
18 | */ | ||
19 | class consumer_t { | ||
20 | public: | ||
21 | |||
22 | /** | ||
23 | * store association. The function should be overridden in the real | ||
24 | * implementation to provide persistent associations store. | ||
25 | * @param server the OpenID server | ||
26 | * @param handle association handle | ||
27 | * @param secret the secret associated with the server and handle | ||
28 | * @param expires_in the number of seconds until the handle is expired | ||
29 | * @return the auto_ptr<> for the newly allocated association_t object | ||
30 | */ | ||
31 | virtual assoc_t store_assoc(const string& server,const string& handle,const secret_t& secret,int expires_in) = 0; | ||
32 | /** | ||
33 | * retrieve stored association. The function should be overridden | ||
34 | * in the real implementation to provide persistent assocations | ||
35 | * store. | ||
36 | * @param server the OpenID server | ||
37 | * @param handle association handle | ||
38 | * @return the autho_ptr<> for the newly allocated association_t object | ||
39 | * @throw failed_lookup in case of error | ||
40 | */ | ||
41 | virtual assoc_t retrieve_assoc(const string& server,const string& handle) = 0; | ||
42 | /** | ||
43 | * invalidate stored association. The function should be overridden | ||
44 | * in the real implementation of the consumer. | ||
45 | * @param server the OpenID server | ||
46 | * @param handle association handle | ||
47 | */ | ||
48 | virtual void invalidate_assoc(const string& server,const string& handle) = 0; | ||
49 | /** | ||
50 | * retrieve any unexpired association for the server. If the | ||
51 | * function is not overridden in the real implementation, the new | ||
52 | * association will be established for each request. | ||
53 | * @param server the OpenID server | ||
54 | * @return the auto_ptr<> for the newly allocated association_t object | ||
55 | * @throw failed_lookup in case of absence of the handle | ||
56 | */ | ||
57 | virtual assoc_t find_assoc(const string& server); | ||
58 | |||
59 | /** | ||
60 | * retrieve the metainformation contained in link tags from the | ||
61 | * page pointed by url. the function may implement caching of the | ||
62 | * information. | ||
63 | * @param url url to harvest for link tags | ||
64 | * @param server reference to the string object where to put | ||
65 | * openid.server value | ||
66 | * @param delegate reference to the string object where to put the | ||
67 | * openid.delegate value (if any) | ||
68 | */ | ||
69 | virtual void retrieve_links(const string& url,string& server,string& delegate); | ||
70 | |||
71 | /** | ||
72 | * perform the associate request to OpenID server. | ||
73 | * @param server the OpenID server | ||
74 | * @return the auto_ptr<> for the newly allocated association_t | ||
75 | * object, representing established association | ||
76 | * @throw exception in case of error | ||
77 | */ | ||
78 | assoc_t associate(const string& server); | ||
79 | /** | ||
80 | * prepare the parameters for the checkid_immediate | ||
81 | * request. | ||
82 | * @param identity the identity to verify | ||
83 | * @param return_to the return_to url to pass with the request | ||
84 | * @param trust_root the trust root to advertise with the request | ||
85 | * @return the location string | ||
86 | * @throw exception in case of error | ||
87 | */ | ||
88 | string checkid_immediate(const string& identity,const string& return_to,const string& trust_root=""); | ||
89 | /** | ||
90 | * prepare the parameters for the checkid_setup | ||
91 | * request. | ||
92 | * @param identity the identity to verify | ||
93 | * @param return_to the return_to url to pass with the request | ||
94 | * @param trust_root the trust root to advertise with the request | ||
95 | * @return the location string | ||
96 | * @throw exception in case of error | ||
97 | */ | ||
98 | string checkid_setup(const string& identity,const string& return_to,const string& trust_root=""); | ||
99 | /** | ||
100 | * the actual implementation behind checkid_immediate() and | ||
101 | * checkid_setup() functions. | ||
102 | * @param mode checkid_* mode - either mode_checkid_immediate or mode_checkid_setup | ||
103 | * @param identity the identity to verify | ||
104 | * @param return_to the return_to url to pass with the request | ||
105 | * @param trust_root the trust root to advertise with the request | ||
106 | * @return the location string | ||
107 | * @throw exception in case of error | ||
108 | */ | ||
109 | string checkid_(mode_t mode,const string& identity,const string& return_to,const string& trust_root=""); | ||
110 | /** | ||
111 | * verify the id_res response | ||
112 | * @param pin the response parameters | ||
113 | * @param identity the identity being checked (if not specified, extracted | ||
114 | * from the openid.identity parameter | ||
115 | * @throw id_res_mismatch in case of signature | ||
116 | * mismatch | ||
117 | * @throw id_res_setup in case of | ||
118 | * openid.user_setup_url failure (supposedly | ||
119 | * checkid_immediate only) | ||
120 | * @throw id_res_failed in case of failure | ||
121 | * @throw exception in case of other failures | ||
122 | */ | ||
123 | void id_res(const params_t& pin,const string& identity=""); | ||
124 | /** | ||
125 | * perform a check_authentication request. | ||
126 | * @param server the OpenID server | ||
127 | * @param p request parameters | ||
128 | */ | ||
129 | void check_authentication(const string& server,const params_t& p); | ||
130 | |||
131 | }; | ||
132 | |||
133 | } | ||
134 | |||
135 | #endif /* __OPKELE_CONSUMER_H */ | ||
diff --git a/include/opkele/data.h b/include/opkele/data.h new file mode 100644 index 0000000..7fc635b --- a/dev/null +++ b/include/opkele/data.h | |||
@@ -0,0 +1,12 @@ | |||
1 | #ifndef __OPKELE_DATA_H | ||
2 | #define __OPKELE_DATA_H | ||
3 | |||
4 | namespace opkele { | ||
5 | |||
6 | namespace data { | ||
7 | extern const char *_default_p; | ||
8 | extern const char *_default_g; | ||
9 | } | ||
10 | } | ||
11 | |||
12 | #endif /* __OPKELE_DATA_H */ | ||
diff --git a/include/opkele/exception.h b/include/opkele/exception.h new file mode 100644 index 0000000..2ac0661 --- a/dev/null +++ b/include/opkele/exception.h | |||
@@ -0,0 +1,206 @@ | |||
1 | #ifndef __OPKELE_EXCEPTION_H | ||
2 | #define __OPKELE_EXCEPTION_H | ||
3 | |||
4 | /** | ||
5 | * @file | ||
6 | * @brief opkele exceptions | ||
7 | */ | ||
8 | |||
9 | #include <curl/curl.h> | ||
10 | |||
11 | #include <opkele/opkele-config.h> | ||
12 | #ifdef OPKELE_HAVE_KONFORKA | ||
13 | # include <konforka/exception.h> | ||
14 | /** | ||
15 | * the exception parameters declaration | ||
16 | */ | ||
17 | # define OPKELE_E_PARS const string& fi,const string&fu,int l,const string& w | ||
18 | /** | ||
19 | * the exception parameters list to pass to constructor | ||
20 | */ | ||
21 | # define OPKELE_E_CONS_ fi,fu,l, | ||
22 | /** | ||
23 | * the exception codepoint specification | ||
24 | */ | ||
25 | # define OPKELE_CP_ CODEPOINT, | ||
26 | /** | ||
27 | * the simple rethrow of konforka-based exception | ||
28 | */ | ||
29 | # define OPKELE_RETHROW catch(konforka::exception& e) { e.see(CODEPOINT); throw } | ||
30 | #else /* OPKELE_HAVE_KONFORKA */ | ||
31 | # include <stdexcept> | ||
32 | /** | ||
33 | * the exception parameter declaration | ||
34 | */ | ||
35 | # define OPKELE_E_PARS const string& w | ||
36 | /** | ||
37 | * the dummy prefix for exception parameters list to prepend in the absence of | ||
38 | * konforka library | ||
39 | */ | ||
40 | # define OPKELE_E_CONS_ | ||
41 | /** | ||
42 | * the dummy placeholder for konforka exception codepoint specification | ||
43 | */ | ||
44 | # define OPKELE_CP_ | ||
45 | /** | ||
46 | * the dummy define for the konforka-based rethrow of exception | ||
47 | */ | ||
48 | # define OPKELE_RETHROW | ||
49 | #endif /* OPKELE_HAVE_KONFORKA */ | ||
50 | /** | ||
51 | * the exception parameters list to pass to constructor | ||
52 | */ | ||
53 | # define OPKELE_E_CONS OPKELE_E_CONS_ w | ||
54 | |||
55 | /* | ||
56 | * @brief the main opkele namespace | ||
57 | */ | ||
58 | namespace opkele { | ||
59 | using std::string; | ||
60 | |||
61 | /** | ||
62 | * the base opkele exception class | ||
63 | */ | ||
64 | class exception : public | ||
65 | # ifdef OPKELE_HAVE_KONFORKA | ||
66 | konforka::exception | ||
67 | # else | ||
68 | std::exception | ||
69 | # endif | ||
70 | { | ||
71 | public: | ||
72 | # ifdef OPKELE_HAVE_KONFORKA | ||
73 | explicit | ||
74 | exception(const string& fi,const string& fu,int l,const string& w) | ||
75 | : konforka::exception(fi,fu,l,w) { } | ||
76 | # else /* OPKELE_HAVE_KONFORKA */ | ||
77 | explicit | ||
78 | exception(const string& w) | ||
79 | : std::exception(w) { } | ||
80 | # endif /* OPKELE_HAVE_KONFORKA */ | ||
81 | }; | ||
82 | |||
83 | /** | ||
84 | * thrown in case of failed conversion | ||
85 | */ | ||
86 | class failed_conversion : public exception { | ||
87 | public: | ||
88 | failed_conversion(OPKELE_E_PARS) | ||
89 | : exception(OPKELE_E_CONS) { } | ||
90 | }; | ||
91 | /** | ||
92 | * thrown in case of failed lookup (either parameter or persistent store) | ||
93 | */ | ||
94 | class failed_lookup : public exception { | ||
95 | public: | ||
96 | failed_lookup(OPKELE_E_PARS) | ||
97 | : exception(OPKELE_E_CONS) { } | ||
98 | }; | ||
99 | /** | ||
100 | * thrown in case of bad input (either local or network) | ||
101 | */ | ||
102 | class bad_input : public exception { | ||
103 | public: | ||
104 | bad_input(OPKELE_E_PARS) | ||
105 | : exception(OPKELE_E_CONS) { } | ||
106 | }; | ||
107 | |||
108 | /** | ||
109 | * thrown on failed assertion | ||
110 | */ | ||
111 | class failed_assertion : public exception { | ||
112 | public: | ||
113 | failed_assertion(OPKELE_E_PARS) | ||
114 | : exception(OPKELE_E_CONS) { } | ||
115 | }; | ||
116 | |||
117 | /** | ||
118 | * thrown if the handle being retrieved is invalid | ||
119 | */ | ||
120 | class invalid_handle : public exception { | ||
121 | public: | ||
122 | invalid_handle(OPKELE_E_PARS) | ||
123 | : exception(OPKELE_E_CONS) { } | ||
124 | }; | ||
125 | /** | ||
126 | * thrown if the handle passed to check_authentication request is not | ||
127 | * stateless | ||
128 | */ | ||
129 | class stateful_handle : public exception { | ||
130 | public: | ||
131 | stateful_handle(OPKELE_E_PARS) | ||
132 | : exception(OPKELE_E_CONS) { } | ||
133 | }; | ||
134 | |||
135 | /** | ||
136 | * thrown if check_authentication request fails | ||
137 | */ | ||
138 | class failed_check_authentication : public exception { | ||
139 | public: | ||
140 | failed_check_authentication(OPKELE_E_PARS) | ||
141 | : exception(OPKELE_E_CONS) { } | ||
142 | }; | ||
143 | |||
144 | /** | ||
145 | * thrown if the id_res request result is negative | ||
146 | */ | ||
147 | class id_res_failed : public exception { | ||
148 | public: | ||
149 | id_res_failed(OPKELE_E_PARS) | ||
150 | : exception(OPKELE_E_CONS) { } | ||
151 | }; | ||
152 | /** | ||
153 | * thrown if the user_setup_url is provided with negative response | ||
154 | */ | ||
155 | class id_res_setup : public id_res_failed { | ||
156 | public: | ||
157 | string setup_url; | ||
158 | id_res_setup(OPKELE_E_PARS,const string& su) | ||
159 | : id_res_failed(OPKELE_E_CONS), setup_url(su) { } | ||
160 | ~id_res_setup() throw() { } | ||
161 | }; | ||
162 | /** | ||
163 | * thrown in case of signature mismatch | ||
164 | */ | ||
165 | class id_res_mismatch : public id_res_failed { | ||
166 | public: | ||
167 | id_res_mismatch(OPKELE_E_PARS) | ||
168 | : id_res_failed(OPKELE_E_CONS) { } | ||
169 | }; | ||
170 | |||
171 | /** | ||
172 | * openssl malfunction occured | ||
173 | */ | ||
174 | class exception_openssl : public exception { | ||
175 | public: | ||
176 | unsigned long _error; | ||
177 | string _ssl_string; | ||
178 | exception_openssl(OPKELE_E_PARS); | ||
179 | ~exception_openssl() throw() { } | ||
180 | }; | ||
181 | |||
182 | /** | ||
183 | * network operation related error occured | ||
184 | */ | ||
185 | class exception_network : public exception { | ||
186 | public: | ||
187 | exception_network(OPKELE_E_PARS) | ||
188 | : exception(OPKELE_E_CONS) { } | ||
189 | }; | ||
190 | |||
191 | /** | ||
192 | * network operation related error occured, specifically, related to | ||
193 | * libcurl | ||
194 | */ | ||
195 | class exception_curl : public exception_network { | ||
196 | public: | ||
197 | CURLcode _error; | ||
198 | string _curl_string; | ||
199 | exception_curl(OPKELE_E_PARS); | ||
200 | exception_curl(OPKELE_E_PARS,CURLcode e); | ||
201 | ~exception_curl() throw() { } | ||
202 | }; | ||
203 | |||
204 | } | ||
205 | |||
206 | #endif /* __OPKELE_EXCEPTION_H */ | ||
diff --git a/include/opkele/opkele-config.h b/include/opkele/opkele-config.h new file mode 100644 index 0000000..70c2d26 --- a/dev/null +++ b/include/opkele/opkele-config.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef __OPKELE_OPKELE_CONFIG_H | ||
2 | #define __OPKELE_OPKELE_CONFIG_H | ||
3 | |||
4 | #include "opkele/acconfig.h" | ||
5 | |||
6 | #endif /* __OPKELE_OPKELE_CONFIG_H */ | ||
diff --git a/include/opkele/server.h b/include/opkele/server.h new file mode 100644 index 0000000..fe07448 --- a/dev/null +++ b/include/opkele/server.h | |||
@@ -0,0 +1,95 @@ | |||
1 | #ifndef __OPKELE_SERVER_H | ||
2 | #define __OPKELE_SERVER_H | ||
3 | |||
4 | /** | ||
5 | * @file | ||
6 | * @brief OpenID server-side functionality | ||
7 | */ | ||
8 | |||
9 | #include <opkele/types.h> | ||
10 | |||
11 | /** | ||
12 | * @brief the main opkele namespace | ||
13 | */ | ||
14 | namespace opkele { | ||
15 | |||
16 | /** | ||
17 | * implementation of basic server functionality | ||
18 | */ | ||
19 | class server_t { | ||
20 | public: | ||
21 | |||
22 | /** | ||
23 | * allocate the new association. The function should be overridden | ||
24 | * in the real implementation to provide persistent assocations | ||
25 | * store. | ||
26 | * @param mode the mode of request being processed to base the | ||
27 | * statelessness of the association upon | ||
28 | * @return the auto_ptr<> for the newly allocated association_t object | ||
29 | */ | ||
30 | virtual assoc_t alloc_assoc(mode_t mode) = 0; | ||
31 | /** | ||
32 | * retrieve the association. The function should be overridden in | ||
33 | * the reqal implementation to provide persistent assocations | ||
34 | * store. | ||
35 | * @param h association handle | ||
36 | * @return the auto_ptr<> for the newly allocated association_t object | ||
37 | * @throw failed_lookup in case of failure | ||
38 | */ | ||
39 | virtual assoc_t retrieve_assoc(const string& h) = 0; | ||
40 | |||
41 | /** | ||
42 | * validate the identity. | ||
43 | * @param assoc association object | ||
44 | * @param pin incoming request parameters | ||
45 | * @param identity being verified | ||
46 | * @param trust_root presented in the request | ||
47 | * @throw exception if identity can not be confirmed | ||
48 | */ | ||
49 | virtual void validate(const association_t& assoc,const params_t& pin,const string& identity,const string& trust_root) = 0; | ||
50 | |||
51 | |||
52 | /** | ||
53 | * process the associate request. | ||
54 | * @param pin the incoming request parameters | ||
55 | * @param pout the store for the response parameters | ||
56 | */ | ||
57 | void associate(const params_t& pin,params_t& pout); | ||
58 | /** | ||
59 | * process the checkid_immediate request. | ||
60 | * @param pin the incoming request parameters | ||
61 | * @param return_to reference to the object to store return_to url to | ||
62 | * @param pout the response parameters | ||
63 | * @throw exception in case of errors or negative reply | ||
64 | */ | ||
65 | void checkid_immediate(const params_t& pin,string& return_to,params_t& pout); | ||
66 | /** | ||
67 | * process the checkid_setup request. | ||
68 | * @param pin the incoming request parameters | ||
69 | * @param return_to reference to the object to store return_to url to | ||
70 | * @param pout the response parameters | ||
71 | * @throw exception in case of errors or negative reply | ||
72 | */ | ||
73 | void checkid_setup(const params_t& pin,string& return_to,params_t& pout); | ||
74 | /** | ||
75 | * the actual functionality behind checkid_immediate() and | ||
76 | * checkid_setup() | ||
77 | * @param mode the request being processed (either | ||
78 | * mode_checkid_immediate or mode_checkid_setup) | ||
79 | * @param pin the incoming request parameters | ||
80 | * @param return_to reference to the object to store return_to url to | ||
81 | * @param pout the response parameters | ||
82 | * @throw exception in case of errors or negative reply | ||
83 | */ | ||
84 | void checkid_(mode_t mode,const params_t& pin,string& return_to,params_t& pout); | ||
85 | /** | ||
86 | * process the check_authentication request. | ||
87 | * @param pin incoming request parameters | ||
88 | * @param pout response parameters | ||
89 | */ | ||
90 | void check_authentication(const params_t& pin,params_t& pout); | ||
91 | }; | ||
92 | |||
93 | } | ||
94 | |||
95 | #endif /* __OPKELE_SERVER_H */ | ||
diff --git a/include/opkele/types.h b/include/opkele/types.h new file mode 100644 index 0000000..ba06776 --- a/dev/null +++ b/include/opkele/types.h | |||
@@ -0,0 +1,168 @@ | |||
1 | #ifndef __OPKELE_TYPES_H | ||
2 | #define __OPKELE_TYPES_H | ||
3 | |||
4 | /** | ||
5 | * @file | ||
6 | * @brief various types declarations | ||
7 | */ | ||
8 | |||
9 | #include <ostream> | ||
10 | #include <vector> | ||
11 | #include <string> | ||
12 | #include <map> | ||
13 | #include <memory> | ||
14 | |||
15 | /** | ||
16 | * @brief the main opkele namespace | ||
17 | */ | ||
18 | namespace opkele { | ||
19 | using std::vector; | ||
20 | using std::string; | ||
21 | using std::map; | ||
22 | using std::ostream; | ||
23 | using std::auto_ptr; | ||
24 | |||
25 | /** | ||
26 | * the OpenID operation mode | ||
27 | */ | ||
28 | typedef enum _mode_t { | ||
29 | mode_associate, | ||
30 | mode_checkid_immediate, | ||
31 | mode_checkid_setup, | ||
32 | mode_check_association | ||
33 | } mode_t; | ||
34 | |||
35 | /** | ||
36 | * the association secret container | ||
37 | */ | ||
38 | class secret_t : public vector<unsigned char> { | ||
39 | public: | ||
40 | |||
41 | /** | ||
42 | * xor the secret and hmac together and encode, using base64 | ||
43 | * @param key_sha1 pointer to the sha1 digest | ||
44 | * @param rv reference to the return value | ||
45 | */ | ||
46 | void enxor_to_base64(const unsigned char *key_sha1,string& rv) const; | ||
47 | /** | ||
48 | * decode base64-encoded secret and xor it with the sha1 digest | ||
49 | * @param key_sha1 pointer to the message digest | ||
50 | * @param b64 base64-encoded secret value | ||
51 | */ | ||
52 | void enxor_from_base64(const unsigned char *key_sha1,const string& b64); | ||
53 | /** | ||
54 | * plainly encode to base64 representation | ||
55 | * @param rv reference to the return value | ||
56 | */ | ||
57 | void to_base64(string& rv) const; | ||
58 | /** | ||
59 | * decode cleartext secret from base64 | ||
60 | * @param b64 base64-encoded representation of the secret value | ||
61 | */ | ||
62 | void from_base64(const string& b64); | ||
63 | }; | ||
64 | |||
65 | /** | ||
66 | * Interface to the association. | ||
67 | */ | ||
68 | class association_t { | ||
69 | public: | ||
70 | |||
71 | /** | ||
72 | * retrieve the server with which association was established. | ||
73 | * @return server name | ||
74 | */ | ||
75 | virtual string server() const = 0; | ||
76 | /** | ||
77 | * retrieve the association handle. | ||
78 | * @return handle | ||
79 | */ | ||
80 | virtual string handle() const = 0; | ||
81 | /** | ||
82 | * retrieve the association type. | ||
83 | * @return association type | ||
84 | */ | ||
85 | virtual string assoc_type() const = 0; | ||
86 | /** | ||
87 | * retrieve the association secret. | ||
88 | * @return association secret | ||
89 | */ | ||
90 | virtual secret_t secret() const = 0; | ||
91 | /** | ||
92 | * retrieve the number of seconds the association expires in. | ||
93 | * @return seconds till expiration | ||
94 | */ | ||
95 | virtual int expires_in() const = 0; | ||
96 | /** | ||
97 | * check whether the association is stateless. | ||
98 | * @return true if stateless | ||
99 | */ | ||
100 | virtual bool stateless() const = 0; | ||
101 | }; | ||
102 | |||
103 | /** | ||
104 | * the auto_ptr<> for association_t object type | ||
105 | */ | ||
106 | typedef auto_ptr<association_t> assoc_t; | ||
107 | |||
108 | /** | ||
109 | * request/response parameters map | ||
110 | */ | ||
111 | class params_t : public map<string,string> { | ||
112 | public: | ||
113 | |||
114 | /** | ||
115 | * check whether the parameter is present. | ||
116 | * @param n the parameter name | ||
117 | * @return true if yes | ||
118 | */ | ||
119 | bool has_param(const string& n) const; | ||
120 | /** | ||
121 | * retrieve the parameter (const version) | ||
122 | * @param n the parameter name | ||
123 | * @return the parameter value | ||
124 | * @throw failed_lookup if there is no such parameter | ||
125 | */ | ||
126 | const string& get_param(const string& n) const; | ||
127 | /** | ||
128 | * retrieve the parameter. | ||
129 | * @param n the parameter name | ||
130 | * @return the parameter value | ||
131 | * @throw failed_lookup if there is no such parameter | ||
132 | */ | ||
133 | string& get_param(const string& n); | ||
134 | |||
135 | /** | ||
136 | * parse the OpenID key/value data. | ||
137 | * @param kv the OpenID key/value data | ||
138 | */ | ||
139 | void parse_keyvalues(const string& kv); | ||
140 | /** | ||
141 | * sign the fields. | ||
142 | * @param secret the secret used for signing | ||
143 | * @param sig reference to the string, containing base64-encoded | ||
144 | * result | ||
145 | * @param slist the comma-separated list of fields to sign | ||
146 | * @param prefix the string to prepend to parameter names | ||
147 | */ | ||
148 | void sign(secret_t secret,string& sig,const string& slist,const char *prefix=0) const; | ||
149 | |||
150 | /** | ||
151 | * append parameters to the URL as a GET-request parameters. | ||
152 | * @param url the base URL | ||
153 | * @param prefix the string to prepend to parameter names | ||
154 | * @return the ready-to-use location | ||
155 | */ | ||
156 | string append_query(const string& url,const char *prefix = "openid.") const; | ||
157 | }; | ||
158 | |||
159 | /** | ||
160 | * dump the key/value pairs for the parameters to the stream. | ||
161 | * @param o output stream | ||
162 | * @param p the parameters | ||
163 | */ | ||
164 | ostream& operator << (ostream& o,const params_t& p); | ||
165 | |||
166 | } | ||
167 | |||
168 | #endif /* __OPKELE_TYPES_H */ | ||
diff --git a/include/opkele/util.h b/include/opkele/util.h new file mode 100644 index 0000000..fbbef93 --- a/dev/null +++ b/include/opkele/util.h | |||
@@ -0,0 +1,60 @@ | |||
1 | #ifndef __OPKELE_UTIL_H | ||
2 | #define __OPKELE_UTIL_H | ||
3 | |||
4 | #include <time.h> | ||
5 | #include <string> | ||
6 | #include <openssl/bn.h> | ||
7 | #include <openssl/dh.h> | ||
8 | |||
9 | namespace opkele { | ||
10 | using std::string; | ||
11 | |||
12 | namespace util { | ||
13 | |||
14 | class bignum_t { | ||
15 | public: | ||
16 | BIGNUM *_bn; | ||
17 | |||
18 | bignum_t() : _bn(0) { } | ||
19 | bignum_t(BIGNUM *bn) : _bn(bn) { } | ||
20 | ~bignum_t() throw() { if(_bn) BN_free(_bn); } | ||
21 | |||
22 | bignum_t& operator=(BIGNUM *bn) { if(_bn) BN_free(_bn); _bn = bn; return *this; } | ||
23 | |||
24 | operator const BIGNUM*(void) const { return _bn; } | ||
25 | operator BIGNUM*(void) { return _bn; } | ||
26 | }; | ||
27 | class dh_t { | ||
28 | public: | ||
29 | DH *_dh; | ||
30 | |||
31 | dh_t() : _dh(0) { } | ||
32 | dh_t(DH *dh) : _dh(dh) { } | ||
33 | ~dh_t() throw() { if(_dh) DH_free(_dh); } | ||
34 | |||
35 | dh_t& operator=(DH *dh) { if(_dh) DH_free(_dh); _dh = dh; return *this; } | ||
36 | |||
37 | operator const DH*(void) const { return _dh; } | ||
38 | operator DH*(void) { return _dh; } | ||
39 | |||
40 | DH* operator->() { return _dh; } | ||
41 | const DH* operator->() const { return _dh; } | ||
42 | }; | ||
43 | |||
44 | BIGNUM *base64_to_bignum(const string& b64); | ||
45 | BIGNUM *dec_to_bignum(const string& dec); | ||
46 | string bignum_to_base64(const BIGNUM *bn); | ||
47 | |||
48 | string time_to_w3c(time_t t); | ||
49 | time_t w3c_to_time(const string& w); | ||
50 | |||
51 | string canonicalize_url(const string& url); | ||
52 | string url_encode(const string& str); | ||
53 | |||
54 | string long_to_string(long l); | ||
55 | long string_to_long(const string& s); | ||
56 | } | ||
57 | |||
58 | } | ||
59 | |||
60 | #endif /* __OPKELE_UTIL_H */ | ||
diff --git a/lib/.gitignore b/lib/.gitignore new file mode 100644 index 0000000..2325be6 --- a/dev/null +++ b/lib/.gitignore | |||
@@ -0,0 +1,7 @@ | |||
1 | *.lo | ||
2 | *.o | ||
3 | Makefile.in | ||
4 | libopkele.la | ||
5 | .libs | ||
6 | .deps | ||
7 | Makefile | ||
diff --git a/lib/Makefile.am b/lib/Makefile.am new file mode 100644 index 0000000..6f3f9f3 --- a/dev/null +++ b/lib/Makefile.am | |||
@@ -0,0 +1,24 @@ | |||
1 | lib_LTLIBRARIES = libopkele.la | ||
2 | |||
3 | INCLUDES = \ | ||
4 | -I${top_srcdir}/include/ \ | ||
5 | ${KONFORKA_CFLAGS} \ | ||
6 | ${OPENSSL_CFLAGS} \ | ||
7 | ${MIMETIC_CFLAGS} \ | ||
8 | ${LIBCURL_CPPFLAGS} \ | ||
9 | ${PCREPP_CFLAGS} | ||
10 | LDADD = \ | ||
11 | ${LIBCURL} \ | ||
12 | ${PCREPP_LIBS} \ | ||
13 | ${MIMETIC_LIBS} \ | ||
14 | ${OPENSSL_LIBS} \ | ||
15 | ${KONFORKA_LIBS} | ||
16 | |||
17 | libopkele_la_SOURCES = \ | ||
18 | params.cc \ | ||
19 | util.cc \ | ||
20 | server.cc \ | ||
21 | secret.cc \ | ||
22 | data.cc \ | ||
23 | consumer.cc \ | ||
24 | exception.cc | ||
diff --git a/lib/consumer.cc b/lib/consumer.cc new file mode 100644 index 0000000..bd76b61 --- a/dev/null +++ b/lib/consumer.cc | |||
@@ -0,0 +1,316 @@ | |||
1 | #include <algorithm> | ||
2 | #include <opkele/util.h> | ||
3 | #include <opkele/exception.h> | ||
4 | #include <opkele/data.h> | ||
5 | #include <opkele/consumer.h> | ||
6 | #include <openssl/sha.h> | ||
7 | #include <openssl/hmac.h> | ||
8 | #include <mimetic/mimetic.h> | ||
9 | #include <curl/curl.h> | ||
10 | #include <pcre++.h> | ||
11 | |||
12 | #include <iostream> | ||
13 | |||
14 | /* silly mimetic */ | ||
15 | #undef PACKAGE | ||
16 | #undef PACKAGE_BUGREPORT | ||
17 | #undef PACKAGE_NAME | ||
18 | #undef PACKAGE_STRING | ||
19 | #undef PACKAGE_TARNAME | ||
20 | #undef PACKAGE_VERSION | ||
21 | #undef VERSION | ||
22 | |||
23 | #include "config.h" | ||
24 | |||
25 | namespace opkele { | ||
26 | using namespace std; | ||
27 | |||
28 | class curl_t { | ||
29 | public: | ||
30 | CURL *_c; | ||
31 | |||
32 | curl_t() : _c(0) { } | ||
33 | curl_t(CURL *c) : _c(c) { } | ||
34 | ~curl_t() throw() { if(_c) curl_easy_cleanup(_c); } | ||
35 | |||
36 | curl_t& operator=(CURL *c) { if(_c) curl_easy_cleanup(_c); _c=c; return *this; } | ||
37 | |||
38 | operator const CURL*(void) const { return _c; } | ||
39 | operator CURL*(void) { return _c; } | ||
40 | }; | ||
41 | |||
42 | static CURLcode curl_misc_sets(CURL* c) { | ||
43 | CURLcode r; | ||
44 | (r=curl_easy_setopt(c,CURLOPT_FOLLOWLOCATION,1)) | ||
45 | || (r=curl_easy_setopt(c,CURLOPT_MAXREDIRS,5)) | ||
46 | || (r=curl_easy_setopt(c,CURLOPT_DNS_CACHE_TIMEOUT,120)) | ||
47 | || (r=curl_easy_setopt(c,CURLOPT_DNS_USE_GLOBAL_CACHE,1)) | ||
48 | || (r=curl_easy_setopt(c,CURLOPT_USERAGENT,PACKAGE_NAME"/"PACKAGE_VERSION)) | ||
49 | || (r=curl_easy_setopt(c,CURLOPT_TIMEOUT,20)) | ||
50 | ; | ||
51 | return r; | ||
52 | } | ||
53 | |||
54 | static size_t _curl_tostring(void *ptr,size_t size,size_t nmemb,void *stream) { | ||
55 | string *str = (string*)stream; | ||
56 | size_t bytes = size*nmemb; | ||
57 | size_t get = min(16384-str->length(),bytes); | ||
58 | str->append((const char*)ptr,get); | ||
59 | return get; | ||
60 | } | ||
61 | |||
62 | assoc_t consumer_t::associate(const string& server) { | ||
63 | util::dh_t dh = DH_new(); | ||
64 | if(!dh) | ||
65 | throw exception_openssl(OPKELE_CP_ "failed to DH_new()"); | ||
66 | dh->p = util::dec_to_bignum(data::_default_p); | ||
67 | dh->g = util::dec_to_bignum(data::_default_g); | ||
68 | if(!DH_generate_key(dh)) | ||
69 | throw exception_openssl(OPKELE_CP_ "failed to DH_generate_key()"); | ||
70 | string request = | ||
71 | "openid.mode=associate" | ||
72 | "&openid.assoc_type=HMAC-SHA1" | ||
73 | "&openid.session_type=DH-SHA1" | ||
74 | "&openid.dh_consumer_public="; | ||
75 | request += util::url_encode(util::bignum_to_base64(dh->pub_key)); | ||
76 | curl_t curl = curl_easy_init(); | ||
77 | if(!curl) | ||
78 | throw exception_curl(OPKELE_CP_ "failed to curl_easy_init()"); | ||
79 | string response; | ||
80 | CURLcode r; | ||
81 | (r=curl_misc_sets(curl)) | ||
82 | || (r=curl_easy_setopt(curl,CURLOPT_URL,server.c_str())) | ||
83 | || (r=curl_easy_setopt(curl,CURLOPT_POST,1)) | ||
84 | || (r=curl_easy_setopt(curl,CURLOPT_POSTFIELDS,request.data())) | ||
85 | || (r=curl_easy_setopt(curl,CURLOPT_POSTFIELDSIZE,request.length())) | ||
86 | || (r=curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,_curl_tostring)) | ||
87 | || (r=curl_easy_setopt(curl,CURLOPT_WRITEDATA,&response)) | ||
88 | ; | ||
89 | if(r) | ||
90 | throw exception_curl(OPKELE_CP_ "failed to curl_easy_setopt()",r); | ||
91 | if(r=curl_easy_perform(curl)) | ||
92 | throw exception_curl(OPKELE_CP_ "failed to curl_easy_perform()",r); | ||
93 | params_t p; p.parse_keyvalues(response); | ||
94 | if(p.has_param("assoc_type") && p.get_param("assoc_type")!="HMAC-SHA1") | ||
95 | throw bad_input(OPKELE_CP_ "unsupported assoc_type"); | ||
96 | string st; | ||
97 | if(p.has_param("session_type")) st = p.get_param("session_type"); | ||
98 | if((!st.empty()) && st!="DH-SHA1") | ||
99 | throw bad_input(OPKELE_CP_ "unsupported session_type"); | ||
100 | secret_t secret; | ||
101 | if(st.empty()) { | ||
102 | secret.from_base64(p.get_param("mac_key")); | ||
103 | }else{ | ||
104 | util::bignum_t s_pub = util::base64_to_bignum(p.get_param("dh_server_public")); | ||
105 | vector<unsigned char> ck(DH_size(dh)); | ||
106 | int cklen = DH_compute_key(&(ck.front()),s_pub,dh); | ||
107 | if(cklen<0) | ||
108 | throw exception_openssl(OPKELE_CP_ "failed to DH_compute_key()"); | ||
109 | ck.resize(cklen); | ||
110 | // OpenID algorithm requires extra zero in case of set bit here | ||
111 | if(ck[0]&0x80) ck.insert(ck.begin(),1,0); | ||
112 | unsigned char key_sha1[SHA_DIGEST_LENGTH]; | ||
113 | SHA1(&(ck.front()),ck.size(),key_sha1); | ||
114 | secret.enxor_from_base64(key_sha1,p.get_param("enc_mac_key")); | ||
115 | } | ||
116 | int expires_in = 0; | ||
117 | if(p.has_param("expires_in")) { | ||
118 | expires_in = util::string_to_long(p.get_param("expires_in")); | ||
119 | }else if(p.has_param("issued") && p.has_param("expiry")) { | ||
120 | expires_in = util::w3c_to_time(p.get_param("expiry"))-util::w3c_to_time(p.get_param("issued")); | ||
121 | }else | ||
122 | throw bad_input(OPKELE_CP_ "no expiration information"); | ||
123 | return store_assoc(server,p.get_param("assoc_handle"),secret,expires_in); | ||
124 | } | ||
125 | |||
126 | string consumer_t::checkid_immediate(const string& identity,const string& return_to,const string& trust_root) { | ||
127 | return checkid_(mode_checkid_immediate,identity,return_to,trust_root); | ||
128 | } | ||
129 | string consumer_t::checkid_setup(const string& identity,const string& return_to,const string& trust_root) { | ||
130 | return checkid_(mode_checkid_setup,identity,return_to,trust_root); | ||
131 | } | ||
132 | string consumer_t::checkid_(mode_t mode,const string& identity,const string& return_to,const string& trust_root) { | ||
133 | params_t p; | ||
134 | if(mode==mode_checkid_immediate) | ||
135 | p["mode"]="checkid_immediate"; | ||
136 | else if(mode==mode_checkid_setup) | ||
137 | p["mode"]="checkid_setup"; | ||
138 | else | ||
139 | throw bad_input(OPKELE_CP_ "unknown checkid_* mode"); | ||
140 | string iurl = util::canonicalize_url(identity); | ||
141 | string server, delegate; | ||
142 | retrieve_links(iurl,server,delegate); | ||
143 | p["identity"] = delegate.empty()?iurl:delegate; | ||
144 | if(!trust_root.empty()) | ||
145 | p["trust_root"] = trust_root; | ||
146 | p["return_to"] = return_to; | ||
147 | try { | ||
148 | try { | ||
149 | string ah = find_assoc(server)->handle(); | ||
150 | p["assoc_handle"] = ah; | ||
151 | }catch(failed_lookup& fl) { | ||
152 | string ah = associate(server)->handle(); | ||
153 | p["assoc_handle"] = ah; | ||
154 | } | ||
155 | }catch(exception& e) { } | ||
156 | return p.append_query(server); | ||
157 | } | ||
158 | |||
159 | void consumer_t::id_res(const params_t& pin,const string& identity) { | ||
160 | if(pin.has_param("openid.user_setup_url")) | ||
161 | throw id_res_setup(OPKELE_CP_ "assertion failed, setup url provided",pin.get_param("openid.user_setup_url")); | ||
162 | string server,delegate; | ||
163 | retrieve_links(identity.empty()?pin.get_param("openid.identity"):util::canonicalize_url(identity),server,delegate); | ||
164 | try { | ||
165 | assoc_t assoc = retrieve_assoc(server,pin.get_param("openid.assoc_handle")); | ||
166 | const string& sigenc = pin.get_param("openid.sig"); | ||
167 | mimetic::Base64::Decoder b; | ||
168 | vector<unsigned char> sig; | ||
169 | mimetic::decode( | ||
170 | sigenc.begin(),sigenc.end(), b, | ||
171 | back_insert_iterator<vector<unsigned char> >(sig) ); | ||
172 | const string& slist = pin.get_param("openid.signed"); | ||
173 | string kv; | ||
174 | string::size_type p = 0; | ||
175 | while(true) { | ||
176 | string::size_type co = slist.find(',',p); | ||
177 | string f = (co==string::npos)?slist.substr(p):slist.substr(p,co-p); | ||
178 | kv += f; | ||
179 | kv += ':'; | ||
180 | f.insert(0,"openid."); | ||
181 | kv += pin.get_param(f); | ||
182 | kv += '\n'; | ||
183 | if(co==string::npos) | ||
184 | break; | ||
185 | p = co+1; | ||
186 | } | ||
187 | secret_t secret = assoc->secret(); | ||
188 | unsigned int md_len = 0; | ||
189 | unsigned char *md = HMAC( | ||
190 | EVP_sha1(), | ||
191 | &(secret.front()),secret.size(), | ||
192 | (const unsigned char *)kv.data(),kv.length(), | ||
193 | 0,&md_len); | ||
194 | if(sig.size()!=md_len || memcmp(&(sig.front()),md,md_len)) | ||
195 | throw id_res_mismatch(OPKELE_CP_ "signature mismatch"); | ||
196 | }catch(failed_lookup& e) { /* XXX: more specific? */ | ||
197 | const string& slist = pin.get_param("openid.signed"); | ||
198 | string::size_type pp = 0; | ||
199 | params_t p; | ||
200 | while(true) { | ||
201 | string::size_type co = slist.find(',',pp); | ||
202 | string f = "openid."; | ||
203 | f += (co==string::npos)?slist.substr(pp):slist.substr(pp,co-pp); | ||
204 | p[f] = pin.get_param(f); | ||
205 | if(co==string::npos) | ||
206 | break; | ||
207 | pp = co+1; | ||
208 | } | ||
209 | p["openid.assoc_handle"] = pin.get_param("openid.assoc_handle"); | ||
210 | p["openid.sig"] = pin.get_param("openid.sig"); | ||
211 | p["openid.signed"] = pin.get_param("openid.signed"); | ||
212 | try { | ||
213 | string ih = pin.get_param("openid.invalidate_handle"); | ||
214 | p["openid.invalidate_handle"] = ih; | ||
215 | }catch(failed_lookup& fl) { } | ||
216 | try { | ||
217 | check_authentication(server,p); | ||
218 | }catch(failed_check_authentication& fca) { | ||
219 | throw id_res_failed(OPKELE_CP_ "failed to check_authentication()"); | ||
220 | } | ||
221 | } | ||
222 | } | ||
223 | |||
224 | void consumer_t::check_authentication(const string& server,const params_t& p) { | ||
225 | string request = "openid.mode=check_authentication"; | ||
226 | for(params_t::const_iterator i=p.begin();i!=p.end();++i) { | ||
227 | if(i->first!="openid.mode") { | ||
228 | request += '&'; | ||
229 | request += i->first; | ||
230 | request += '='; | ||
231 | request += util::url_encode(i->second); | ||
232 | } | ||
233 | } | ||
234 | curl_t curl = curl_easy_init(); | ||
235 | if(!curl) | ||
236 | throw exception_curl(OPKELE_CP_ "failed to curl_easy_init()"); | ||
237 | string response; | ||
238 | CURLcode r; | ||
239 | (r=curl_misc_sets(curl)) | ||
240 | || (r=curl_easy_setopt(curl,CURLOPT_URL,server.c_str())) | ||
241 | || (r=curl_easy_setopt(curl,CURLOPT_POST,1)) | ||
242 | || (r=curl_easy_setopt(curl,CURLOPT_POSTFIELDS,request.data())) | ||
243 | || (r=curl_easy_setopt(curl,CURLOPT_POSTFIELDSIZE,request.length())) | ||
244 | || (r=curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,_curl_tostring)) | ||
245 | || (r=curl_easy_setopt(curl,CURLOPT_WRITEDATA,&response)) | ||
246 | ; | ||
247 | if(r) | ||
248 | throw exception_curl(OPKELE_CP_ "failed to curl_easy_setopt()",r); | ||
249 | if(r=curl_easy_perform(curl)) | ||
250 | throw exception_curl(OPKELE_CP_ "failed to curl_easy_perform()",r); | ||
251 | params_t pp; pp.parse_keyvalues(response); | ||
252 | if(pp.has_param("invalidate_handle")) | ||
253 | invalidate_assoc(server,pp.get_param("invalidate_handle")); | ||
254 | if(pp.has_param("is_valid")) { | ||
255 | if(pp.get_param("is_valid")=="true") | ||
256 | return; | ||
257 | }else if(pp.has_param("lifetime")) { | ||
258 | if(util::string_to_long(pp.get_param("lifetime"))) | ||
259 | return; | ||
260 | } | ||
261 | throw failed_check_authentication(OPKELE_CP_ "failed to verify response"); | ||
262 | } | ||
263 | |||
264 | void consumer_t::retrieve_links(const string& url,string& server,string& delegate) { | ||
265 | server.erase(); | ||
266 | delegate.erase(); | ||
267 | curl_t curl = curl_easy_init(); | ||
268 | if(!curl) | ||
269 | throw exception_curl(OPKELE_CP_ "failed to curl_easy_init()"); | ||
270 | string html; | ||
271 | CURLcode r; | ||
272 | (r=curl_misc_sets(curl)) | ||
273 | || (r=curl_easy_setopt(curl,CURLOPT_URL,url.c_str())) | ||
274 | || (r=curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,_curl_tostring)) | ||
275 | || (r=curl_easy_setopt(curl,CURLOPT_WRITEDATA,&html)) | ||
276 | ; | ||
277 | if(r) | ||
278 | throw exception_curl(OPKELE_CP_ "failed to curl_easy_setopt()",r); | ||
279 | r = curl_easy_perform(curl); | ||
280 | if(r && r!=CURLE_WRITE_ERROR) | ||
281 | throw exception_curl(OPKELE_CP_ "failed to curl_easy_perform()",r); | ||
282 | pcrepp::Pcre bre("<body\\b",PCRE_CASELESS); | ||
283 | // strip out everything past body | ||
284 | if(bre.search(html)) | ||
285 | html.erase(bre.get_match_start()); | ||
286 | pcrepp::Pcre hdre("<head[^>]*>",PCRE_CASELESS); | ||
287 | if(!hdre.search(html)) | ||
288 | throw bad_input(OPKELE_CP_ "failed to find head"); | ||
289 | html.erase(0,hdre.get_match_end()+1); | ||
290 | pcrepp::Pcre lre("<link\\b([^>]+)>",PCRE_CASELESS), | ||
291 | rre("\\brel=['\"]([^'\"]+)['\"]",PCRE_CASELESS), | ||
292 | hre("\\bhref=['\"]([^'\"]+)['\"]",PCRE_CASELESS); | ||
293 | while(lre.search(html)) { | ||
294 | string attrs = lre[0]; | ||
295 | html.erase(0,lre.get_match_end()+1); | ||
296 | if(!(rre.search(attrs)&&hre.search(attrs))) | ||
297 | continue; | ||
298 | if(rre[0]=="openid.server") { | ||
299 | server = hre[0]; | ||
300 | if(!delegate.empty()) | ||
301 | break; | ||
302 | }else if(rre[0]=="openid.delegate") { | ||
303 | delegate = hre[0]; | ||
304 | if(!server.empty()) | ||
305 | break; | ||
306 | } | ||
307 | } | ||
308 | if(server.empty()) | ||
309 | throw failed_assertion(OPKELE_CP_ "The location has no openid.server declaration"); | ||
310 | } | ||
311 | |||
312 | assoc_t consumer_t::find_assoc(const string& server) { | ||
313 | throw failed_lookup(OPKELE_CP_ "no find_assoc() provided"); | ||
314 | } | ||
315 | |||
316 | } | ||
diff --git a/lib/data.cc b/lib/data.cc new file mode 100644 index 0000000..c040430 --- a/dev/null +++ b/lib/data.cc | |||
@@ -0,0 +1,11 @@ | |||
1 | #include <opkele/data.h> | ||
2 | |||
3 | namespace opkele { | ||
4 | |||
5 | namespace data { | ||
6 | |||
7 | const char *_default_p = "155172898181473697471232257763715539915724801966915404479707795314057629378541917580651227423698188993727816152646631438561595825688188889951272158842675419950341258706556549803580104870537681476726513255747040765857479291291572334510643245094715007229621094194349783925984760375594985848253359305585439638443"; | ||
8 | const char *_default_g = "2"; | ||
9 | |||
10 | } | ||
11 | } | ||
diff --git a/lib/exception.cc b/lib/exception.cc new file mode 100644 index 0000000..b7c1702 --- a/dev/null +++ b/lib/exception.cc | |||
@@ -0,0 +1,22 @@ | |||
1 | #include <openssl/err.h> | ||
2 | #include <curl/curl.h> | ||
3 | #include <opkele/exception.h> | ||
4 | |||
5 | namespace opkele { | ||
6 | |||
7 | exception_openssl::exception_openssl(OPKELE_E_PARS) | ||
8 | : _error(ERR_peek_last_error()), | ||
9 | _ssl_string(ERR_error_string(_error,0)), | ||
10 | exception(OPKELE_E_CONS_ w+" ["+_ssl_string+']') { | ||
11 | } | ||
12 | |||
13 | exception_curl::exception_curl(OPKELE_E_PARS) | ||
14 | : _error(CURLE_OK), | ||
15 | exception_network(OPKELE_E_CONS) { } | ||
16 | exception_curl::exception_curl(OPKELE_E_PARS,CURLcode e) | ||
17 | : _error(e), | ||
18 | _curl_string(curl_easy_strerror(e)), | ||
19 | exception_network(OPKELE_E_CONS_ w+" ["+_curl_string+']') { | ||
20 | } | ||
21 | |||
22 | } | ||
diff --git a/lib/params.cc b/lib/params.cc new file mode 100644 index 0000000..14f1a53 --- a/dev/null +++ b/lib/params.cc | |||
@@ -0,0 +1,96 @@ | |||
1 | #include <opkele/types.h> | ||
2 | #include <opkele/exception.h> | ||
3 | #include <opkele/util.h> | ||
4 | #include <openssl/sha.h> | ||
5 | #include <openssl/hmac.h> | ||
6 | #include <mimetic/mimetic.h> | ||
7 | |||
8 | namespace opkele { | ||
9 | using namespace std; | ||
10 | |||
11 | bool params_t::has_param(const string& n) const { | ||
12 | return find(n)!=end(); | ||
13 | } | ||
14 | const string& params_t::get_param(const string& n) const { | ||
15 | const_iterator i = find(n); | ||
16 | if(i==end()) | ||
17 | throw failed_lookup(OPKELE_CP_ n+": no such parameter"); | ||
18 | return i->second; | ||
19 | } | ||
20 | string& params_t::get_param(const string& n) { | ||
21 | iterator i = find(n); | ||
22 | if(i==end()) | ||
23 | throw failed_lookup(OPKELE_CP_ n+": no such parameter"); | ||
24 | return i->second; | ||
25 | } | ||
26 | |||
27 | void params_t::parse_keyvalues(const string& kv) { | ||
28 | clear(); | ||
29 | string::size_type p = 0; | ||
30 | while(true) { | ||
31 | string::size_type co = kv.find(':',p); | ||
32 | if(co==string::npos) | ||
33 | break; | ||
34 | string::size_type nl = kv.find('\n',co+1); | ||
35 | if(nl==string::npos) | ||
36 | throw bad_input(OPKELE_CP_ "malformed input"); | ||
37 | insert(value_type(kv.substr(p,co-p),kv.substr(co+1,nl-co-1))); | ||
38 | p = nl+1; | ||
39 | } | ||
40 | } | ||
41 | |||
42 | void params_t::sign(secret_t secret,string& sig,const string& slist,const char *prefix) const { | ||
43 | string kv; | ||
44 | string::size_type p = 0; | ||
45 | while(true) { | ||
46 | string::size_type co = slist.find(',',p); | ||
47 | string f = (co==string::npos)?slist.substr(p):slist.substr(p,co-p); | ||
48 | kv += f; | ||
49 | kv += ':'; | ||
50 | if(prefix) f.insert(0,prefix); | ||
51 | kv += get_param(f); | ||
52 | kv += '\n'; | ||
53 | if(co==string::npos) | ||
54 | break; | ||
55 | p = co+1; | ||
56 | } | ||
57 | unsigned int md_len = 0; | ||
58 | unsigned char *md = HMAC( | ||
59 | EVP_sha1(), | ||
60 | &(secret.front()),secret.size(), | ||
61 | (const unsigned char *)kv.data(),kv.length(), | ||
62 | 0,&md_len); | ||
63 | mimetic::Base64::Encoder b(0); | ||
64 | sig.erase(); | ||
65 | mimetic::encode( | ||
66 | md,md+md_len, b, | ||
67 | back_insert_iterator<string>(sig) ); | ||
68 | } | ||
69 | |||
70 | string params_t::append_query(const string& url,const char *prefix) const { | ||
71 | string rv = url; | ||
72 | bool p = true; | ||
73 | if(rv.find('?')==string::npos) { | ||
74 | rv += '?'; | ||
75 | p = false; | ||
76 | } | ||
77 | for(const_iterator i=begin();i!=end();++i) { | ||
78 | if(p) | ||
79 | rv += '&'; | ||
80 | else | ||
81 | p = true; | ||
82 | rv += prefix; | ||
83 | rv += i->first; | ||
84 | rv += '='; | ||
85 | rv += util::url_encode(i->second); | ||
86 | } | ||
87 | return rv; | ||
88 | } | ||
89 | |||
90 | ostream& operator << (ostream& o,const params_t& p) { | ||
91 | for(params_t::const_iterator i=p.begin();i!=p.end();++i) | ||
92 | o << i->first << ':' << i->second << '\n'; | ||
93 | return o; | ||
94 | } | ||
95 | |||
96 | } | ||
diff --git a/lib/secret.cc b/lib/secret.cc new file mode 100644 index 0000000..ae8a3c5 --- a/dev/null +++ b/lib/secret.cc | |||
@@ -0,0 +1,61 @@ | |||
1 | #include <algorithm> | ||
2 | #include <functional> | ||
3 | #include <opkele/types.h> | ||
4 | #include <opkele/exception.h> | ||
5 | #include <mimetic/mimetic.h> | ||
6 | |||
7 | namespace opkele { | ||
8 | using namespace std; | ||
9 | |||
10 | template<class __a1,class __a2,class __r> | ||
11 | struct bitwise_xor : public binary_function<__a1,__a2,__r> { | ||
12 | __r operator() (const __a1& a1,const __a2& a2) const { | ||
13 | return a1^a2; | ||
14 | } | ||
15 | }; | ||
16 | |||
17 | void secret_t::enxor_to_base64(const unsigned char *key_sha1,string& rv) const { | ||
18 | if(size()!=20) | ||
19 | throw bad_input(OPKELE_CP_ "wrong secret size"); | ||
20 | vector<unsigned char> tmp; | ||
21 | transform( | ||
22 | begin(), end(), | ||
23 | key_sha1, | ||
24 | back_insert_iterator<vector<unsigned char> >(tmp), | ||
25 | bitwise_xor<unsigned char,unsigned char,unsigned char>() ); | ||
26 | mimetic::Base64::Encoder b(0); | ||
27 | mimetic::encode( | ||
28 | tmp.begin(),tmp.end(), b, | ||
29 | back_insert_iterator<string>(rv) ); | ||
30 | } | ||
31 | |||
32 | void secret_t::enxor_from_base64(const unsigned char *key_sha1,const string& b64) { | ||
33 | mimetic::Base64::Decoder b; | ||
34 | clear(); | ||
35 | mimetic::decode( | ||
36 | b64.begin(),b64.end(), b, | ||
37 | back_insert_iterator<secret_t>(*this) ); | ||
38 | transform( | ||
39 | begin(), end(), | ||
40 | key_sha1, | ||
41 | begin(), | ||
42 | bitwise_xor<unsigned char,unsigned char,unsigned char>() ); | ||
43 | } | ||
44 | |||
45 | void secret_t::to_base64(string& rv) const { | ||
46 | if(size()!=20) | ||
47 | throw bad_input(OPKELE_CP_ "wrong secret size"); | ||
48 | mimetic::Base64::Encoder b(0); | ||
49 | mimetic::encode( | ||
50 | begin(),end(), b, | ||
51 | back_insert_iterator<string>(rv) ); | ||
52 | } | ||
53 | |||
54 | void secret_t::from_base64(const string& b64) { | ||
55 | mimetic::Base64::Decoder b; | ||
56 | mimetic::decode( | ||
57 | b64.begin(),b64.end(), b, | ||
58 | back_insert_iterator<secret_t>(*this) ); | ||
59 | } | ||
60 | |||
61 | } | ||
diff --git a/lib/server.cc b/lib/server.cc new file mode 100644 index 0000000..51d4554 --- a/dev/null +++ b/lib/server.cc | |||
@@ -0,0 +1,169 @@ | |||
1 | #include <vector> | ||
2 | #include <openssl/sha.h> | ||
3 | #include <openssl/hmac.h> | ||
4 | #include <mimetic/mimetic.h> | ||
5 | #include <opkele/util.h> | ||
6 | #include <opkele/exception.h> | ||
7 | #include <opkele/server.h> | ||
8 | #include <opkele/data.h> | ||
9 | |||
10 | namespace opkele { | ||
11 | using namespace std; | ||
12 | |||
13 | void server_t::associate(const params_t& pin,params_t& pout) { | ||
14 | util::dh_t dh; | ||
15 | util::bignum_t c_pub; | ||
16 | unsigned char key_sha1[SHA_DIGEST_LENGTH]; | ||
17 | enum { | ||
18 | sess_cleartext, | ||
19 | sess_dh_sha1 | ||
20 | } st = sess_cleartext; | ||
21 | if( | ||
22 | pin.has_param("openid.session_type") | ||
23 | && pin.get_param("openid.session_type")=="DH-SHA1" ) { | ||
24 | /* TODO: fallback to cleartext in case of exceptions here? */ | ||
25 | if(!(dh = DH_new())) | ||
26 | throw exception_openssl(OPKELE_CP_ "failed to DH_new()"); | ||
27 | c_pub = util::base64_to_bignum(pin.get_param("openid.dh_consumer_public")); | ||
28 | if(pin.has_param("openid.dh_modulus")) | ||
29 | dh->p = util::base64_to_bignum(pin.get_param("openid.dh_modulus")); | ||
30 | else | ||
31 | dh->p = util::dec_to_bignum(data::_default_p); | ||
32 | if(pin.has_param("openid.dh_gen")) | ||
33 | dh->g = util::base64_to_bignum(pin.get_param("openid.dh_gen")); | ||
34 | else | ||
35 | dh->g = util::dec_to_bignum(data::_default_g); | ||
36 | if(!DH_generate_key(dh)) | ||
37 | throw exception_openssl(OPKELE_CP_ "failed to DH_generate_key()"); | ||
38 | vector<unsigned char> ck(DH_size(dh)); | ||
39 | int cklen = DH_compute_key(&(ck.front()),c_pub,dh); | ||
40 | if(cklen<0) | ||
41 | throw exception_openssl(OPKELE_CP_ "failed to DH_compute_key()"); | ||
42 | ck.resize(cklen); | ||
43 | // OpenID algorithm requires extra zero in case of set bit here | ||
44 | if(ck[0]&0x80) ck.insert(ck.begin(),1,0); | ||
45 | SHA1(&(ck.front()),ck.size(),key_sha1); | ||
46 | st = sess_dh_sha1; | ||
47 | } | ||
48 | assoc_t assoc = alloc_assoc(mode_associate); | ||
49 | time_t now = time(0); | ||
50 | pout.clear(); | ||
51 | pout["assoc_type"] = assoc->assoc_type(); | ||
52 | pout["assoc_handle"] = assoc->handle(); | ||
53 | /* TODO: eventually remove deprecated stuff */ | ||
54 | pout["issued"] = util::time_to_w3c(now); | ||
55 | pout["expiry"] = util::time_to_w3c(now+assoc->expires_in()); | ||
56 | pout["expires_in"] = util::long_to_string(assoc->expires_in()); | ||
57 | secret_t secret = assoc->secret(); | ||
58 | switch(st) { | ||
59 | case sess_dh_sha1: | ||
60 | pout["session_type"] = "DH-SHA1"; | ||
61 | pout["dh_server_public"] = util::bignum_to_base64(dh->pub_key); | ||
62 | secret.enxor_to_base64(key_sha1,pout["enc_mac_key"]); | ||
63 | break; | ||
64 | default: | ||
65 | secret.to_base64(pout["mac_key"]); | ||
66 | break; | ||
67 | } | ||
68 | } | ||
69 | |||
70 | void server_t::checkid_immediate(const params_t& pin,string& return_to,params_t& pout) { | ||
71 | checkid_(mode_checkid_immediate,pin,return_to,pout); | ||
72 | } | ||
73 | |||
74 | void server_t::checkid_setup(const params_t& pin,string& return_to,params_t& pout) { | ||
75 | checkid_(mode_checkid_setup,pin,return_to,pout); | ||
76 | } | ||
77 | |||
78 | void server_t::checkid_(mode_t mode,const params_t& pin,string& return_to,params_t& pout) { | ||
79 | if(mode!=mode_checkid_immediate && mode!=mode_checkid_setup) | ||
80 | throw bad_input(OPKELE_CP_ "invalid checkid_* mode"); | ||
81 | assoc_t assoc; | ||
82 | try { | ||
83 | assoc = retrieve_assoc(pin.get_param("openid.assoc_handle")); | ||
84 | }catch(failed_lookup& fl) { | ||
85 | // no handle specified or no valid handle found, going dumb | ||
86 | assoc = alloc_assoc(mode_checkid_setup); | ||
87 | } | ||
88 | string trust_root; | ||
89 | try { | ||
90 | trust_root = pin.get_param("openid.trust_root"); | ||
91 | }catch(failed_lookup& fl) { } | ||
92 | string identity = pin.get_param("openid.identity"); | ||
93 | return_to = pin.get_param("openid.return_to"); | ||
94 | validate(*assoc,pin,identity,trust_root); | ||
95 | pout.clear(); | ||
96 | pout["mode"] = "id_res"; | ||
97 | pout["assoc_handle"] = assoc->handle(); | ||
98 | if(pin.has_param("openid.assoc_handle") && assoc->stateless()) | ||
99 | pout["invalidate_handle"] = pin.get_param("openid.assoc_handle"); | ||
100 | pout["identity"] = identity; | ||
101 | pout["return_to"] = return_to; | ||
102 | /* TODO: eventually remove deprecated stuff */ | ||
103 | time_t now = time(0); | ||
104 | pout["issued"] = util::time_to_w3c(now); | ||
105 | pout["valid_to"] = util::time_to_w3c(now+120); | ||
106 | pout["exipres_in"] = "120"; | ||
107 | pout.sign(assoc->secret(),pout["sig"],pout["signed"]="mode,identity,return_to"); | ||
108 | } | ||
109 | |||
110 | void server_t::check_authentication(const params_t& pin,params_t& pout) { | ||
111 | vector<unsigned char> sig; | ||
112 | mimetic::Base64::Decoder b; | ||
113 | const string& sigenc = pin.get_param("openid.sig"); | ||
114 | mimetic::decode( | ||
115 | sigenc.begin(),sigenc.end(), b, | ||
116 | back_insert_iterator<vector<unsigned char> >(sig)); | ||
117 | assoc_t assoc; | ||
118 | try { | ||
119 | assoc = retrieve_assoc(pin.get_param("openid.assoc_handle")); | ||
120 | }catch(failed_lookup& fl) { | ||
121 | throw failed_assertion(OPKELE_CP_ "invalid handle or handle not specified"); | ||
122 | } | ||
123 | if(!assoc->stateless()) | ||
124 | throw stateful_handle(OPKELE_CP_ "will not do check_authentication on a stateful handle"); | ||
125 | const string& slist = pin.get_param("openid.signed"); | ||
126 | string kv; | ||
127 | string::size_type p =0; | ||
128 | while(true) { | ||
129 | string::size_type co = slist.find(',',p); | ||
130 | string f = (co==string::npos)?slist.substr(p):slist.substr(p,co-p); | ||
131 | kv += f; | ||
132 | kv += ':'; | ||
133 | if(f=="mode") | ||
134 | kv += "id_res"; | ||
135 | else { | ||
136 | f.insert(0,"openid."); | ||
137 | kv += pin.get_param(f); | ||
138 | } | ||
139 | kv += '\n'; | ||
140 | if(co==string::npos) | ||
141 | break; | ||
142 | p = co+1; | ||
143 | } | ||
144 | secret_t secret = assoc->secret(); | ||
145 | unsigned int md_len = 0; | ||
146 | unsigned char *md = HMAC( | ||
147 | EVP_sha1(), | ||
148 | &(secret.front()),secret.size(), | ||
149 | (const unsigned char *)kv.data(),kv.length(), | ||
150 | 0,&md_len); | ||
151 | pout.clear(); | ||
152 | if(sig.size()==md_len && !memcmp(&(sig.front()),md,md_len)) { | ||
153 | pout["is_valid"]="true"; | ||
154 | pout["lifetime"]="60"; /* TODO: eventually remove deprecated stuff */ | ||
155 | }else{ | ||
156 | pout["is_valid"]="false"; | ||
157 | pout["lifetime"]="0"; /* TODO: eventually remove deprecated stuff */ | ||
158 | } | ||
159 | if(pin.has_param("openid.invalidate_handle")) { | ||
160 | string h = pin.get_param("openid.invalidate_handle"); | ||
161 | try { | ||
162 | assoc_t assoc = retrieve_assoc(h); | ||
163 | }catch(invalid_handle& ih) { | ||
164 | pout["invalidate_handle"] = h; | ||
165 | }catch(failed_lookup& fl) { } | ||
166 | } | ||
167 | } | ||
168 | |||
169 | } | ||
diff --git a/lib/util.cc b/lib/util.cc new file mode 100644 index 0000000..1e7335c --- a/dev/null +++ b/lib/util.cc | |||
@@ -0,0 +1,138 @@ | |||
1 | #include <errno.h> | ||
2 | #include <cassert> | ||
3 | #include <vector> | ||
4 | #include <string> | ||
5 | #include <mimetic/mimetic.h> | ||
6 | #include <curl/curl.h> | ||
7 | #include "opkele/util.h" | ||
8 | #include "opkele/exception.h" | ||
9 | |||
10 | namespace opkele { | ||
11 | using namespace std; | ||
12 | |||
13 | namespace util { | ||
14 | |||
15 | /* | ||
16 | * big numerics | ||
17 | */ | ||
18 | |||
19 | BIGNUM *base64_to_bignum(const string& b64) { | ||
20 | vector<unsigned char> bin; | ||
21 | mimetic::Base64::Decoder b; | ||
22 | mimetic::decode( | ||
23 | b64.begin(),b64.end(), b, | ||
24 | back_insert_iterator<vector<unsigned char> >(bin) ); | ||
25 | BIGNUM *rv = BN_bin2bn(&(bin.front()),bin.size(),0); | ||
26 | if(!rv) | ||
27 | throw failed_conversion(OPKELE_CP_ "failed to BN_bin2bn()"); | ||
28 | return rv; | ||
29 | } | ||
30 | |||
31 | BIGNUM *dec_to_bignum(const string& dec) { | ||
32 | BIGNUM *rv = 0; | ||
33 | if(!BN_dec2bn(&rv,dec.c_str())) | ||
34 | throw failed_conversion(OPKELE_CP_ "failed to BN_dec2bn()"); | ||
35 | return rv; | ||
36 | } | ||
37 | |||
38 | string bignum_to_base64(const BIGNUM *bn) { | ||
39 | vector<unsigned char> bin(BN_num_bytes(bn)); | ||
40 | int l = BN_bn2bin(bn,&(bin.front())); | ||
41 | string rv; | ||
42 | mimetic::Base64::Encoder b(0); | ||
43 | mimetic::encode( | ||
44 | bin.begin(),bin.begin()+l, b, | ||
45 | back_insert_iterator<string>(rv) ); | ||
46 | return rv; | ||
47 | } | ||
48 | |||
49 | /* | ||
50 | * w3c times | ||
51 | */ | ||
52 | |||
53 | string time_to_w3c(time_t t) { | ||
54 | struct tm tm_t; | ||
55 | if(!gmtime_r(&t,&tm_t)) | ||
56 | throw failed_conversion(OPKELE_CP_ "failed to BN_dec2bn()"); | ||
57 | char rv[25]; | ||
58 | if(!strftime(rv,sizeof(rv)-1,"%Y-%m-%dT%H:%M:%SZ",&tm_t)) | ||
59 | throw failed_conversion(OPKELE_CP_ "failed to strftime()"); | ||
60 | return rv; | ||
61 | } | ||
62 | |||
63 | time_t w3c_to_time(const string& w) { | ||
64 | struct tm tm_t; | ||
65 | memset(&tm_t,0,sizeof(tm_t)); | ||
66 | if( | ||
67 | sscanf( | ||
68 | w.c_str(), | ||
69 | "%04d-%02d-%02dT%02d:%02d:%02dZ", | ||
70 | &tm_t.tm_year,&tm_t.tm_mon,&tm_t.tm_mday, | ||
71 | &tm_t.tm_hour,&tm_t.tm_min,&tm_t.tm_sec | ||
72 | ) != 6 ) | ||
73 | throw failed_conversion(OPKELE_CP_ "failed to sscanf()"); | ||
74 | tm_t.tm_mon--; | ||
75 | tm_t.tm_year-=1900; | ||
76 | time_t rv = mktime(&tm_t); | ||
77 | if(rv==(time_t)-1) | ||
78 | throw failed_conversion(OPKELE_CP_ "failed to mktime()"); | ||
79 | return rv; | ||
80 | } | ||
81 | |||
82 | /* | ||
83 | * | ||
84 | */ | ||
85 | |||
86 | string canonicalize_url(const string& url) { | ||
87 | string rv = url; | ||
88 | // strip leading and trailing spaces | ||
89 | string::size_type i = rv.find_first_not_of(" \t\r\n"); | ||
90 | if(i==string::npos) | ||
91 | throw bad_input(OPKELE_CP_ "empty URL"); | ||
92 | if(i) | ||
93 | rv.erase(0,i); | ||
94 | i = rv.find_last_not_of(" \t\r\n"); | ||
95 | assert(i!=string::npos); | ||
96 | if(i<(rv.length()-1)) | ||
97 | rv.erase(i+1); | ||
98 | // add missing http:// | ||
99 | i = rv.find("://"); | ||
100 | if(i==string::npos) { // primitive. but do we need more? | ||
101 | rv.insert(0,"http://"); | ||
102 | i = sizeof("http://")-1; | ||
103 | }else{ | ||
104 | i += sizeof("://")-1; | ||
105 | } | ||
106 | if(rv.find('/',i)==string::npos) | ||
107 | rv += '/'; | ||
108 | return rv; | ||
109 | } | ||
110 | |||
111 | string url_encode(const string& str) { | ||
112 | char * t = curl_escape(str.c_str(),str.length()); | ||
113 | if(!t) | ||
114 | throw failed_conversion(OPKELE_CP_ "failed to curl_escape()"); | ||
115 | string rv(t); | ||
116 | curl_free(t); | ||
117 | return rv; | ||
118 | } | ||
119 | |||
120 | string long_to_string(long l) { | ||
121 | char rv[32]; | ||
122 | int r=snprintf(rv,sizeof(rv),"%ld",l); | ||
123 | if(r<0 || r>=sizeof(rv)) | ||
124 | throw failed_conversion(OPKELE_CP_ "failed to snprintf()"); | ||
125 | return rv; | ||
126 | } | ||
127 | |||
128 | long string_to_long(const string& s) { | ||
129 | char *endptr = 0; | ||
130 | long rv = strtol(s.c_str(),&endptr,10); | ||
131 | if((!endptr) || endptr==s.c_str()) | ||
132 | throw failed_conversion(OPKELE_CP_ "failed to strtol()"); | ||
133 | return rv; | ||
134 | } | ||
135 | |||
136 | } | ||
137 | |||
138 | } | ||
diff --git a/libopkele.pc.in b/libopkele.pc.in new file mode 100644 index 0000000..60bca34 --- a/dev/null +++ b/libopkele.pc.in | |||
@@ -0,0 +1,11 @@ | |||
1 | prefix=@prefix@ | ||
2 | exec_prefix=@exec_prefix@ | ||
3 | libdir=@libdir@ | ||
4 | includedir=@includedir@ | ||
5 | |||
6 | Name: libopkele | ||
7 | Description: C++ implementation of OpenID protocol | ||
8 | Version: @VERSION@ | ||
9 | Requires: openssl @KONFORKA_KONFORKA@ | ||
10 | Cflags: -I${includedir} @LIBCURL_CPPFLAGS@ @PCREPP_CFLAGS@ | ||
11 | Libs: -L${libdir} -lopkele @LIBCURL@ @PCREPP_LIBS@ @MIMETIC_LIBS@ | ||