feat: build proect for restproxy

This commit is contained in:
zhangsz committed 2025-03-06 20:02:40 +08:00
1 parent aca2bace68
commit fea044e6fe
3962 files changed
+979480 -222551

No files matched your search

Binary file not shown.
-44
View File
@@ -1,44 +0,0 @@
release = no
cover = no
CC = gcc
CPP = g++
LD = ld
AR = ar
CP = cp
ifeq ($(release), no)
CFLAGS += -Wall -Werror -g -fPIC
else
CFLAGS += -Wall -Werror -O3 -fPIC
endif
LIB_DIR = ./lib
CSRC_DIR = ./src
OBJ_DIR = ./obj
CSRCS = $(wildcard $(CSRC_DIR)/*.c)
COBJS := $(patsubst %.c, $(OBJ_DIR)/%.o, $(notdir $(CSRCS)))
TARGET_LIB = $(OBJ_DIR)/libjson.a
all : chkobjdir $(TARGET_LIB)
chkobjdir:
@if test ! -d $(OBJ_DIR); \
then \
mkdir $(OBJ_DIR);\
fi
$(OBJ_DIR)/%.o : $(CSRC_DIR)/%.c
@echo "COMPILE $<"
@$(CC) -fPIC $(CFLAGS) -c $< -o $@
$(TARGET_LIB) : $(COBJS)
@echo "AR $(TARGET_LIB)"
@$(AR) cr $(TARGET_LIB) $(COBJS)
@$(CP) $(TARGET_LIB) $(LIB_DIR)
.PHONY:clean
clean:
@echo "CLEAN $(TARGET_LIB)"
@rm -rf $(TARGET_LIB) $(OBJ_DIR)
@@ -1,70 +0,0 @@
/*
* $Id: arraylist.h,v 1.4 2006/01/26 02:16:28 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*/
/**
* @file
* @brief Internal methods for working with json_type_array objects.
* Although this is exposed by the json_object_get_array() method,
* it is not recommended for direct use.
*/
#ifndef _arraylist_h_
#define _arraylist_h_
#ifdef __cplusplus
extern "C" {
#endif
#define ARRAY_LIST_DEFAULT_SIZE 32
typedef void (array_list_free_fn) (void *data);
struct array_list
{
void **array;
size_t length;
size_t size;
array_list_free_fn *free_fn;
};
typedef struct array_list array_list;
extern struct array_list*
array_list_new(array_list_free_fn *free_fn);
extern void
array_list_free(struct array_list *al);
extern void*
array_list_get_idx(struct array_list *al, size_t i);
extern int
array_list_put_idx(struct array_list *al, size_t i, void *data);
extern int
array_list_add(struct array_list *al, void *data);
extern size_t
array_list_length(struct array_list *al);
extern void
array_list_sort(struct array_list *arr, int(*compar)(const void *, const void *));
extern void* array_list_bsearch(const void **key,
struct array_list *arr,
int (*sort_fn)(const void *, const void *));
extern int
array_list_del_idx(struct array_list *arr, size_t idx, size_t count);
#ifdef __cplusplus
}
#endif
#endif
@@ -1,42 +0,0 @@
/*
* $Id: json.h,v 1.6 2006/01/26 02:16:28 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
* Copyright (c) 2009 Hewlett-Packard Development Company, L.P.
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*/
/**
* @file
* @brief A convenience header that may be included instead of other individual ones.
*/
#ifndef _json_h_
#define _json_h_
#ifdef __cplusplus
extern "C" {
#endif
/* BEGIN lihua 2018-07-11 PN: 屏蔽此行 */
#if 0
#include "debug.h"
#endif
/* BEGIN lihua 2018-07-11 */
#include "linkhash.h"
#include "arraylist.h"
#include "json_util.h"
#include "json_object.h"
#include "json_pointer.h"
#include "json_tokener.h"
#include "json_object_iterator.h"
#include "json_c_version.h"
#ifdef __cplusplus
}
#endif
#endif
@@ -1,40 +0,0 @@
/*
* Copyright (c) 2012,2017 Eric Haszlakiewicz
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*/
/**
* @file
* @brief Methods for retrieving the json-c version.
*/
#ifndef _json_c_version_h_
#define _json_c_version_h_
#define JSON_C_MAJOR_VERSION 0
#define JSON_C_MINOR_VERSION 13
#define JSON_C_MICRO_VERSION 99
#define JSON_C_VERSION_NUM ((JSON_C_MAJOR_VERSION << 16) | \
(JSON_C_MINOR_VERSION << 8) | \
JSON_C_MICRO_VERSION)
#define JSON_C_VERSION "0.13.99"
/**
* @see JSON_C_VERSION
* @return the version of the json-c library as a string
*/
const char *json_c_version(void); /* Returns JSON_C_VERSION */
/**
* The json-c version encoded into an int, with the low order 8 bits
* being the micro version, the next higher 8 bits being the minor version
* and the next higher 8 bits being the major version.
* For example, 7.12.99 would be 0x00070B63.
*
* @see JSON_C_VERSION_NUM
* @return the version of the json-c library as an int
*/
int json_c_version_num(void); /* Returns JSON_C_VERSION_NUM */
#endif
@@ -1,4 +0,0 @@
/* json_config.h. Generated from json_config.h.in by configure. */
/* Define to 1 if you have the <inttypes.h> header file. */
#define JSON_C_HAVE_INTTYPES_H 1
@@ -1,23 +0,0 @@
/**
* @file
* @brief Do not use, json-c internal, may be changed or removed at any time.
*/
#ifndef _json_inttypes_h_
#define _json_inttypes_h_
#include "json_config.h"
#ifdef JSON_C_HAVE_INTTYPES_H
/* inttypes.h includes stdint.h */
#include <inttypes.h>
#else
#include <stdint.h>
#define PRId64 "I64d"
#define SCNd64 "I64d"
#endif
#endif
File diff suppressed because it is too large. Load diff
@@ -1,240 +0,0 @@
/**
*******************************************************************************
* @file json_object_iterator.h
*
* Copyright (c) 2009-2012 Hewlett-Packard Development Company, L.P.
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
* @brief An API for iterating over json_type_object objects,
* styled to be familiar to C++ programmers.
* Unlike json_object_object_foreach() and
* json_object_object_foreachC(), this avoids the need to expose
* json-c internals like lh_entry.
*
* API attributes: <br>
* * Thread-safe: NO<br>
* * Reentrant: NO
*
*******************************************************************************
*/
#ifndef JSON_OBJECT_ITERATOR_H
#define JSON_OBJECT_ITERATOR_H
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* Forward declaration for the opaque iterator information.
*/
struct json_object_iter_info_;
/**
* The opaque iterator that references a name/value pair within
* a JSON Object instance or the "end" iterator value.
*/
struct json_object_iterator {
const void* opaque_;
};
/**
* forward declaration of json-c's JSON value instance structure
*/
struct json_object;
/**
* Initializes an iterator structure to a "default" value that
* is convenient for initializing an iterator variable to a
* default state (e.g., initialization list in a class'
* constructor).
*
* @code
* struct json_object_iterator iter = json_object_iter_init_default();
* MyClass() : iter_(json_object_iter_init_default())
* @endcode
*
* @note The initialized value doesn't reference any specific
* pair, is considered an invalid iterator, and MUST NOT
* be passed to any json-c API that expects a valid
* iterator.
*
* @note User and internal code MUST NOT make any assumptions
* about and dependencies on the value of the "default"
* iterator value.
*
* @return json_object_iterator
*/
struct json_object_iterator
json_object_iter_init_default(void);
/** Retrieves an iterator to the first pair of the JSON Object.
*
* @warning Any modification of the underlying pair invalidates all
* iterators to that pair.
*
* @param obj JSON Object instance (MUST be of type json_object)
*
* @return json_object_iterator If the JSON Object has at
* least one pair, on return, the iterator refers
* to the first pair. If the JSON Object doesn't
* have any pairs, the returned iterator is
* equivalent to the "end" iterator for the same
* JSON Object instance.
*
* @code
* struct json_object_iterator it;
* struct json_object_iterator itEnd;
* struct json_object* obj;
*
* obj = json_tokener_parse("{'first':'george', 'age':100}");
* it = json_object_iter_begin(obj);
* itEnd = json_object_iter_end(obj);
*
* while (!json_object_iter_equal(&it, &itEnd)) {
* printf("%s\n",
* json_object_iter_peek_name(&it));
* json_object_iter_next(&it);
* }
*
* @endcode
*/
struct json_object_iterator
json_object_iter_begin(struct json_object* obj);
/** Retrieves the iterator that represents the position beyond the
* last pair of the given JSON Object instance.
*
* @warning Do NOT write code that assumes that the "end"
* iterator value is NULL, even if it is so in a
* particular instance of the implementation.
*
* @note The reason we do not (and MUST NOT) provide
* "json_object_iter_is_end(json_object_iterator* iter)"
* type of API is because it would limit the underlying
* representation of name/value containment (or force us
* to add additional, otherwise unnecessary, fields to
* the iterator structure). The "end" iterator and the
* equality test method, on the other hand, permit us to
* cleanly abstract pretty much any reasonable underlying
* representation without burdening the iterator
* structure with unnecessary data.
*
* @note For performance reasons, memorize the "end" iterator prior
* to any loop.
*
* @param obj JSON Object instance (MUST be of type json_object)
*
* @return json_object_iterator On return, the iterator refers
* to the "end" of the Object instance's pairs
* (i.e., NOT the last pair, but "beyond the last
* pair" value)
*/
struct json_object_iterator
json_object_iter_end(const struct json_object* obj);
/** Returns an iterator to the next pair, if any
*
* @warning Any modification of the underlying pair
* invalidates all iterators to that pair.
*
* @param iter [IN/OUT] Pointer to iterator that references a
* name/value pair; MUST be a valid, non-end iterator.
* WARNING: bad things will happen if invalid or "end"
* iterator is passed. Upon return will contain the
* reference to the next pair if there is one; if there
* are no more pairs, will contain the "end" iterator
* value, which may be compared against the return value
* of json_object_iter_end() for the same JSON Object
* instance.
*/
void
json_object_iter_next(struct json_object_iterator* iter);
/** Returns a const pointer to the name of the pair referenced
* by the given iterator.
*
* @param iter pointer to iterator that references a name/value
* pair; MUST be a valid, non-end iterator.
*
* @warning bad things will happen if an invalid or
* "end" iterator is passed.
*
* @return const char* Pointer to the name of the referenced
* name/value pair. The name memory belongs to the
* name/value pair, will be freed when the pair is
* deleted or modified, and MUST NOT be modified or
* freed by the user.
*/
const char*
json_object_iter_peek_name(const struct json_object_iterator* iter);
/** Returns a pointer to the json-c instance representing the
* value of the referenced name/value pair, without altering
* the instance's reference count.
*
* @param iter pointer to iterator that references a name/value
* pair; MUST be a valid, non-end iterator.
*
* @warning bad things will happen if invalid or
* "end" iterator is passed.
*
* @return struct json_object* Pointer to the json-c value
* instance of the referenced name/value pair; the
* value's reference count is not changed by this
* function: if you plan to hold on to this json-c node,
* take a look at json_object_get() and
* json_object_put(). IMPORTANT: json-c API represents
* the JSON Null value as a NULL json_object instance
* pointer.
*/
struct json_object*
json_object_iter_peek_value(const struct json_object_iterator* iter);
/** Tests two iterators for equality. Typically used to test
* for end of iteration by comparing an iterator to the
* corresponding "end" iterator (that was derived from the same
* JSON Object instance).
*
* @note The reason we do not (and MUST NOT) provide
* "json_object_iter_is_end(json_object_iterator* iter)"
* type of API is because it would limit the underlying
* representation of name/value containment (or force us
* to add additional, otherwise unnecessary, fields to
* the iterator structure). The equality test method, on
* the other hand, permits us to cleanly abstract pretty
* much any reasonable underlying representation.
*
* @param iter1 Pointer to first valid, non-NULL iterator
* @param iter2 POinter to second valid, non-NULL iterator
*
* @warning if a NULL iterator pointer or an uninitialized
* or invalid iterator, or iterators derived from
* different JSON Object instances are passed, bad things
* will happen!
*
* @return json_bool non-zero if iterators are equal (i.e., both
* reference the same name/value pair or are both at
* "end"); zero if they are not equal.
*/
json_bool
json_object_iter_equal(const struct json_object_iterator* iter1,
const struct json_object_iterator* iter2);
#ifdef __cplusplus
}
#endif
#endif /* JSON_OBJECT_ITERATOR_H */
@@ -1,120 +0,0 @@
/*
* Copyright (c) 2016 Alexadru Ardelean.
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*/
/**
* @file
* @brief JSON Pointer (RFC 6901) implementation for retrieving
* objects from a json-c object tree.
*/
#ifndef _json_pointer_h_
#define _json_pointer_h_
#include "json_object.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* Retrieves a JSON sub-object from inside another JSON object
* using the JSON pointer notation as defined in RFC 6901
* https://tools.ietf.org/html/rfc6901
*
* The returned JSON sub-object is equivalent to parsing manually the
* 'obj' JSON tree ; i.e. it's not a new object that is created, but rather
* a pointer inside the JSON tree.
*
* Internally, this is equivalent to doing a series of 'json_object_object_get()'
* and 'json_object_array_get_idx()' along the given 'path'.
*
* Note that the 'path' string supports 'printf()' type arguments, so, whatever
* is added after the 'res' param will be treated as an argument for 'path'
* Example: json_pointer_get(obj, "/foo/%d/%s", &res, 0, bar)
* This means, that you need to escape '%' with '%%' (just like in printf())
*
* @param obj the json_object instance/tree from where to retrieve sub-objects
* @param path a (RFC6901) string notation for the sub-object to retrieve
* @param res a pointer where to store a reference to the json_object
* associated with the given path
*
* @return negative if an error (or not found), or 0 if succeeded
*/
int json_pointer_get(struct json_object *obj, const char *path, struct json_object **res);
/**
* This is a variant of 'json_pointer_get()' that supports printf() style arguments.
*
* Example: json_pointer_getf(obj, res, "/foo/%d/%s", 0, bak)
* This also means that you need to escape '%' with '%%' (just like in printf())
*
* Please take into consideration all recommended 'printf()' format security
* aspects when using this function.
*
* @param obj the json_object instance/tree to which to add a sub-object
* @param res a pointer where to store a reference to the json_object
* associated with the given path
* @param path_fmt a printf() style format for the path
*
* @return negative if an error (or not found), or 0 if succeeded
*/
int json_pointer_getf(struct json_object *obj, struct json_object **res, const char *path_fmt, ...);
/**
* Sets JSON object 'value' in the 'obj' tree at the location specified
* by the 'path'. 'path' is JSON pointer notation as defined in RFC 6901
* https://tools.ietf.org/html/rfc6901
*
* Note that 'obj' is a double pointer, mostly for the "" (empty string)
* case, where the entire JSON object would be replaced by 'value'.
* In the case of the "" path, the object at '*obj' will have it's refcount
* decremented with 'json_object_put()' and the 'value' object will be assigned to it.
*
* For other cases (JSON sub-objects) ownership of 'value' will be transferred into
* '*obj' via 'json_object_object_add()' & 'json_object_array_put_idx()', so the
* only time the refcount should be decremented for 'value' is when the return value of
* 'json_pointer_set()' is negative (meaning the 'value' object did not get set into '*obj').
*
* That also implies that 'json_pointer_set()' does not do any refcount incrementing.
* (Just that single decrement that was mentioned above).
*
* Note that the 'path' string supports 'printf()' type arguments, so, whatever
* is added after the 'value' param will be treated as an argument for 'path'
* Example: json_pointer_set(obj, "/foo/%d/%s", value, 0, bak)
* This means, that you need to escape '%' with '%%' (just like in printf())
*
* @param obj the json_object instance/tree to which to add a sub-object
* @param path a (RFC6901) string notation for the sub-object to set in the tree
* @param value object to set at path
*
* @return negative if an error (or not found), or 0 if succeeded
*/
int json_pointer_set(struct json_object **obj, const char *path, struct json_object *value);
/**
* This is a variant of 'json_pointer_set()' that supports printf() style arguments.
*
* Example: json_pointer_setf(obj, value, "/foo/%d/%s", 0, bak)
* This also means that you need to escape '%' with '%%' (just like in printf())
*
* Please take into consideration all recommended 'printf()' format security
* aspects when using this function.
*
* @param obj the json_object instance/tree to which to add a sub-object
* @param value object to set at path
* @param path_fmt a printf() style format for the path
*
* @return negative if an error (or not found), or 0 if succeeded
*/
int json_pointer_setf(struct json_object **obj, struct json_object *value, const char *path_fmt, ...);
#ifdef __cplusplus
}
#endif
#endif
@@ -1,216 +0,0 @@
/*
* $Id: json_tokener.h,v 1.10 2006/07/25 03:24:50 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*/
/**
* @file
* @brief Methods to parse an input string into a tree of json_object objects.
*/
#ifndef _json_tokener_h_
#define _json_tokener_h_
#include <stddef.h>
#include "json_object.h"
#ifdef __cplusplus
extern "C" {
#endif
enum json_tokener_error {
json_tokener_success,
json_tokener_continue,
json_tokener_error_depth,
json_tokener_error_parse_eof,
json_tokener_error_parse_unexpected,
json_tokener_error_parse_null,
json_tokener_error_parse_boolean,
json_tokener_error_parse_number,
json_tokener_error_parse_array,
json_tokener_error_parse_object_key_name,
json_tokener_error_parse_object_key_sep,
json_tokener_error_parse_object_value_sep,
json_tokener_error_parse_string,
json_tokener_error_parse_comment,
json_tokener_error_size
};
enum json_tokener_state {
json_tokener_state_eatws,
json_tokener_state_start,
json_tokener_state_finish,
json_tokener_state_null,
json_tokener_state_comment_start,
json_tokener_state_comment,
json_tokener_state_comment_eol,
json_tokener_state_comment_end,
json_tokener_state_string,
json_tokener_state_string_escape,
json_tokener_state_escape_unicode,
json_tokener_state_boolean,
json_tokener_state_number,
json_tokener_state_array,
json_tokener_state_array_add,
json_tokener_state_array_sep,
json_tokener_state_object_field_start,
json_tokener_state_object_field,
json_tokener_state_object_field_end,
json_tokener_state_object_value,
json_tokener_state_object_value_add,
json_tokener_state_object_sep,
json_tokener_state_array_after_sep,
json_tokener_state_object_field_start_after_sep,
json_tokener_state_inf
};
struct json_tokener_srec
{
enum json_tokener_state state, saved_state;
struct json_object *obj;
struct json_object *current;
char *obj_field_name;
};
#define JSON_TOKENER_DEFAULT_DEPTH 32
struct json_tokener
{
char *str;
struct printbuf *pb;
int max_depth, depth, is_double, st_pos, char_offset;
enum json_tokener_error err;
unsigned int ucs_char;
char quote_char;
struct json_tokener_srec *stack;
int flags;
};
/**
* @deprecated Unused in json-c code
*/
typedef struct json_tokener json_tokener;
/**
* Be strict when parsing JSON input. Use caution with
* this flag as what is considered valid may become more
* restrictive from one release to the next, causing your
* code to fail on previously working input.
*
* This flag is not set by default.
*
* @see json_tokener_set_flags()
*/
#define JSON_TOKENER_STRICT 0x01
/**
* Given an error previously returned by json_tokener_get_error(),
* return a human readable description of the error.
*
* @return a generic error message is returned if an invalid error value is provided.
*/
const char *json_tokener_error_desc(enum json_tokener_error jerr);
/**
* Retrieve the error caused by the last call to json_tokener_parse_ex(),
* or json_tokener_success if there is no error.
*
* When parsing a JSON string in pieces, if the tokener is in the middle
* of parsing this will return json_tokener_continue.
*
* See also json_tokener_error_desc().
*/
JSON_EXPORT enum json_tokener_error json_tokener_get_error(struct json_tokener *tok);
JSON_EXPORT struct json_tokener* json_tokener_new(void);
JSON_EXPORT struct json_tokener* json_tokener_new_ex(int depth);
JSON_EXPORT void json_tokener_free(struct json_tokener *tok);
JSON_EXPORT void json_tokener_reset(struct json_tokener *tok);
JSON_EXPORT struct json_object* json_tokener_parse(const char *str);
JSON_EXPORT struct json_object* json_tokener_parse_verbose(const char *str, enum json_tokener_error *error);
/**
* Set flags that control how parsing will be done.
*/
JSON_EXPORT void json_tokener_set_flags(struct json_tokener *tok, int flags);
/**
* Parse a string and return a non-NULL json_object if a valid JSON value
* is found. The string does not need to be a JSON object or array;
* it can also be a string, number or boolean value.
*
* A partial JSON string can be parsed. If the parsing is incomplete,
* NULL will be returned and json_tokener_get_error() will return
* json_tokener_continue.
* json_tokener_parse_ex() can then be called with additional bytes in str
* to continue the parsing.
*
* If json_tokener_parse_ex() returns NULL and the error is anything other than
* json_tokener_continue, a fatal error has occurred and parsing must be
* halted. Then, the tok object must not be reused until json_tokener_reset() is
* called.
*
* When a valid JSON value is parsed, a non-NULL json_object will be
* returned. Also, json_tokener_get_error() will return json_tokener_success.
* Be sure to check the type with json_object_is_type() or
* json_object_get_type() before using the object.
*
* @b XXX this shouldn't use internal fields:
* Trailing characters after the parsed value do not automatically cause an
* error. It is up to the caller to decide whether to treat this as an
* error or to handle the additional characters, perhaps by parsing another
* json value starting from that point.
*
* Extra characters can be detected by comparing the tok->char_offset against
* the length of the last len parameter passed in.
*
* The tokener does \b not maintain an internal buffer so the caller is
* responsible for calling json_tokener_parse_ex with an appropriate str
* parameter starting with the extra characters.
*
* This interface is presently not 64-bit clean due to the int len argument
* so the function limits the maximum string size to INT32_MAX (2GB).
* If the function is called with len == -1 then strlen is called to check
* the string length is less than INT32_MAX (2GB)
*
* Example:
* @code
json_object *jobj = NULL;
const char *mystring = NULL;
int stringlen = 0;
enum json_tokener_error jerr;
do {
mystring = ... // get JSON string, e.g. read from file, etc...
stringlen = strlen(mystring);
jobj = json_tokener_parse_ex(tok, mystring, stringlen);
} while ((jerr = json_tokener_get_error(tok)) == json_tokener_continue);
if (jerr != json_tokener_success)
{
fprintf(stderr, "Error: %s\n", json_tokener_error_desc(jerr));
// Handle errors, as appropriate for your application.
}
if (tok->char_offset < stringlen) // XXX shouldn't access internal fields
{
// Handle extra characters after parsed object as desired.
// e.g. issue an error, parse another object from that point, etc...
}
// Success, use jobj here.
@endcode
*
* @param tok a json_tokener previously allocated with json_tokener_new()
* @param str an string with any valid JSON expression, or portion of. This does not need to be null terminated.
* @param len the length of str
*/
JSON_EXPORT struct json_object* json_tokener_parse_ex(struct json_tokener *tok,
const char *str, int len);
#ifdef __cplusplus
}
#endif
#endif
@@ -1,106 +0,0 @@
/*
* $Id: json_util.h,v 1.4 2006/01/30 23:07:57 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*/
/**
* @file
* @brief Miscllaneous utility functions and macros.
*/
#ifndef _json_util_h_
#define _json_util_h_
#include "json_object.h"
#ifndef json_min
#define json_min(a,b) ((a) < (b) ? (a) : (b))
#endif
#ifndef json_max
#define json_max(a,b) ((a) > (b) ? (a) : (b))
#endif
#ifdef __cplusplus
extern "C" {
#endif
#define JSON_FILE_BUF_SIZE 4096
/* utility functions */
/**
* Read the full contents of the given file, then convert it to a
* json_object using json_tokener_parse().
*
* Returns -1 if something fails. See json_util_get_last_err() for details.
*/
extern struct json_object* json_object_from_file(const char *filename);
/**
* Create a JSON object from already opened file descriptor.
*
* This function can be helpful, when you opened the file already,
* e.g. when you have a temp file.
* Note, that the fd must be readable at the actual position, i.e.
* use lseek(fd, 0, SEEK_SET) before.
*
* Returns -1 if something fails. See json_util_get_last_err() for details.
*/
extern struct json_object* json_object_from_fd(int fd);
/**
* Equivalent to:
* json_object_to_file_ext(filename, obj, JSON_C_TO_STRING_PLAIN);
*
* Returns -1 if something fails. See json_util_get_last_err() for details.
*/
extern int json_object_to_file(const char *filename, struct json_object *obj);
/**
* Open and truncate the given file, creating it if necessary, then
* convert the json_object to a string and write it to the file.
*
* Returns -1 if something fails. See json_util_get_last_err() for details.
*/
extern int json_object_to_file_ext(const char *filename, struct json_object *obj, int flags);
/**
* Convert the json_object to a string and write it to the file descriptor.
* Handles partial writes and will keep writing until done, or an error
* occurs.
*
* @param fd an open, writable file descriptor to write to
* @param obj the object to serializer and write
* @param flags flags to pass to json_object_to_json_string_ext()
* @return -1 if something fails. See json_util_get_last_err() for details.
*/
extern int json_object_to_fd(int fd, struct json_object *obj, int flags);
/**
* Return the last error from various json-c functions, including:
* json_object_to_file{,_ext}, json_object_to_fd() or
* json_object_from_{file,fd}, or NULL if there is none.
*/
const char *json_util_get_last_err(void);
extern int json_parse_int64(const char *buf, int64_t *retval);
extern int json_parse_double(const char *buf, double *retval);
/**
* Return a string describing the type of the object.
* e.g. "int", or "object", etc...
*/
extern const char *json_type_to_name(enum json_type o_type);
#ifdef __cplusplus
}
#endif
#endif
@@ -1,381 +0,0 @@
/*
* $Id: linkhash.h,v 1.6 2006/01/30 23:07:57 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
* Copyright (c) 2009 Hewlett-Packard Development Company, L.P.
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*/
/**
* @file
* @brief Internal methods for working with json_type_object objects. Although
* this is exposed by the json_object_get_object() function and within the
* json_object_iter type, it is not recommended for direct use.
*/
#ifndef _linkhash_h_
#define _linkhash_h_
#include "json_object.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* golden prime used in hash functions
*/
#define LH_PRIME 0x9e370001UL
/**
* The fraction of filled hash buckets until an insert will cause the table
* to be resized.
* This can range from just above 0 up to 1.0.
*/
#define LH_LOAD_FACTOR 0.66
/**
* sentinel pointer value for empty slots
*/
#define LH_EMPTY (void*)-1
/**
* sentinel pointer value for freed slots
*/
#define LH_FREED (void*)-2
/**
* default string hash function
*/
#define JSON_C_STR_HASH_DFLT 0
/**
* perl-like string hash function
*/
#define JSON_C_STR_HASH_PERLLIKE 1
/**
* This function sets the hash function to be used for strings.
* Must be one of the JSON_C_STR_HASH_* values.
* @returns 0 - ok, -1 if parameter was invalid
*/
int json_global_set_string_hash(const int h);
struct lh_entry;
/**
* callback function prototypes
*/
typedef void (lh_entry_free_fn) (struct lh_entry *e);
/**
* callback function prototypes
*/
typedef unsigned long (lh_hash_fn) (const void *k);
/**
* callback function prototypes
*/
typedef int (lh_equal_fn) (const void *k1, const void *k2);
/**
* An entry in the hash table
*/
struct lh_entry {
/**
* The key. Use lh_entry_k() instead of accessing this directly.
*/
const void *k;
/**
* A flag for users of linkhash to know whether or not they
* need to free k.
*/
int k_is_constant;
/**
* The value. Use lh_entry_v() instead of accessing this directly.
*/
const void *v;
/**
* The next entry
*/
struct lh_entry *next;
/**
* The previous entry.
*/
struct lh_entry *prev;
};
/**
* The hash table structure.
*/
struct lh_table {
/**
* Size of our hash.
*/
int size;
/**
* Numbers of entries.
*/
int count;
/**
* The first entry.
*/
struct lh_entry *head;
/**
* The last entry.
*/
struct lh_entry *tail;
struct lh_entry *table;
/**
* A pointer onto the function responsible for freeing an entry.
*/
lh_entry_free_fn *free_fn;
lh_hash_fn *hash_fn;
lh_equal_fn *equal_fn;
};
typedef struct lh_table lh_table;
/**
* Convenience list iterator.
*/
#define lh_foreach(table, entry) \
for(entry = table->head; entry; entry = entry->next)
/**
* lh_foreach_safe allows calling of deletion routine while iterating.
*
* @param table a struct lh_table * to iterate over
* @param entry a struct lh_entry * variable to hold each element
* @param tmp a struct lh_entry * variable to hold a temporary pointer to the next element
*/
#define lh_foreach_safe(table, entry, tmp) \
for(entry = table->head; entry && ((tmp = entry->next) || 1); entry = tmp)
/**
* Create a new linkhash table.
*
* @param size initial table size. The table is automatically resized
* although this incurs a performance penalty.
* @param free_fn callback function used to free memory for entries
* when lh_table_free or lh_table_delete is called.
* If NULL is provided, then memory for keys and values
* must be freed by the caller.
* @param hash_fn function used to hash keys. 2 standard ones are defined:
* lh_ptr_hash and lh_char_hash for hashing pointer values
* and C strings respectively.
* @param equal_fn comparison function to compare keys. 2 standard ones defined:
* lh_ptr_hash and lh_char_hash for comparing pointer values
* and C strings respectively.
* @return On success, a pointer to the new linkhash table is returned.
* On error, a null pointer is returned.
*/
extern struct lh_table* lh_table_new(int size,
lh_entry_free_fn *free_fn,
lh_hash_fn *hash_fn,
lh_equal_fn *equal_fn);
/**
* Convenience function to create a new linkhash table with char keys.
*
* @param size initial table size.
* @param free_fn callback function used to free memory for entries.
* @return On success, a pointer to the new linkhash table is returned.
* On error, a null pointer is returned.
*/
extern struct lh_table* lh_kchar_table_new(int size,
lh_entry_free_fn *free_fn);
/**
* Convenience function to create a new linkhash table with ptr keys.
*
* @param size initial table size.
* @param free_fn callback function used to free memory for entries.
* @return On success, a pointer to the new linkhash table is returned.
* On error, a null pointer is returned.
*/
extern struct lh_table* lh_kptr_table_new(int size,
lh_entry_free_fn *free_fn);
/**
* Free a linkhash table.
*
* If a lh_entry_free_fn callback free function was provided then it is
* called for all entries in the table.
*
* @param t table to free.
*/
extern void lh_table_free(struct lh_table *t);
/**
* Insert a record into the table.
*
* @param t the table to insert into.
* @param k a pointer to the key to insert.
* @param v a pointer to the value to insert.
*
* @return On success, <code>0</code> is returned.
* On error, a negative value is returned.
*/
extern int lh_table_insert(struct lh_table *t, const void *k, const void *v);
/**
* Insert a record into the table using a precalculated key hash.
*
* The hash h, which should be calculated with lh_get_hash() on k, is provided by
* the caller, to allow for optimization when multiple operations with the same
* key are known to be needed.
*
* @param t the table to insert into.
* @param k a pointer to the key to insert.
* @param v a pointer to the value to insert.
* @param h hash value of the key to insert
* @param opts if set to JSON_C_OBJECT_KEY_IS_CONSTANT, sets lh_entry.k_is_constant
* so t's free function knows to avoid freeing the key.
*/
extern int lh_table_insert_w_hash(struct lh_table *t, const void *k, const void *v, const unsigned long h, const unsigned opts);
/**
* Lookup a record in the table.
*
* @param t the table to lookup
* @param k a pointer to the key to lookup
* @return a pointer to the record structure of the value or NULL if it does not exist.
*/
extern struct lh_entry* lh_table_lookup_entry(struct lh_table *t, const void *k);
/**
* Lookup a record in the table using a precalculated key hash.
*
* The hash h, which should be calculated with lh_get_hash() on k, is provided by
* the caller, to allow for optimization when multiple operations with the same
* key are known to be needed.
*
* @param t the table to lookup
* @param k a pointer to the key to lookup
* @param h hash value of the key to lookup
* @return a pointer to the record structure of the value or NULL if it does not exist.
*/
extern struct lh_entry* lh_table_lookup_entry_w_hash(struct lh_table *t, const void *k, const unsigned long h);
/**
* Lookup a record in the table.
*
* @param t the table to lookup
* @param k a pointer to the key to lookup
* @param v a pointer to a where to store the found value (set to NULL if it doesn't exist).
* @return whether or not the key was found
*/
extern json_bool lh_table_lookup_ex(struct lh_table *t, const void *k, void **v);
/**
* Delete a record from the table.
*
* If a callback free function is provided then it is called for the
* for the item being deleted.
* @param t the table to delete from.
* @param e a pointer to the entry to delete.
* @return 0 if the item was deleted.
* @return -1 if it was not found.
*/
extern int lh_table_delete_entry(struct lh_table *t, struct lh_entry *e);
/**
* Delete a record from the table.
*
* If a callback free function is provided then it is called for the
* for the item being deleted.
* @param t the table to delete from.
* @param k a pointer to the key to delete.
* @return 0 if the item was deleted.
* @return -1 if it was not found.
*/
extern int lh_table_delete(struct lh_table *t, const void *k);
extern int lh_table_length(struct lh_table *t);
/**
* Resizes the specified table.
*
* @param t Pointer to table to resize.
* @param new_size New table size. Must be positive.
*
* @return On success, <code>0</code> is returned.
* On error, a negative value is returned.
*/
int lh_table_resize(struct lh_table *t, int new_size);
/**
* @deprecated Don't use this outside of linkhash.h:
*/
#if !defined(_MSC_VER) || (_MSC_VER > 1800)
/* VS2010 can't handle inline funcs, so skip it there */
#define _LH_INLINE inline
#else
#define _LH_INLINE
#endif
/**
* Calculate the hash of a key for a given table.
*
* This is an exension to support functions that need to calculate
* the hash several times and allows them to do it just once and then pass
* in the hash to all utility functions. Depending on use case, this can be a
* considerable performance improvement.
* @param t the table (used to obtain hash function)
* @param k a pointer to the key to lookup
* @return the key's hash
*/
static _LH_INLINE unsigned long lh_get_hash(const struct lh_table *t, const void *k)
{
return t->hash_fn(k);
}
#undef _LH_INLINE
/**
* @deprecated Don't use this outside of linkhash.h:
*/
#ifdef __UNCONST
#define _LH_UNCONST(a) __UNCONST(a)
#else
#define _LH_UNCONST(a) ((void *)(uintptr_t)(const void *)(a))
#endif
/**
* Return a non-const version of lh_entry.k.
*
* lh_entry.k is const to indicate and help ensure that linkhash itself doesn't modify
* it, but callers are allowed to do what they want with it.
* See also lh_entry.k_is_constant
*/
#define lh_entry_k(entry) _LH_UNCONST((entry)->k)
/**
* Return a non-const version of lh_entry.v.
*
* v is const to indicate and help ensure that linkhash itself doesn't modify
* it, but callers are allowed to do what they want with it.
*/
#define lh_entry_v(entry) _LH_UNCONST((entry)->v)
#ifdef __cplusplus
}
#endif
#endif
@@ -1,122 +0,0 @@
/*
* $Id: printbuf.h,v 1.4 2006/01/26 02:16:28 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*
* Copyright (c) 2008-2009 Yahoo! Inc. All rights reserved.
* The copyrights to the contents of this file are licensed under the MIT License
* (http://www.opensource.org/licenses/mit-license.php)
*/
/**
* @file
* @brief Internal string buffer handing. Unless you're writing a
* json_object_to_json_string_fn implementation for use with
* json_object_set_serializer() direct use of this is not
* recommended.
*/
#ifndef _printbuf_h_
#define _printbuf_h_
#ifdef __cplusplus
extern "C" {
#endif
struct printbuf {
char *buf;
int bpos;
int size;
};
typedef struct printbuf printbuf;
extern struct printbuf*
printbuf_new(void);
/* As an optimization, printbuf_memappend_fast() is defined as a macro
* that handles copying data if the buffer is large enough; otherwise
* it invokes printbuf_memappend() which performs the heavy
* lifting of realloc()ing the buffer and copying data.
*
* Your code should not use printbuf_memappend() directly unless it
* checks the return code. Use printbuf_memappend_fast() instead.
*/
extern int
printbuf_memappend(struct printbuf *p, const char *buf, int size);
#define printbuf_memappend_fast(p, bufptr, bufsize) \
do { \
if ((p->size - p->bpos) > bufsize) { \
memcpy(p->buf + p->bpos, (bufptr), bufsize); \
p->bpos += bufsize; \
p->buf[p->bpos]= '\0'; \
} else { printbuf_memappend(p, (bufptr), bufsize); } \
} while (0)
#define printbuf_length(p) ((p)->bpos)
/**
* Results in a compile error if the argument is not a string literal.
*/
#define _printbuf_check_literal(mystr) ("" mystr)
/**
* This is an optimization wrapper around printbuf_memappend() that is useful
* for appending string literals. Since the size of string constants is known
* at compile time, using this macro can avoid a costly strlen() call. This is
* especially helpful when a constant string must be appended many times. If
* you got here because of a compilation error caused by passing something
* other than a string literal, use printbuf_memappend_fast() in conjunction
* with strlen().
*
* See also:
* printbuf_memappend_fast()
* printbuf_memappend()
* sprintbuf()
*/
#define printbuf_strappend(pb, str) \
printbuf_memappend ((pb), _printbuf_check_literal(str), sizeof(str) - 1)
/**
* Set len bytes of the buffer to charvalue, starting at offset offset.
* Similar to calling memset(x, charvalue, len);
*
* The memory allocated for the buffer is extended as necessary.
*
* If offset is -1, this starts at the end of the current data in the buffer.
*/
extern int
printbuf_memset(struct printbuf *pb, int offset, int charvalue, int len);
/**
* Formatted print to printbuf.
*
* This function is the most expensive of the available functions for appending
* string data to a printbuf and should be used only where convenience is more
* important than speed. Avoid using this function in high performance code or
* tight loops; in these scenarios, consider using snprintf() with a static
* buffer in conjunction with one of the printbuf_*append() functions.
*
* See also:
* printbuf_memappend_fast()
* printbuf_memappend()
* printbuf_strappend()
*/
extern int
sprintbuf(struct printbuf *p, const char *msg, ...);
extern void
printbuf_reset(struct printbuf *p);
extern void
printbuf_free(struct printbuf *p);
#ifdef __cplusplus
}
#endif
#endif
-146
View File
@@ -1,146 +0,0 @@
/*
* $Id: arraylist.c,v 1.4 2006/01/26 02:16:28 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*/
#include "config_json_c.h"
#include <limits.h>
#ifdef STDC_HEADERS
# include <stdlib.h>
# include <string.h>
#endif /* STDC_HEADERS */
#if defined(HAVE_STRINGS_H) && !defined(_STRING_H) && !defined(__USE_BSD)
# include <strings.h>
#endif /* HAVE_STRINGS_H */
#ifndef SIZE_T_MAX
#if SIZEOF_SIZE_T == SIZEOF_INT
#define SIZE_T_MAX UINT_MAX
#elif SIZEOF_SIZE_T == SIZEOF_LONG
#define SIZE_T_MAX ULONG_MAX
#elif SIZEOF_SIZE_T == SIZEOF_LONG_LONG
#define SIZE_T_MAX ULLONG_MAX
#else
#error Unable to determine size of size_t
#endif
#endif
#include "arraylist.h"
struct array_list*
array_list_new(array_list_free_fn *free_fn)
{
struct array_list *arr;
arr = (struct array_list*)calloc(1, sizeof(struct array_list));
if(!arr) return NULL;
arr->size = ARRAY_LIST_DEFAULT_SIZE;
arr->length = 0;
arr->free_fn = free_fn;
if(!(arr->array = (void**)calloc(sizeof(void*), arr->size))) {
free(arr);
return NULL;
}
return arr;
}
extern void
array_list_free(struct array_list *arr)
{
size_t i;
for(i = 0; i < arr->length; i++)
if(arr->array[i]) arr->free_fn(arr->array[i]);
free(arr->array);
free(arr);
}
void*
array_list_get_idx(struct array_list *arr, size_t i)
{
if(i >= arr->length) return NULL;
return arr->array[i];
}
static int array_list_expand_internal(struct array_list *arr, size_t max)
{
void *t;
size_t new_size;
if(max < arr->size) return 0;
/* Avoid undefined behaviour on size_t overflow */
if( arr->size >= SIZE_T_MAX / 2 )
new_size = max;
else
{
new_size = arr->size << 1;
if (new_size < max)
new_size = max;
}
if (new_size > (~((size_t)0)) / sizeof(void*)) return -1;
if (!(t = realloc(arr->array, new_size*sizeof(void*)))) return -1;
arr->array = (void**)t;
(void)memset(arr->array + arr->size, 0, (new_size-arr->size)*sizeof(void*));
arr->size = new_size;
return 0;
}
int
array_list_put_idx(struct array_list *arr, size_t idx, void *data)
{
if (idx > SIZE_T_MAX - 1 ) return -1;
if(array_list_expand_internal(arr, idx+1)) return -1;
if(idx < arr->length && arr->array[idx])
arr->free_fn(arr->array[idx]);
arr->array[idx] = data;
if(arr->length <= idx) arr->length = idx + 1;
return 0;
}
int
array_list_add(struct array_list *arr, void *data)
{
return array_list_put_idx(arr, arr->length, data);
}
void
array_list_sort(struct array_list *arr, int(*sort_fn)(const void *, const void *))
{
qsort(arr->array, arr->length, sizeof(arr->array[0]), sort_fn);
}
void* array_list_bsearch(const void **key, struct array_list *arr,
int (*sort_fn)(const void *, const void *))
{
return bsearch(key, arr->array, arr->length, sizeof(arr->array[0]),
sort_fn);
}
size_t
array_list_length(struct array_list *arr)
{
return arr->length;
}
int
array_list_del_idx( struct array_list *arr, size_t idx, size_t count )
{
size_t i, stop;
stop = idx + count;
if ( idx >= arr->length || stop > arr->length ) return -1;
for ( i = idx; i < stop; ++i ) {
if ( arr->array[i] ) arr->free_fn( arr->array[i] );
}
memmove( arr->array + idx, arr->array + stop, (arr->length - stop) * sizeof(void*) );
arr->length -= count;
return 0;
}
-70
View File
@@ -1,70 +0,0 @@
/*
* $Id: arraylist.h,v 1.4 2006/01/26 02:16:28 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*/
/**
* @file
* @brief Internal methods for working with json_type_array objects.
* Although this is exposed by the json_object_get_array() method,
* it is not recommended for direct use.
*/
#ifndef _arraylist_h_
#define _arraylist_h_
#ifdef __cplusplus
extern "C" {
#endif
#define ARRAY_LIST_DEFAULT_SIZE 32
typedef void (array_list_free_fn) (void *data);
struct array_list
{
void **array;
size_t length;
size_t size;
array_list_free_fn *free_fn;
};
typedef struct array_list array_list;
extern struct array_list*
array_list_new(array_list_free_fn *free_fn);
extern void
array_list_free(struct array_list *al);
extern void*
array_list_get_idx(struct array_list *al, size_t i);
extern int
array_list_put_idx(struct array_list *al, size_t i, void *data);
extern int
array_list_add(struct array_list *al, void *data);
extern size_t
array_list_length(struct array_list *al);
extern void
array_list_sort(struct array_list *arr, int(*compar)(const void *, const void *));
extern void* array_list_bsearch(const void **key,
struct array_list *arr,
int (*sort_fn)(const void *, const void *));
extern int
array_list_del_idx(struct array_list *arr, size_t idx, size_t count);
#ifdef __cplusplus
}
#endif
#endif
@@ -1,200 +0,0 @@
/* config.h. Generated from config.h.in by configure. */
/* config.h.in. Generated from configure.ac by autoheader. */
/* Enable RDRAND Hardware RNG Hash Seed */
/* #undef ENABLE_RDRAND */
/* Enable partial threading support */
/* #undef ENABLE_THREADING */
/* Define if .gnu.warning accepts long strings. */
/* #undef HAS_GNU_WARNING_LONG */
/* Has atomic builtins */
#define HAVE_ATOMIC_BUILTINS 1
/* Define to 1 if you have the declaration of `INFINITY', and to 0 if you
don't. */
#define HAVE_DECL_INFINITY 1
/* Define to 1 if you have the declaration of `isinf', and to 0 if you don't.
*/
#define HAVE_DECL_ISINF 1
/* Define to 1 if you have the declaration of `isnan', and to 0 if you don't.
*/
#define HAVE_DECL_ISNAN 1
/* Define to 1 if you have the declaration of `nan', and to 0 if you don't. */
#define HAVE_DECL_NAN 1
/* Define to 1 if you have the declaration of `_finite', and to 0 if you
don't. */
#define HAVE_DECL__FINITE 0
/* Define to 1 if you have the declaration of `_isnan', and to 0 if you don't.
*/
#define HAVE_DECL__ISNAN 0
/* Define to 1 if you have the <dlfcn.h> header file. */
#define HAVE_DLFCN_H 1
/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
/* #undef HAVE_DOPRNT */
/* Define to 1 if you have the <endian.h> header file. */
#define HAVE_ENDIAN_H 1
/* Define to 1 if you have the <fcntl.h> header file. */
#define HAVE_FCNTL_H 1
/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1
/* Define to 1 if you have the <limits.h> header file. */
#define HAVE_LIMITS_H 1
/* Define to 1 if you have the <locale.h> header file. */
#define HAVE_LOCALE_H 1
/* Define to 1 if you have the <memory.h> header file. */
#define HAVE_MEMORY_H 1
/* Define to 1 if you have the `open' function. */
#define HAVE_OPEN 1
/* Define to 1 if you have the `realloc' function. */
#define HAVE_REALLOC 1
/* Define to 1 if you have the `setlocale' function. */
#define HAVE_SETLOCALE 1
/* Define to 1 if you have the `snprintf' function. */
#define HAVE_SNPRINTF 1
/* Define to 1 if you have the <stdarg.h> header file. */
#define HAVE_STDARG_H 1
/* Define to 1 if you have the <stdint.h> header file. */
#define HAVE_STDINT_H 1
/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1
/* Define to 1 if you have the `strcasecmp' function. */
#define HAVE_STRCASECMP 1
/* Define to 1 if you have the `strdup' function. */
#define HAVE_STRDUP 1
/* Define to 1 if you have the `strerror' function. */
#define HAVE_STRERROR 1
/* Define to 1 if you have the <strings.h> header file. */
#define HAVE_STRINGS_H 1
/* Define to 1 if you have the <string.h> header file. */
#define HAVE_STRING_H 1
/* Define to 1 if you have the `strncasecmp' function. */
#define HAVE_STRNCASECMP 1
/* Define to 1 if you have the <syslog.h> header file. */
#define HAVE_SYSLOG_H 1
/* Define to 1 if you have the <sys/cdefs.h> header file. */
#define HAVE_SYS_CDEFS_H 1
/* Define to 1 if you have the <sys/param.h> header file. */
#define HAVE_SYS_PARAM_H 1
/* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1
/* Define to 1 if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1
/* Define to 1 if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 1
/* Define to 1 if you have the `uselocale' function. */
#define HAVE_USELOCALE 1
/* Define to 1 if you have the `vasprintf' function. */
//#define HAVE_VASPRINTF 1
/* Define to 1 if you have the `vprintf' function. */
#define HAVE_VPRINTF 1
/* Define to 1 if you have the `vsnprintf' function. */
#define HAVE_VSNPRINTF 1
/* Define to 1 if you have the `vsyslog' function. */
#define HAVE_VSYSLOG 1
/* Define to 1 if you have the <xlocale.h> header file. */
#define HAVE_XLOCALE_H 1
/* Have __thread */
#define HAVE___THREAD 1
/* Public define for json_inttypes.h */
#define JSON_C_HAVE_INTTYPES_H 1
/* Define to the sub-directory in which libtool stores uninstalled libraries.
*/
#define LT_OBJDIR ".libs/"
/* Define to 1 if your C compiler doesn't accept -c and -o together. */
/* #undef NO_MINUS_C_MINUS_O */
/* Name of package */
#define PACKAGE "json-c"
/* Define to the address where bug reports for this package should be sent. */
#define PACKAGE_BUGREPORT "json-c@googlegroups.com"
/* Define to the full name of this package. */
#define PACKAGE_NAME "json-c"
/* Define to the full name and version of this package. */
#define PACKAGE_STRING "json-c 0.13.99"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "json-c"
/* Define to the home page for this package. */
#define PACKAGE_URL ""
/* Define to the version of this package. */
#define PACKAGE_VERSION "0.13.99"
/* The number of bytes in type int */
#define SIZEOF_INT 4
/* The number of bytes in type int64_t */
#define SIZEOF_INT64_T 8
/* The number of bytes in type long */
#define SIZEOF_LONG 8
/* The number of bytes in type long long */
#define SIZEOF_LONG_LONG 8
/* The number of bytes in type size_t */
#define SIZEOF_SIZE_T 8
/* Specifier for __thread */
#define SPEC___THREAD __thread
/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* Version number of package */
#define VERSION "0.13.99"
/* Define to empty if `const' does not conform to ANSI C. */
/* #undef const */
/* Define to `unsigned int' if <sys/types.h> does not define. */
/* #undef size_t */
-83
View File
@@ -1,83 +0,0 @@
/*
* $Id: debug.c,v 1.5 2006/01/26 02:16:28 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*/
#include "config_json_c.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#if HAVE_SYSLOG_H
# include <syslog.h>
#endif /* HAVE_SYSLOG_H */
#if HAVE_UNISTD_H
# include <unistd.h>
#endif /* HAVE_UNISTD_H */
#if HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif /* HAVE_SYS_PARAM_H */
#include "debug.h"
static int _syslog = 0;
static int _debug = 0;
void mc_set_debug(int debug) { _debug = debug; }
int mc_get_debug(void) { return _debug; }
extern void mc_set_syslog(int syslog)
{
_syslog = syslog;
}
void mc_debug(const char *msg, ...)
{
va_list ap;
if(_debug) {
va_start(ap, msg);
#if HAVE_VSYSLOG
if(_syslog) {
vsyslog(LOG_DEBUG, msg, ap);
} else
#endif
vprintf(msg, ap);
va_end(ap);
}
}
void mc_error(const char *msg, ...)
{
va_list ap;
va_start(ap, msg);
#if HAVE_VSYSLOG
if(_syslog) {
vsyslog(LOG_ERR, msg, ap);
} else
#endif
vfprintf(stderr, msg, ap);
va_end(ap);
}
void mc_info(const char *msg, ...)
{
va_list ap;
va_start(ap, msg);
#if HAVE_VSYSLOG
if(_syslog) {
vsyslog(LOG_INFO, msg, ap);
} else
#endif
vfprintf(stderr, msg, ap);
va_end(ap);
}
-75
View File
@@ -1,75 +0,0 @@
/*
* $Id: debug.h,v 1.5 2006/01/30 23:07:57 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
* Copyright (c) 2009 Hewlett-Packard Development Company, L.P.
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*/
/**
* @file
* @brief Do not use, json-c internal, may be changed or removed at any time.
*/
#ifndef _DEBUG_H_
#define _DEBUG_H_
#include <stdlib.h>
#ifdef __cplusplus
extern "C" {
#endif
extern void mc_set_debug(int debug);
extern int mc_get_debug(void);
extern void mc_set_syslog(int syslog);
extern void mc_debug(const char *msg, ...);
extern void mc_error(const char *msg, ...);
extern void mc_info(const char *msg, ...);
#ifndef __STRING
#define __STRING(x) #x
#endif
#ifndef PARSER_BROKEN_FIXED
#define JASSERT(cond) do {} while(0)
#else
#define JASSERT(cond) do { \
if (!(cond)) { \
mc_error("cjson assert failure %s:%d : cond \"" __STRING(cond) "failed\n", __FILE__, __LINE__); \
*(int *)0 = 1;\
abort(); \
}\
} while(0)
#endif
#define MC_ERROR(x, ...) mc_error(x, ##__VA_ARGS__)
#ifdef MC_MAINTAINER_MODE
#define MC_SET_DEBUG(x) mc_set_debug(x)
#define MC_GET_DEBUG() mc_get_debug()
#define MC_SET_SYSLOG(x) mc_set_syslog(x)
#define MC_DEBUG(x, ...) mc_debug(x, ##__VA_ARGS__)
#define MC_INFO(x, ...) mc_info(x, ##__VA_ARGS__)
#else
#define MC_SET_DEBUG(x) if (0) mc_set_debug(x)
#define MC_GET_DEBUG() (0)
#define MC_SET_SYSLOG(x) if (0) mc_set_syslog(x)
#define MC_DEBUG(x, ...) if (0) mc_debug(x, ##__VA_ARGS__)
#define MC_INFO(x, ...) if (0) mc_info(x, ##__VA_ARGS__)
#endif
#ifdef __cplusplus
}
#endif
#endif
-38
View File
@@ -1,38 +0,0 @@
/*
* $Id: json.h,v 1.6 2006/01/26 02:16:28 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
* Copyright (c) 2009 Hewlett-Packard Development Company, L.P.
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*/
/**
* @file
* @brief A convenience header that may be included instead of other individual ones.
*/
#ifndef _json_h_
#define _json_h_
#ifdef __cplusplus
extern "C" {
#endif
#include "debug.h"
#include "linkhash.h"
#include "arraylist.h"
#include "json_util.h"
#include "json_object.h"
#include "json_pointer.h"
#include "json_tokener.h"
#include "json_object_iterator.h"
#include "json_c_version.h"
#ifdef __cplusplus
}
#endif
#endif
@@ -1,20 +0,0 @@
/*
* Copyright (c) 2012 Eric Haszlakiewicz
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*/
#include "config_json_c.h"
#include "json_c_version.h"
const char *json_c_version(void)
{
return JSON_C_VERSION;
}
int json_c_version_num(void)
{
return JSON_C_VERSION_NUM;
}
@@ -1,40 +0,0 @@
/*
* Copyright (c) 2012,2017 Eric Haszlakiewicz
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*/
/**
* @file
* @brief Methods for retrieving the json-c version.
*/
#ifndef _json_c_version_h_
#define _json_c_version_h_
#define JSON_C_MAJOR_VERSION 0
#define JSON_C_MINOR_VERSION 13
#define JSON_C_MICRO_VERSION 99
#define JSON_C_VERSION_NUM ((JSON_C_MAJOR_VERSION << 16) | \
(JSON_C_MINOR_VERSION << 8) | \
JSON_C_MICRO_VERSION)
#define JSON_C_VERSION "0.13.99"
/**
* @see JSON_C_VERSION
* @return the version of the json-c library as a string
*/
const char *json_c_version(void); /* Returns JSON_C_VERSION */
/**
* The json-c version encoded into an int, with the low order 8 bits
* being the micro version, the next higher 8 bits being the minor version
* and the next higher 8 bits being the major version.
* For example, 7.12.99 would be 0x00070B63.
*
* @see JSON_C_VERSION_NUM
* @return the version of the json-c library as an int
*/
int json_c_version_num(void); /* Returns JSON_C_VERSION_NUM */
#endif
@@ -1,4 +0,0 @@
/* json_config.h. Generated from json_config.h.in by configure. */
/* Define to 1 if you have the <inttypes.h> header file. */
#define JSON_C_HAVE_INTTYPES_H 1
@@ -1,23 +0,0 @@
/**
* @file
* @brief Do not use, json-c internal, may be changed or removed at any time.
*/
#ifndef _json_inttypes_h_
#define _json_inttypes_h_
#include "json_config.h"
#ifdef JSON_C_HAVE_INTTYPES_H
/* inttypes.h includes stdint.h */
#include <inttypes.h>
#else
#include <stdint.h>
#define PRId64 "I64d"
#define SCNd64 "I64d"
#endif
#endif
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
@@ -1,163 +0,0 @@
/**
*******************************************************************************
* @file json_object_iterator.c
*
* Copyright (c) 2009-2012 Hewlett-Packard Development Company, L.P.
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*******************************************************************************
*/
#include <stddef.h>
#include "json.h"
#include "json_object_private.h"
#include "json_object_iterator.h"
/**
* How It Works
*
* For each JSON Object, json-c maintains a linked list of zero
* or more lh_entry (link-hash entry) structures inside the
* Object's link-hash table (lh_table).
*
* Each lh_entry structure on the JSON Object's linked list
* represents a single name/value pair. The "next" field of the
* last lh_entry in the list is set to NULL, which terminates
* the list.
*
* We represent a valid iterator that refers to an actual
* name/value pair via a pointer to the pair's lh_entry
* structure set as the iterator's opaque_ field.
*
* We follow json-c's current pair list representation by
* representing a valid "end" iterator (one that refers past the
* last pair) with a NULL value in the iterator's opaque_ field.
*
* A JSON Object without any pairs in it will have the "head"
* field of its lh_table structure set to NULL. For such an
* object, json_object_iter_begin will return an iterator with
* the opaque_ field set to NULL, which is equivalent to the
* "end" iterator.
*
* When iterating, we simply update the iterator's opaque_ field
* to point to the next lh_entry structure in the linked list.
* opaque_ will become NULL once we iterate past the last pair
* in the list, which makes the iterator equivalent to the "end"
* iterator.
*/
/// Our current representation of the "end" iterator;
///
/// @note May not always be NULL
static const void* kObjectEndIterValue = NULL;
/**
* ****************************************************************************
*/
struct json_object_iterator
json_object_iter_begin(struct json_object* obj)
{
struct json_object_iterator iter;
struct lh_table* pTable;
/// @note json_object_get_object will return NULL if passed NULL
/// or a non-json_type_object instance
pTable = json_object_get_object(obj);
JASSERT(NULL != pTable);
/// @note For a pair-less Object, head is NULL, which matches our
/// definition of the "end" iterator
iter.opaque_ = pTable->head;
return iter;
}
/**
* ****************************************************************************
*/
struct json_object_iterator
json_object_iter_end(const struct json_object* obj)
{
struct json_object_iterator iter;
JASSERT(NULL != obj);
JASSERT(json_object_is_type(obj, json_type_object));
iter.opaque_ = kObjectEndIterValue;
return iter;
}
/**
* ****************************************************************************
*/
void
json_object_iter_next(struct json_object_iterator* iter)
{
JASSERT(NULL != iter);
JASSERT(kObjectEndIterValue != iter->opaque_);
iter->opaque_ = ((const struct lh_entry *)iter->opaque_)->next;
}
/**
* ****************************************************************************
*/
const char*
json_object_iter_peek_name(const struct json_object_iterator* iter)
{
JASSERT(NULL != iter);
JASSERT(kObjectEndIterValue != iter->opaque_);
return (const char*)(((const struct lh_entry *)iter->opaque_)->k);
}
/**
* ****************************************************************************
*/
struct json_object*
json_object_iter_peek_value(const struct json_object_iterator* iter)
{
JASSERT(NULL != iter);
JASSERT(kObjectEndIterValue != iter->opaque_);
return (struct json_object*)lh_entry_v((const struct lh_entry *)iter->opaque_);
}
/**
* ****************************************************************************
*/
json_bool
json_object_iter_equal(const struct json_object_iterator* iter1,
const struct json_object_iterator* iter2)
{
JASSERT(NULL != iter1);
JASSERT(NULL != iter2);
return (iter1->opaque_ == iter2->opaque_);
}
/**
* ****************************************************************************
*/
struct json_object_iterator
json_object_iter_init_default(void)
{
struct json_object_iterator iter;
/**
* @note Make this a negative, invalid value, such that
* accidental access to it would likely be trapped by the
* hardware as an invalid address.
*/
iter.opaque_ = NULL;
return iter;
}
@@ -1,240 +0,0 @@
/**
*******************************************************************************
* @file json_object_iterator.h
*
* Copyright (c) 2009-2012 Hewlett-Packard Development Company, L.P.
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
* @brief An API for iterating over json_type_object objects,
* styled to be familiar to C++ programmers.
* Unlike json_object_object_foreach() and
* json_object_object_foreachC(), this avoids the need to expose
* json-c internals like lh_entry.
*
* API attributes: <br>
* * Thread-safe: NO<br>
* * Reentrant: NO
*
*******************************************************************************
*/
#ifndef JSON_OBJECT_ITERATOR_H
#define JSON_OBJECT_ITERATOR_H
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* Forward declaration for the opaque iterator information.
*/
struct json_object_iter_info_;
/**
* The opaque iterator that references a name/value pair within
* a JSON Object instance or the "end" iterator value.
*/
struct json_object_iterator {
const void* opaque_;
};
/**
* forward declaration of json-c's JSON value instance structure
*/
struct json_object;
/**
* Initializes an iterator structure to a "default" value that
* is convenient for initializing an iterator variable to a
* default state (e.g., initialization list in a class'
* constructor).
*
* @code
* struct json_object_iterator iter = json_object_iter_init_default();
* MyClass() : iter_(json_object_iter_init_default())
* @endcode
*
* @note The initialized value doesn't reference any specific
* pair, is considered an invalid iterator, and MUST NOT
* be passed to any json-c API that expects a valid
* iterator.
*
* @note User and internal code MUST NOT make any assumptions
* about and dependencies on the value of the "default"
* iterator value.
*
* @return json_object_iterator
*/
struct json_object_iterator
json_object_iter_init_default(void);
/** Retrieves an iterator to the first pair of the JSON Object.
*
* @warning Any modification of the underlying pair invalidates all
* iterators to that pair.
*
* @param obj JSON Object instance (MUST be of type json_object)
*
* @return json_object_iterator If the JSON Object has at
* least one pair, on return, the iterator refers
* to the first pair. If the JSON Object doesn't
* have any pairs, the returned iterator is
* equivalent to the "end" iterator for the same
* JSON Object instance.
*
* @code
* struct json_object_iterator it;
* struct json_object_iterator itEnd;
* struct json_object* obj;
*
* obj = json_tokener_parse("{'first':'george', 'age':100}");
* it = json_object_iter_begin(obj);
* itEnd = json_object_iter_end(obj);
*
* while (!json_object_iter_equal(&it, &itEnd)) {
* printf("%s\n",
* json_object_iter_peek_name(&it));
* json_object_iter_next(&it);
* }
*
* @endcode
*/
struct json_object_iterator
json_object_iter_begin(struct json_object* obj);
/** Retrieves the iterator that represents the position beyond the
* last pair of the given JSON Object instance.
*
* @warning Do NOT write code that assumes that the "end"
* iterator value is NULL, even if it is so in a
* particular instance of the implementation.
*
* @note The reason we do not (and MUST NOT) provide
* "json_object_iter_is_end(json_object_iterator* iter)"
* type of API is because it would limit the underlying
* representation of name/value containment (or force us
* to add additional, otherwise unnecessary, fields to
* the iterator structure). The "end" iterator and the
* equality test method, on the other hand, permit us to
* cleanly abstract pretty much any reasonable underlying
* representation without burdening the iterator
* structure with unnecessary data.
*
* @note For performance reasons, memorize the "end" iterator prior
* to any loop.
*
* @param obj JSON Object instance (MUST be of type json_object)
*
* @return json_object_iterator On return, the iterator refers
* to the "end" of the Object instance's pairs
* (i.e., NOT the last pair, but "beyond the last
* pair" value)
*/
struct json_object_iterator
json_object_iter_end(const struct json_object* obj);
/** Returns an iterator to the next pair, if any
*
* @warning Any modification of the underlying pair
* invalidates all iterators to that pair.
*
* @param iter [IN/OUT] Pointer to iterator that references a
* name/value pair; MUST be a valid, non-end iterator.
* WARNING: bad things will happen if invalid or "end"
* iterator is passed. Upon return will contain the
* reference to the next pair if there is one; if there
* are no more pairs, will contain the "end" iterator
* value, which may be compared against the return value
* of json_object_iter_end() for the same JSON Object
* instance.
*/
void
json_object_iter_next(struct json_object_iterator* iter);
/** Returns a const pointer to the name of the pair referenced
* by the given iterator.
*
* @param iter pointer to iterator that references a name/value
* pair; MUST be a valid, non-end iterator.
*
* @warning bad things will happen if an invalid or
* "end" iterator is passed.
*
* @return const char* Pointer to the name of the referenced
* name/value pair. The name memory belongs to the
* name/value pair, will be freed when the pair is
* deleted or modified, and MUST NOT be modified or
* freed by the user.
*/
const char*
json_object_iter_peek_name(const struct json_object_iterator* iter);
/** Returns a pointer to the json-c instance representing the
* value of the referenced name/value pair, without altering
* the instance's reference count.
*
* @param iter pointer to iterator that references a name/value
* pair; MUST be a valid, non-end iterator.
*
* @warning bad things will happen if invalid or
* "end" iterator is passed.
*
* @return struct json_object* Pointer to the json-c value
* instance of the referenced name/value pair; the
* value's reference count is not changed by this
* function: if you plan to hold on to this json-c node,
* take a look at json_object_get() and
* json_object_put(). IMPORTANT: json-c API represents
* the JSON Null value as a NULL json_object instance
* pointer.
*/
struct json_object*
json_object_iter_peek_value(const struct json_object_iterator* iter);
/** Tests two iterators for equality. Typically used to test
* for end of iteration by comparing an iterator to the
* corresponding "end" iterator (that was derived from the same
* JSON Object instance).
*
* @note The reason we do not (and MUST NOT) provide
* "json_object_iter_is_end(json_object_iterator* iter)"
* type of API is because it would limit the underlying
* representation of name/value containment (or force us
* to add additional, otherwise unnecessary, fields to
* the iterator structure). The equality test method, on
* the other hand, permits us to cleanly abstract pretty
* much any reasonable underlying representation.
*
* @param iter1 Pointer to first valid, non-NULL iterator
* @param iter2 POinter to second valid, non-NULL iterator
*
* @warning if a NULL iterator pointer or an uninitialized
* or invalid iterator, or iterators derived from
* different JSON Object instances are passed, bad things
* will happen!
*
* @return json_bool non-zero if iterators are equal (i.e., both
* reference the same name/value pair or are both at
* "end"); zero if they are not equal.
*/
json_bool
json_object_iter_equal(const struct json_object_iterator* iter1,
const struct json_object_iterator* iter2);
#ifdef __cplusplus
}
#endif
#endif /* JSON_OBJECT_ITERATOR_H */
@@ -1,64 +0,0 @@
/*
* $Id: json_object_private.h,v 1.4 2006/01/26 02:16:28 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*/
/**
* @file
* @brief Do not use, json-c internal, may be changed or removed at any time.
*/
#ifndef _json_object_private_h_
#define _json_object_private_h_
#ifdef __cplusplus
extern "C" {
#endif
#define LEN_DIRECT_STRING_DATA 32 /**< how many bytes are directly stored in json_object for strings? */
typedef void (json_object_private_delete_fn)(struct json_object *o);
struct json_object
{
enum json_type o_type;
json_object_private_delete_fn *_delete;
json_object_to_json_string_fn *_to_json_string;
uint_fast32_t _ref_count;
struct printbuf *_pb;
union data {
json_bool c_boolean;
double c_double;
int64_t c_int64;
struct lh_table *c_object;
struct array_list *c_array;
struct {
union {
/* optimize: if we have small strings, we can store them
* directly. This saves considerable CPU cycles AND memory.
*/
char *ptr;
char data[LEN_DIRECT_STRING_DATA];
} str;
int len;
} c_string;
} o;
json_object_delete_fn *_user_delete;
void *_userdata;
};
void _json_c_set_last_err(const char *err_fmt, ...);
extern const char *json_number_chars;
extern const char *json_hex_chars;
#ifdef __cplusplus
}
#endif
#endif
-327
View File
@@ -1,327 +0,0 @@
/*
* Copyright (c) 2016 Alexandru Ardelean.
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*/
#include "config_json_c.h"
#include "strerror_override.h"
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "json_pointer.h"
#include "strdup_compat.h"
#include "vasprintf_compat.h"
/**
* JavaScript Object Notation (JSON) Pointer
* RFC 6901 - https://tools.ietf.org/html/rfc6901
*/
static void string_replace_all_occurrences_with_char(char *s, const char *occur, char repl_char)
{
int slen = strlen(s);
int skip = strlen(occur) - 1; /* length of the occurence, minus the char we're replacing */
char *p = s;
while ((p = strstr(p, occur))) {
*p = repl_char;
p++;
slen -= skip;
memmove(p, (p + skip), slen - (p - s) + 1); /* includes null char too */
}
}
static int is_valid_index(struct json_object *jo, const char *path, int32_t *idx)
{
int i, len = strlen(path);
/* this code-path optimizes a bit, for when we reference the 0-9 index range in a JSON array
and because leading zeros not allowed */
if (len == 1) {
if (isdigit((int)path[0])) {
*idx = (path[0] - '0');
goto check_oob;
}
errno = EINVAL;
return 0;
}
/* leading zeros not allowed per RFC */
if (path[0] == '0') {
errno = EINVAL;
return 0;
}
/* RFC states base-10 decimals */
for (i = 0; i < len; i++) {
if (!isdigit((int)path[i])) {
errno = EINVAL;
return 0;
}
}
*idx = strtol(path, NULL, 10);
if (*idx < 0) {
errno = EINVAL;
return 0;
}
check_oob:
len = json_object_array_length(jo);
if (*idx >= len) {
errno = ENOENT;
return 0;
}
return 1;
}
static int json_pointer_get_single_path(struct json_object *obj, char *path, struct json_object **value)
{
if (json_object_is_type(obj, json_type_array)) {
int32_t idx;
if (!is_valid_index(obj, path, &idx))
return -1;
obj = json_object_array_get_idx(obj, idx);
if (obj) {
if (value)
*value = obj;
return 0;
}
/* Entry not found */
errno = ENOENT;
return -1;
}
/* RFC states that we first must eval all ~1 then all ~0 */
string_replace_all_occurrences_with_char(path, "~1", '/');
string_replace_all_occurrences_with_char(path, "~0", '~');
if (!json_object_object_get_ex(obj, path, value)) {
errno = ENOENT;
return -1;
}
return 0;
}
static int json_pointer_set_single_path(
struct json_object *parent,
const char *path,
struct json_object *value)
{
if (json_object_is_type(parent, json_type_array)) {
int32_t idx;
/* RFC (Chapter 4) states that '-' may be used to add new elements to an array */
if (path[0] == '-' && path[1] == '\0')
return json_object_array_add(parent, value);
if (!is_valid_index(parent, path, &idx))
return -1;
return json_object_array_put_idx(parent, idx, value);
}
/* path replacements should have been done in json_pointer_get_single_path(),
and we should still be good here */
if (json_object_is_type(parent, json_type_object))
return json_object_object_add(parent, path, value);
/* Getting here means that we tried to "dereference" a primitive JSON type (like string, int, bool).
i.e. add a sub-object to it */
errno = ENOENT;
return -1;
}
static int json_pointer_get_recursive(
struct json_object *obj,
char *path,
struct json_object **value)
{
char *endp;
int rc;
/* All paths (on each recursion level must have a leading '/' */
if (path[0] != '/') {
errno = EINVAL;
return -1;
}
path++;
endp = strchr(path, '/');
if (endp)
*endp = '\0';
/* If we err-ed here, return here */
if ((rc = json_pointer_get_single_path(obj, path, &obj)))
return rc;
if (endp) {
*endp = '/'; /* Put the slash back, so that the sanity check passes on next recursion level */
return json_pointer_get_recursive(obj, endp, value);
}
/* We should be at the end of the recursion here */
if (value)
*value = obj;
return 0;
}
int json_pointer_get(struct json_object *obj, const char *path, struct json_object **res)
{
char *path_copy = NULL;
int rc;
if (!obj || !path) {
errno = EINVAL;
return -1;
}
if (path[0] == '\0') {
if (res)
*res = obj;
return 0;
}
/* pass a working copy to the recursive call */
if (!(path_copy = strdup(path))) {
errno = ENOMEM;
return -1;
}
rc = json_pointer_get_recursive(obj, path_copy, res);
free(path_copy);
return rc;
}
int json_pointer_getf(struct json_object *obj, struct json_object **res, const char *path_fmt, ...)
{
char *path_copy = NULL;
int rc = 0;
va_list args;
if (!obj || !path_fmt) {
errno = EINVAL;
return -1;
}
va_start(args, path_fmt);
rc = vasprintf(&path_copy, path_fmt, args);
va_end(args);
if (rc < 0)
return rc;
if (path_copy[0] == '\0') {
if (res)
*res = obj;
goto out;
}
rc = json_pointer_get_recursive(obj, path_copy, res);
out:
free(path_copy);
return rc;
}
int json_pointer_set(struct json_object **obj, const char *path, struct json_object *value)
{
const char *endp;
char *path_copy = NULL;
struct json_object *set = NULL;
int rc;
if (!obj || !path) {
errno = EINVAL;
return -1;
}
if (path[0] == '\0') {
json_object_put(*obj);
*obj = value;
return 0;
}
if (path[0] != '/') {
errno = EINVAL;
return -1;
}
/* If there's only 1 level to set, stop here */
if ((endp = strrchr(path, '/')) == path) {
path++;
return json_pointer_set_single_path(*obj, path, value);
}
/* pass a working copy to the recursive call */
if (!(path_copy = strdup(path))) {
errno = ENOMEM;
return -1;
}
path_copy[endp - path] = '\0';
rc = json_pointer_get_recursive(*obj, path_copy, &set);
free(path_copy);
if (rc)
return rc;
endp++;
return json_pointer_set_single_path(set, endp, value);
}
int json_pointer_setf(struct json_object **obj, struct json_object *value, const char *path_fmt, ...)
{
char *endp;
char *path_copy = NULL;
struct json_object *set = NULL;
va_list args;
int rc = 0;
if (!obj || !path_fmt) {
errno = EINVAL;
return -1;
}
/* pass a working copy to the recursive call */
va_start(args, path_fmt);
rc = vasprintf(&path_copy, path_fmt, args);
va_end(args);
if (rc < 0)
return rc;
if (path_copy[0] == '\0') {
json_object_put(*obj);
*obj = value;
goto out;
}
if (path_copy[0] != '/') {
errno = EINVAL;
rc = -1;
goto out;
}
/* If there's only 1 level to set, stop here */
if ((endp = strrchr(path_copy, '/')) == path_copy) {
set = *obj;
goto set_single_path;
}
*endp = '\0';
rc = json_pointer_get_recursive(*obj, path_copy, &set);
if (rc)
goto out;
set_single_path:
endp++;
rc = json_pointer_set_single_path(set, endp, value);
out:
free(path_copy);
return rc;
}
-120
View File
@@ -1,120 +0,0 @@
/*
* Copyright (c) 2016 Alexadru Ardelean.
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*/
/**
* @file
* @brief JSON Pointer (RFC 6901) implementation for retrieving
* objects from a json-c object tree.
*/
#ifndef _json_pointer_h_
#define _json_pointer_h_
#include "json_object.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* Retrieves a JSON sub-object from inside another JSON object
* using the JSON pointer notation as defined in RFC 6901
* https://tools.ietf.org/html/rfc6901
*
* The returned JSON sub-object is equivalent to parsing manually the
* 'obj' JSON tree ; i.e. it's not a new object that is created, but rather
* a pointer inside the JSON tree.
*
* Internally, this is equivalent to doing a series of 'json_object_object_get()'
* and 'json_object_array_get_idx()' along the given 'path'.
*
* Note that the 'path' string supports 'printf()' type arguments, so, whatever
* is added after the 'res' param will be treated as an argument for 'path'
* Example: json_pointer_get(obj, "/foo/%d/%s", &res, 0, bar)
* This means, that you need to escape '%' with '%%' (just like in printf())
*
* @param obj the json_object instance/tree from where to retrieve sub-objects
* @param path a (RFC6901) string notation for the sub-object to retrieve
* @param res a pointer where to store a reference to the json_object
* associated with the given path
*
* @return negative if an error (or not found), or 0 if succeeded
*/
int json_pointer_get(struct json_object *obj, const char *path, struct json_object **res);
/**
* This is a variant of 'json_pointer_get()' that supports printf() style arguments.
*
* Example: json_pointer_getf(obj, res, "/foo/%d/%s", 0, bak)
* This also means that you need to escape '%' with '%%' (just like in printf())
*
* Please take into consideration all recommended 'printf()' format security
* aspects when using this function.
*
* @param obj the json_object instance/tree to which to add a sub-object
* @param res a pointer where to store a reference to the json_object
* associated with the given path
* @param path_fmt a printf() style format for the path
*
* @return negative if an error (or not found), or 0 if succeeded
*/
int json_pointer_getf(struct json_object *obj, struct json_object **res, const char *path_fmt, ...);
/**
* Sets JSON object 'value' in the 'obj' tree at the location specified
* by the 'path'. 'path' is JSON pointer notation as defined in RFC 6901
* https://tools.ietf.org/html/rfc6901
*
* Note that 'obj' is a double pointer, mostly for the "" (empty string)
* case, where the entire JSON object would be replaced by 'value'.
* In the case of the "" path, the object at '*obj' will have it's refcount
* decremented with 'json_object_put()' and the 'value' object will be assigned to it.
*
* For other cases (JSON sub-objects) ownership of 'value' will be transferred into
* '*obj' via 'json_object_object_add()' & 'json_object_array_put_idx()', so the
* only time the refcount should be decremented for 'value' is when the return value of
* 'json_pointer_set()' is negative (meaning the 'value' object did not get set into '*obj').
*
* That also implies that 'json_pointer_set()' does not do any refcount incrementing.
* (Just that single decrement that was mentioned above).
*
* Note that the 'path' string supports 'printf()' type arguments, so, whatever
* is added after the 'value' param will be treated as an argument for 'path'
* Example: json_pointer_set(obj, "/foo/%d/%s", value, 0, bak)
* This means, that you need to escape '%' with '%%' (just like in printf())
*
* @param obj the json_object instance/tree to which to add a sub-object
* @param path a (RFC6901) string notation for the sub-object to set in the tree
* @param value object to set at path
*
* @return negative if an error (or not found), or 0 if succeeded
*/
int json_pointer_set(struct json_object **obj, const char *path, struct json_object *value);
/**
* This is a variant of 'json_pointer_set()' that supports printf() style arguments.
*
* Example: json_pointer_setf(obj, value, "/foo/%d/%s", 0, bak)
* This also means that you need to escape '%' with '%%' (just like in printf())
*
* Please take into consideration all recommended 'printf()' format security
* aspects when using this function.
*
* @param obj the json_object instance/tree to which to add a sub-object
* @param value object to set at path
* @param path_fmt a printf() style format for the path
*
* @return negative if an error (or not found), or 0 if succeeded
*/
int json_pointer_setf(struct json_object **obj, struct json_object *value, const char *path_fmt, ...);
#ifdef __cplusplus
}
#endif
#endif
-997
View File
@@ -1,997 +0,0 @@
/*
* $Id: json_tokener.c,v 1.20 2006/07/25 03:24:50 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*
* Copyright (c) 2008-2009 Yahoo! Inc. All rights reserved.
* The copyrights to the contents of this file are licensed under the MIT License
* (http://www.opensource.org/licenses/mit-license.php)
*/
#include "config_json_c.h"
#include <math.h>
#include "math_compat.h"
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <ctype.h>
#include <string.h>
#include <limits.h>
#include "debug.h"
#include "printbuf.h"
#include "arraylist.h"
#include "json_inttypes.h"
#include "json_object.h"
#include "json_object_private.h"
#include "json_tokener.h"
#include "json_util.h"
#include "strdup_compat.h"
#ifdef HAVE_LOCALE_H
#include <locale.h>
#endif /* HAVE_LOCALE_H */
#ifdef HAVE_XLOCALE_H
#include <xlocale.h>
#endif
#define jt_hexdigit(x) (((x) <= '9') ? (x) - '0' : ((x) & 7) + 9)
#if !HAVE_STRNCASECMP && defined(_MSC_VER)
/* MSC has the version as _strnicmp */
# define strncasecmp _strnicmp
#elif !HAVE_STRNCASECMP
# error You do not have strncasecmp on your system.
#endif /* HAVE_STRNCASECMP */
/* Use C99 NAN by default; if not available, nan("") should work too. */
#ifndef NAN
#define NAN nan("")
#endif /* !NAN */
static const char json_null_str[] = "null";
static const int json_null_str_len = sizeof(json_null_str) - 1;
static const char json_inf_str[] = "Infinity";
static const char json_inf_str_lower[] = "infinity";
static const unsigned int json_inf_str_len = sizeof(json_inf_str) - 1;
static const char json_nan_str[] = "NaN";
static const int json_nan_str_len = sizeof(json_nan_str) - 1;
static const char json_true_str[] = "true";
static const int json_true_str_len = sizeof(json_true_str) - 1;
static const char json_false_str[] = "false";
static const int json_false_str_len = sizeof(json_false_str) - 1;
static const char* json_tokener_errors[] = {
"success",
"continue",
"nesting too deep",
"unexpected end of data",
"unexpected character",
"null expected",
"boolean expected",
"number expected",
"array value separator ',' expected",
"quoted object property name expected",
"object property name separator ':' expected",
"object value separator ',' expected",
"invalid string sequence",
"expected comment",
"buffer size overflow"
};
const char *json_tokener_error_desc(enum json_tokener_error jerr)
{
int jerr_int = (int) jerr;
if (jerr_int < 0 ||
jerr_int >= (int)(sizeof(json_tokener_errors) / sizeof(json_tokener_errors[0])))
return "Unknown error, "
"invalid json_tokener_error value passed to json_tokener_error_desc()";
return json_tokener_errors[jerr];
}
enum json_tokener_error json_tokener_get_error(struct json_tokener *tok)
{
return tok->err;
}
/* Stuff for decoding unicode sequences */
#define IS_HIGH_SURROGATE(uc) (((uc) & 0xFC00) == 0xD800)
#define IS_LOW_SURROGATE(uc) (((uc) & 0xFC00) == 0xDC00)
#define DECODE_SURROGATE_PAIR(hi,lo) ((((hi) & 0x3FF) << 10) + ((lo) & 0x3FF) + 0x10000)
static unsigned char utf8_replacement_char[3] = { 0xEF, 0xBF, 0xBD };
struct json_tokener* json_tokener_new_ex(int depth)
{
struct json_tokener *tok;
tok = (struct json_tokener*)calloc(1, sizeof(struct json_tokener));
if (!tok) return NULL;
tok->stack = (struct json_tokener_srec *) calloc(depth,
sizeof(struct json_tokener_srec));
if (!tok->stack) {
free(tok);
return NULL;
}
tok->pb = printbuf_new();
tok->max_depth = depth;
json_tokener_reset(tok);
return tok;
}
struct json_tokener* json_tokener_new(void)
{
return json_tokener_new_ex(JSON_TOKENER_DEFAULT_DEPTH);
}
void json_tokener_free(struct json_tokener *tok)
{
json_tokener_reset(tok);
if (tok->pb) printbuf_free(tok->pb);
free(tok->stack);
free(tok);
}
static void json_tokener_reset_level(struct json_tokener *tok, int depth)
{
tok->stack[depth].state = json_tokener_state_eatws;
tok->stack[depth].saved_state = json_tokener_state_start;
json_object_put(tok->stack[depth].current);
tok->stack[depth].current = NULL;
free(tok->stack[depth].obj_field_name);
tok->stack[depth].obj_field_name = NULL;
}
void json_tokener_reset(struct json_tokener *tok)
{
int i;
if (!tok)
return;
for(i = tok->depth; i >= 0; i--)
json_tokener_reset_level(tok, i);
tok->depth = 0;
tok->err = json_tokener_success;
}
struct json_object* json_tokener_parse(const char *str)
{
enum json_tokener_error jerr_ignored;
struct json_object* obj;
obj = json_tokener_parse_verbose(str, &jerr_ignored);
return obj;
}
struct json_object* json_tokener_parse_verbose(const char *str,
enum json_tokener_error *error)
{
struct json_tokener* tok;
struct json_object* obj;
tok = json_tokener_new();
if (!tok)
return NULL;
obj = json_tokener_parse_ex(tok, str, -1);
*error = tok->err;
if(tok->err != json_tokener_success) {
if (obj != NULL)
json_object_put(obj);
obj = NULL;
}
json_tokener_free(tok);
return obj;
}
#define state tok->stack[tok->depth].state
#define saved_state tok->stack[tok->depth].saved_state
#define current tok->stack[tok->depth].current
#define obj_field_name tok->stack[tok->depth].obj_field_name
/* Optimization:
* json_tokener_parse_ex() consumed a lot of CPU in its main loop,
* iterating character-by character. A large performance boost is
* achieved by using tighter loops to locally handle units such as
* comments and strings. Loops that handle an entire token within
* their scope also gather entire strings and pass them to
* printbuf_memappend() in a single call, rather than calling
* printbuf_memappend() one char at a time.
*
* PEEK_CHAR() and ADVANCE_CHAR() macros are used for code that is
* common to both the main loop and the tighter loops.
*/
/* PEEK_CHAR(dest, tok) macro:
* Peeks at the current char and stores it in dest.
* Returns 1 on success, sets tok->err and returns 0 if no more chars.
* Implicit inputs: str, len vars
*/
#define PEEK_CHAR(dest, tok) \
(((tok)->char_offset == len) ? \
(((tok)->depth == 0 && \
state == json_tokener_state_eatws && \
saved_state == json_tokener_state_finish \
) ? \
(((tok)->err = json_tokener_success), 0) \
: \
(((tok)->err = json_tokener_continue), 0) \
) : \
(((dest) = *str), 1) \
)
/* ADVANCE_CHAR() macro:
* Incrementes str & tok->char_offset.
* For convenience of existing conditionals, returns the old value of c (0 on eof)
* Implicit inputs: c var
*/
#define ADVANCE_CHAR(str, tok) \
( ++(str), ((tok)->char_offset)++, c)
/* End optimization macro defs */
struct json_object* json_tokener_parse_ex(struct json_tokener *tok,
const char *str, int len)
{
struct json_object *obj = NULL;
char c = '\1';
#ifdef HAVE_USELOCALE
locale_t oldlocale = uselocale(NULL);
locale_t newloc;
#elif defined(HAVE_SETLOCALE)
char *oldlocale = NULL;
#endif
tok->char_offset = 0;
tok->err = json_tokener_success;
/* this interface is presently not 64-bit clean due to the int len argument
and the internal printbuf interface that takes 32-bit int len arguments
so the function limits the maximum string size to INT32_MAX (2GB).
If the function is called with len == -1 then strlen is called to check
the string length is less than INT32_MAX (2GB) */
if ((len < -1) || (len == -1 && strlen(str) > INT32_MAX)) {
tok->err = json_tokener_error_size;
return NULL;
}
#ifdef HAVE_USELOCALE
{
locale_t duploc = duplocale(oldlocale);
newloc = newlocale(LC_NUMERIC, "C", duploc);
// XXX at least Debian 8.4 has a bug in newlocale where it doesn't
// change the decimal separator unless you set LC_TIME!
if (newloc)
{
duploc = newloc; // original duploc has been freed by newlocale()
newloc = newlocale(LC_TIME, "C", duploc);
}
if (newloc == NULL)
{
freelocale(duploc);
return NULL;
}
uselocale(newloc);
}
#elif defined(HAVE_SETLOCALE)
{
char *tmplocale;
tmplocale = setlocale(LC_NUMERIC, NULL);
if (tmplocale) oldlocale = strdup(tmplocale);
setlocale(LC_NUMERIC, "C");
}
#endif
while (PEEK_CHAR(c, tok)) {
redo_char:
switch(state) {
case json_tokener_state_eatws:
/* Advance until we change state */
while (isspace((int)c)) {
if ((!ADVANCE_CHAR(str, tok)) || (!PEEK_CHAR(c, tok)))
goto out;
}
if(c == '/' && !(tok->flags & JSON_TOKENER_STRICT)) {
printbuf_reset(tok->pb);
printbuf_memappend_fast(tok->pb, &c, 1);
state = json_tokener_state_comment_start;
} else {
state = saved_state;
goto redo_char;
}
break;
case json_tokener_state_start:
switch(c) {
case '{':
state = json_tokener_state_eatws;
saved_state = json_tokener_state_object_field_start;
current = json_object_new_object();
if(current == NULL)
goto out;
break;
case '[':
state = json_tokener_state_eatws;
saved_state = json_tokener_state_array;
current = json_object_new_array();
if(current == NULL)
goto out;
break;
case 'I':
case 'i':
state = json_tokener_state_inf;
printbuf_reset(tok->pb);
tok->st_pos = 0;
goto redo_char;
case 'N':
case 'n':
state = json_tokener_state_null; // or NaN
printbuf_reset(tok->pb);
tok->st_pos = 0;
goto redo_char;
case '\'':
if (tok->flags & JSON_TOKENER_STRICT) {
/* in STRICT mode only double-quote are allowed */
tok->err = json_tokener_error_parse_unexpected;
goto out;
}
/* FALLTHRU */
case '"':
state = json_tokener_state_string;
printbuf_reset(tok->pb);
tok->quote_char = c;
break;
case 'T':
case 't':
case 'F':
case 'f':
state = json_tokener_state_boolean;
printbuf_reset(tok->pb);
tok->st_pos = 0;
goto redo_char;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case '-':
state = json_tokener_state_number;
printbuf_reset(tok->pb);
tok->is_double = 0;
goto redo_char;
default:
tok->err = json_tokener_error_parse_unexpected;
goto out;
}
break;
case json_tokener_state_finish:
if(tok->depth == 0) goto out;
obj = json_object_get(current);
json_tokener_reset_level(tok, tok->depth);
tok->depth--;
goto redo_char;
case json_tokener_state_inf: /* aka starts with 'i' (or 'I', or "-i", or "-I") */
{
/* If we were guaranteed to have len set, then we could (usually) handle
* the entire "Infinity" check in a single strncmp (strncasecmp), but
* since len might be -1 (i.e. "read until \0"), we need to check it
* a character at a time.
* Trying to handle it both ways would make this code considerably more
* complicated with likely little performance benefit.
*/
int is_negative = 0;
const char *_json_inf_str = json_inf_str;
if (!(tok->flags & JSON_TOKENER_STRICT))
_json_inf_str = json_inf_str_lower;
/* Note: tok->st_pos must be 0 when state is set to json_tokener_state_inf */
while (tok->st_pos < (int)json_inf_str_len)
{
char inf_char = *str;
if (!(tok->flags & JSON_TOKENER_STRICT))
inf_char = tolower((int)*str);
if (inf_char != _json_inf_str[tok->st_pos])
{
tok->err = json_tokener_error_parse_unexpected;
goto out;
}
tok->st_pos++;
(void)ADVANCE_CHAR(str, tok);
if (!PEEK_CHAR(c, tok))
{
/* out of input chars, for now at least */
goto out;
}
}
/* We checked the full length of "Infinity", so create the object.
* When handling -Infinity, the number parsing code will have dropped
* the "-" into tok->pb for us, so check it now.
*/
if (printbuf_length(tok->pb) > 0 && *(tok->pb->buf) == '-')
{
is_negative = 1;
}
current = json_object_new_double(is_negative
? -INFINITY : INFINITY);
if (current == NULL)
goto out;
saved_state = json_tokener_state_finish;
state = json_tokener_state_eatws;
goto redo_char;
}
break;
case json_tokener_state_null: /* aka starts with 'n' */
{
int size;
int size_nan;
printbuf_memappend_fast(tok->pb, &c, 1);
size = json_min(tok->st_pos+1, json_null_str_len);
size_nan = json_min(tok->st_pos+1, json_nan_str_len);
if((!(tok->flags & JSON_TOKENER_STRICT) &&
strncasecmp(json_null_str, tok->pb->buf, size) == 0)
|| (strncmp(json_null_str, tok->pb->buf, size) == 0)
) {
if (tok->st_pos == json_null_str_len) {
current = NULL;
saved_state = json_tokener_state_finish;
state = json_tokener_state_eatws;
goto redo_char;
}
}
else if ((!(tok->flags & JSON_TOKENER_STRICT) &&
strncasecmp(json_nan_str, tok->pb->buf, size_nan) == 0) ||
(strncmp(json_nan_str, tok->pb->buf, size_nan) == 0)
)
{
if (tok->st_pos == json_nan_str_len)
{
current = json_object_new_double(NAN);
if (current == NULL)
goto out;
saved_state = json_tokener_state_finish;
state = json_tokener_state_eatws;
goto redo_char;
}
} else {
tok->err = json_tokener_error_parse_null;
goto out;
}
tok->st_pos++;
}
break;
case json_tokener_state_comment_start:
if(c == '*') {
state = json_tokener_state_comment;
} else if(c == '/') {
state = json_tokener_state_comment_eol;
} else {
tok->err = json_tokener_error_parse_comment;
goto out;
}
printbuf_memappend_fast(tok->pb, &c, 1);
break;
case json_tokener_state_comment:
{
/* Advance until we change state */
const char *case_start = str;
while(c != '*') {
if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) {
printbuf_memappend_fast(tok->pb, case_start, str-case_start);
goto out;
}
}
printbuf_memappend_fast(tok->pb, case_start, 1+str-case_start);
state = json_tokener_state_comment_end;
}
break;
case json_tokener_state_comment_eol:
{
/* Advance until we change state */
const char *case_start = str;
while(c != '\n') {
if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) {
printbuf_memappend_fast(tok->pb, case_start, str-case_start);
goto out;
}
}
printbuf_memappend_fast(tok->pb, case_start, str-case_start);
MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf);
state = json_tokener_state_eatws;
}
break;
case json_tokener_state_comment_end:
printbuf_memappend_fast(tok->pb, &c, 1);
if(c == '/') {
MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf);
state = json_tokener_state_eatws;
} else {
state = json_tokener_state_comment;
}
break;
case json_tokener_state_string:
{
/* Advance until we change state */
const char *case_start = str;
while(1) {
if(c == tok->quote_char) {
printbuf_memappend_fast(tok->pb, case_start, str-case_start);
current = json_object_new_string_len(tok->pb->buf, tok->pb->bpos);
if(current == NULL)
goto out;
saved_state = json_tokener_state_finish;
state = json_tokener_state_eatws;
break;
} else if(c == '\\') {
printbuf_memappend_fast(tok->pb, case_start, str-case_start);
saved_state = json_tokener_state_string;
state = json_tokener_state_string_escape;
break;
}
if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) {
printbuf_memappend_fast(tok->pb, case_start, str-case_start);
goto out;
}
}
}
break;
case json_tokener_state_string_escape:
switch(c) {
case '"':
case '\\':
case '/':
printbuf_memappend_fast(tok->pb, &c, 1);
state = saved_state;
break;
case 'b':
case 'n':
case 'r':
case 't':
case 'f':
if(c == 'b') printbuf_memappend_fast(tok->pb, "\b", 1);
else if(c == 'n') printbuf_memappend_fast(tok->pb, "\n", 1);
else if(c == 'r') printbuf_memappend_fast(tok->pb, "\r", 1);
else if(c == 't') printbuf_memappend_fast(tok->pb, "\t", 1);
else if(c == 'f') printbuf_memappend_fast(tok->pb, "\f", 1);
state = saved_state;
break;
case 'u':
tok->ucs_char = 0;
tok->st_pos = 0;
state = json_tokener_state_escape_unicode;
break;
default:
tok->err = json_tokener_error_parse_string;
goto out;
}
break;
case json_tokener_state_escape_unicode:
{
unsigned int got_hi_surrogate = 0;
/* Handle a 4-byte sequence, or two sequences if a surrogate pair */
while(1) {
if (c && strchr(json_hex_chars, c)) {
tok->ucs_char += ((unsigned int)jt_hexdigit(c) << ((3-tok->st_pos++)*4));
if(tok->st_pos == 4) {
unsigned char unescaped_utf[4];
if (got_hi_surrogate) {
if (IS_LOW_SURROGATE(tok->ucs_char)) {
/* Recalculate the ucs_char, then fall thru to process normally */
tok->ucs_char = DECODE_SURROGATE_PAIR(got_hi_surrogate, tok->ucs_char);
} else {
/* Hi surrogate was not followed by a low surrogate */
/* Replace the hi and process the rest normally */
printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3);
}
got_hi_surrogate = 0;
}
if (tok->ucs_char < 0x80) {
unescaped_utf[0] = tok->ucs_char;
printbuf_memappend_fast(tok->pb, (char*)unescaped_utf, 1);
} else if (tok->ucs_char < 0x800) {
unescaped_utf[0] = 0xc0 | (tok->ucs_char >> 6);
unescaped_utf[1] = 0x80 | (tok->ucs_char & 0x3f);
printbuf_memappend_fast(tok->pb, (char*)unescaped_utf, 2);
} else if (IS_HIGH_SURROGATE(tok->ucs_char)) {
/* Got a high surrogate. Remember it and look for the
* the beginning of another sequence, which should be the
* low surrogate.
*/
got_hi_surrogate = tok->ucs_char;
/* Not at end, and the next two chars should be "\u" */
if ((len == -1 || len > (tok->char_offset + 2)) &&
// str[0] != '0' && // implied by json_hex_chars, above.
(str[1] == '\\') &&
(str[2] == 'u'))
{
/* Advance through the 16 bit surrogate, and move on to the
* next sequence. The next step is to process the following
* characters.
*/
if( !ADVANCE_CHAR(str, tok) || !ADVANCE_CHAR(str, tok) ) {
printbuf_memappend_fast(tok->pb,
(char*) utf8_replacement_char, 3);
}
/* Advance to the first char of the next sequence and
* continue processing with the next sequence.
*/
if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) {
printbuf_memappend_fast(tok->pb,
(char*) utf8_replacement_char, 3);
goto out;
}
tok->ucs_char = 0;
tok->st_pos = 0;
continue; /* other json_tokener_state_escape_unicode */
} else {
/* Got a high surrogate without another sequence following
* it. Put a replacement char in for the hi surrogate
* and pretend we finished.
*/
printbuf_memappend_fast(tok->pb,
(char*) utf8_replacement_char, 3);
}
} else if (IS_LOW_SURROGATE(tok->ucs_char)) {
/* Got a low surrogate not preceded by a high */
printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3);
} else if (tok->ucs_char < 0x10000) {
unescaped_utf[0] = 0xe0 | (tok->ucs_char >> 12);
unescaped_utf[1] = 0x80 | ((tok->ucs_char >> 6) & 0x3f);
unescaped_utf[2] = 0x80 | (tok->ucs_char & 0x3f);
printbuf_memappend_fast(tok->pb, (char*)unescaped_utf, 3);
} else if (tok->ucs_char < 0x110000) {
unescaped_utf[0] = 0xf0 | ((tok->ucs_char >> 18) & 0x07);
unescaped_utf[1] = 0x80 | ((tok->ucs_char >> 12) & 0x3f);
unescaped_utf[2] = 0x80 | ((tok->ucs_char >> 6) & 0x3f);
unescaped_utf[3] = 0x80 | (tok->ucs_char & 0x3f);
printbuf_memappend_fast(tok->pb, (char*)unescaped_utf, 4);
} else {
/* Don't know what we got--insert the replacement char */
printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3);
}
state = saved_state;
break;
}
} else {
tok->err = json_tokener_error_parse_string;
goto out;
}
if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) {
if (got_hi_surrogate) /* Clean up any pending chars */
printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3);
goto out;
}
}
}
break;
case json_tokener_state_boolean:
{
int size1, size2;
printbuf_memappend_fast(tok->pb, &c, 1);
size1 = json_min(tok->st_pos+1, json_true_str_len);
size2 = json_min(tok->st_pos+1, json_false_str_len);
if((!(tok->flags & JSON_TOKENER_STRICT) &&
strncasecmp(json_true_str, tok->pb->buf, size1) == 0)
|| (strncmp(json_true_str, tok->pb->buf, size1) == 0)
) {
if(tok->st_pos == json_true_str_len) {
current = json_object_new_boolean(1);
if(current == NULL)
goto out;
saved_state = json_tokener_state_finish;
state = json_tokener_state_eatws;
goto redo_char;
}
} else if((!(tok->flags & JSON_TOKENER_STRICT) &&
strncasecmp(json_false_str, tok->pb->buf, size2) == 0)
|| (strncmp(json_false_str, tok->pb->buf, size2) == 0)) {
if(tok->st_pos == json_false_str_len) {
current = json_object_new_boolean(0);
if(current == NULL)
goto out;
saved_state = json_tokener_state_finish;
state = json_tokener_state_eatws;
goto redo_char;
}
} else {
tok->err = json_tokener_error_parse_boolean;
goto out;
}
tok->st_pos++;
}
break;
case json_tokener_state_number:
{
/* Advance until we change state */
const char *case_start = str;
int case_len=0;
int is_exponent=0;
int negativesign_next_possible_location=1;
while(c && strchr(json_number_chars, c)) {
++case_len;
/* non-digit characters checks */
/* note: since the main loop condition to get here was
an input starting with 0-9 or '-', we are
protected from input starting with '.' or
e/E. */
if (c == '.') {
if (tok->is_double != 0) {
/* '.' can only be found once, and out of the exponent part.
Thus, if the input is already flagged as double, it
is invalid. */
tok->err = json_tokener_error_parse_number;
goto out;
}
tok->is_double = 1;
}
if (c == 'e' || c == 'E') {
if (is_exponent != 0) {
/* only one exponent possible */
tok->err = json_tokener_error_parse_number;
goto out;
}
is_exponent = 1;
tok->is_double = 1;
/* the exponent part can begin with a negative sign */
negativesign_next_possible_location = case_len + 1;
}
if (c == '-' && case_len != negativesign_next_possible_location) {
/* If the negative sign is not where expected (ie
start of input or start of exponent part), the
input is invalid. */
tok->err = json_tokener_error_parse_number;
goto out;
}
if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) {
printbuf_memappend_fast(tok->pb, case_start, case_len);
goto out;
}
}
if (case_len>0)
printbuf_memappend_fast(tok->pb, case_start, case_len);
// Check for -Infinity
if (tok->pb->buf[0] == '-' && case_len <= 1 &&
(c == 'i' || c == 'I'))
{
state = json_tokener_state_inf;
tok->st_pos = 0;
goto redo_char;
}
}
{
int64_t num64;
double numd;
if (!tok->is_double && json_parse_int64(tok->pb->buf, &num64) == 0) {
if (num64 && tok->pb->buf[0]=='0' &&
(tok->flags & JSON_TOKENER_STRICT)) {
/* in strict mode, number must not start with 0 */
tok->err = json_tokener_error_parse_number;
goto out;
}
current = json_object_new_int64(num64);
if(current == NULL)
goto out;
}
else if(tok->is_double && json_parse_double(tok->pb->buf, &numd) == 0)
{
current = json_object_new_double_s(numd, tok->pb->buf);
if(current == NULL)
goto out;
} else {
tok->err = json_tokener_error_parse_number;
goto out;
}
saved_state = json_tokener_state_finish;
state = json_tokener_state_eatws;
goto redo_char;
}
break;
case json_tokener_state_array_after_sep:
case json_tokener_state_array:
if(c == ']') {
if (state == json_tokener_state_array_after_sep &&
(tok->flags & JSON_TOKENER_STRICT))
{
tok->err = json_tokener_error_parse_unexpected;
goto out;
}
saved_state = json_tokener_state_finish;
state = json_tokener_state_eatws;
} else {
if(tok->depth >= tok->max_depth-1) {
tok->err = json_tokener_error_depth;
goto out;
}
state = json_tokener_state_array_add;
tok->depth++;
json_tokener_reset_level(tok, tok->depth);
goto redo_char;
}
break;
case json_tokener_state_array_add:
if( json_object_array_add(current, obj) != 0 )
goto out;
saved_state = json_tokener_state_array_sep;
state = json_tokener_state_eatws;
goto redo_char;
case json_tokener_state_array_sep:
if(c == ']') {
saved_state = json_tokener_state_finish;
state = json_tokener_state_eatws;
} else if(c == ',') {
saved_state = json_tokener_state_array_after_sep;
state = json_tokener_state_eatws;
} else {
tok->err = json_tokener_error_parse_array;
goto out;
}
break;
case json_tokener_state_object_field_start:
case json_tokener_state_object_field_start_after_sep:
if(c == '}') {
if (state == json_tokener_state_object_field_start_after_sep &&
(tok->flags & JSON_TOKENER_STRICT))
{
tok->err = json_tokener_error_parse_unexpected;
goto out;
}
saved_state = json_tokener_state_finish;
state = json_tokener_state_eatws;
} else if (c == '"' || c == '\'') {
tok->quote_char = c;
printbuf_reset(tok->pb);
state = json_tokener_state_object_field;
} else {
tok->err = json_tokener_error_parse_object_key_name;
goto out;
}
break;
case json_tokener_state_object_field:
{
/* Advance until we change state */
const char *case_start = str;
while(1) {
if(c == tok->quote_char) {
printbuf_memappend_fast(tok->pb, case_start, str-case_start);
obj_field_name = strdup(tok->pb->buf);
saved_state = json_tokener_state_object_field_end;
state = json_tokener_state_eatws;
break;
} else if(c == '\\') {
printbuf_memappend_fast(tok->pb, case_start, str-case_start);
saved_state = json_tokener_state_object_field;
state = json_tokener_state_string_escape;
break;
}
if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) {
printbuf_memappend_fast(tok->pb, case_start, str-case_start);
goto out;
}
}
}
break;
case json_tokener_state_object_field_end:
if(c == ':') {
saved_state = json_tokener_state_object_value;
state = json_tokener_state_eatws;
} else {
tok->err = json_tokener_error_parse_object_key_sep;
goto out;
}
break;
case json_tokener_state_object_value:
if(tok->depth >= tok->max_depth-1) {
tok->err = json_tokener_error_depth;
goto out;
}
state = json_tokener_state_object_value_add;
tok->depth++;
json_tokener_reset_level(tok, tok->depth);
goto redo_char;
case json_tokener_state_object_value_add:
json_object_object_add(current, obj_field_name, obj);
free(obj_field_name);
obj_field_name = NULL;
saved_state = json_tokener_state_object_sep;
state = json_tokener_state_eatws;
goto redo_char;
case json_tokener_state_object_sep:
/* { */
if(c == '}') {
saved_state = json_tokener_state_finish;
state = json_tokener_state_eatws;
} else if(c == ',') {
saved_state = json_tokener_state_object_field_start_after_sep;
state = json_tokener_state_eatws;
} else {
tok->err = json_tokener_error_parse_object_value_sep;
goto out;
}
break;
}
if (!ADVANCE_CHAR(str, tok))
goto out;
} /* while(PEEK_CHAR) */
out:
if (c &&
(state == json_tokener_state_finish) &&
(tok->depth == 0) &&
(tok->flags & JSON_TOKENER_STRICT)) {
/* unexpected char after JSON data */
tok->err = json_tokener_error_parse_unexpected;
}
if (!c) { /* We hit an eof char (0) */
if(state != json_tokener_state_finish &&
saved_state != json_tokener_state_finish)
tok->err = json_tokener_error_parse_eof;
}
#ifdef HAVE_USELOCALE
uselocale(oldlocale);
freelocale(newloc);
#elif defined(HAVE_SETLOCALE)
setlocale(LC_NUMERIC, oldlocale);
free(oldlocale);
#endif
if (tok->err == json_tokener_success)
{
json_object *ret = json_object_get(current);
int ii;
/* Partially reset, so we parse additional objects on subsequent calls. */
for(ii = tok->depth; ii >= 0; ii--)
json_tokener_reset_level(tok, ii);
return ret;
}
MC_DEBUG("json_tokener_parse_ex: error %s at offset %d\n",
json_tokener_errors[tok->err], tok->char_offset);
return NULL;
}
void json_tokener_set_flags(struct json_tokener *tok, int flags)
{
tok->flags = flags;
}
-216
View File
@@ -1,216 +0,0 @@
/*
* $Id: json_tokener.h,v 1.10 2006/07/25 03:24:50 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*/
/**
* @file
* @brief Methods to parse an input string into a tree of json_object objects.
*/
#ifndef _json_tokener_h_
#define _json_tokener_h_
#include <stddef.h>
#include "json_object.h"
#ifdef __cplusplus
extern "C" {
#endif
enum json_tokener_error {
json_tokener_success,
json_tokener_continue,
json_tokener_error_depth,
json_tokener_error_parse_eof,
json_tokener_error_parse_unexpected,
json_tokener_error_parse_null,
json_tokener_error_parse_boolean,
json_tokener_error_parse_number,
json_tokener_error_parse_array,
json_tokener_error_parse_object_key_name,
json_tokener_error_parse_object_key_sep,
json_tokener_error_parse_object_value_sep,
json_tokener_error_parse_string,
json_tokener_error_parse_comment,
json_tokener_error_size
};
enum json_tokener_state {
json_tokener_state_eatws,
json_tokener_state_start,
json_tokener_state_finish,
json_tokener_state_null,
json_tokener_state_comment_start,
json_tokener_state_comment,
json_tokener_state_comment_eol,
json_tokener_state_comment_end,
json_tokener_state_string,
json_tokener_state_string_escape,
json_tokener_state_escape_unicode,
json_tokener_state_boolean,
json_tokener_state_number,
json_tokener_state_array,
json_tokener_state_array_add,
json_tokener_state_array_sep,
json_tokener_state_object_field_start,
json_tokener_state_object_field,
json_tokener_state_object_field_end,
json_tokener_state_object_value,
json_tokener_state_object_value_add,
json_tokener_state_object_sep,
json_tokener_state_array_after_sep,
json_tokener_state_object_field_start_after_sep,
json_tokener_state_inf
};
struct json_tokener_srec
{
enum json_tokener_state state, saved_state;
struct json_object *obj;
struct json_object *current;
char *obj_field_name;
};
#define JSON_TOKENER_DEFAULT_DEPTH 32
struct json_tokener
{
char *str;
struct printbuf *pb;
int max_depth, depth, is_double, st_pos, char_offset;
enum json_tokener_error err;
unsigned int ucs_char;
char quote_char;
struct json_tokener_srec *stack;
int flags;
};
/**
* @deprecated Unused in json-c code
*/
typedef struct json_tokener json_tokener;
/**
* Be strict when parsing JSON input. Use caution with
* this flag as what is considered valid may become more
* restrictive from one release to the next, causing your
* code to fail on previously working input.
*
* This flag is not set by default.
*
* @see json_tokener_set_flags()
*/
#define JSON_TOKENER_STRICT 0x01
/**
* Given an error previously returned by json_tokener_get_error(),
* return a human readable description of the error.
*
* @return a generic error message is returned if an invalid error value is provided.
*/
const char *json_tokener_error_desc(enum json_tokener_error jerr);
/**
* Retrieve the error caused by the last call to json_tokener_parse_ex(),
* or json_tokener_success if there is no error.
*
* When parsing a JSON string in pieces, if the tokener is in the middle
* of parsing this will return json_tokener_continue.
*
* See also json_tokener_error_desc().
*/
JSON_EXPORT enum json_tokener_error json_tokener_get_error(struct json_tokener *tok);
JSON_EXPORT struct json_tokener* json_tokener_new(void);
JSON_EXPORT struct json_tokener* json_tokener_new_ex(int depth);
JSON_EXPORT void json_tokener_free(struct json_tokener *tok);
JSON_EXPORT void json_tokener_reset(struct json_tokener *tok);
JSON_EXPORT struct json_object* json_tokener_parse(const char *str);
JSON_EXPORT struct json_object* json_tokener_parse_verbose(const char *str, enum json_tokener_error *error);
/**
* Set flags that control how parsing will be done.
*/
JSON_EXPORT void json_tokener_set_flags(struct json_tokener *tok, int flags);
/**
* Parse a string and return a non-NULL json_object if a valid JSON value
* is found. The string does not need to be a JSON object or array;
* it can also be a string, number or boolean value.
*
* A partial JSON string can be parsed. If the parsing is incomplete,
* NULL will be returned and json_tokener_get_error() will return
* json_tokener_continue.
* json_tokener_parse_ex() can then be called with additional bytes in str
* to continue the parsing.
*
* If json_tokener_parse_ex() returns NULL and the error is anything other than
* json_tokener_continue, a fatal error has occurred and parsing must be
* halted. Then, the tok object must not be reused until json_tokener_reset() is
* called.
*
* When a valid JSON value is parsed, a non-NULL json_object will be
* returned. Also, json_tokener_get_error() will return json_tokener_success.
* Be sure to check the type with json_object_is_type() or
* json_object_get_type() before using the object.
*
* @b XXX this shouldn't use internal fields:
* Trailing characters after the parsed value do not automatically cause an
* error. It is up to the caller to decide whether to treat this as an
* error or to handle the additional characters, perhaps by parsing another
* json value starting from that point.
*
* Extra characters can be detected by comparing the tok->char_offset against
* the length of the last len parameter passed in.
*
* The tokener does \b not maintain an internal buffer so the caller is
* responsible for calling json_tokener_parse_ex with an appropriate str
* parameter starting with the extra characters.
*
* This interface is presently not 64-bit clean due to the int len argument
* so the function limits the maximum string size to INT32_MAX (2GB).
* If the function is called with len == -1 then strlen is called to check
* the string length is less than INT32_MAX (2GB)
*
* Example:
* @code
json_object *jobj = NULL;
const char *mystring = NULL;
int stringlen = 0;
enum json_tokener_error jerr;
do {
mystring = ... // get JSON string, e.g. read from file, etc...
stringlen = strlen(mystring);
jobj = json_tokener_parse_ex(tok, mystring, stringlen);
} while ((jerr = json_tokener_get_error(tok)) == json_tokener_continue);
if (jerr != json_tokener_success)
{
fprintf(stderr, "Error: %s\n", json_tokener_error_desc(jerr));
// Handle errors, as appropriate for your application.
}
if (tok->char_offset < stringlen) // XXX shouldn't access internal fields
{
// Handle extra characters after parsed object as desired.
// e.g. issue an error, parse another object from that point, etc...
}
// Success, use jobj here.
@endcode
*
* @param tok a json_tokener previously allocated with json_tokener_new()
* @param str an string with any valid JSON expression, or portion of. This does not need to be null terminated.
* @param len the length of str
*/
JSON_EXPORT struct json_object* json_tokener_parse_ex(struct json_tokener *tok,
const char *str, int len);
#ifdef __cplusplus
}
#endif
#endif
-243
View File
@@ -1,243 +0,0 @@
/*
* $Id: json_util.c,v 1.4 2006/01/30 23:07:57 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*/
#include "config_json_c.h"
#undef realloc
#include "strerror_override.h"
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <limits.h>
#include <string.h>
#include <ctype.h>
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif /* HAVE_SYS_TYPES_H */
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif /* HAVE_SYS_STAT_H */
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif /* HAVE_FCNTL_H */
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif /* HAVE_UNISTD_H */
#ifdef WIN32
# if MSC_VER < 1800
/* strtoll is available only since Visual Studio 2013 */
# define strtoll _strtoi64
# endif
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
# include <io.h>
#endif /* defined(WIN32) */
#if !defined(HAVE_OPEN) && defined(WIN32)
# define open _open
#endif
#include "snprintf_compat.h"
#include "debug.h"
#include "printbuf.h"
#include "json_inttypes.h"
#include "json_object.h"
#include "json_tokener.h"
#include "json_util.h"
static int _json_object_to_fd(int fd, struct json_object *obj, int flags, const char *filename);
static char _last_err[256] = "";
const char *json_util_get_last_err()
{
if (_last_err[0] == '\0')
return NULL;
return _last_err;
}
void _json_c_set_last_err(const char *err_fmt, ...)
{
va_list ap;
va_start(ap, err_fmt);
// Ignore (attempted) overruns from snprintf
(void)vsnprintf(_last_err, sizeof(_last_err), err_fmt, ap);
va_end(ap);
}
struct json_object* json_object_from_fd(int fd)
{
struct printbuf *pb;
struct json_object *obj;
char buf[JSON_FILE_BUF_SIZE];
int ret;
if(!(pb = printbuf_new())) {
_json_c_set_last_err("json_object_from_file: printbuf_new failed\n");
return NULL;
}
while((ret = read(fd, buf, JSON_FILE_BUF_SIZE)) > 0) {
printbuf_memappend(pb, buf, ret);
}
if(ret < 0) {
_json_c_set_last_err("json_object_from_fd: error reading fd %d: %s\n", fd, strerror(errno));
printbuf_free(pb);
return NULL;
}
obj = json_tokener_parse(pb->buf);
printbuf_free(pb);
return obj;
}
struct json_object* json_object_from_file(const char *filename)
{
struct json_object *obj;
int fd;
if((fd = open(filename, O_RDONLY)) < 0) {
_json_c_set_last_err("json_object_from_file: error opening file %s: %s\n",
filename, strerror(errno));
return NULL;
}
obj = json_object_from_fd(fd);
close(fd);
return obj;
}
/* extended "format and write to file" function */
int json_object_to_file_ext(const char *filename, struct json_object *obj, int flags)
{
int fd, ret;
int saved_errno;
if (!obj) {
_json_c_set_last_err("json_object_to_file: object is null\n");
return -1;
}
if ((fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, 0644)) < 0) {
_json_c_set_last_err("json_object_to_file: error opening file %s: %s\n",
filename, strerror(errno));
return -1;
}
ret = _json_object_to_fd(fd, obj, flags, filename);
saved_errno = errno;
close(fd);
errno = saved_errno;
return ret;
}
int json_object_to_fd(int fd, struct json_object *obj, int flags)
{
if (!obj) {
_json_c_set_last_err("json_object_to_fd: object is null\n");
return -1;
}
return _json_object_to_fd(fd, obj, flags, NULL);
}
static int _json_object_to_fd(int fd, struct json_object *obj, int flags, const char *filename)
{
int ret;
const char *json_str;
unsigned int wpos, wsize;
filename = filename ? filename : "(fd)";
if (!(json_str = json_object_to_json_string_ext(obj,flags))) {
return -1;
}
wsize = (unsigned int)(strlen(json_str) & UINT_MAX); /* CAW: probably unnecessary, but the most 64bit safe */
wpos = 0;
while(wpos < wsize) {
if((ret = write(fd, json_str + wpos, wsize-wpos)) < 0) {
_json_c_set_last_err("json_object_to_file: error writing file %s: %s\n",
filename, strerror(errno));
return -1;
}
/* because of the above check for ret < 0, we can safely cast and add */
wpos += (unsigned int)ret;
}
return 0;
}
// backwards compatible "format and write to file" function
int json_object_to_file(const char *filename, struct json_object *obj)
{
return json_object_to_file_ext(filename, obj, JSON_C_TO_STRING_PLAIN);
}
int json_parse_double(const char *buf, double *retval)
{
char *end;
*retval = strtod(buf, &end);
return end == buf ? 1 : 0;
}
int json_parse_int64(const char *buf, int64_t *retval)
{
char *end = NULL;
int64_t val;
errno = 0;
val = strtoll(buf, &end, 10);
if (end != buf)
*retval = val;
return ((val == 0 && errno != 0) || (end == buf)) ? 1 : 0;
}
#ifndef HAVE_REALLOC
void* rpl_realloc(void* p, size_t n)
{
if (n == 0)
n = 1;
if (p == 0)
return malloc(n);
return realloc(p, n);
}
#endif
#define NELEM(a) (sizeof(a) / sizeof(a[0]))
static const char* json_type_name[] = {
/* If you change this, be sure to update the enum json_type definition too */
"null",
"boolean",
"double",
"int",
"object",
"array",
"string",
};
const char *json_type_to_name(enum json_type o_type)
{
int o_type_int = (int)o_type;
if (o_type_int < 0 || o_type_int >= (int)NELEM(json_type_name))
{
_json_c_set_last_err("json_type_to_name: type %d is out of range [0,%d]\n", o_type, NELEM(json_type_name));
return NULL;
}
return json_type_name[o_type];
}
-106
View File
@@ -1,106 +0,0 @@
/*
* $Id: json_util.h,v 1.4 2006/01/30 23:07:57 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*/
/**
* @file
* @brief Miscllaneous utility functions and macros.
*/
#ifndef _json_util_h_
#define _json_util_h_
#include "json_object.h"
#ifndef json_min
#define json_min(a,b) ((a) < (b) ? (a) : (b))
#endif
#ifndef json_max
#define json_max(a,b) ((a) > (b) ? (a) : (b))
#endif
#ifdef __cplusplus
extern "C" {
#endif
#define JSON_FILE_BUF_SIZE 4096
/* utility functions */
/**
* Read the full contents of the given file, then convert it to a
* json_object using json_tokener_parse().
*
* Returns -1 if something fails. See json_util_get_last_err() for details.
*/
extern struct json_object* json_object_from_file(const char *filename);
/**
* Create a JSON object from already opened file descriptor.
*
* This function can be helpful, when you opened the file already,
* e.g. when you have a temp file.
* Note, that the fd must be readable at the actual position, i.e.
* use lseek(fd, 0, SEEK_SET) before.
*
* Returns -1 if something fails. See json_util_get_last_err() for details.
*/
extern struct json_object* json_object_from_fd(int fd);
/**
* Equivalent to:
* json_object_to_file_ext(filename, obj, JSON_C_TO_STRING_PLAIN);
*
* Returns -1 if something fails. See json_util_get_last_err() for details.
*/
extern int json_object_to_file(const char *filename, struct json_object *obj);
/**
* Open and truncate the given file, creating it if necessary, then
* convert the json_object to a string and write it to the file.
*
* Returns -1 if something fails. See json_util_get_last_err() for details.
*/
extern int json_object_to_file_ext(const char *filename, struct json_object *obj, int flags);
/**
* Convert the json_object to a string and write it to the file descriptor.
* Handles partial writes and will keep writing until done, or an error
* occurs.
*
* @param fd an open, writable file descriptor to write to
* @param obj the object to serializer and write
* @param flags flags to pass to json_object_to_json_string_ext()
* @return -1 if something fails. See json_util_get_last_err() for details.
*/
extern int json_object_to_fd(int fd, struct json_object *obj, int flags);
/**
* Return the last error from various json-c functions, including:
* json_object_to_file{,_ext}, json_object_to_fd() or
* json_object_from_{file,fd}, or NULL if there is none.
*/
const char *json_util_get_last_err(void);
extern int json_parse_int64(const char *buf, int64_t *retval);
extern int json_parse_double(const char *buf, double *retval);
/**
* Return a string describing the type of the object.
* e.g. "int", or "object", etc...
*/
extern const char *json_type_to_name(enum json_type o_type);
#ifdef __cplusplus
}
#endif
#endif
-133
View File
@@ -1,133 +0,0 @@
/*
* Copyright (c) 2016 Eric Haszlakiewicz
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*/
#include <stdio.h>
#include "config_json_c.h"
#include "json_inttypes.h"
#include "json_object.h"
#include "json_visit.h"
#include "linkhash.h"
static int _json_c_visit(json_object *jso, json_object *parent_jso,
const char *jso_key, size_t *jso_index,
json_c_visit_userfunc *userfunc, void *userarg);
int json_c_visit(json_object *jso, int future_flags,
json_c_visit_userfunc *userfunc, void *userarg)
{
int ret = _json_c_visit(jso, NULL, NULL, NULL, userfunc, userarg);
switch(ret)
{
case JSON_C_VISIT_RETURN_CONTINUE:
case JSON_C_VISIT_RETURN_SKIP:
case JSON_C_VISIT_RETURN_POP:
case JSON_C_VISIT_RETURN_STOP:
return 0;
default:
return JSON_C_VISIT_RETURN_ERROR;
}
}
static int _json_c_visit(json_object *jso, json_object *parent_jso,
const char *jso_key, size_t *jso_index,
json_c_visit_userfunc *userfunc, void *userarg)
{
int userret = userfunc(jso, 0, parent_jso, jso_key, jso_index, userarg);
switch(userret)
{
case JSON_C_VISIT_RETURN_CONTINUE:
break;
case JSON_C_VISIT_RETURN_SKIP:
case JSON_C_VISIT_RETURN_POP:
case JSON_C_VISIT_RETURN_STOP:
case JSON_C_VISIT_RETURN_ERROR:
return userret;
default:
fprintf(stderr, "ERROR: invalid return value from json_c_visit userfunc: %d\n", userret);
return JSON_C_VISIT_RETURN_ERROR;
}
switch(json_object_get_type(jso))
{
case json_type_null:
case json_type_boolean:
case json_type_double:
case json_type_int:
case json_type_string:
// we already called userfunc above, move on to the next object
return JSON_C_VISIT_RETURN_CONTINUE;
case json_type_object:
{
json_object_object_foreach(jso, key, child)
{
userret = _json_c_visit(child, jso, key, NULL, userfunc, userarg);
if (userret == JSON_C_VISIT_RETURN_POP)
break;
if (userret == JSON_C_VISIT_RETURN_STOP ||
userret == JSON_C_VISIT_RETURN_ERROR)
return userret;
if (userret != JSON_C_VISIT_RETURN_CONTINUE &&
userret != JSON_C_VISIT_RETURN_SKIP)
{
fprintf(stderr, "INTERNAL ERROR: _json_c_visit returned %d\n", userret);
return JSON_C_VISIT_RETURN_ERROR;
}
}
break;
}
case json_type_array:
{
size_t array_len = json_object_array_length(jso);
size_t ii;
for (ii = 0; ii < array_len; ii++)
{
json_object *child = json_object_array_get_idx(jso, ii);
userret = _json_c_visit(child, jso, NULL, &ii, userfunc, userarg);
if (userret == JSON_C_VISIT_RETURN_POP)
break;
if (userret == JSON_C_VISIT_RETURN_STOP ||
userret == JSON_C_VISIT_RETURN_ERROR)
return userret;
if (userret != JSON_C_VISIT_RETURN_CONTINUE &&
userret != JSON_C_VISIT_RETURN_SKIP)
{
fprintf(stderr, "INTERNAL ERROR: _json_c_visit returned %d\n", userret);
return JSON_C_VISIT_RETURN_ERROR;
}
}
break;
}
default:
fprintf(stderr, "INTERNAL ERROR: _json_c_visit found object of unknown type: %d\n", json_object_get_type(jso));
return JSON_C_VISIT_RETURN_ERROR;
}
// Call userfunc for the second type on container types, after all
// members of the container have been visited.
// Non-container types will have already returned before this point.
userret = userfunc(jso, JSON_C_VISIT_SECOND, parent_jso, jso_key, jso_index, userarg);
switch(userret)
{
case JSON_C_VISIT_RETURN_SKIP:
case JSON_C_VISIT_RETURN_POP:
// These are not really sensible during JSON_C_VISIT_SECOND,
// but map them to JSON_C_VISIT_CONTINUE anyway.
// FALLTHROUGH
case JSON_C_VISIT_RETURN_CONTINUE:
return JSON_C_VISIT_RETURN_CONTINUE;
case JSON_C_VISIT_RETURN_STOP:
case JSON_C_VISIT_RETURN_ERROR:
return userret;
default:
fprintf(stderr, "ERROR: invalid return value from json_c_visit userfunc: %d\n", userret);
return JSON_C_VISIT_RETURN_ERROR;
}
// NOTREACHED
}
-95
View File
@@ -1,95 +0,0 @@
#ifndef _json_c_json_visit_h_
#define _json_c_json_visit_h_
/**
* @file
* @brief Methods for walking a tree of objects.
*/
#include "json_object.h"
typedef int (json_c_visit_userfunc)(json_object *jso, int flags,
json_object *parent_jso, const char *jso_key,
size_t *jso_index, void *userarg);
/**
* Visit each object in the JSON hierarchy starting at jso.
* For each object, userfunc is called, passing the object and userarg.
* If the object has a parent (i.e. anything other than jso itself)
* its parent will be passed as parent_jso, and either jso_key or jso_index
* will be set, depending on whether the parent is an object or an array.
*
* Nodes will be visited depth first, but containers (arrays and objects)
* will be visited twice, the second time with JSON_C_VISIT_SECOND set in
* flags.
*
* userfunc must return one of the defined return values, to indicate
* whether and how to continue visiting nodes, or one of various ways to stop.
*
* Returns 0 if nodes were visited successfully, even if some were
* intentionally skipped due to what userfunc returned.
* Returns <0 if an error occurred during iteration, including if
* userfunc returned JSON_C_VISIT_RETURN_ERROR.
*/
int json_c_visit(json_object *jso, int future_flags,
json_c_visit_userfunc *userfunc, void *userarg);
/**
* Passed to json_c_visit_userfunc as one of the flags values to indicate
* that this is the second time a container (array or object) is being
* called, after all of it's members have been iterated over.
*/
#define JSON_C_VISIT_SECOND 0x02
/**
* This json_c_visit_userfunc return value indicates that iteration
* should proceed normally.
*/
#define JSON_C_VISIT_RETURN_CONTINUE 0
/**
* This json_c_visit_userfunc return value indicates that iteration
* over the members of the current object should be skipped.
* If the current object isn't a container (array or object), this
* is no different than JSON_C_VISIT_RETURN_CONTINUE.
*/
#define JSON_C_VISIT_RETURN_SKIP 7547
/**
* This json_c_visit_userfunc return value indicates that iteration
* of the fields/elements of the <b>containing</b> object should stop
* and continue "popped up" a level of the object hierarchy.
* For example, returning this when handling arg will result in
* arg3 and any other fields being skipped. The next call to userfunc
* will be the JSON_C_VISIT_SECOND call on "foo", followed by a userfunc
* call on "bar".
* <pre>
* {
* "foo": {
* "arg1": 1,
* "arg2": 2,
* "arg3": 3,
* ...
* },
* "bar": {
* ...
* }
* }
* </pre>
*/
#define JSON_C_VISIT_RETURN_POP 767
/**
* This json_c_visit_userfunc return value indicates that iteration
* should stop immediately, and cause json_c_visit to return success.
*/
#define JSON_C_VISIT_RETURN_STOP 7867
/**
* This json_c_visit_userfunc return value indicates that iteration
* should stop immediately, and cause json_c_visit to return an error.
*/
#define JSON_C_VISIT_RETURN_ERROR -1
#endif /* _json_c_json_visit_h_ */
-26
View File
@@ -1,26 +0,0 @@
/* dummy source file for compatibility purposes */
#if defined(HAVE_CDEFS_H)
#include <sys/cdefs.h>
#endif
#ifndef __warn_references
#if defined(__GNUC__) && defined (HAS_GNU_WARNING_LONG)
#define __warn_references(sym,msg) \
__asm__(".section .gnu" #sym ",\n\t.ascii \"" msg "\"\n\t.text");
#else
#define __warn_references(sym,msg) /* nothing */
#endif
#endif
#include "json_object.h"
__warn_references(json_object_get, "Warning: please link against libjson-c instead of libjson");
/* __asm__(".section .gnu.warning." __STRING(sym) \
" ; .ascii \"" msg "\" ; .text") */
-674
View File
@@ -1,674 +0,0 @@
/*
* $Id: linkhash.c,v 1.4 2006/01/26 02:16:28 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
* Copyright (c) 2009 Hewlett-Packard Development Company, L.P.
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*/
#include "config_json_c.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stddef.h>
#include <limits.h>
#ifdef HAVE_ENDIAN_H
# include <endian.h> /* attempt to define endianness */
#endif
#if defined(_MSC_VER) || defined(__MINGW32__)
# define WIN32_LEAN_AND_MEAN
# include <windows.h> /* Get InterlockedCompareExchange */
#endif
#include "random_seed.h"
#include "linkhash.h"
/* hash functions */
static unsigned long lh_char_hash(const void *k);
static unsigned long lh_perllike_str_hash(const void *k);
static lh_hash_fn *char_hash_fn = lh_char_hash;
int
json_global_set_string_hash(const int h)
{
switch(h) {
case JSON_C_STR_HASH_DFLT:
char_hash_fn = lh_char_hash;
break;
case JSON_C_STR_HASH_PERLLIKE:
char_hash_fn = lh_perllike_str_hash;
break;
default:
return -1;
}
return 0;
}
static unsigned long lh_ptr_hash(const void *k)
{
/* CAW: refactored to be 64bit nice */
return (unsigned long)((((ptrdiff_t)k * LH_PRIME) >> 4) & ULONG_MAX);
}
int lh_ptr_equal(const void *k1, const void *k2)
{
return (k1 == k2);
}
/*
* hashlittle from lookup3.c, by Bob Jenkins, May 2006, Public Domain.
* http://burtleburtle.net/bob/c/lookup3.c
* minor modifications to make functions static so no symbols are exported
* minor mofifications to compile with -Werror
*/
/*
-------------------------------------------------------------------------------
lookup3.c, by Bob Jenkins, May 2006, Public Domain.
These are functions for producing 32-bit hashes for hash table lookup.
hashword(), hashlittle(), hashlittle2(), hashbig(), mix(), and final()
are externally useful functions. Routines to test the hash are included
if SELF_TEST is defined. You can use this free for any purpose. It's in
the public domain. It has no warranty.
You probably want to use hashlittle(). hashlittle() and hashbig()
hash byte arrays. hashlittle() is is faster than hashbig() on
little-endian machines. Intel and AMD are little-endian machines.
On second thought, you probably want hashlittle2(), which is identical to
hashlittle() except it returns two 32-bit hashes for the price of one.
You could implement hashbig2() if you wanted but I haven't bothered here.
If you want to find a hash of, say, exactly 7 integers, do
a = i1; b = i2; c = i3;
mix(a,b,c);
a += i4; b += i5; c += i6;
mix(a,b,c);
a += i7;
final(a,b,c);
then use c as the hash value. If you have a variable length array of
4-byte integers to hash, use hashword(). If you have a byte array (like
a character string), use hashlittle(). If you have several byte arrays, or
a mix of things, see the comments above hashlittle().
Why is this so big? I read 12 bytes at a time into 3 4-byte integers,
then mix those integers. This is fast (you can do a lot more thorough
mixing with 12*3 instructions on 3 integers than you can with 3 instructions
on 1 byte), but shoehorning those bytes into integers efficiently is messy.
-------------------------------------------------------------------------------
*/
/*
* My best guess at if you are big-endian or little-endian. This may
* need adjustment.
*/
#if (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && \
__BYTE_ORDER == __LITTLE_ENDIAN) || \
(defined(i386) || defined(__i386__) || defined(__i486__) || \
defined(__i586__) || defined(__i686__) || defined(vax) || defined(MIPSEL))
# define HASH_LITTLE_ENDIAN 1
# define HASH_BIG_ENDIAN 0
#elif (defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && \
__BYTE_ORDER == __BIG_ENDIAN) || \
(defined(sparc) || defined(POWERPC) || defined(mc68000) || defined(sel))
# define HASH_LITTLE_ENDIAN 0
# define HASH_BIG_ENDIAN 1
#else
# define HASH_LITTLE_ENDIAN 0
# define HASH_BIG_ENDIAN 0
#endif
#define hashsize(n) ((uint32_t)1<<(n))
#define hashmask(n) (hashsize(n)-1)
#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k))))
/*
-------------------------------------------------------------------------------
mix -- mix 3 32-bit values reversibly.
This is reversible, so any information in (a,b,c) before mix() is
still in (a,b,c) after mix().
If four pairs of (a,b,c) inputs are run through mix(), or through
mix() in reverse, there are at least 32 bits of the output that
are sometimes the same for one pair and different for another pair.
This was tested for:
* pairs that differed by one bit, by two bits, in any combination
of top bits of (a,b,c), or in any combination of bottom bits of
(a,b,c).
* "differ" is defined as +, -, ^, or ~^. For + and -, I transformed
the output delta to a Gray code (a^(a>>1)) so a string of 1's (as
is commonly produced by subtraction) look like a single 1-bit
difference.
* the base values were pseudorandom, all zero but one bit set, or
all zero plus a counter that starts at zero.
Some k values for my "a-=c; a^=rot(c,k); c+=b;" arrangement that
satisfy this are
4 6 8 16 19 4
9 15 3 18 27 15
14 9 3 7 17 3
Well, "9 15 3 18 27 15" didn't quite get 32 bits diffing
for "differ" defined as + with a one-bit base and a two-bit delta. I
used http://burtleburtle.net/bob/hash/avalanche.html to choose
the operations, constants, and arrangements of the variables.
This does not achieve avalanche. There are input bits of (a,b,c)
that fail to affect some output bits of (a,b,c), especially of a. The
most thoroughly mixed value is c, but it doesn't really even achieve
avalanche in c.
This allows some parallelism. Read-after-writes are good at doubling
the number of bits affected, so the goal of mixing pulls in the opposite
direction as the goal of parallelism. I did what I could. Rotates
seem to cost as much as shifts on every machine I could lay my hands
on, and rotates are much kinder to the top and bottom bits, so I used
rotates.
-------------------------------------------------------------------------------
*/
#define mix(a,b,c) \
{ \
a -= c; a ^= rot(c, 4); c += b; \
b -= a; b ^= rot(a, 6); a += c; \
c -= b; c ^= rot(b, 8); b += a; \
a -= c; a ^= rot(c,16); c += b; \
b -= a; b ^= rot(a,19); a += c; \
c -= b; c ^= rot(b, 4); b += a; \
}
/*
-------------------------------------------------------------------------------
final -- final mixing of 3 32-bit values (a,b,c) into c
Pairs of (a,b,c) values differing in only a few bits will usually
produce values of c that look totally different. This was tested for
* pairs that differed by one bit, by two bits, in any combination
of top bits of (a,b,c), or in any combination of bottom bits of
(a,b,c).
* "differ" is defined as +, -, ^, or ~^. For + and -, I transformed
the output delta to a Gray code (a^(a>>1)) so a string of 1's (as
is commonly produced by subtraction) look like a single 1-bit
difference.
* the base values were pseudorandom, all zero but one bit set, or
all zero plus a counter that starts at zero.
These constants passed:
14 11 25 16 4 14 24
12 14 25 16 4 14 24
and these came close:
4 8 15 26 3 22 24
10 8 15 26 3 22 24
11 8 15 26 3 22 24
-------------------------------------------------------------------------------
*/
#define final(a,b,c) \
{ \
c ^= b; c -= rot(b,14); \
a ^= c; a -= rot(c,11); \
b ^= a; b -= rot(a,25); \
c ^= b; c -= rot(b,16); \
a ^= c; a -= rot(c,4); \
b ^= a; b -= rot(a,14); \
c ^= b; c -= rot(b,24); \
}
/*
-------------------------------------------------------------------------------
hashlittle() -- hash a variable-length key into a 32-bit value
k : the key (the unaligned variable-length array of bytes)
length : the length of the key, counting by bytes
initval : can be any 4-byte value
Returns a 32-bit value. Every bit of the key affects every bit of
the return value. Two keys differing by one or two bits will have
totally different hash values.
The best hash table sizes are powers of 2. There is no need to do
mod a prime (mod is sooo slow!). If you need less than 32 bits,
use a bitmask. For example, if you need only 10 bits, do
h = (h & hashmask(10));
In which case, the hash table should have hashsize(10) elements.
If you are hashing n strings (uint8_t **)k, do it like this:
for (i=0, h=0; i<n; ++i) h = hashlittle( k[i], len[i], h);
By Bob Jenkins, 2006. bob_jenkins@burtleburtle.net. You may use this
code any way you wish, private, educational, or commercial. It's free.
Use for hash table lookup, or anything where one collision in 2^^32 is
acceptable. Do NOT use for cryptographic purposes.
-------------------------------------------------------------------------------
*/
static uint32_t hashlittle( const void *key, size_t length, uint32_t initval)
{
uint32_t a,b,c; /* internal state */
union { const void *ptr; size_t i; } u; /* needed for Mac Powerbook G4 */
/* Set up the internal state */
a = b = c = 0xdeadbeef + ((uint32_t)length) + initval;
u.ptr = key;
if (HASH_LITTLE_ENDIAN && ((u.i & 0x3) == 0)) {
const uint32_t *k = (const uint32_t *)key; /* read 32-bit chunks */
/*------ all but last block: aligned reads and affect 32 bits of (a,b,c) */
while (length > 12)
{
a += k[0];
b += k[1];
c += k[2];
mix(a,b,c);
length -= 12;
k += 3;
}
/*----------------------------- handle the last (probably partial) block */
/*
* "k[2]&0xffffff" actually reads beyond the end of the string, but
* then masks off the part it's not allowed to read. Because the
* string is aligned, the masked-off tail is in the same word as the
* rest of the string. Every machine with memory protection I've seen
* does it on word boundaries, so is OK with this. But VALGRIND will
* still catch it and complain. The masking trick does make the hash
* noticably faster for short strings (like English words).
* AddressSanitizer is similarly picky about overrunning
* the buffer. (http://clang.llvm.org/docs/AddressSanitizer.html
*/
#ifdef VALGRIND
# define PRECISE_MEMORY_ACCESS 1
#elif defined(__SANITIZE_ADDRESS__) /* GCC's ASAN */
# define PRECISE_MEMORY_ACCESS 1
#elif defined(__has_feature)
# if __has_feature(address_sanitizer) /* Clang's ASAN */
# define PRECISE_MEMORY_ACCESS 1
# endif
#endif
#ifndef PRECISE_MEMORY_ACCESS
switch(length)
{
case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
case 11: c+=k[2]&0xffffff; b+=k[1]; a+=k[0]; break;
case 10: c+=k[2]&0xffff; b+=k[1]; a+=k[0]; break;
case 9 : c+=k[2]&0xff; b+=k[1]; a+=k[0]; break;
case 8 : b+=k[1]; a+=k[0]; break;
case 7 : b+=k[1]&0xffffff; a+=k[0]; break;
case 6 : b+=k[1]&0xffff; a+=k[0]; break;
case 5 : b+=k[1]&0xff; a+=k[0]; break;
case 4 : a+=k[0]; break;
case 3 : a+=k[0]&0xffffff; break;
case 2 : a+=k[0]&0xffff; break;
case 1 : a+=k[0]&0xff; break;
case 0 : return c; /* zero length strings require no mixing */
}
#else /* make valgrind happy */
const uint8_t *k8 = (const uint8_t *)k;
switch(length)
{
case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
case 11: c+=((uint32_t)k8[10])<<16; /* fall through */
case 10: c+=((uint32_t)k8[9])<<8; /* fall through */
case 9 : c+=k8[8]; /* fall through */
case 8 : b+=k[1]; a+=k[0]; break;
case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */
case 6 : b+=((uint32_t)k8[5])<<8; /* fall through */
case 5 : b+=k8[4]; /* fall through */
case 4 : a+=k[0]; break;
case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */
case 2 : a+=((uint32_t)k8[1])<<8; /* fall through */
case 1 : a+=k8[0]; break;
case 0 : return c;
}
#endif /* !valgrind */
} else if (HASH_LITTLE_ENDIAN && ((u.i & 0x1) == 0)) {
const uint16_t *k = (const uint16_t *)key; /* read 16-bit chunks */
const uint8_t *k8;
/*--------------- all but last block: aligned reads and different mixing */
while (length > 12)
{
a += k[0] + (((uint32_t)k[1])<<16);
b += k[2] + (((uint32_t)k[3])<<16);
c += k[4] + (((uint32_t)k[5])<<16);
mix(a,b,c);
length -= 12;
k += 6;
}
/*----------------------------- handle the last (probably partial) block */
k8 = (const uint8_t *)k;
switch(length)
{
case 12: c+=k[4]+(((uint32_t)k[5])<<16);
b+=k[2]+(((uint32_t)k[3])<<16);
a+=k[0]+(((uint32_t)k[1])<<16);
break;
case 11: c+=((uint32_t)k8[10])<<16; /* fall through */
case 10: c+=k[4];
b+=k[2]+(((uint32_t)k[3])<<16);
a+=k[0]+(((uint32_t)k[1])<<16);
break;
case 9 : c+=k8[8]; /* fall through */
case 8 : b+=k[2]+(((uint32_t)k[3])<<16);
a+=k[0]+(((uint32_t)k[1])<<16);
break;
case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */
case 6 : b+=k[2];
a+=k[0]+(((uint32_t)k[1])<<16);
break;
case 5 : b+=k8[4]; /* fall through */
case 4 : a+=k[0]+(((uint32_t)k[1])<<16);
break;
case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */
case 2 : a+=k[0];
break;
case 1 : a+=k8[0];
break;
case 0 : return c; /* zero length requires no mixing */
}
} else { /* need to read the key one byte at a time */
const uint8_t *k = (const uint8_t *)key;
/*--------------- all but the last block: affect some 32 bits of (a,b,c) */
while (length > 12)
{
a += k[0];
a += ((uint32_t)k[1])<<8;
a += ((uint32_t)k[2])<<16;
a += ((uint32_t)k[3])<<24;
b += k[4];
b += ((uint32_t)k[5])<<8;
b += ((uint32_t)k[6])<<16;
b += ((uint32_t)k[7])<<24;
c += k[8];
c += ((uint32_t)k[9])<<8;
c += ((uint32_t)k[10])<<16;
c += ((uint32_t)k[11])<<24;
mix(a,b,c);
length -= 12;
k += 12;
}
/*-------------------------------- last block: affect all 32 bits of (c) */
switch(length) /* all the case statements fall through */
{
case 12: c+=((uint32_t)k[11])<<24; /* FALLTHRU */
case 11: c+=((uint32_t)k[10])<<16; /* FALLTHRU */
case 10: c+=((uint32_t)k[9])<<8; /* FALLTHRU */
case 9 : c+=k[8]; /* FALLTHRU */
case 8 : b+=((uint32_t)k[7])<<24; /* FALLTHRU */
case 7 : b+=((uint32_t)k[6])<<16; /* FALLTHRU */
case 6 : b+=((uint32_t)k[5])<<8; /* FALLTHRU */
case 5 : b+=k[4]; /* FALLTHRU */
case 4 : a+=((uint32_t)k[3])<<24; /* FALLTHRU */
case 3 : a+=((uint32_t)k[2])<<16; /* FALLTHRU */
case 2 : a+=((uint32_t)k[1])<<8; /* FALLTHRU */
case 1 : a+=k[0];
break;
case 0 : return c;
}
}
final(a,b,c);
return c;
}
/* a simple hash function similiar to what perl does for strings.
* for good results, the string should not be excessivly large.
*/
static unsigned long lh_perllike_str_hash(const void *k)
{
const char *rkey = (const char *)k;
unsigned hashval = 1;
while (*rkey)
hashval = hashval * 33 + *rkey++;
return hashval;
}
static unsigned long lh_char_hash(const void *k)
{
#if defined _MSC_VER || defined __MINGW32__
#define RANDOM_SEED_TYPE LONG
#else
#define RANDOM_SEED_TYPE int
#endif
static volatile RANDOM_SEED_TYPE random_seed = -1;
if (random_seed == -1) {
RANDOM_SEED_TYPE seed;
/* we can't use -1 as it is the unitialized sentinel */
while ((seed = json_c_get_random_seed()) == -1);
#if SIZEOF_INT == 8 && defined __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8
#define USE_SYNC_COMPARE_AND_SWAP 1
#endif
#if SIZEOF_INT == 4 && defined __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4
#define USE_SYNC_COMPARE_AND_SWAP 1
#endif
#if SIZEOF_INT == 2 && defined __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2
#define USE_SYNC_COMPARE_AND_SWAP 1
#endif
#if defined USE_SYNC_COMPARE_AND_SWAP
(void)__sync_val_compare_and_swap(&random_seed, -1, seed);
#elif defined _MSC_VER || defined __MINGW32__
InterlockedCompareExchange(&random_seed, seed, -1);
#else
//#warning "racy random seed initializtion if used by multiple threads"
random_seed = seed; /* potentially racy */
#endif
}
return hashlittle((const char*)k, strlen((const char*)k), random_seed);
}
int lh_char_equal(const void *k1, const void *k2)
{
return (strcmp((const char*)k1, (const char*)k2) == 0);
}
struct lh_table* lh_table_new(int size,
lh_entry_free_fn *free_fn,
lh_hash_fn *hash_fn,
lh_equal_fn *equal_fn)
{
int i;
struct lh_table *t;
t = (struct lh_table*)calloc(1, sizeof(struct lh_table));
if (!t)
return NULL;
t->count = 0;
t->size = size;
t->table = (struct lh_entry*)calloc(size, sizeof(struct lh_entry));
if (!t->table)
{
free(t);
return NULL;
}
t->free_fn = free_fn;
t->hash_fn = hash_fn;
t->equal_fn = equal_fn;
for(i = 0; i < size; i++) t->table[i].k = LH_EMPTY;
return t;
}
struct lh_table* lh_kchar_table_new(int size,
lh_entry_free_fn *free_fn)
{
return lh_table_new(size, free_fn, char_hash_fn, lh_char_equal);
}
struct lh_table* lh_kptr_table_new(int size,
lh_entry_free_fn *free_fn)
{
return lh_table_new(size, free_fn, lh_ptr_hash, lh_ptr_equal);
}
int lh_table_resize(struct lh_table *t, int new_size)
{
struct lh_table *new_t;
struct lh_entry *ent;
new_t = lh_table_new(new_size, NULL, t->hash_fn, t->equal_fn);
if (new_t == NULL)
return -1;
for (ent = t->head; ent != NULL; ent = ent->next)
{
unsigned long h = lh_get_hash(new_t, ent->k);
unsigned int opts = 0;
if (ent->k_is_constant)
opts = JSON_C_OBJECT_KEY_IS_CONSTANT;
if (lh_table_insert_w_hash(new_t, ent->k, ent->v, h, opts) != 0)
{
lh_table_free(new_t);
return -1;
}
}
free(t->table);
t->table = new_t->table;
t->size = new_size;
t->head = new_t->head;
t->tail = new_t->tail;
free(new_t);
return 0;
}
void lh_table_free(struct lh_table *t)
{
struct lh_entry *c;
if(t->free_fn) {
for(c = t->head; c != NULL; c = c->next)
t->free_fn(c);
}
free(t->table);
free(t);
}
int lh_table_insert_w_hash(struct lh_table *t, const void *k, const void *v, const unsigned long h, const unsigned opts)
{
unsigned long n;
if (t->count >= t->size * LH_LOAD_FACTOR)
if (lh_table_resize(t, t->size * 2) != 0)
return -1;
n = h % t->size;
while( 1 ) {
if(t->table[n].k == LH_EMPTY || t->table[n].k == LH_FREED) break;
if ((int)++n == t->size) n = 0;
}
t->table[n].k = k;
t->table[n].k_is_constant = (opts & JSON_C_OBJECT_KEY_IS_CONSTANT);
t->table[n].v = v;
t->count++;
if(t->head == NULL) {
t->head = t->tail = &t->table[n];
t->table[n].next = t->table[n].prev = NULL;
} else {
t->tail->next = &t->table[n];
t->table[n].prev = t->tail;
t->table[n].next = NULL;
t->tail = &t->table[n];
}
return 0;
}
int lh_table_insert(struct lh_table *t, const void *k, const void *v)
{
return lh_table_insert_w_hash(t, k, v, lh_get_hash(t, k), 0);
}
struct lh_entry* lh_table_lookup_entry_w_hash(struct lh_table *t, const void *k, const unsigned long h)
{
unsigned long n = h % t->size;
int count = 0;
while( count < t->size ) {
if(t->table[n].k == LH_EMPTY) return NULL;
if(t->table[n].k != LH_FREED &&
t->equal_fn(t->table[n].k, k)) return &t->table[n];
if ((int)++n == t->size) n = 0;
count++;
}
return NULL;
}
struct lh_entry* lh_table_lookup_entry(struct lh_table *t, const void *k)
{
return lh_table_lookup_entry_w_hash(t, k, lh_get_hash(t, k));
}
json_bool lh_table_lookup_ex(struct lh_table* t, const void* k, void **v)
{
struct lh_entry *e = lh_table_lookup_entry(t, k);
if (e != NULL) {
if (v != NULL) *v = lh_entry_v(e);
return 1; /* key found */
}
if (v != NULL) *v = NULL;
return 0; /* key not found */
}
int lh_table_delete_entry(struct lh_table *t, struct lh_entry *e)
{
ptrdiff_t n = (ptrdiff_t)(e - t->table); /* CAW: fixed to be 64bit nice, still need the crazy negative case... */
/* CAW: this is bad, really bad, maybe stack goes other direction on this machine... */
if(n < 0) { return -2; }
if(t->table[n].k == LH_EMPTY || t->table[n].k == LH_FREED) return -1;
t->count--;
if(t->free_fn) t->free_fn(e);
t->table[n].v = NULL;
t->table[n].k = LH_FREED;
if(t->tail == &t->table[n] && t->head == &t->table[n]) {
t->head = t->tail = NULL;
} else if (t->head == &t->table[n]) {
t->head->next->prev = NULL;
t->head = t->head->next;
} else if (t->tail == &t->table[n]) {
t->tail->prev->next = NULL;
t->tail = t->tail->prev;
} else {
t->table[n].prev->next = t->table[n].next;
t->table[n].next->prev = t->table[n].prev;
}
t->table[n].next = t->table[n].prev = NULL;
return 0;
}
int lh_table_delete(struct lh_table *t, const void *k)
{
struct lh_entry *e = lh_table_lookup_entry(t, k);
if(!e) return -1;
return lh_table_delete_entry(t, e);
}
int lh_table_length(struct lh_table *t)
{
return t->count;
}
-381
View File
@@ -1,381 +0,0 @@
/*
* $Id: linkhash.h,v 1.6 2006/01/30 23:07:57 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
* Copyright (c) 2009 Hewlett-Packard Development Company, L.P.
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*/
/**
* @file
* @brief Internal methods for working with json_type_object objects. Although
* this is exposed by the json_object_get_object() function and within the
* json_object_iter type, it is not recommended for direct use.
*/
#ifndef _linkhash_h_
#define _linkhash_h_
#include "json_object.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* golden prime used in hash functions
*/
#define LH_PRIME 0x9e370001UL
/**
* The fraction of filled hash buckets until an insert will cause the table
* to be resized.
* This can range from just above 0 up to 1.0.
*/
#define LH_LOAD_FACTOR 0.66
/**
* sentinel pointer value for empty slots
*/
#define LH_EMPTY (void*)-1
/**
* sentinel pointer value for freed slots
*/
#define LH_FREED (void*)-2
/**
* default string hash function
*/
#define JSON_C_STR_HASH_DFLT 0
/**
* perl-like string hash function
*/
#define JSON_C_STR_HASH_PERLLIKE 1
/**
* This function sets the hash function to be used for strings.
* Must be one of the JSON_C_STR_HASH_* values.
* @returns 0 - ok, -1 if parameter was invalid
*/
int json_global_set_string_hash(const int h);
struct lh_entry;
/**
* callback function prototypes
*/
typedef void (lh_entry_free_fn) (struct lh_entry *e);
/**
* callback function prototypes
*/
typedef unsigned long (lh_hash_fn) (const void *k);
/**
* callback function prototypes
*/
typedef int (lh_equal_fn) (const void *k1, const void *k2);
/**
* An entry in the hash table
*/
struct lh_entry {
/**
* The key. Use lh_entry_k() instead of accessing this directly.
*/
const void *k;
/**
* A flag for users of linkhash to know whether or not they
* need to free k.
*/
int k_is_constant;
/**
* The value. Use lh_entry_v() instead of accessing this directly.
*/
const void *v;
/**
* The next entry
*/
struct lh_entry *next;
/**
* The previous entry.
*/
struct lh_entry *prev;
};
/**
* The hash table structure.
*/
struct lh_table {
/**
* Size of our hash.
*/
int size;
/**
* Numbers of entries.
*/
int count;
/**
* The first entry.
*/
struct lh_entry *head;
/**
* The last entry.
*/
struct lh_entry *tail;
struct lh_entry *table;
/**
* A pointer onto the function responsible for freeing an entry.
*/
lh_entry_free_fn *free_fn;
lh_hash_fn *hash_fn;
lh_equal_fn *equal_fn;
};
typedef struct lh_table lh_table;
/**
* Convenience list iterator.
*/
#define lh_foreach(table, entry) \
for(entry = table->head; entry; entry = entry->next)
/**
* lh_foreach_safe allows calling of deletion routine while iterating.
*
* @param table a struct lh_table * to iterate over
* @param entry a struct lh_entry * variable to hold each element
* @param tmp a struct lh_entry * variable to hold a temporary pointer to the next element
*/
#define lh_foreach_safe(table, entry, tmp) \
for(entry = table->head; entry && ((tmp = entry->next) || 1); entry = tmp)
/**
* Create a new linkhash table.
*
* @param size initial table size. The table is automatically resized
* although this incurs a performance penalty.
* @param free_fn callback function used to free memory for entries
* when lh_table_free or lh_table_delete is called.
* If NULL is provided, then memory for keys and values
* must be freed by the caller.
* @param hash_fn function used to hash keys. 2 standard ones are defined:
* lh_ptr_hash and lh_char_hash for hashing pointer values
* and C strings respectively.
* @param equal_fn comparison function to compare keys. 2 standard ones defined:
* lh_ptr_hash and lh_char_hash for comparing pointer values
* and C strings respectively.
* @return On success, a pointer to the new linkhash table is returned.
* On error, a null pointer is returned.
*/
extern struct lh_table* lh_table_new(int size,
lh_entry_free_fn *free_fn,
lh_hash_fn *hash_fn,
lh_equal_fn *equal_fn);
/**
* Convenience function to create a new linkhash table with char keys.
*
* @param size initial table size.
* @param free_fn callback function used to free memory for entries.
* @return On success, a pointer to the new linkhash table is returned.
* On error, a null pointer is returned.
*/
extern struct lh_table* lh_kchar_table_new(int size,
lh_entry_free_fn *free_fn);
/**
* Convenience function to create a new linkhash table with ptr keys.
*
* @param size initial table size.
* @param free_fn callback function used to free memory for entries.
* @return On success, a pointer to the new linkhash table is returned.
* On error, a null pointer is returned.
*/
extern struct lh_table* lh_kptr_table_new(int size,
lh_entry_free_fn *free_fn);
/**
* Free a linkhash table.
*
* If a lh_entry_free_fn callback free function was provided then it is
* called for all entries in the table.
*
* @param t table to free.
*/
extern void lh_table_free(struct lh_table *t);
/**
* Insert a record into the table.
*
* @param t the table to insert into.
* @param k a pointer to the key to insert.
* @param v a pointer to the value to insert.
*
* @return On success, <code>0</code> is returned.
* On error, a negative value is returned.
*/
extern int lh_table_insert(struct lh_table *t, const void *k, const void *v);
/**
* Insert a record into the table using a precalculated key hash.
*
* The hash h, which should be calculated with lh_get_hash() on k, is provided by
* the caller, to allow for optimization when multiple operations with the same
* key are known to be needed.
*
* @param t the table to insert into.
* @param k a pointer to the key to insert.
* @param v a pointer to the value to insert.
* @param h hash value of the key to insert
* @param opts if set to JSON_C_OBJECT_KEY_IS_CONSTANT, sets lh_entry.k_is_constant
* so t's free function knows to avoid freeing the key.
*/
extern int lh_table_insert_w_hash(struct lh_table *t, const void *k, const void *v, const unsigned long h, const unsigned opts);
/**
* Lookup a record in the table.
*
* @param t the table to lookup
* @param k a pointer to the key to lookup
* @return a pointer to the record structure of the value or NULL if it does not exist.
*/
extern struct lh_entry* lh_table_lookup_entry(struct lh_table *t, const void *k);
/**
* Lookup a record in the table using a precalculated key hash.
*
* The hash h, which should be calculated with lh_get_hash() on k, is provided by
* the caller, to allow for optimization when multiple operations with the same
* key are known to be needed.
*
* @param t the table to lookup
* @param k a pointer to the key to lookup
* @param h hash value of the key to lookup
* @return a pointer to the record structure of the value or NULL if it does not exist.
*/
extern struct lh_entry* lh_table_lookup_entry_w_hash(struct lh_table *t, const void *k, const unsigned long h);
/**
* Lookup a record in the table.
*
* @param t the table to lookup
* @param k a pointer to the key to lookup
* @param v a pointer to a where to store the found value (set to NULL if it doesn't exist).
* @return whether or not the key was found
*/
extern json_bool lh_table_lookup_ex(struct lh_table *t, const void *k, void **v);
/**
* Delete a record from the table.
*
* If a callback free function is provided then it is called for the
* for the item being deleted.
* @param t the table to delete from.
* @param e a pointer to the entry to delete.
* @return 0 if the item was deleted.
* @return -1 if it was not found.
*/
extern int lh_table_delete_entry(struct lh_table *t, struct lh_entry *e);
/**
* Delete a record from the table.
*
* If a callback free function is provided then it is called for the
* for the item being deleted.
* @param t the table to delete from.
* @param k a pointer to the key to delete.
* @return 0 if the item was deleted.
* @return -1 if it was not found.
*/
extern int lh_table_delete(struct lh_table *t, const void *k);
extern int lh_table_length(struct lh_table *t);
/**
* Resizes the specified table.
*
* @param t Pointer to table to resize.
* @param new_size New table size. Must be positive.
*
* @return On success, <code>0</code> is returned.
* On error, a negative value is returned.
*/
int lh_table_resize(struct lh_table *t, int new_size);
/**
* @deprecated Don't use this outside of linkhash.h:
*/
#if !defined(_MSC_VER) || (_MSC_VER > 1800)
/* VS2010 can't handle inline funcs, so skip it there */
#define _LH_INLINE inline
#else
#define _LH_INLINE
#endif
/**
* Calculate the hash of a key for a given table.
*
* This is an exension to support functions that need to calculate
* the hash several times and allows them to do it just once and then pass
* in the hash to all utility functions. Depending on use case, this can be a
* considerable performance improvement.
* @param t the table (used to obtain hash function)
* @param k a pointer to the key to lookup
* @return the key's hash
*/
static _LH_INLINE unsigned long lh_get_hash(const struct lh_table *t, const void *k)
{
return t->hash_fn(k);
}
#undef _LH_INLINE
/**
* @deprecated Don't use this outside of linkhash.h:
*/
#ifdef __UNCONST
#define _LH_UNCONST(a) __UNCONST(a)
#else
#define _LH_UNCONST(a) ((void *)(uintptr_t)(const void *)(a))
#endif
/**
* Return a non-const version of lh_entry.k.
*
* lh_entry.k is const to indicate and help ensure that linkhash itself doesn't modify
* it, but callers are allowed to do what they want with it.
* See also lh_entry.k_is_constant
*/
#define lh_entry_k(entry) _LH_UNCONST((entry)->k)
/**
* Return a non-const version of lh_entry.v.
*
* v is const to indicate and help ensure that linkhash itself doesn't modify
* it, but callers are allowed to do what they want with it.
*/
#define lh_entry_v(entry) _LH_UNCONST((entry)->v)
#ifdef __cplusplus
}
#endif
#endif
@@ -1,36 +0,0 @@
#ifndef __math_compat_h
#define __math_compat_h
/**
* @file
* @brief Do not use, json-c internal, may be changed or removed at any time.
*/
/* Define isnan, isinf, infinity and nan on Windows/MSVC */
#ifndef HAVE_DECL_ISNAN
# ifdef HAVE_DECL__ISNAN
#include <float.h>
#define isnan(x) _isnan(x)
# endif
#endif
#ifndef HAVE_DECL_ISINF
# ifdef HAVE_DECL__FINITE
#include <float.h>
#define isinf(x) (!_finite(x))
# endif
#endif
#ifndef HAVE_DECL_INFINITY
#include <float.h>
#define INFINITY (DBL_MAX + DBL_MAX)
#define HAVE_DECL_INFINITY
#endif
#ifndef HAVE_DECL_NAN
#define NAN (INFINITY - INFINITY)
#define HAVE_DECL_NAN
#endif
#endif
-155
View File
@@ -1,155 +0,0 @@
/*
* $Id: printbuf.c,v 1.5 2006/01/26 02:16:28 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*
* Copyright (c) 2008-2009 Yahoo! Inc. All rights reserved.
* The copyrights to the contents of this file are licensed under the MIT License
* (http://www.opensource.org/licenses/mit-license.php)
*/
#include "config_json_c.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_STDARG_H
# include <stdarg.h>
#else /* !HAVE_STDARG_H */
# error Not enough var arg support!
#endif /* HAVE_STDARG_H */
#include "debug.h"
#include "printbuf.h"
#include "snprintf_compat.h"
#include "vasprintf_compat.h"
static int printbuf_extend(struct printbuf *p, int min_size);
struct printbuf* printbuf_new(void)
{
struct printbuf *p;
p = (struct printbuf*)calloc(1, sizeof(struct printbuf));
if(!p) return NULL;
p->size = 32;
p->bpos = 0;
if(!(p->buf = (char*)malloc(p->size))) {
free(p);
return NULL;
}
p->buf[0]= '\0';
return p;
}
/**
* Extend the buffer p so it has a size of at least min_size.
*
* If the current size is large enough, nothing is changed.
*
* Note: this does not check the available space! The caller
* is responsible for performing those calculations.
*/
static int printbuf_extend(struct printbuf *p, int min_size)
{
char *t;
int new_size;
if (p->size >= min_size)
return 0;
new_size = p->size * 2;
if (new_size < min_size + 8)
new_size = min_size + 8;
#ifdef PRINTBUF_DEBUG
MC_DEBUG("printbuf_memappend: realloc "
"bpos=%d min_size=%d old_size=%d new_size=%d\n",
p->bpos, min_size, p->size, new_size);
#endif /* PRINTBUF_DEBUG */
if(!(t = (char*)realloc(p->buf, new_size)))
return -1;
p->size = new_size;
p->buf = t;
return 0;
}
int printbuf_memappend(struct printbuf *p, const char *buf, int size)
{
if (p->size <= p->bpos + size + 1) {
if (printbuf_extend(p, p->bpos + size + 1) < 0)
return -1;
}
memcpy(p->buf + p->bpos, buf, size);
p->bpos += size;
p->buf[p->bpos]= '\0';
return size;
}
int printbuf_memset(struct printbuf *pb, int offset, int charvalue, int len)
{
int size_needed;
if (offset == -1)
offset = pb->bpos;
size_needed = offset + len;
if (pb->size < size_needed)
{
if (printbuf_extend(pb, size_needed) < 0)
return -1;
}
memset(pb->buf + offset, charvalue, len);
if (pb->bpos < size_needed)
pb->bpos = size_needed;
return 0;
}
int sprintbuf(struct printbuf *p, const char *msg, ...)
{
va_list ap;
char *t;
int size;
char buf[128];
/* user stack buffer first */
va_start(ap, msg);
size = vsnprintf(buf, 128, msg, ap);
va_end(ap);
/* if string is greater than stack buffer, then use dynamic string
with vasprintf. Note: some implementation of vsnprintf return -1
if output is truncated whereas some return the number of bytes that
would have been written - this code handles both cases. */
if(size == -1 || size > 127) {
va_start(ap, msg);
if((size = vasprintf(&t, msg, ap)) < 0) { va_end(ap); return -1; }
va_end(ap);
printbuf_memappend(p, t, size);
free(t);
return size;
} else {
printbuf_memappend(p, buf, size);
return size;
}
}
void printbuf_reset(struct printbuf *p)
{
p->buf[0] = '\0';
p->bpos = 0;
}
void printbuf_free(struct printbuf *p)
{
if(p) {
free(p->buf);
free(p);
}
}
-122
View File
@@ -1,122 +0,0 @@
/*
* $Id: printbuf.h,v 1.4 2006/01/26 02:16:28 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*
* Copyright (c) 2008-2009 Yahoo! Inc. All rights reserved.
* The copyrights to the contents of this file are licensed under the MIT License
* (http://www.opensource.org/licenses/mit-license.php)
*/
/**
* @file
* @brief Internal string buffer handing. Unless you're writing a
* json_object_to_json_string_fn implementation for use with
* json_object_set_serializer() direct use of this is not
* recommended.
*/
#ifndef _printbuf_h_
#define _printbuf_h_
#ifdef __cplusplus
extern "C" {
#endif
struct printbuf {
char *buf;
int bpos;
int size;
};
typedef struct printbuf printbuf;
extern struct printbuf*
printbuf_new(void);
/* As an optimization, printbuf_memappend_fast() is defined as a macro
* that handles copying data if the buffer is large enough; otherwise
* it invokes printbuf_memappend() which performs the heavy
* lifting of realloc()ing the buffer and copying data.
*
* Your code should not use printbuf_memappend() directly unless it
* checks the return code. Use printbuf_memappend_fast() instead.
*/
extern int
printbuf_memappend(struct printbuf *p, const char *buf, int size);
#define printbuf_memappend_fast(p, bufptr, bufsize) \
do { \
if ((p->size - p->bpos) > bufsize) { \
memcpy(p->buf + p->bpos, (bufptr), bufsize); \
p->bpos += bufsize; \
p->buf[p->bpos]= '\0'; \
} else { printbuf_memappend(p, (bufptr), bufsize); } \
} while (0)
#define printbuf_length(p) ((p)->bpos)
/**
* Results in a compile error if the argument is not a string literal.
*/
#define _printbuf_check_literal(mystr) ("" mystr)
/**
* This is an optimization wrapper around printbuf_memappend() that is useful
* for appending string literals. Since the size of string constants is known
* at compile time, using this macro can avoid a costly strlen() call. This is
* especially helpful when a constant string must be appended many times. If
* you got here because of a compilation error caused by passing something
* other than a string literal, use printbuf_memappend_fast() in conjunction
* with strlen().
*
* See also:
* printbuf_memappend_fast()
* printbuf_memappend()
* sprintbuf()
*/
#define printbuf_strappend(pb, str) \
printbuf_memappend ((pb), _printbuf_check_literal(str), sizeof(str) - 1)
/**
* Set len bytes of the buffer to charvalue, starting at offset offset.
* Similar to calling memset(x, charvalue, len);
*
* The memory allocated for the buffer is extended as necessary.
*
* If offset is -1, this starts at the end of the current data in the buffer.
*/
extern int
printbuf_memset(struct printbuf *pb, int offset, int charvalue, int len);
/**
* Formatted print to printbuf.
*
* This function is the most expensive of the available functions for appending
* string data to a printbuf and should be used only where convenience is more
* important than speed. Avoid using this function in high performance code or
* tight loops; in these scenarios, consider using snprintf() with a static
* buffer in conjunction with one of the printbuf_*append() functions.
*
* See also:
* printbuf_memappend_fast()
* printbuf_memappend()
* printbuf_strappend()
*/
extern int
sprintbuf(struct printbuf *p, const char *msg, ...);
extern void
printbuf_reset(struct printbuf *p);
extern void
printbuf_free(struct printbuf *p);
#ifdef __cplusplus
}
#endif
#endif
-238
View File
@@ -1,238 +0,0 @@
/*
* random_seed.c
*
* Copyright (c) 2013 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*/
#include "strerror_override.h"
#include <stdio.h>
#include "config_json_c.h"
#include "random_seed.h"
#define DEBUG_SEED(s)
#if defined ENABLE_RDRAND
/* cpuid */
#if defined __GNUC__ && (defined __i386__ || defined __x86_64__)
#define HAS_X86_CPUID 1
static void do_cpuid(int regs[], int h)
{
__asm__ __volatile__(
#if defined __x86_64__
"pushq %%rbx;\n"
#else
"pushl %%ebx;\n"
#endif
"cpuid;\n"
#if defined __x86_64__
"popq %%rbx;\n"
#else
"popl %%ebx;\n"
#endif
: "=a"(regs[0]), [ebx] "=r"(regs[1]), "=c"(regs[2]), "=d"(regs[3])
: "a"(h));
}
#elif defined _MSC_VER
#define HAS_X86_CPUID 1
#define do_cpuid __cpuid
#endif
/* has_rdrand */
#if HAS_X86_CPUID
static int has_rdrand()
{
// CPUID.01H:ECX.RDRAND[bit 30] == 1
int regs[4];
do_cpuid(regs, 1);
return (regs[2] & (1 << 30)) != 0;
}
#endif
/* get_rdrand_seed - GCC x86 and X64 */
#if defined __GNUC__ && (defined __i386__ || defined __x86_64__)
#define HAVE_RDRAND 1
static int get_rdrand_seed()
{
DEBUG_SEED("get_rdrand_seed");
int _eax;
// rdrand eax
__asm__ __volatile__("1: .byte 0x0F\n"
" .byte 0xC7\n"
" .byte 0xF0\n"
" jnc 1b;\n"
: "=a" (_eax));
return _eax;
}
#endif
#if defined _MSC_VER
#if _MSC_VER >= 1700
#define HAVE_RDRAND 1
/* get_rdrand_seed - Visual Studio 2012 and above */
static int get_rdrand_seed()
{
DEBUG_SEED("get_rdrand_seed");
int r;
while (_rdrand32_step(&r) == 0);
return r;
}
#elif defined _M_IX86
#define HAVE_RDRAND 1
/* get_rdrand_seed - Visual Studio 2010 and below - x86 only */
static int get_rdrand_seed()
{
DEBUG_SEED("get_rdrand_seed");
int _eax;
retry:
// rdrand eax
__asm _emit 0x0F __asm _emit 0xC7 __asm _emit 0xF0
__asm jnc retry
__asm mov _eax, eax
return _eax;
}
#endif
#endif
#endif /* defined ENABLE_RDRAND */
/* has_dev_urandom */
#if defined (__APPLE__) || defined(__unix__) || defined(__linux__)
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
#define HAVE_DEV_RANDOM 1
static const char *dev_random_file = "/dev/urandom";
static int has_dev_urandom()
{
struct stat buf;
if (stat(dev_random_file, &buf)) {
return 0;
}
return ((buf.st_mode & S_IFCHR) != 0);
}
/* get_dev_random_seed */
static int get_dev_random_seed()
{
DEBUG_SEED("get_dev_random_seed");
int fd = open(dev_random_file, O_RDONLY);
if (fd < 0) {
fprintf(stderr, "error opening %s: %s", dev_random_file, strerror(errno));
exit(1);
}
int r;
ssize_t nread = read(fd, &r, sizeof(r));
if (nread != sizeof(r)) {
fprintf(stderr, "error short read %s: %s", dev_random_file, strerror(errno));
exit(1);
}
close(fd);
return r;
}
#endif
/* get_cryptgenrandom_seed */
#ifdef WIN32
#define HAVE_CRYPTGENRANDOM 1
#include <windows.h>
#include <wincrypt.h>
#ifndef __GNUC__
#pragma comment(lib, "advapi32.lib")
#endif
static int get_cryptgenrandom_seed()
{
HCRYPTPROV hProvider = 0;
int r;
DEBUG_SEED("get_cryptgenrandom_seed");
if (!CryptAcquireContextW(&hProvider, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) {
fprintf(stderr, "error CryptAcquireContextW");
exit(1);
}
if (!CryptGenRandom(hProvider, sizeof(r), (BYTE*)&r)) {
fprintf(stderr, "error CryptGenRandom");
exit(1);
}
CryptReleaseContext(hProvider, 0);
return r;
}
#endif
/* get_time_seed */
#include <time.h>
static int get_time_seed()
{
DEBUG_SEED("get_time_seed");
return (int)time(NULL) * 433494437;
}
/* json_c_get_random_seed */
int json_c_get_random_seed()
{
#if HAVE_RDRAND
if (has_rdrand()) return get_rdrand_seed();
#endif
#if HAVE_DEV_RANDOM
if (has_dev_urandom()) return get_dev_random_seed();
#endif
#if HAVE_CRYPTGENRANDOM
return get_cryptgenrandom_seed();
#endif
return get_time_seed();
}
@@ -1,29 +0,0 @@
/*
* random_seed.h
*
* Copyright (c) 2013 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*/
/**
* @file
* @brief Do not use, json-c internal, may be changed or removed at any time.
*/
#ifndef seed_h
#define seed_h
#ifdef __cplusplus
extern "C" {
#endif
extern int json_c_get_random_seed();
#ifdef __cplusplus
}
#endif
#endif
@@ -1,41 +0,0 @@
#ifndef __snprintf_compat_h
#define __snprintf_compat_h
/**
* @file
* @brief Do not use, json-c internal, may be changed or removed at any time.
*/
/*
* Microsoft's _vsnprintf and _snprint don't always terminate
* the string, so use wrappers that ensure that.
*/
#include <stdarg.h>
#if !defined(HAVE_SNPRINTF) && defined(_MSC_VER)
static int json_c_vsnprintf(char *str, size_t size, const char *format, va_list ap)
{
int ret;
ret = _vsnprintf(str, size, format, ap);
str[size - 1] = '\0';
return ret;
}
#define vsnprintf json_c_vsnprintf
static int json_c_snprintf(char *str, size_t size, const char *format, ...)
{
va_list ap;
int ret;
va_start(ap, format);
ret = json_c_vsnprintf(str, size, format, ap);
va_end(ap);
return ret;
}
#define snprintf json_c_snprintf
#elif !defined(HAVE_SNPRINTF) /* !HAVE_SNPRINTF */
# error Need vsnprintf!
#endif /* !HAVE_SNPRINTF && defined(WIN32) */
#endif /* __snprintf_compat_h */
@@ -1,16 +0,0 @@
#ifndef __strdup_compat_h
#define __strdup_compat_h
/**
* @file
* @brief Do not use, json-c internal, may be changed or removed at any time.
*/
#if !defined(HAVE_STRDUP) && defined(_MSC_VER)
/* MSC has the version as _strdup */
# define strdup _strdup
#elif !defined(HAVE_STRDUP)
# error You do not have strdup on your system.
#endif /* HAVE_STRDUP */
#endif
@@ -1,101 +0,0 @@
#define STRERROR_OVERRIDE_IMPL 1
#include "strerror_override.h"
/*
* Override strerror() to get consistent output across platforms.
*/
static struct {
int errno_value;
const char *errno_str;
} errno_list[] = {
#define STRINGIFY(x) #x
#define ENTRY(x) {x, &STRINGIFY(undef_ ## x)[6]}
ENTRY(EPERM),
ENTRY(ENOENT),
ENTRY(ESRCH),
ENTRY(EINTR),
ENTRY(EIO),
ENTRY(ENXIO),
ENTRY(E2BIG),
ENTRY(ENOEXEC),
ENTRY(EBADF),
ENTRY(ECHILD),
ENTRY(EDEADLK),
ENTRY(ENOMEM),
ENTRY(EACCES),
ENTRY(EFAULT),
#ifdef ENOTBLK
ENTRY(ENOTBLK),
#endif
ENTRY(EBUSY),
ENTRY(EEXIST),
ENTRY(EXDEV),
ENTRY(ENODEV),
ENTRY(ENOTDIR),
ENTRY(EISDIR),
ENTRY(EINVAL),
ENTRY(ENFILE),
ENTRY(EMFILE),
ENTRY(ENOTTY),
#ifdef ETXTBSY
ENTRY(ETXTBSY),
#endif
ENTRY(EFBIG),
ENTRY(ENOSPC),
ENTRY(ESPIPE),
ENTRY(EROFS),
ENTRY(EMLINK),
ENTRY(EPIPE),
ENTRY(EDOM),
ENTRY(ERANGE),
ENTRY(EAGAIN),
{ 0, (char *)0 }
};
// Enabled during tests
int _json_c_strerror_enable = 0;
#define PREFIX "ERRNO="
static char errno_buf[128] = PREFIX;
char *_json_c_strerror(int errno_in)
{
int start_idx;
char digbuf[20];
int ii, jj;
if (!_json_c_strerror_enable)
return strerror(errno_in);
// Avoid standard functions, so we don't need to include any
// headers, or guess at signatures.
for (ii = 0; errno_list[ii].errno_str != (char *)0; ii++)
{
const char *errno_str = errno_list[ii].errno_str;
if (errno_list[ii].errno_value != errno_in)
continue;
for (start_idx = sizeof(PREFIX) - 1, jj = 0; errno_str[jj] != '\0'; jj++, start_idx++)
{
errno_buf[start_idx] = errno_str[jj];
}
errno_buf[start_idx] = '\0';
return errno_buf;
}
// It's not one of the known errno values, return the numeric value.
for (ii = 0; errno_in > 10; errno_in /= 10, ii++)
{
digbuf[ii] = "0123456789"[(errno_in % 10)];
}
digbuf[ii] = "0123456789"[(errno_in % 10)];
// Reverse the digits
for (start_idx = sizeof(PREFIX) - 1 ; ii >= 0; ii--, start_idx++)
{
errno_buf[start_idx] = digbuf[ii];
}
return errno_buf;
}
@@ -1,30 +0,0 @@
#ifndef _json_strerror_override_h_
#define _json_strerror_override_h_
/**
* @file
* @brief Do not use, json-c internal, may be changed or removed at any time.
*/
#include "config_json_c.h"
#include <errno.h>
#include "json_object.h" /* for JSON_EXPORT */
#ifdef __cplusplus
extern "C" {
#endif
#include <string.h>
JSON_EXPORT char *_json_c_strerror(int errno_in);
#ifndef STRERROR_OVERRIDE_IMPL
#define strerror _json_c_strerror
#endif
#ifdef __cplusplus
}
#endif
#endif /* _json_strerror_override_h_ */
@@ -1,12 +0,0 @@
#ifndef __json_strerror_override_private_h__
#define __json_strerror_override_private_h__
/**
* @file
* @brief Do not use, json-c internal, may be changed or removed at any time.
*/
/* Used by tests to get consistent output */
extern int _json_c_strerror_enable;
#endif
@@ -1,46 +0,0 @@
#ifndef __vasprintf_compat_h
#define __vasprintf_compat_h
/**
* @file
* @brief Do not use, json-c internal, may be changed or removed at any time.
*/
#include "snprintf_compat.h"
#if !defined(HAVE_VASPRINTF)
/* CAW: compliant version of vasprintf */
static int vasprintf(char **buf, const char *fmt, va_list ap)
{
#ifndef WIN32
static char _T_emptybuffer = '\0';
#endif /* !defined(WIN32) */
int chars;
char *b;
if(!buf) { return -1; }
#ifdef WIN32
chars = _vscprintf(fmt, ap)+1;
#else /* !defined(WIN32) */
/* CAW: RAWR! We have to hope to god here that vsnprintf doesn't overwrite
our buffer like on some 64bit sun systems.... but hey, its time to move on */
chars = vsnprintf(&_T_emptybuffer, 0, fmt, ap)+1;
if(chars < 0) { chars *= -1; } /* CAW: old glibc versions have this problem */
#endif /* defined(WIN32) */
b = (char*)malloc(sizeof(char)*chars);
if(!b) { return -1; }
if((chars = vsprintf(b, fmt, ap)) < 0)
{
free(b);
} else {
*buf = b;
}
return chars;
}
#endif /* !HAVE_VASPRINTF */
#endif /* __vasprintf_compat_h */
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,2 @@
@CMAKE_CONFIGURABLE_FILE_CONTENT@
@@ -0,0 +1,61 @@
include(CheckCSourceCompiles)
option(CURL_HIDDEN_SYMBOLS "Set to ON to hide libcurl internal symbols (=hide all symbols that aren't officially external)." ON)
mark_as_advanced(CURL_HIDDEN_SYMBOLS)
if(CURL_HIDDEN_SYMBOLS)
set(SUPPORTS_SYMBOL_HIDING FALSE)
if(CMAKE_C_COMPILER_ID MATCHES "Clang")
set(SUPPORTS_SYMBOL_HIDING TRUE)
set(_SYMBOL_EXTERN "__attribute__ ((__visibility__ (\"default\")))")
set(_CFLAG_SYMBOLS_HIDE "-fvisibility=hidden")
elseif(CMAKE_COMPILER_IS_GNUCC)
if(NOT CMAKE_VERSION VERSION_LESS 2.8.10)
set(GCC_VERSION ${CMAKE_C_COMPILER_VERSION})
else()
execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion
OUTPUT_VARIABLE GCC_VERSION)
endif()
if(NOT GCC_VERSION VERSION_LESS 3.4)
# note: this is considered buggy prior to 4.0 but the autotools don't care, so let's ignore that fact
set(SUPPORTS_SYMBOL_HIDING TRUE)
set(_SYMBOL_EXTERN "__attribute__ ((__visibility__ (\"default\")))")
set(_CFLAG_SYMBOLS_HIDE "-fvisibility=hidden")
endif()
elseif(CMAKE_C_COMPILER_ID MATCHES "SunPro" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 8.0)
set(SUPPORTS_SYMBOL_HIDING TRUE)
set(_SYMBOL_EXTERN "__global")
set(_CFLAG_SYMBOLS_HIDE "-xldscope=hidden")
elseif(CMAKE_C_COMPILER_ID MATCHES "Intel" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 9.0)
# note: this should probably just check for version 9.1.045 but I'm not 100% sure
# so let's to it the same way autotools do.
set(SUPPORTS_SYMBOL_HIDING TRUE)
set(_SYMBOL_EXTERN "__attribute__ ((__visibility__ (\"default\")))")
set(_CFLAG_SYMBOLS_HIDE "-fvisibility=hidden")
check_c_source_compiles("#include <stdio.h>
int main (void) { printf(\"icc fvisibility bug test\"); return 0; }" _no_bug)
if(NOT _no_bug)
set(SUPPORTS_SYMBOL_HIDING FALSE)
set(_SYMBOL_EXTERN "")
set(_CFLAG_SYMBOLS_HIDE "")
endif()
elseif(MSVC)
set(SUPPORTS_SYMBOL_HIDING TRUE)
endif()
set(HIDES_CURL_PRIVATE_SYMBOLS ${SUPPORTS_SYMBOL_HIDING})
elseif(MSVC)
if(NOT CMAKE_VERSION VERSION_LESS 3.7)
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS TRUE) #present since 3.4.3 but broken
set(HIDES_CURL_PRIVATE_SYMBOLS FALSE)
else()
message(WARNING "Hiding private symbols regardless CURL_HIDDEN_SYMBOLS being disabled.")
set(HIDES_CURL_PRIVATE_SYMBOLS TRUE)
endif()
elseif()
set(HIDES_CURL_PRIVATE_SYMBOLS FALSE)
endif()
set(CURL_CFLAG_SYMBOLS_HIDE ${_CFLAG_SYMBOLS_HIDE})
set(CURL_EXTERN_SYMBOL ${_SYMBOL_EXTERN})
+535
View File
@@ -0,0 +1,535 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
***************************************************************************/
#ifdef TIME_WITH_SYS_TIME
/* Time with sys/time test */
#include <sys/types.h>
#include <sys/time.h>
#include <time.h>
int
main ()
{
if ((struct tm *) 0)
return 0;
;
return 0;
}
#endif
#ifdef HAVE_FCNTL_O_NONBLOCK
/* headers for FCNTL_O_NONBLOCK test */
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
/* */
#if defined(sun) || defined(__sun__) || \
defined(__SUNPRO_C) || defined(__SUNPRO_CC)
# if defined(__SVR4) || defined(__srv4__)
# define PLATFORM_SOLARIS
# else
# define PLATFORM_SUNOS4
# endif
#endif
#if (defined(_AIX) || defined(__xlC__)) && !defined(_AIX41)
# define PLATFORM_AIX_V3
#endif
/* */
#if defined(PLATFORM_SUNOS4) || defined(PLATFORM_AIX_V3) || defined(__BEOS__)
#error "O_NONBLOCK does not work on this platform"
#endif
int
main ()
{
/* O_NONBLOCK source test */
int flags = 0;
if(0 != fcntl(0, F_SETFL, flags | O_NONBLOCK))
return 1;
return 0;
}
#endif
/* tests for gethostbyaddr_r or gethostbyname_r */
#if defined(HAVE_GETHOSTBYADDR_R_5_REENTRANT) || \
defined(HAVE_GETHOSTBYADDR_R_7_REENTRANT) || \
defined(HAVE_GETHOSTBYADDR_R_8_REENTRANT) || \
defined(HAVE_GETHOSTBYNAME_R_3_REENTRANT) || \
defined(HAVE_GETHOSTBYNAME_R_5_REENTRANT) || \
defined(HAVE_GETHOSTBYNAME_R_6_REENTRANT)
# define _REENTRANT
/* no idea whether _REENTRANT is always set, just invent a new flag */
# define TEST_GETHOSTBYFOO_REENTRANT
#endif
#if defined(HAVE_GETHOSTBYADDR_R_5) || \
defined(HAVE_GETHOSTBYADDR_R_7) || \
defined(HAVE_GETHOSTBYADDR_R_8) || \
defined(HAVE_GETHOSTBYNAME_R_3) || \
defined(HAVE_GETHOSTBYNAME_R_5) || \
defined(HAVE_GETHOSTBYNAME_R_6) || \
defined(TEST_GETHOSTBYFOO_REENTRANT)
#include <sys/types.h>
#include <netdb.h>
int main(void)
{
char *address = "example.com";
int length = 0;
int type = 0;
struct hostent h;
int rc = 0;
#if defined(HAVE_GETHOSTBYADDR_R_5) || \
defined(HAVE_GETHOSTBYADDR_R_5_REENTRANT) || \
\
defined(HAVE_GETHOSTBYNAME_R_3) || \
defined(HAVE_GETHOSTBYNAME_R_3_REENTRANT)
struct hostent_data hdata;
#elif defined(HAVE_GETHOSTBYADDR_R_7) || \
defined(HAVE_GETHOSTBYADDR_R_7_REENTRANT) || \
defined(HAVE_GETHOSTBYADDR_R_8) || \
defined(HAVE_GETHOSTBYADDR_R_8_REENTRANT) || \
\
defined(HAVE_GETHOSTBYNAME_R_5) || \
defined(HAVE_GETHOSTBYNAME_R_5_REENTRANT) || \
defined(HAVE_GETHOSTBYNAME_R_6) || \
defined(HAVE_GETHOSTBYNAME_R_6_REENTRANT)
char buffer[8192];
int h_errnop;
struct hostent *hp;
#endif
#ifndef gethostbyaddr_r
(void)gethostbyaddr_r;
#endif
#if defined(HAVE_GETHOSTBYADDR_R_5) || \
defined(HAVE_GETHOSTBYADDR_R_5_REENTRANT)
rc = gethostbyaddr_r(address, length, type, &h, &hdata);
#elif defined(HAVE_GETHOSTBYADDR_R_7) || \
defined(HAVE_GETHOSTBYADDR_R_7_REENTRANT)
hp = gethostbyaddr_r(address, length, type, &h, buffer, 8192, &h_errnop);
(void)hp;
#elif defined(HAVE_GETHOSTBYADDR_R_8) || \
defined(HAVE_GETHOSTBYADDR_R_8_REENTRANT)
rc = gethostbyaddr_r(address, length, type, &h, buffer, 8192, &hp, &h_errnop);
#endif
#if defined(HAVE_GETHOSTBYNAME_R_3) || \
defined(HAVE_GETHOSTBYNAME_R_3_REENTRANT)
rc = gethostbyname_r(address, &h, &hdata);
#elif defined(HAVE_GETHOSTBYNAME_R_5) || \
defined(HAVE_GETHOSTBYNAME_R_5_REENTRANT)
rc = gethostbyname_r(address, &h, buffer, 8192, &h_errnop);
(void)hp; /* not used for test */
#elif defined(HAVE_GETHOSTBYNAME_R_6) || \
defined(HAVE_GETHOSTBYNAME_R_6_REENTRANT)
rc = gethostbyname_r(address, &h, buffer, 8192, &hp, &h_errnop);
#endif
(void)length;
(void)type;
(void)rc;
return 0;
}
#endif
#ifdef HAVE_SOCKLEN_T
#ifdef _WIN32
#include <ws2tcpip.h>
#else
#include <sys/types.h>
#include <sys/socket.h>
#endif
int
main ()
{
if ((socklen_t *) 0)
return 0;
if (sizeof (socklen_t))
return 0;
;
return 0;
}
#endif
#ifdef HAVE_IN_ADDR_T
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
int
main ()
{
if ((in_addr_t *) 0)
return 0;
if (sizeof (in_addr_t))
return 0;
;
return 0;
}
#endif
#ifdef HAVE_BOOL_T
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_STDBOOL_H
#include <stdbool.h>
#endif
int
main ()
{
if (sizeof (bool *) )
return 0;
;
return 0;
}
#endif
#ifdef STDC_HEADERS
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <float.h>
int main() { return 0; }
#endif
#ifdef RETSIGTYPE_TEST
#include <sys/types.h>
#include <signal.h>
#ifdef signal
# undef signal
#endif
#ifdef __cplusplus
extern "C" void (*signal (int, void (*)(int)))(int);
#else
void (*signal ()) ();
#endif
int
main ()
{
return 0;
}
#endif
#ifdef HAVE_INET_NTOA_R_DECL
#include <arpa/inet.h>
typedef void (*func_type)();
int main()
{
#ifndef inet_ntoa_r
func_type func;
func = (func_type)inet_ntoa_r;
#endif
return 0;
}
#endif
#ifdef HAVE_INET_NTOA_R_DECL_REENTRANT
#define _REENTRANT
#include <arpa/inet.h>
typedef void (*func_type)();
int main()
{
#ifndef inet_ntoa_r
func_type func;
func = (func_type)&inet_ntoa_r;
#endif
return 0;
}
#endif
#ifdef HAVE_GETADDRINFO
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
int main(void) {
struct addrinfo hints, *ai;
int error;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
#ifndef getaddrinfo
(void)getaddrinfo;
#endif
error = getaddrinfo("127.0.0.1", "8080", &hints, &ai);
if (error) {
return 1;
}
return 0;
}
#endif
#ifdef HAVE_FILE_OFFSET_BITS
#ifdef _FILE_OFFSET_BITS
#undef _FILE_OFFSET_BITS
#endif
#define _FILE_OFFSET_BITS 64
#include <sys/types.h>
/* Check that off_t can represent 2**63 - 1 correctly.
We can't simply define LARGE_OFF_T to be 9223372036854775807,
since some C++ compilers masquerading as C compilers
incorrectly reject 9223372036854775807. */
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
&& LARGE_OFF_T % 2147483647 == 1)
? 1 : -1];
int main () { ; return 0; }
#endif
#ifdef HAVE_IOCTLSOCKET
/* includes start */
#ifdef HAVE_WINDOWS_H
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
# endif
# include <windows.h>
# ifdef HAVE_WINSOCK2_H
# include <winsock2.h>
# else
# ifdef HAVE_WINSOCK_H
# include <winsock.h>
# endif
# endif
#endif
int
main ()
{
/* ioctlsocket source code */
int socket;
unsigned long flags = ioctlsocket(socket, FIONBIO, &flags);
;
return 0;
}
#endif
#ifdef HAVE_IOCTLSOCKET_CAMEL
/* includes start */
#ifdef HAVE_WINDOWS_H
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
# endif
# include <windows.h>
# ifdef HAVE_WINSOCK2_H
# include <winsock2.h>
# else
# ifdef HAVE_WINSOCK_H
# include <winsock.h>
# endif
# endif
#endif
int
main ()
{
/* IoctlSocket source code */
if(0 != IoctlSocket(0, 0, 0))
return 1;
;
return 0;
}
#endif
#ifdef HAVE_IOCTLSOCKET_CAMEL_FIONBIO
/* includes start */
#ifdef HAVE_WINDOWS_H
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
# endif
# include <windows.h>
# ifdef HAVE_WINSOCK2_H
# include <winsock2.h>
# else
# ifdef HAVE_WINSOCK_H
# include <winsock.h>
# endif
# endif
#endif
int
main ()
{
/* IoctlSocket source code */
long flags = 0;
if(0 != ioctlsocket(0, FIONBIO, &flags))
return 1;
;
return 0;
}
#endif
#ifdef HAVE_IOCTLSOCKET_FIONBIO
/* includes start */
#ifdef HAVE_WINDOWS_H
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
# endif
# include <windows.h>
# ifdef HAVE_WINSOCK2_H
# include <winsock2.h>
# else
# ifdef HAVE_WINSOCK_H
# include <winsock.h>
# endif
# endif
#endif
int
main ()
{
int flags = 0;
if(0 != ioctlsocket(0, FIONBIO, &flags))
return 1;
;
return 0;
}
#endif
#ifdef HAVE_IOCTL_FIONBIO
/* headers for FIONBIO test */
/* includes start */
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h>
#endif
#ifdef HAVE_SYS_IOCTL_H
# include <sys/ioctl.h>
#endif
#ifdef HAVE_STROPTS_H
# include <stropts.h>
#endif
int
main ()
{
int flags = 0;
if(0 != ioctl(0, FIONBIO, &flags))
return 1;
;
return 0;
}
#endif
#ifdef HAVE_IOCTL_SIOCGIFADDR
/* headers for FIONBIO test */
/* includes start */
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h>
#endif
#ifdef HAVE_SYS_IOCTL_H
# include <sys/ioctl.h>
#endif
#ifdef HAVE_STROPTS_H
# include <stropts.h>
#endif
#include <net/if.h>
int
main ()
{
struct ifreq ifr;
if(0 != ioctl(0, SIOCGIFADDR, &ifr))
return 1;
;
return 0;
}
#endif
#ifdef HAVE_SETSOCKOPT_SO_NONBLOCK
/* includes start */
#ifdef HAVE_WINDOWS_H
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
# endif
# include <windows.h>
# ifdef HAVE_WINSOCK2_H
# include <winsock2.h>
# else
# ifdef HAVE_WINSOCK_H
# include <winsock.h>
# endif
# endif
#endif
/* includes start */
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h>
#endif
/* includes end */
int
main ()
{
if(0 != setsockopt(0, SOL_SOCKET, SO_NONBLOCK, 0, 0))
return 1;
;
return 0;
}
#endif
#ifdef HAVE_GLIBC_STRERROR_R
#include <string.h>
#include <errno.h>
int
main () {
char buffer[1024]; /* big enough to play with */
char *string =
strerror_r(EACCES, buffer, sizeof(buffer));
/* this should've returned a string */
if(!string || !string[0])
return 99;
return 0;
}
#endif
#ifdef HAVE_POSIX_STRERROR_R
#include <string.h>
#include <errno.h>
int
main () {
char buffer[1024]; /* big enough to play with */
int error =
strerror_r(EACCES, buffer, sizeof(buffer));
/* This should've returned zero, and written an error string in the
buffer.*/
if(!buffer[0] || error)
return 99;
return 0;
}
#endif
@@ -0,0 +1,42 @@
# - Find c-ares
# Find the c-ares includes and library
# This module defines
# CARES_INCLUDE_DIR, where to find ares.h, etc.
# CARES_LIBRARIES, the libraries needed to use c-ares.
# CARES_FOUND, If false, do not try to use c-ares.
# also defined, but not for general use are
# CARES_LIBRARY, where to find the c-ares library.
FIND_PATH(CARES_INCLUDE_DIR ares.h
/usr/local/include
/usr/include
)
SET(CARES_NAMES ${CARES_NAMES} cares)
FIND_LIBRARY(CARES_LIBRARY
NAMES ${CARES_NAMES}
PATHS /usr/lib /usr/local/lib
)
IF (CARES_LIBRARY AND CARES_INCLUDE_DIR)
SET(CARES_LIBRARIES ${CARES_LIBRARY})
SET(CARES_FOUND "YES")
ELSE (CARES_LIBRARY AND CARES_INCLUDE_DIR)
SET(CARES_FOUND "NO")
ENDIF (CARES_LIBRARY AND CARES_INCLUDE_DIR)
IF (CARES_FOUND)
IF (NOT CARES_FIND_QUIETLY)
MESSAGE(STATUS "Found c-ares: ${CARES_LIBRARIES}")
ENDIF (NOT CARES_FIND_QUIETLY)
ELSE (CARES_FOUND)
IF (CARES_FIND_REQUIRED)
MESSAGE(FATAL_ERROR "Could not find c-ares library")
ENDIF (CARES_FIND_REQUIRED)
ENDIF (CARES_FOUND)
MARK_AS_ADVANCED(
CARES_LIBRARY
CARES_INCLUDE_DIR
)
@@ -0,0 +1,289 @@
# - Try to find the GSS Kerberos library
# Once done this will define
#
# GSS_ROOT_DIR - Set this variable to the root installation of GSS
#
# Read-Only variables:
# GSS_FOUND - system has the Heimdal library
# GSS_FLAVOUR - "MIT" or "Heimdal" if anything found.
# GSS_INCLUDE_DIR - the Heimdal include directory
# GSS_LIBRARIES - The libraries needed to use GSS
# GSS_LINK_DIRECTORIES - Directories to add to linker search path
# GSS_LINKER_FLAGS - Additional linker flags
# GSS_COMPILER_FLAGS - Additional compiler flags
# GSS_VERSION - This is set to version advertised by pkg-config or read from manifest.
# In case the library is found but no version info availabe it'll be set to "unknown"
set(_MIT_MODNAME mit-krb5-gssapi)
set(_HEIMDAL_MODNAME heimdal-gssapi)
include(CheckIncludeFile)
include(CheckIncludeFiles)
include(CheckTypeSize)
set(_GSS_ROOT_HINTS
"${GSS_ROOT_DIR}"
"$ENV{GSS_ROOT_DIR}"
)
# try to find library using system pkg-config if user didn't specify root dir
if(NOT GSS_ROOT_DIR AND NOT "$ENV{GSS_ROOT_DIR}")
if(UNIX)
find_package(PkgConfig QUIET)
pkg_search_module(_GSS_PKG ${_MIT_MODNAME} ${_HEIMDAL_MODNAME})
list(APPEND _GSS_ROOT_HINTS "${_GSS_PKG_PREFIX}")
elseif(WIN32)
list(APPEND _GSS_ROOT_HINTS "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MIT\\Kerberos;InstallDir]")
endif()
endif()
if(NOT _GSS_FOUND) #not found by pkg-config. Let's take more traditional approach.
find_file(_GSS_CONFIGURE_SCRIPT
NAMES
"krb5-config"
HINTS
${_GSS_ROOT_HINTS}
PATH_SUFFIXES
bin
NO_CMAKE_PATH
NO_CMAKE_ENVIRONMENT_PATH
)
# if not found in user-supplied directories, maybe system knows better
find_file(_GSS_CONFIGURE_SCRIPT
NAMES
"krb5-config"
PATH_SUFFIXES
bin
)
if(_GSS_CONFIGURE_SCRIPT)
execute_process(
COMMAND ${_GSS_CONFIGURE_SCRIPT} "--cflags" "gssapi"
OUTPUT_VARIABLE _GSS_CFLAGS
RESULT_VARIABLE _GSS_CONFIGURE_FAILED
)
message(STATUS "CFLAGS: ${_GSS_CFLAGS}")
if(NOT _GSS_CONFIGURE_FAILED) # 0 means success
# should also work in an odd case when multiple directories are given
string(STRIP "${_GSS_CFLAGS}" _GSS_CFLAGS)
string(REGEX REPLACE " +-I" ";" _GSS_CFLAGS "${_GSS_CFLAGS}")
string(REGEX REPLACE " +-([^I][^ \\t;]*)" ";-\\1"_GSS_CFLAGS "${_GSS_CFLAGS}")
foreach(_flag ${_GSS_CFLAGS})
if(_flag MATCHES "^-I.*")
string(REGEX REPLACE "^-I" "" _val "${_flag}")
list(APPEND _GSS_INCLUDE_DIR "${_val}")
else()
list(APPEND _GSS_COMPILER_FLAGS "${_flag}")
endif()
endforeach()
endif()
execute_process(
COMMAND ${_GSS_CONFIGURE_SCRIPT} "--libs" "gssapi"
OUTPUT_VARIABLE _GSS_LIB_FLAGS
RESULT_VARIABLE _GSS_CONFIGURE_FAILED
)
message(STATUS "LDFLAGS: ${_GSS_LIB_FLAGS}")
if(NOT _GSS_CONFIGURE_FAILED) # 0 means success
# this script gives us libraries and link directories. Blah. We have to deal with it.
string(STRIP "${_GSS_LIB_FLAGS}" _GSS_LIB_FLAGS)
string(REGEX REPLACE " +-(L|l)" ";-\\1" _GSS_LIB_FLAGS "${_GSS_LIB_FLAGS}")
string(REGEX REPLACE " +-([^Ll][^ \\t;]*)" ";-\\1"_GSS_LIB_FLAGS "${_GSS_LIB_FLAGS}")
foreach(_flag ${_GSS_LIB_FLAGS})
if(_flag MATCHES "^-l.*")
string(REGEX REPLACE "^-l" "" _val "${_flag}")
list(APPEND _GSS_LIBRARIES "${_val}")
elseif(_flag MATCHES "^-L.*")
string(REGEX REPLACE "^-L" "" _val "${_flag}")
list(APPEND _GSS_LINK_DIRECTORIES "${_val}")
else()
list(APPEND _GSS_LINKER_FLAGS "${_flag}")
endif()
endforeach()
endif()
execute_process(
COMMAND ${_GSS_CONFIGURE_SCRIPT} "--version"
OUTPUT_VARIABLE _GSS_VERSION
RESULT_VARIABLE _GSS_CONFIGURE_FAILED
)
# older versions may not have the "--version" parameter. In this case we just don't care.
if(_GSS_CONFIGURE_FAILED)
set(_GSS_VERSION 0)
endif()
execute_process(
COMMAND ${_GSS_CONFIGURE_SCRIPT} "--vendor"
OUTPUT_VARIABLE _GSS_VENDOR
RESULT_VARIABLE _GSS_CONFIGURE_FAILED
)
# older versions may not have the "--vendor" parameter. In this case we just don't care.
if(_GSS_CONFIGURE_FAILED)
set(GSS_FLAVOUR "Heimdal") # most probably, shouldn't really matter
else()
if(_GSS_VENDOR MATCHES ".*H|heimdal.*")
set(GSS_FLAVOUR "Heimdal")
else()
set(GSS_FLAVOUR "MIT")
endif()
endif()
else() # either there is no config script or we are on platform that doesn't provide one (Windows?)
find_path(_GSS_INCLUDE_DIR
NAMES
"gssapi/gssapi.h"
HINTS
${_GSS_ROOT_HINTS}
PATH_SUFFIXES
include
inc
)
if(_GSS_INCLUDE_DIR) #jay, we've found something
set(CMAKE_REQUIRED_INCLUDES "${_GSS_INCLUDE_DIR}")
check_include_files( "gssapi/gssapi_generic.h;gssapi/gssapi_krb5.h" _GSS_HAVE_MIT_HEADERS)
if(_GSS_HAVE_MIT_HEADERS)
set(GSS_FLAVOUR "MIT")
else()
# prevent compiling the header - just check if we can include it
set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -D__ROKEN_H__")
check_include_file( "roken.h" _GSS_HAVE_ROKEN_H)
check_include_file( "heimdal/roken.h" _GSS_HAVE_HEIMDAL_ROKEN_H)
if(_GSS_HAVE_ROKEN_H OR _GSS_HAVE_HEIMDAL_ROKEN_H)
set(GSS_FLAVOUR "Heimdal")
endif()
set(CMAKE_REQUIRED_DEFINITIONS "")
endif()
else()
# I'm not convienced if this is the right way but this is what autotools do at the moment
find_path(_GSS_INCLUDE_DIR
NAMES
"gssapi.h"
HINTS
${_GSS_ROOT_HINTS}
PATH_SUFFIXES
include
inc
)
if(_GSS_INCLUDE_DIR)
set(GSS_FLAVOUR "Heimdal")
endif()
endif()
# if we have headers, check if we can link libraries
if(GSS_FLAVOUR)
set(_GSS_LIBDIR_SUFFIXES "")
set(_GSS_LIBDIR_HINTS ${_GSS_ROOT_HINTS})
get_filename_component(_GSS_CALCULATED_POTENTIAL_ROOT "${_GSS_INCLUDE_DIR}" PATH)
list(APPEND _GSS_LIBDIR_HINTS ${_GSS_CALCULATED_POTENTIAL_ROOT})
if(WIN32)
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
list(APPEND _GSS_LIBDIR_SUFFIXES "lib/AMD64")
if(GSS_FLAVOUR STREQUAL "MIT")
set(_GSS_LIBNAME "gssapi64")
else()
set(_GSS_LIBNAME "libgssapi")
endif()
else()
list(APPEND _GSS_LIBDIR_SUFFIXES "lib/i386")
if(GSS_FLAVOUR STREQUAL "MIT")
set(_GSS_LIBNAME "gssapi32")
else()
set(_GSS_LIBNAME "libgssapi")
endif()
endif()
else()
list(APPEND _GSS_LIBDIR_SUFFIXES "lib;lib64") # those suffixes are not checked for HINTS
if(GSS_FLAVOUR STREQUAL "MIT")
set(_GSS_LIBNAME "gssapi_krb5")
else()
set(_GSS_LIBNAME "gssapi")
endif()
endif()
find_library(_GSS_LIBRARIES
NAMES
${_GSS_LIBNAME}
HINTS
${_GSS_LIBDIR_HINTS}
PATH_SUFFIXES
${_GSS_LIBDIR_SUFFIXES}
)
endif()
endif()
else()
if(_GSS_PKG_${_MIT_MODNAME}_VERSION)
set(GSS_FLAVOUR "MIT")
set(_GSS_VERSION _GSS_PKG_${_MIT_MODNAME}_VERSION)
else()
set(GSS_FLAVOUR "Heimdal")
set(_GSS_VERSION _GSS_PKG_${_MIT_HEIMDAL}_VERSION)
endif()
endif()
set(GSS_INCLUDE_DIR ${_GSS_INCLUDE_DIR})
set(GSS_LIBRARIES ${_GSS_LIBRARIES})
set(GSS_LINK_DIRECTORIES ${_GSS_LINK_DIRECTORIES})
set(GSS_LINKER_FLAGS ${_GSS_LINKER_FLAGS})
set(GSS_COMPILER_FLAGS ${_GSS_COMPILER_FLAGS})
set(GSS_VERSION ${_GSS_VERSION})
if(GSS_FLAVOUR)
if(NOT GSS_VERSION AND GSS_FLAVOUR STREQUAL "Heimdal")
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(HEIMDAL_MANIFEST_FILE "Heimdal.Application.amd64.manifest")
else()
set(HEIMDAL_MANIFEST_FILE "Heimdal.Application.x86.manifest")
endif()
if(EXISTS "${GSS_INCLUDE_DIR}/${HEIMDAL_MANIFEST_FILE}")
file(STRINGS "${GSS_INCLUDE_DIR}/${HEIMDAL_MANIFEST_FILE}" heimdal_version_str
REGEX "^.*version=\"[0-9]\\.[^\"]+\".*$")
string(REGEX MATCH "[0-9]\\.[^\"]+"
GSS_VERSION "${heimdal_version_str}")
endif()
if(NOT GSS_VERSION)
set(GSS_VERSION "Heimdal Unknown")
endif()
elseif(NOT GSS_VERSION AND GSS_FLAVOUR STREQUAL "MIT")
get_filename_component(_MIT_VERSION "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MIT\\Kerberos\\SDK\\CurrentVersion;VersionString]" NAME CACHE)
if(WIN32 AND _MIT_VERSION)
set(GSS_VERSION "${_MIT_VERSION}")
else()
set(GSS_VERSION "MIT Unknown")
endif()
endif()
endif()
include(FindPackageHandleStandardArgs)
set(_GSS_REQUIRED_VARS GSS_LIBRARIES GSS_FLAVOUR)
find_package_handle_standard_args(GSS
REQUIRED_VARS
${_GSS_REQUIRED_VARS}
VERSION_VAR
GSS_VERSION
FAIL_MESSAGE
"Could NOT find GSS, try to set the path to GSS root folder in the system variable GSS_ROOT_DIR"
)
mark_as_advanced(GSS_INCLUDE_DIR GSS_LIBRARIES)
@@ -0,0 +1,35 @@
# - Try to find the libssh2 library
# Once done this will define
#
# LIBSSH2_FOUND - system has the libssh2 library
# LIBSSH2_INCLUDE_DIR - the libssh2 include directory
# LIBSSH2_LIBRARY - the libssh2 library name
if (LIBSSH2_INCLUDE_DIR AND LIBSSH2_LIBRARY)
set(LibSSH2_FIND_QUIETLY TRUE)
endif (LIBSSH2_INCLUDE_DIR AND LIBSSH2_LIBRARY)
FIND_PATH(LIBSSH2_INCLUDE_DIR libssh2.h
)
FIND_LIBRARY(LIBSSH2_LIBRARY NAMES ssh2
)
if(LIBSSH2_INCLUDE_DIR)
file(STRINGS "${LIBSSH2_INCLUDE_DIR}/libssh2.h" libssh2_version_str REGEX "^#define[\t ]+LIBSSH2_VERSION_NUM[\t ]+0x[0-9][0-9][0-9][0-9][0-9][0-9].*")
string(REGEX REPLACE "^.*LIBSSH2_VERSION_NUM[\t ]+0x([0-9][0-9]).*$" "\\1" LIBSSH2_VERSION_MAJOR "${libssh2_version_str}")
string(REGEX REPLACE "^.*LIBSSH2_VERSION_NUM[\t ]+0x[0-9][0-9]([0-9][0-9]).*$" "\\1" LIBSSH2_VERSION_MINOR "${libssh2_version_str}")
string(REGEX REPLACE "^.*LIBSSH2_VERSION_NUM[\t ]+0x[0-9][0-9][0-9][0-9]([0-9][0-9]).*$" "\\1" LIBSSH2_VERSION_PATCH "${libssh2_version_str}")
string(REGEX REPLACE "^0(.+)" "\\1" LIBSSH2_VERSION_MAJOR "${LIBSSH2_VERSION_MAJOR}")
string(REGEX REPLACE "^0(.+)" "\\1" LIBSSH2_VERSION_MINOR "${LIBSSH2_VERSION_MINOR}")
string(REGEX REPLACE "^0(.+)" "\\1" LIBSSH2_VERSION_PATCH "${LIBSSH2_VERSION_PATCH}")
set(LIBSSH2_VERSION "${LIBSSH2_VERSION_MAJOR}.${LIBSSH2_VERSION_MINOR}.${LIBSSH2_VERSION_PATCH}")
endif(LIBSSH2_INCLUDE_DIR)
include(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibSSH2 DEFAULT_MSG LIBSSH2_INCLUDE_DIR LIBSSH2_LIBRARY )
MARK_AS_ADVANCED(LIBSSH2_INCLUDE_DIR LIBSSH2_LIBRARY LIBSSH2_VERSION_MAJOR LIBSSH2_VERSION_MINOR LIBSSH2_VERSION_PATCH LIBSSH2_VERSION)
@@ -0,0 +1,18 @@
include(FindPackageHandleStandardArgs)
find_path(NGHTTP2_INCLUDE_DIR "nghttp2/nghttp2.h")
find_library(NGHTTP2_LIBRARY NAMES nghttp2)
find_package_handle_standard_args(NGHTTP2
FOUND_VAR
NGHTTP2_FOUND
REQUIRED_VARS
NGHTTP2_LIBRARY
NGHTTP2_INCLUDE_DIR
FAIL_MESSAGE
"Could NOT find NGHTTP2"
)
set(NGHTTP2_INCLUDE_DIRS ${NGHTTP2_INCLUDE_DIR} )
set(NGHTTP2_LIBRARIES ${NGHTTP2_LIBRARY})
@@ -0,0 +1,95 @@
#File defines convenience macros for available feature testing
# This macro checks if the symbol exists in the library and if it
# does, it prepends library to the list. It is intended to be called
# multiple times with a sequence of possibly dependent libraries in
# order of least-to-most-dependent. Some libraries depend on others
# to link correctly.
macro(CHECK_LIBRARY_EXISTS_CONCAT LIBRARY SYMBOL VARIABLE)
check_library_exists("${LIBRARY};${CURL_LIBS}" ${SYMBOL} "${CMAKE_LIBRARY_PATH}"
${VARIABLE})
if(${VARIABLE})
set(CURL_LIBS ${LIBRARY} ${CURL_LIBS})
endif(${VARIABLE})
endmacro(CHECK_LIBRARY_EXISTS_CONCAT)
# Check if header file exists and add it to the list.
# This macro is intended to be called multiple times with a sequence of
# possibly dependent header files. Some headers depend on others to be
# compiled correctly.
macro(CHECK_INCLUDE_FILE_CONCAT FILE VARIABLE)
check_include_files("${CURL_INCLUDES};${FILE}" ${VARIABLE})
if(${VARIABLE})
set(CURL_INCLUDES ${CURL_INCLUDES} ${FILE})
set(CURL_TEST_DEFINES "${CURL_TEST_DEFINES} -D${VARIABLE}")
endif(${VARIABLE})
endmacro(CHECK_INCLUDE_FILE_CONCAT)
# For other curl specific tests, use this macro.
macro(CURL_INTERNAL_TEST CURL_TEST)
if(NOT DEFINED "${CURL_TEST}")
set(MACRO_CHECK_FUNCTION_DEFINITIONS
"-D${CURL_TEST} ${CURL_TEST_DEFINES} ${CMAKE_REQUIRED_FLAGS}")
if(CMAKE_REQUIRED_LIBRARIES)
set(CURL_TEST_ADD_LIBRARIES
"-DLINK_LIBRARIES:STRING=${CMAKE_REQUIRED_LIBRARIES}")
endif(CMAKE_REQUIRED_LIBRARIES)
message(STATUS "Performing Curl Test ${CURL_TEST}")
try_compile(${CURL_TEST}
${CMAKE_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/CMake/CurlTests.c
CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_FUNCTION_DEFINITIONS}
"${CURL_TEST_ADD_LIBRARIES}"
OUTPUT_VARIABLE OUTPUT)
if(${CURL_TEST})
set(${CURL_TEST} 1 CACHE INTERNAL "Curl test ${FUNCTION}")
message(STATUS "Performing Curl Test ${CURL_TEST} - Success")
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
"Performing Curl Test ${CURL_TEST} passed with the following output:\n"
"${OUTPUT}\n")
else(${CURL_TEST})
message(STATUS "Performing Curl Test ${CURL_TEST} - Failed")
set(${CURL_TEST} "" CACHE INTERNAL "Curl test ${FUNCTION}")
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
"Performing Curl Test ${CURL_TEST} failed with the following output:\n"
"${OUTPUT}\n")
endif(${CURL_TEST})
endif()
endmacro(CURL_INTERNAL_TEST)
macro(CURL_INTERNAL_TEST_RUN CURL_TEST)
if(NOT DEFINED "${CURL_TEST}_COMPILE")
set(MACRO_CHECK_FUNCTION_DEFINITIONS
"-D${CURL_TEST} ${CMAKE_REQUIRED_FLAGS}")
if(CMAKE_REQUIRED_LIBRARIES)
set(CURL_TEST_ADD_LIBRARIES
"-DLINK_LIBRARIES:STRING=${CMAKE_REQUIRED_LIBRARIES}")
endif(CMAKE_REQUIRED_LIBRARIES)
message(STATUS "Performing Curl Test ${CURL_TEST}")
try_run(${CURL_TEST} ${CURL_TEST}_COMPILE
${CMAKE_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/CMake/CurlTests.c
CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_FUNCTION_DEFINITIONS}
"${CURL_TEST_ADD_LIBRARIES}"
OUTPUT_VARIABLE OUTPUT)
if(${CURL_TEST}_COMPILE AND NOT ${CURL_TEST})
set(${CURL_TEST} 1 CACHE INTERNAL "Curl test ${FUNCTION}")
message(STATUS "Performing Curl Test ${CURL_TEST} - Success")
else(${CURL_TEST}_COMPILE AND NOT ${CURL_TEST})
message(STATUS "Performing Curl Test ${CURL_TEST} - Failed")
set(${CURL_TEST} "" CACHE INTERNAL "Curl test ${FUNCTION}")
file(APPEND "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log"
"Performing Curl Test ${CURL_TEST} failed with the following output:\n"
"${OUTPUT}")
if(${CURL_TEST}_COMPILE)
file(APPEND
"${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log"
"There was a problem running this test\n")
endif(${CURL_TEST}_COMPILE)
file(APPEND "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log"
"\n\n")
endif(${CURL_TEST}_COMPILE AND NOT ${CURL_TEST})
endif()
endmacro(CURL_INTERNAL_TEST_RUN)
@@ -0,0 +1,232 @@
include(CheckCSourceCompiles)
# The begin of the sources (macros and includes)
set(_source_epilogue "#undef inline")
macro(add_header_include check header)
if(${check})
set(_source_epilogue "${_source_epilogue}\n#include <${header}>")
endif(${check})
endmacro(add_header_include)
set(signature_call_conv)
if(HAVE_WINDOWS_H)
add_header_include(HAVE_WINSOCK2_H "winsock2.h")
add_header_include(HAVE_WINDOWS_H "windows.h")
add_header_include(HAVE_WINSOCK_H "winsock.h")
set(_source_epilogue
"${_source_epilogue}\n#ifndef WIN32_LEAN_AND_MEAN\n#define WIN32_LEAN_AND_MEAN\n#endif")
set(signature_call_conv "PASCAL")
if(HAVE_LIBWS2_32)
set(CMAKE_REQUIRED_LIBRARIES ws2_32)
endif()
else(HAVE_WINDOWS_H)
add_header_include(HAVE_SYS_TYPES_H "sys/types.h")
add_header_include(HAVE_SYS_SOCKET_H "sys/socket.h")
endif(HAVE_WINDOWS_H)
check_c_source_compiles("${_source_epilogue}
int main(void) {
recv(0, 0, 0, 0);
return 0;
}" curl_cv_recv)
if(curl_cv_recv)
if(NOT DEFINED curl_cv_func_recv_args OR "${curl_cv_func_recv_args}" STREQUAL "unknown")
foreach(recv_retv "int" "ssize_t" )
foreach(recv_arg1 "int" "ssize_t" "SOCKET")
foreach(recv_arg2 "void *" "char *")
foreach(recv_arg3 "size_t" "int" "socklen_t" "unsigned int")
foreach(recv_arg4 "int" "unsigned int")
if(NOT curl_cv_func_recv_done)
unset(curl_cv_func_recv_test CACHE)
check_c_source_compiles("
${_source_epilogue}
extern ${recv_retv} ${signature_call_conv}
recv(${recv_arg1}, ${recv_arg2}, ${recv_arg3}, ${recv_arg4});
int main(void) {
${recv_arg1} s=0;
${recv_arg2} buf=0;
${recv_arg3} len=0;
${recv_arg4} flags=0;
${recv_retv} res = recv(s, buf, len, flags);
(void) res;
return 0;
}"
curl_cv_func_recv_test)
message(STATUS
"Tested: ${recv_retv} recv(${recv_arg1}, ${recv_arg2}, ${recv_arg3}, ${recv_arg4})")
if(curl_cv_func_recv_test)
set(curl_cv_func_recv_args
"${recv_arg1},${recv_arg2},${recv_arg3},${recv_arg4},${recv_retv}")
set(RECV_TYPE_ARG1 "${recv_arg1}")
set(RECV_TYPE_ARG2 "${recv_arg2}")
set(RECV_TYPE_ARG3 "${recv_arg3}")
set(RECV_TYPE_ARG4 "${recv_arg4}")
set(RECV_TYPE_RETV "${recv_retv}")
set(HAVE_RECV 1)
set(curl_cv_func_recv_done 1)
endif(curl_cv_func_recv_test)
endif(NOT curl_cv_func_recv_done)
endforeach(recv_arg4)
endforeach(recv_arg3)
endforeach(recv_arg2)
endforeach(recv_arg1)
endforeach(recv_retv)
else()
string(REGEX REPLACE "^([^,]*),[^,]*,[^,]*,[^,]*,[^,]*$" "\\1" RECV_TYPE_ARG1 "${curl_cv_func_recv_args}")
string(REGEX REPLACE "^[^,]*,([^,]*),[^,]*,[^,]*,[^,]*$" "\\1" RECV_TYPE_ARG2 "${curl_cv_func_recv_args}")
string(REGEX REPLACE "^[^,]*,[^,]*,([^,]*),[^,]*,[^,]*$" "\\1" RECV_TYPE_ARG3 "${curl_cv_func_recv_args}")
string(REGEX REPLACE "^[^,]*,[^,]*,[^,]*,([^,]*),[^,]*$" "\\1" RECV_TYPE_ARG4 "${curl_cv_func_recv_args}")
string(REGEX REPLACE "^[^,]*,[^,]*,[^,]*,[^,]*,([^,]*)$" "\\1" RECV_TYPE_RETV "${curl_cv_func_recv_args}")
endif()
if("${curl_cv_func_recv_args}" STREQUAL "unknown")
message(FATAL_ERROR "Cannot find proper types to use for recv args")
endif("${curl_cv_func_recv_args}" STREQUAL "unknown")
else(curl_cv_recv)
message(FATAL_ERROR "Unable to link function recv")
endif(curl_cv_recv)
set(curl_cv_func_recv_args "${curl_cv_func_recv_args}" CACHE INTERNAL "Arguments for recv")
set(HAVE_RECV 1)
check_c_source_compiles("${_source_epilogue}
int main(void) {
send(0, 0, 0, 0);
return 0;
}" curl_cv_send)
if(curl_cv_send)
if(NOT DEFINED curl_cv_func_send_args OR "${curl_cv_func_send_args}" STREQUAL "unknown")
foreach(send_retv "int" "ssize_t" )
foreach(send_arg1 "int" "ssize_t" "SOCKET")
foreach(send_arg2 "const void *" "void *" "char *" "const char *")
foreach(send_arg3 "size_t" "int" "socklen_t" "unsigned int")
foreach(send_arg4 "int" "unsigned int")
if(NOT curl_cv_func_send_done)
unset(curl_cv_func_send_test CACHE)
check_c_source_compiles("
${_source_epilogue}
extern ${send_retv} ${signature_call_conv}
send(${send_arg1}, ${send_arg2}, ${send_arg3}, ${send_arg4});
int main(void) {
${send_arg1} s=0;
${send_arg2} buf=0;
${send_arg3} len=0;
${send_arg4} flags=0;
${send_retv} res = send(s, buf, len, flags);
(void) res;
return 0;
}"
curl_cv_func_send_test)
message(STATUS
"Tested: ${send_retv} send(${send_arg1}, ${send_arg2}, ${send_arg3}, ${send_arg4})")
if(curl_cv_func_send_test)
string(REGEX REPLACE "(const) .*" "\\1" send_qual_arg2 "${send_arg2}")
string(REGEX REPLACE "const (.*)" "\\1" send_arg2 "${send_arg2}")
set(curl_cv_func_send_args
"${send_arg1},${send_arg2},${send_arg3},${send_arg4},${send_retv},${send_qual_arg2}")
set(SEND_TYPE_ARG1 "${send_arg1}")
set(SEND_TYPE_ARG2 "${send_arg2}")
set(SEND_TYPE_ARG3 "${send_arg3}")
set(SEND_TYPE_ARG4 "${send_arg4}")
set(SEND_TYPE_RETV "${send_retv}")
set(HAVE_SEND 1)
set(curl_cv_func_send_done 1)
endif(curl_cv_func_send_test)
endif(NOT curl_cv_func_send_done)
endforeach(send_arg4)
endforeach(send_arg3)
endforeach(send_arg2)
endforeach(send_arg1)
endforeach(send_retv)
else()
string(REGEX REPLACE "^([^,]*),[^,]*,[^,]*,[^,]*,[^,]*,[^,]*$" "\\1" SEND_TYPE_ARG1 "${curl_cv_func_send_args}")
string(REGEX REPLACE "^[^,]*,([^,]*),[^,]*,[^,]*,[^,]*,[^,]*$" "\\1" SEND_TYPE_ARG2 "${curl_cv_func_send_args}")
string(REGEX REPLACE "^[^,]*,[^,]*,([^,]*),[^,]*,[^,]*,[^,]*$" "\\1" SEND_TYPE_ARG3 "${curl_cv_func_send_args}")
string(REGEX REPLACE "^[^,]*,[^,]*,[^,]*,([^,]*),[^,]*,[^,]*$" "\\1" SEND_TYPE_ARG4 "${curl_cv_func_send_args}")
string(REGEX REPLACE "^[^,]*,[^,]*,[^,]*,[^,]*,([^,]*),[^,]*$" "\\1" SEND_TYPE_RETV "${curl_cv_func_send_args}")
string(REGEX REPLACE "^[^,]*,[^,]*,[^,]*,[^,]*,[^,]*,([^,]*)$" "\\1" SEND_QUAL_ARG2 "${curl_cv_func_send_args}")
endif()
if("${curl_cv_func_send_args}" STREQUAL "unknown")
message(FATAL_ERROR "Cannot find proper types to use for send args")
endif("${curl_cv_func_send_args}" STREQUAL "unknown")
set(SEND_QUAL_ARG2 "const")
else(curl_cv_send)
message(FATAL_ERROR "Unable to link function send")
endif(curl_cv_send)
set(curl_cv_func_send_args "${curl_cv_func_send_args}" CACHE INTERNAL "Arguments for send")
set(HAVE_SEND 1)
check_c_source_compiles("${_source_epilogue}
int main(void) {
int flag = MSG_NOSIGNAL;
(void)flag;
return 0;
}" HAVE_MSG_NOSIGNAL)
if(NOT HAVE_WINDOWS_H)
add_header_include(HAVE_SYS_TIME_H "sys/time.h")
add_header_include(TIME_WITH_SYS_TIME "time.h")
add_header_include(HAVE_TIME_H "time.h")
endif()
check_c_source_compiles("${_source_epilogue}
int main(void) {
struct timeval ts;
ts.tv_sec = 0;
ts.tv_usec = 0;
(void)ts;
return 0;
}" HAVE_STRUCT_TIMEVAL)
include(CheckCSourceRuns)
# See HAVE_POLL in CMakeLists.txt for why poll is disabled on macOS
if(NOT APPLE)
set(CMAKE_REQUIRED_FLAGS)
if(HAVE_SYS_POLL_H)
set(CMAKE_REQUIRED_FLAGS "-DHAVE_SYS_POLL_H")
endif(HAVE_SYS_POLL_H)
check_c_source_runs("
#ifdef HAVE_SYS_POLL_H
# include <sys/poll.h>
#endif
int main(void) {
return poll((void *)0, 0, 10 /*ms*/);
}" HAVE_POLL_FINE)
endif()
set(HAVE_SIG_ATOMIC_T 1)
set(CMAKE_REQUIRED_FLAGS)
if(HAVE_SIGNAL_H)
set(CMAKE_REQUIRED_FLAGS "-DHAVE_SIGNAL_H")
set(CMAKE_EXTRA_INCLUDE_FILES "signal.h")
endif(HAVE_SIGNAL_H)
check_type_size("sig_atomic_t" SIZEOF_SIG_ATOMIC_T)
if(HAVE_SIZEOF_SIG_ATOMIC_T)
check_c_source_compiles("
#ifdef HAVE_SIGNAL_H
# include <signal.h>
#endif
int main(void) {
static volatile sig_atomic_t dummy = 0;
(void)dummy;
return 0;
}" HAVE_SIG_ATOMIC_T_NOT_VOLATILE)
if(NOT HAVE_SIG_ATOMIC_T_NOT_VOLATILE)
set(HAVE_SIG_ATOMIC_T_VOLATILE 1)
endif(NOT HAVE_SIG_ATOMIC_T_NOT_VOLATILE)
endif(HAVE_SIZEOF_SIG_ATOMIC_T)
if(HAVE_WINDOWS_H)
set(CMAKE_EXTRA_INCLUDE_FILES winsock2.h)
else()
set(CMAKE_EXTRA_INCLUDE_FILES)
if(HAVE_SYS_SOCKET_H)
set(CMAKE_EXTRA_INCLUDE_FILES sys/socket.h)
endif(HAVE_SYS_SOCKET_H)
endif()
check_type_size("struct sockaddr_storage" SIZEOF_STRUCT_SOCKADDR_STORAGE)
if(HAVE_SIZEOF_STRUCT_SOCKADDR_STORAGE)
set(HAVE_STRUCT_SOCKADDR_STORAGE 1)
endif(HAVE_SIZEOF_STRUCT_SOCKADDR_STORAGE)
@@ -0,0 +1,125 @@
if(NOT UNIX)
if(WIN32)
set(HAVE_LIBDL 0)
set(HAVE_LIBUCB 0)
set(HAVE_LIBSOCKET 0)
set(NOT_NEED_LIBNSL 0)
set(HAVE_LIBNSL 0)
set(HAVE_GETHOSTNAME 1)
set(HAVE_LIBZ 0)
set(HAVE_LIBCRYPTO 0)
set(HAVE_DLOPEN 0)
set(HAVE_ALLOCA_H 0)
set(HAVE_ARPA_INET_H 0)
set(HAVE_DLFCN_H 0)
set(HAVE_FCNTL_H 1)
set(HAVE_INTTYPES_H 0)
set(HAVE_IO_H 1)
set(HAVE_MALLOC_H 1)
set(HAVE_MEMORY_H 1)
set(HAVE_NETDB_H 0)
set(HAVE_NETINET_IF_ETHER_H 0)
set(HAVE_NETINET_IN_H 0)
set(HAVE_NET_IF_H 0)
set(HAVE_PROCESS_H 1)
set(HAVE_PWD_H 0)
set(HAVE_SETJMP_H 1)
set(HAVE_SGTTY_H 0)
set(HAVE_SIGNAL_H 1)
set(HAVE_SOCKIO_H 0)
set(HAVE_STDINT_H 0)
set(HAVE_STDLIB_H 1)
set(HAVE_STRINGS_H 0)
set(HAVE_STRING_H 1)
set(HAVE_SYS_PARAM_H 0)
set(HAVE_SYS_POLL_H 0)
set(HAVE_SYS_SELECT_H 0)
set(HAVE_SYS_SOCKET_H 0)
set(HAVE_SYS_SOCKIO_H 0)
set(HAVE_SYS_STAT_H 1)
set(HAVE_SYS_TIME_H 0)
set(HAVE_SYS_TYPES_H 1)
set(HAVE_SYS_UTIME_H 1)
set(HAVE_TERMIOS_H 0)
set(HAVE_TERMIO_H 0)
set(HAVE_TIME_H 1)
set(HAVE_UNISTD_H 0)
set(HAVE_UTIME_H 0)
set(HAVE_X509_H 0)
set(HAVE_ZLIB_H 0)
set(HAVE_SIZEOF_LONG_DOUBLE 1)
set(SIZEOF_LONG_DOUBLE 8)
set(HAVE_SOCKET 1)
set(HAVE_POLL 0)
set(HAVE_SELECT 1)
set(HAVE_STRDUP 1)
set(HAVE_STRSTR 1)
set(HAVE_STRTOK_R 0)
set(HAVE_STRFTIME 1)
set(HAVE_UNAME 0)
set(HAVE_STRCASECMP 0)
set(HAVE_STRICMP 1)
set(HAVE_STRCMPI 1)
set(HAVE_GETHOSTBYADDR 1)
set(HAVE_GETTIMEOFDAY 0)
set(HAVE_INET_ADDR 1)
set(HAVE_INET_NTOA 1)
set(HAVE_INET_NTOA_R 0)
set(HAVE_TCGETATTR 0)
set(HAVE_TCSETATTR 0)
set(HAVE_PERROR 1)
set(HAVE_CLOSESOCKET 1)
set(HAVE_SETVBUF 0)
set(HAVE_SIGSETJMP 0)
set(HAVE_GETPASS_R 0)
set(HAVE_STRLCAT 0)
set(HAVE_GETPWUID 0)
set(HAVE_GETEUID 0)
set(HAVE_UTIME 1)
set(HAVE_RAND_EGD 0)
set(HAVE_RAND_SCREEN 0)
set(HAVE_RAND_STATUS 0)
set(HAVE_GMTIME_R 0)
set(HAVE_LOCALTIME_R 0)
set(HAVE_GETHOSTBYADDR_R 0)
set(HAVE_GETHOSTBYNAME_R 0)
set(HAVE_SIGNAL_FUNC 1)
set(HAVE_SIGNAL_MACRO 0)
set(HAVE_GETHOSTBYADDR_R_5 0)
set(HAVE_GETHOSTBYADDR_R_5_REENTRANT 0)
set(HAVE_GETHOSTBYADDR_R_7 0)
set(HAVE_GETHOSTBYADDR_R_7_REENTRANT 0)
set(HAVE_GETHOSTBYADDR_R_8 0)
set(HAVE_GETHOSTBYADDR_R_8_REENTRANT 0)
set(HAVE_GETHOSTBYNAME_R_3 0)
set(HAVE_GETHOSTBYNAME_R_3_REENTRANT 0)
set(HAVE_GETHOSTBYNAME_R_5 0)
set(HAVE_GETHOSTBYNAME_R_5_REENTRANT 0)
set(HAVE_GETHOSTBYNAME_R_6 0)
set(HAVE_GETHOSTBYNAME_R_6_REENTRANT 0)
set(TIME_WITH_SYS_TIME 0)
set(HAVE_O_NONBLOCK 0)
set(HAVE_IN_ADDR_T 0)
set(HAVE_INET_NTOA_R_DECL 0)
set(HAVE_INET_NTOA_R_DECL_REENTRANT 0)
if(ENABLE_IPV6)
set(HAVE_GETADDRINFO 1)
else()
set(HAVE_GETADDRINFO 0)
endif()
set(STDC_HEADERS 1)
set(RETSIGTYPE_TEST 1)
set(HAVE_SIGACTION 0)
set(HAVE_MACRO_SIGSETJMP 0)
else(WIN32)
message("This file should be included on Windows platform only")
endif(WIN32)
endif(NOT UNIX)
@@ -0,0 +1,31 @@
# File containing various utilities
# Converts a CMake list to a string containing elements separated by spaces
function(TO_LIST_SPACES _LIST_NAME OUTPUT_VAR)
set(NEW_LIST_SPACE)
foreach(ITEM ${${_LIST_NAME}})
set(NEW_LIST_SPACE "${NEW_LIST_SPACE} ${ITEM}")
endforeach()
string(STRIP ${NEW_LIST_SPACE} NEW_LIST_SPACE)
set(${OUTPUT_VAR} "${NEW_LIST_SPACE}" PARENT_SCOPE)
endfunction()
# Appends a lis of item to a string which is a space-separated list, if they don't already exist.
function(LIST_SPACES_APPEND_ONCE LIST_NAME)
string(REPLACE " " ";" _LIST ${${LIST_NAME}})
list(APPEND _LIST ${ARGN})
list(REMOVE_DUPLICATES _LIST)
to_list_spaces(_LIST NEW_LIST_SPACE)
set(${LIST_NAME} "${NEW_LIST_SPACE}" PARENT_SCOPE)
endfunction()
# Convinience function that does the same as LIST(FIND ...) but with a TRUE/FALSE return value.
# Ex: IN_STR_LIST(MY_LIST "Searched item" WAS_FOUND)
function(IN_STR_LIST LIST_NAME ITEM_SEARCHED RETVAL)
list(FIND ${LIST_NAME} ${ITEM_SEARCHED} FIND_POS)
if(${FIND_POS} EQUAL -1)
set(${RETVAL} FALSE PARENT_SCOPE)
else()
set(${RETVAL} TRUE PARENT_SCOPE)
endif()
endfunction()
File diff suppressed because it is too large. Load diff
+22
View File
@@ -0,0 +1,22 @@
COPYRIGHT AND PERMISSION NOTICE
Copyright (c) 1996 - 2016, Daniel Stenberg, <daniel@haxx.se>, and many
contributors, see the THANKS file.
All rights reserved.
Permission to use, copy, modify, and distribute this software for any purpose
with or without fee is hereby granted, provided that the above copyright
notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN
NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of a copyright holder shall not
be used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization of the copyright holder.
+146
View File
@@ -0,0 +1,146 @@
#!/bin/bash
# This script performs all of the steps needed to build a
# universal binary libcurl.framework for Mac OS X 10.4 or greater.
#
# Hendrik Visage:
# Generalizations added since Snowleopard (10.6) do not include
# the 10.4u SDK.
#
# Also note:
# 10.5 is the *ONLY* SDK that support PPC64 :( -- 10.6 do not have ppc64 support
#If you need to have PPC64 support then change below to 1
PPC64_NEEDED=0
# Apple does not support building for PPC anymore in Xcode 4 and later.
# If you're using Xcode 3 or earlier and need PPC support, then change
# the setting below to 1
PPC_NEEDED=0
# For me the default is to develop for the platform I am on, and if you
#desire compatibility with older versions then change USE_OLD to 1 :)
USE_OLD=0
VERSION=`/usr/bin/sed -ne 's/^#define LIBCURL_VERSION "\(.*\)"/\1/p' include/curl/curlver.h`
FRAMEWORK_VERSION=Versions/Release-$VERSION
#I also wanted to "copy over" the system, and thus the reason I added the
# version to Versions/Release-7.20.1 etc.
# now a simple rsync -vaP libcurl.framework /Library/Frameworks will install it
# and setup the right paths to this version, leaving the system version
# "intact", so you can "fix" it later with the links to Versions/A/...
DEVELOPER_PATH=`xcode-select --print-path`
# Around Xcode 4.3, SDKs were moved from the Developer folder into the
# MacOSX.platform folder
if test -d "$DEVELOPER_PATH/Platforms/MacOSX.platform/Developer/SDKs"; then
SDK_PATH="$DEVELOPER_PATH/Platforms/MacOSX.platform/Developer/SDKs"
else
SDK_PATH="$DEVELOPER_PATH/SDKs";
fi
OLD_SDK=`ls $SDK_PATH|head -1`
NEW_SDK=`ls -r $SDK_PATH|head -1`
if test "0"$USE_OLD -gt 0
then
SDK32=$OLD_SDK
else
SDK32=$NEW_SDK
fi
MACVER=`echo $SDK32|sed -e s/[a-zA-Z]//g -e s/.\$//`
SDK32_DIR=$SDK_PATH/$SDK32
MINVER32='-mmacosx-version-min='$MACVER
if test $PPC_NEEDED -gt 0; then
ARCHES32='-arch i386 -arch ppc'
else
ARCHES32='-arch i386'
fi
if test $PPC64_NEEDED -gt 0
then
SDK64=10.5
ARCHES64='-arch x86_64 -arch ppc64'
SDK64=`ls $SDK_PATH|grep 10.5|head -1`
else
ARCHES64='-arch x86_64'
#We "know" that 10.4 and earlier do not support 64bit
OLD_SDK64=`ls $SDK_PATH|egrep -v "10.[0-4]"|head -1`
NEW_SDK64=`ls -r $SDK_PATH|egrep -v "10.[0-4][^0-9]" | head -1`
if test $USE_OLD -gt 0
then
SDK64=$OLD_SDK64
else
SDK64=$NEW_SDK64
fi
fi
SDK64_DIR=$SDK_PATH/$SDK64
MACVER64=`echo $SDK64|sed -e s/[a-zA-Z]//g -e s/.\$//`
MINVER64='-mmacosx-version-min='$MACVER64
if test ! -z $SDK32; then
echo "----Configuring libcurl for 32 bit universal framework..."
make clean
./configure --disable-dependency-tracking --disable-static --with-gssapi --with-darwinssl \
CFLAGS="-Os -isysroot $SDK32_DIR $ARCHES32" \
LDFLAGS="-Wl,-syslibroot,$SDK32_DIR $ARCHES32 -Wl,-headerpad_max_install_names" \
CC=$CC
echo "----Building 32 bit libcurl..."
make -j `sysctl -n hw.logicalcpu_max`
echo "----Creating 32 bit framework..."
rm -r libcurl.framework
mkdir -p libcurl.framework/${FRAMEWORK_VERSION}/Resources
cp lib/.libs/libcurl.dylib libcurl.framework/${FRAMEWORK_VERSION}/libcurl
install_name_tool -id @rpath/libcurl.framework/${FRAMEWORK_VERSION}/libcurl libcurl.framework/${FRAMEWORK_VERSION}/libcurl
/usr/bin/sed -e "s/7\.12\.3/$VERSION/" lib/libcurl.plist >libcurl.framework/${FRAMEWORK_VERSION}/Resources/Info.plist
mkdir -p libcurl.framework/${FRAMEWORK_VERSION}/Headers/curl
cp include/curl/*.h libcurl.framework/${FRAMEWORK_VERSION}/Headers/curl
pushd libcurl.framework
ln -fs ${FRAMEWORK_VERSION}/libcurl libcurl
ln -fs ${FRAMEWORK_VERSION}/Resources Resources
ln -fs ${FRAMEWORK_VERSION}/Headers Headers
cd Versions
ln -fs $(basename "${FRAMEWORK_VERSION}") Current
echo Testing for SDK64
if test -d $SDK64_DIR; then
echo entering...
popd
make clean
echo "----Configuring libcurl for 64 bit universal framework..."
./configure --disable-dependency-tracking --disable-static --with-gssapi --with-darwinssl \
CFLAGS="-Os -isysroot $SDK64_DIR $ARCHES64" \
LDFLAGS="-Wl,-syslibroot,$SDK64_DIR $ARCHES64 -Wl,-headerpad_max_install_names" \
CC=$CC
echo "----Building 64 bit libcurl..."
make -j `sysctl -n hw.logicalcpu_max`
echo "----Appending 64 bit framework to 32 bit framework..."
cp lib/.libs/libcurl.dylib libcurl.framework/${FRAMEWORK_VERSION}/libcurl64
install_name_tool -id @rpath/libcurl.framework/${FRAMEWORK_VERSION}/libcurl libcurl.framework/${FRAMEWORK_VERSION}/libcurl64
cp libcurl.framework/${FRAMEWORK_VERSION}/libcurl libcurl.framework/${FRAMEWORK_VERSION}/libcurl32
pwd
lipo libcurl.framework/${FRAMEWORK_VERSION}/libcurl32 libcurl.framework/${FRAMEWORK_VERSION}/libcurl64 -create -output libcurl.framework/${FRAMEWORK_VERSION}/libcurl
rm libcurl.framework/${FRAMEWORK_VERSION}/libcurl32 libcurl.framework/${FRAMEWORK_VERSION}/libcurl64
cp libcurl.framework/${FRAMEWORK_VERSION}/Headers/curl/curlbuild.h libcurl.framework/${FRAMEWORK_VERSION}/Headers/curl/curlbuild32.h
cp include/curl/curlbuild.h libcurl.framework/${FRAMEWORK_VERSION}/Headers/curl/curlbuild64.h
cat >libcurl.framework/${FRAMEWORK_VERSION}/Headers/curl/curlbuild.h <<EOF
#ifdef __LP64__
#include "curl/curlbuild64.h"
#else
#include "curl/curlbuild32.h"
#endif
EOF
fi
pwd
lipo -info libcurl.framework/${FRAMEWORK_VERSION}/libcurl
echo "libcurl.framework is built and can now be included in other projects."
echo "Copy libcurl.framework to your bundle's Contents/Frameworks folder, ~/Library/Frameworks or /Library/Frameworks."
else
echo "Building libcurl.framework requires Mac OS X 10.4 or later with the MacOSX10.4/5/6 SDK installed."
fi
File diff suppressed because it is too large. Load diff
+609
View File
@@ -0,0 +1,609 @@
#***************************************************************************
# _ _ ____ _
# Project ___| | | | _ \| |
# / __| | | | |_) | |
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
# Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
# are also available at https://curl.haxx.se/docs/copyright.html.
#
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
# copies of the Software, and permit persons to whom the Software is
# furnished to do so, under the terms of the COPYING file.
#
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
###########################################################################
AUTOMAKE_OPTIONS = foreign
ACLOCAL_AMFLAGS = -I m4
CMAKE_DIST = CMakeLists.txt CMake/CMakeConfigurableFile.in \
CMake/CurlTests.c CMake/FindGSS.cmake CMake/OtherTests.cmake \
CMake/Platforms/WindowsCache.cmake CMake/Utilities.cmake \
include/curl/curlbuild.h.cmake CMake/Macros.cmake \
CMake/CurlSymbolHiding.cmake CMake/FindCARES.cmake \
CMake/FindLibSSH2.cmake CMake/FindNGHTTP2.cmake
VC6_LIBTMPL = projects/Windows/VC6/lib/libcurl.tmpl
VC6_LIBDSP = projects/Windows/VC6/lib/libcurl.dsp.dist
VC6_LIBDSP_DEPS = $(VC6_LIBTMPL) Makefile.am lib/Makefile.inc
VC6_SRCTMPL = projects/Windows/VC6/src/curl.tmpl
VC6_SRCDSP = projects/Windows/VC6/src/curl.dsp.dist
VC6_SRCDSP_DEPS = $(VC6_SRCTMPL) Makefile.am src/Makefile.inc
VC7_LIBTMPL = projects/Windows/VC7/lib/libcurl.tmpl
VC7_LIBVCPROJ = projects/Windows/VC7/lib/libcurl.vcproj.dist
VC7_LIBVCPROJ_DEPS = $(VC7_LIBTMPL) Makefile.am lib/Makefile.inc
VC7_SRCTMPL = projects/Windows/VC7/src/curl.tmpl
VC7_SRCVCPROJ = projects/Windows/VC7/src/curl.vcproj.dist
VC7_SRCVCPROJ_DEPS = $(VC7_SRCTMPL) Makefile.am src/Makefile.inc
VC71_LIBTMPL = projects/Windows/VC7.1/lib/libcurl.tmpl
VC71_LIBVCPROJ = projects/Windows/VC7.1/lib/libcurl.vcproj.dist
VC71_LIBVCPROJ_DEPS = $(VC71_LIBTMPL) Makefile.am lib/Makefile.inc
VC71_SRCTMPL = projects/Windows/VC7.1/src/curl.tmpl
VC71_SRCVCPROJ = projects/Windows/VC7.1/src/curl.vcproj.dist
VC71_SRCVCPROJ_DEPS = $(VC71_SRCTMPL) Makefile.am src/Makefile.inc
VC8_LIBTMPL = projects/Windows/VC8/lib/libcurl.tmpl
VC8_LIBVCPROJ = projects/Windows/VC8/lib/libcurl.vcproj.dist
VC8_LIBVCPROJ_DEPS = $(VC8_LIBTMPL) Makefile.am lib/Makefile.inc
VC8_SRCTMPL = projects/Windows/VC8/src/curl.tmpl
VC8_SRCVCPROJ = projects/Windows/VC8/src/curl.vcproj.dist
VC8_SRCVCPROJ_DEPS = $(VC8_SRCTMPL) Makefile.am src/Makefile.inc
VC9_LIBTMPL = projects/Windows/VC9/lib/libcurl.tmpl
VC9_LIBVCPROJ = projects/Windows/VC9/lib/libcurl.vcproj.dist
VC9_LIBVCPROJ_DEPS = $(VC9_LIBTMPL) Makefile.am lib/Makefile.inc
VC9_SRCTMPL = projects/Windows/VC9/src/curl.tmpl
VC9_SRCVCPROJ = projects/Windows/VC9/src/curl.vcproj.dist
VC9_SRCVCPROJ_DEPS = $(VC9_SRCTMPL) Makefile.am src/Makefile.inc
VC10_LIBTMPL = projects/Windows/VC10/lib/libcurl.tmpl
VC10_LIBVCXPROJ = projects/Windows/VC10/lib/libcurl.vcxproj.dist
VC10_LIBVCXPROJ_DEPS = $(VC10_LIBTMPL) Makefile.am lib/Makefile.inc
VC10_SRCTMPL = projects/Windows/VC10/src/curl.tmpl
VC10_SRCVCXPROJ = projects/Windows/VC10/src/curl.vcxproj.dist
VC10_SRCVCXPROJ_DEPS = $(VC10_SRCTMPL) Makefile.am src/Makefile.inc
VC11_LIBTMPL = projects/Windows/VC11/lib/libcurl.tmpl
VC11_LIBVCXPROJ = projects/Windows/VC11/lib/libcurl.vcxproj.dist
VC11_LIBVCXPROJ_DEPS = $(VC11_LIBTMPL) Makefile.am lib/Makefile.inc
VC11_SRCTMPL = projects/Windows/VC11/src/curl.tmpl
VC11_SRCVCXPROJ = projects/Windows/VC11/src/curl.vcxproj.dist
VC11_SRCVCXPROJ_DEPS = $(VC11_SRCTMPL) Makefile.am src/Makefile.inc
VC12_LIBTMPL = projects/Windows/VC12/lib/libcurl.tmpl
VC12_LIBVCXPROJ = projects/Windows/VC12/lib/libcurl.vcxproj.dist
VC12_LIBVCXPROJ_DEPS = $(VC12_LIBTMPL) Makefile.am lib/Makefile.inc
VC12_SRCTMPL = projects/Windows/VC12/src/curl.tmpl
VC12_SRCVCXPROJ = projects/Windows/VC12/src/curl.vcxproj.dist
VC12_SRCVCXPROJ_DEPS = $(VC12_SRCTMPL) Makefile.am src/Makefile.inc
VC14_LIBTMPL = projects/Windows/VC14/lib/libcurl.tmpl
VC14_LIBVCXPROJ = projects/Windows/VC14/lib/libcurl.vcxproj.dist
VC14_LIBVCXPROJ_DEPS = $(VC14_LIBTMPL) Makefile.am lib/Makefile.inc
VC14_SRCTMPL = projects/Windows/VC14/src/curl.tmpl
VC14_SRCVCXPROJ = projects/Windows/VC14/src/curl.vcxproj.dist
VC14_SRCVCXPROJ_DEPS = $(VC14_SRCTMPL) Makefile.am src/Makefile.inc
VC_DIST = projects/README \
projects/build-openssl.bat \
projects/build-wolfssl.bat \
projects/checksrc.bat \
projects/Windows/VC6/curl-all.dsw \
projects/Windows/VC6/lib/libcurl.dsw \
projects/Windows/VC6/src/curl.dsw \
projects/Windows/VC7/curl-all.sln \
projects/Windows/VC7/lib/libcurl.sln \
projects/Windows/VC7/src/curl.sln \
projects/Windows/VC7.1/curl-all.sln \
projects/Windows/VC7.1/lib/libcurl.sln \
projects/Windows/VC7.1/src/curl.sln \
projects/Windows/VC8/curl-all.sln \
projects/Windows/VC8/lib/libcurl.sln \
projects/Windows/VC8/src/curl.sln \
projects/Windows/VC9/curl-all.sln \
projects/Windows/VC9/lib/libcurl.sln \
projects/Windows/VC9/src/curl.sln \
projects/Windows/VC10/curl-all.sln \
projects/Windows/VC10/lib/libcurl.sln \
projects/Windows/VC10/lib/libcurl.vcxproj.filters \
projects/Windows/VC10/src/curl.sln \
projects/Windows/VC10/src/curl.vcxproj.filters \
projects/Windows/VC11/curl-all.sln \
projects/Windows/VC11/lib/libcurl.sln \
projects/Windows/VC11/lib/libcurl.vcxproj.filters \
projects/Windows/VC11/src/curl.sln \
projects/Windows/VC11/src/curl.vcxproj.filters \
projects/Windows/VC12/curl-all.sln \
projects/Windows/VC12/lib/libcurl.sln \
projects/Windows/VC12/lib/libcurl.vcxproj.filters \
projects/Windows/VC12/src/curl.sln \
projects/Windows/VC12/src/curl.vcxproj.filters \
projects/Windows/VC14/curl-all.sln \
projects/Windows/VC14/lib/libcurl.sln \
projects/Windows/VC14/lib/libcurl.vcxproj.filters \
projects/Windows/VC14/src/curl.sln \
projects/Windows/VC14/src/curl.vcxproj.filters
WINBUILD_DIST = winbuild/BUILD.WINDOWS.txt winbuild/gen_resp_file.bat \
winbuild/MakefileBuild.vc winbuild/Makefile.vc \
winbuild/Makefile.msvc.names
EXTRA_DIST = CHANGES COPYING maketgz Makefile.dist curl-config.in \
RELEASE-NOTES buildconf libcurl.pc.in MacOSX-Framework scripts/zsh.pl \
$(CMAKE_DIST) $(VC_DIST) $(WINBUILD_DIST) lib/libcurl.vers.in \
buildconf.bat
CLEANFILES = $(VC6_LIBDSP) $(VC6_SRCDSP) $(VC7_LIBVCPROJ) $(VC7_SRCVCPROJ) \
$(VC71_LIBVCPROJ) $(VC71_SRCVCPROJ) $(VC8_LIBVCPROJ) $(VC8_SRCVCPROJ) \
$(VC9_LIBVCPROJ) $(VC9_SRCVCPROJ) $(VC10_LIBVCXPROJ) $(VC10_SRCVCXPROJ) \
$(VC11_LIBVCXPROJ) $(VC11_SRCVCXPROJ) $(VC12_LIBVCXPROJ) $(VC12_SRCVCXPROJ) \
$(VC14_LIBVCXPROJ) $(VC14_SRCVCXPROJ)
bin_SCRIPTS = curl-config
SUBDIRS = lib src include
DIST_SUBDIRS = $(SUBDIRS) tests packages docs scripts
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libcurl.pc
# List of files required to generate VC IDE .dsp, .vcproj and .vcxproj files
include lib/Makefile.inc
include src/Makefile.inc
dist-hook:
rm -rf $(top_builddir)/tests/log
find $(distdir) -name "*.dist" -exec rm {} \;
(distit=`find $(srcdir) -name "*.dist" | grep -v ./ares/`; \
for file in $$distit; do \
strip=`echo $$file | sed -e s/^$(srcdir)// -e s/\.dist//`; \
cp $$file $(distdir)$$strip; \
done)
html:
cd docs && make html
pdf:
cd docs && make pdf
check: test examples check-docs
if CROSSCOMPILING
test-full: test
test-torture: test
test:
@echo "NOTICE: we can't run the tests when cross-compiling!"
else
test:
@(cd tests; $(MAKE) all quiet-test)
test-full:
@(cd tests; $(MAKE) all full-test)
test-torture:
@(cd tests; $(MAKE) all torture-test)
test-am:
@(cd tests; $(MAKE) all am-test)
endif
examples:
@(cd docs/examples; $(MAKE) check)
check-docs:
@(cd docs/libcurl; $(MAKE) check)
# This is a hook to have 'make clean' also clean up the docs and the tests
# dir. The extra check for the Makefiles being present is necessary because
# 'make distcheck' will make clean first in these directories _before_ it runs
# this hook.
clean-local:
@(if test -f tests/Makefile; then cd tests; $(MAKE) clean; fi)
@(if test -f docs/Makefile; then cd docs; $(MAKE) clean; fi)
#
# Build source and binary rpms. For rpm-3.0 and above, the ~/.rpmmacros
# must contain the following line:
# %_topdir /home/loic/local/rpm
# and that /home/loic/local/rpm contains the directory SOURCES, BUILD etc.
#
# cd /home/loic/local/rpm ; mkdir -p SOURCES BUILD RPMS/i386 SPECS SRPMS
#
# If additional configure flags are needed to build the package, add the
# following in ~/.rpmmacros
# %configure CFLAGS="%{optflags}" ./configure %{_target_platform} --prefix=%{_prefix} ${AM_CONFIGFLAGS}
# and run make rpm in the following way:
# AM_CONFIGFLAGS='--with-uri=/home/users/loic/local/RedHat-6.2' make rpm
#
rpms:
$(MAKE) RPMDIST=curl rpm
$(MAKE) RPMDIST=curl-ssl rpm
rpm:
RPM_TOPDIR=`rpm --showrc | $(PERL) -n -e 'print if(s/.*_topdir\s+(.*)/$$1/)'` ; \
cp $(srcdir)/packages/Linux/RPM/$(RPMDIST).spec $$RPM_TOPDIR/SPECS ; \
cp $(PACKAGE)-$(VERSION).tar.gz $$RPM_TOPDIR/SOURCES ; \
rpm -ba --clean --rmsource $$RPM_TOPDIR/SPECS/$(RPMDIST).spec ; \
mv $$RPM_TOPDIR/RPMS/i386/$(RPMDIST)-*.rpm . ; \
mv $$RPM_TOPDIR/SRPMS/$(RPMDIST)-*.src.rpm .
#
# Build a Solaris pkgadd format file
# run 'make pkgadd' once you've done './configure' and 'make' to make a Solaris pkgadd format
# file (which ends up back in this directory).
# The pkgadd file is in 'pkgtrans' format, so to install on Solaris, do
# pkgadd -d ./HAXXcurl-*
#
# gak - libtool requires an absoulte directory, hence the pwd below...
pkgadd:
umask 022 ; \
make install DESTDIR=`/bin/pwd`/packages/Solaris/root ; \
cat COPYING > $(srcdir)/packages/Solaris/copyright ; \
cd $(srcdir)/packages/Solaris && $(MAKE) package
#
# Build a cygwin binary tarball installation file
# resulting .tar.bz2 file will end up at packages/Win32/cygwin
cygwinbin:
$(MAKE) -C packages/Win32/cygwin cygwinbin
# We extend the standard install with a custom hook:
install-data-hook:
cd include && $(MAKE) install
cd docs && $(MAKE) install
# We extend the standard uninstall with a custom hook:
uninstall-hook:
cd include && $(MAKE) uninstall
cd docs && $(MAKE) uninstall
ca-bundle: lib/mk-ca-bundle.pl
@echo "generating a fresh ca-bundle.crt"
@perl $< -b -l -u lib/ca-bundle.crt
ca-firefox: lib/firefox-db2pem.sh
@echo "generating a fresh ca-bundle.crt"
./lib/firefox-db2pem.sh lib/ca-bundle.crt
checksrc:
cd lib && $(MAKE) checksrc
cd src && $(MAKE) checksrc
cd tests && $(MAKE) checksrc
cd include/curl && $(MAKE) checksrc
cd docs/examples && $(MAKE) checksrc
.PHONY: vc-ide
vc-ide: $(VC6_LIBDSP_DEPS) $(VC6_SRCDSP_DEPS) $(VC7_LIBVCPROJ_DEPS) \
$(VC7_SRCVCPROJ_DEPS) $(VC71_LIBVCPROJ_DEPS) $(VC71_SRCVCPROJ_DEPS) \
$(VC8_LIBVCPROJ_DEPS) $(VC8_SRCVCPROJ_DEPS) $(VC9_LIBVCPROJ_DEPS) \
$(VC9_SRCVCPROJ_DEPS) $(VC10_LIBVCXPROJ_DEPS) $(VC10_SRCVCXPROJ_DEPS) \
$(VC11_LIBVCXPROJ_DEPS) $(VC11_SRCVCXPROJ_DEPS) $(VC12_LIBVCXPROJ_DEPS) \
$(VC12_SRCVCXPROJ_DEPS) $(VC14_LIBVCXPROJ_DEPS) $(VC14_SRCVCXPROJ_DEPS)
@(win32_lib_srcs='$(LIB_CFILES)'; \
win32_lib_hdrs='$(LIB_HFILES) config-win32.h'; \
win32_lib_rc='$(LIB_RCFILES)'; \
win32_lib_vauth_srcs='$(LIB_VAUTH_CFILES)'; \
win32_lib_vauth_hdrs='$(LIB_VAUTH_HFILES)'; \
win32_lib_vtls_srcs='$(LIB_VTLS_CFILES)'; \
win32_lib_vtls_hdrs='$(LIB_VTLS_HFILES)'; \
win32_src_srcs='$(CURL_CFILES)'; \
win32_src_hdrs='$(CURL_HFILES)'; \
win32_src_rc='$(CURL_RCFILES)'; \
win32_src_x_srcs='$(CURLX_CFILES)'; \
win32_src_x_hdrs='$(CURLX_HFILES) ../lib/config-win32.h'; \
\
sorted_lib_srcs=`for file in $$win32_lib_srcs; do echo $$file; done | sort`; \
sorted_lib_hdrs=`for file in $$win32_lib_hdrs; do echo $$file; done | sort`; \
sorted_lib_vauth_srcs=`for file in $$win32_lib_vauth_srcs; do echo $$file; done | sort`; \
sorted_lib_vauth_hdrs=`for file in $$win32_lib_vauth_hdrs; do echo $$file; done | sort`; \
sorted_lib_vtls_srcs=`for file in $$win32_lib_vtls_srcs; do echo $$file; done | sort`; \
sorted_lib_vtls_hdrs=`for file in $$win32_lib_vtls_hdrs; do echo $$file; done | sort`; \
sorted_src_srcs=`for file in $$win32_src_srcs; do echo $$file; done | sort`; \
sorted_src_hdrs=`for file in $$win32_src_hdrs; do echo $$file; done | sort`; \
sorted_src_x_srcs=`for file in $$win32_src_x_srcs; do echo $$file; done | sort`; \
sorted_src_x_hdrs=`for file in $$win32_src_x_hdrs; do echo $$file; done | sort`; \
\
awk_code='\
function gen_element(type, dir, file)\
{\
sub(/vauth\//, "", file);\
sub(/vtls\//, "", file);\
\
spaces=" ";\
if(dir == "lib\\vauth" || dir == "lib\\vtls")\
tabs=" ";\
else\
tabs=" ";\
\
if(type == "dsp") {\
printf("# Begin Source File\r\n");\
printf("\r\n");\
printf("SOURCE=..\\..\\..\\..\\%s\\%s\r\n", dir, file);\
printf("# End Source File\r\n");\
}\
else if(type == "vcproj1") {\
printf("%s<File\r\n", tabs);\
printf("%s RelativePath=\"..\\..\\..\\..\\%s\\%s\">\r\n",\
tabs, dir, file);\
printf("%s</File>\r\n", tabs);\
}\
else if(type == "vcproj2") {\
printf("%s<File\r\n", tabs);\
printf("%s RelativePath=\"..\\..\\..\\..\\%s\\%s\"\r\n",\
tabs, dir, file);\
printf("%s>\r\n", tabs);\
printf("%s</File>\r\n", tabs);\
}\
else if(type == "vcxproj") {\
i = index(file, ".");\
ext = substr(file, i == 0 ? 0 : i + 1);\
\
if(ext == "c")\
printf("%s<ClCompile Include=\"..\\..\\..\\..\\%s\\%s\" />\r\n",\
spaces, dir, file);\
else if(ext == "h")\
printf("%s<ClInclude Include=\"..\\..\\..\\..\\%s\\%s\" />\r\n",\
spaces, dir, file);\
else if(ext == "rc")\
printf("%s<ResourceCompile Include=\"..\\..\\..\\..\\%s\\%s\" />\r\n",\
spaces, dir, file);\
}\
}\
\
{\
\
if($$0 == "CURL_LIB_C_FILES") {\
split(lib_srcs, arr);\
for(val in arr) gen_element(proj_type, "lib", arr[val]);\
}\
else if($$0 == "CURL_LIB_H_FILES") {\
split(lib_hdrs, arr);\
for(val in arr) gen_element(proj_type, "lib", arr[val]);\
}\
else if($$0 == "CURL_LIB_RC_FILES") {\
split(lib_rc, arr);\
for(val in arr) gen_element(proj_type, "lib", arr[val]);\
}\
else if($$0 == "CURL_LIB_VAUTH_C_FILES") {\
split(lib_vauth_srcs, arr);\
for(val in arr) gen_element(proj_type, "lib\\vauth", arr[val]);\
}\
else if($$0 == "CURL_LIB_VAUTH_H_FILES") {\
split(lib_vauth_hdrs, arr);\
for(val in arr) gen_element(proj_type, "lib\\vauth", arr[val]);\
}\
else if($$0 == "CURL_LIB_VTLS_C_FILES") {\
split(lib_vtls_srcs, arr);\
for(val in arr) gen_element(proj_type, "lib\\vtls", arr[val]);\
}\
else if($$0 == "CURL_LIB_VTLS_H_FILES") {\
split(lib_vtls_hdrs, arr);\
for(val in arr) gen_element(proj_type, "lib\\vtls", arr[val]);\
}\
else if($$0 == "CURL_SRC_C_FILES") {\
split(src_srcs, arr);\
for(val in arr) gen_element(proj_type, "src", arr[val]);\
}\
else if($$0 == "CURL_SRC_H_FILES") {\
split(src_hdrs, arr);\
for(val in arr) gen_element(proj_type, "src", arr[val]);\
}\
else if($$0 == "CURL_SRC_RC_FILES") {\
split(src_rc, arr);\
for(val in arr) gen_element(proj_type, "src", arr[val]);\
}\
else if($$0 == "CURL_SRC_X_C_FILES") {\
split(src_x_srcs, arr);\
for(val in arr) {\
sub(/..\/lib\//, "", arr[val]);\
gen_element(proj_type, "lib", arr[val]);\
}\
}\
else if($$0 == "CURL_SRC_X_H_FILES") {\
split(src_x_hdrs, arr);\
for(val in arr) {\
sub(/..\/lib\//, "", arr[val]);\
gen_element(proj_type, "lib", arr[val]);\
}\
}\
else\
printf("%s\r\n", $$0);\
}';\
\
echo "generating '$(VC6_LIBDSP)'"; \
awk -v proj_type=dsp \
-v lib_srcs="$$sorted_lib_srcs" \
-v lib_hdrs="$$sorted_lib_hdrs" \
-v lib_rc="$$win32_lib_rc" \
-v lib_vauth_srcs="$$sorted_lib_vauth_srcs" \
-v lib_vauth_hdrs="$$sorted_lib_vauth_hdrs" \
-v lib_vtls_srcs="$$sorted_lib_vtls_srcs" \
-v lib_vtls_hdrs="$$sorted_lib_vtls_hdrs" \
"$$awk_code" $(srcdir)/$(VC6_LIBTMPL) > $(VC6_LIBDSP) || { exit 1; }; \
\
echo "generating '$(VC6_SRCDSP)'"; \
awk -v proj_type=dsp \
-v src_srcs="$$sorted_src_srcs" \
-v src_hdrs="$$sorted_src_hdrs" \
-v src_rc="$$win32_src_rc" \
-v src_x_srcs="$$sorted_src_x_srcs" \
-v src_x_hdrs="$$sorted_src_x_hdrs" \
"$$awk_code" $(srcdir)/$(VC6_SRCTMPL) > $(VC6_SRCDSP) || { exit 1; }; \
\
echo "generating '$(VC7_LIBVCPROJ)'"; \
awk -v proj_type=vcproj1 \
-v lib_srcs="$$sorted_lib_srcs" \
-v lib_hdrs="$$sorted_lib_hdrs" \
-v lib_rc="$$win32_lib_rc" \
-v lib_vauth_srcs="$$sorted_lib_vauth_srcs" \
-v lib_vauth_hdrs="$$sorted_lib_vauth_hdrs" \
-v lib_vtls_srcs="$$sorted_lib_vtls_srcs" \
-v lib_vtls_hdrs="$$sorted_lib_vtls_hdrs" \
"$$awk_code" $(srcdir)/$(VC7_LIBTMPL) > $(VC7_LIBVCPROJ) || { exit 1; }; \
\
echo "generating '$(VC7_SRCVCPROJ)'"; \
awk -v proj_type=vcproj1 \
-v src_srcs="$$sorted_src_srcs" \
-v src_hdrs="$$sorted_src_hdrs" \
-v src_rc="$$win32_src_rc" \
-v src_x_srcs="$$sorted_src_x_srcs" \
-v src_x_hdrs="$$sorted_src_x_hdrs" \
"$$awk_code" $(srcdir)/$(VC7_SRCTMPL) > $(VC7_SRCVCPROJ) || { exit 1; }; \
\
echo "generating '$(VC71_LIBVCPROJ)'"; \
awk -v proj_type=vcproj1 \
-v lib_srcs="$$sorted_lib_srcs" \
-v lib_hdrs="$$sorted_lib_hdrs" \
-v lib_rc="$$win32_lib_rc" \
-v lib_vauth_srcs="$$sorted_lib_vauth_srcs" \
-v lib_vauth_hdrs="$$sorted_lib_vauth_hdrs" \
-v lib_vtls_srcs="$$sorted_lib_vtls_srcs" \
-v lib_vtls_hdrs="$$sorted_lib_vtls_hdrs" \
"$$awk_code" $(srcdir)/$(VC71_LIBTMPL) > $(VC71_LIBVCPROJ) || { exit 1; }; \
\
echo "generating '$(VC71_SRCVCPROJ)'"; \
awk -v proj_type=vcproj1 \
-v src_srcs="$$sorted_src_srcs" \
-v src_hdrs="$$sorted_src_hdrs" \
-v src_rc="$$win32_src_rc" \
-v src_x_srcs="$$sorted_src_x_srcs" \
-v src_x_hdrs="$$sorted_src_x_hdrs" \
"$$awk_code" $(srcdir)/$(VC71_SRCTMPL) > $(VC71_SRCVCPROJ) || { exit 1; }; \
\
echo "generating '$(VC8_LIBVCPROJ)'"; \
awk -v proj_type=vcproj2 \
-v lib_srcs="$$sorted_lib_srcs" \
-v lib_hdrs="$$sorted_lib_hdrs" \
-v lib_rc="$$win32_lib_rc" \
-v lib_vauth_srcs="$$sorted_lib_vauth_srcs" \
-v lib_vauth_hdrs="$$sorted_lib_vauth_hdrs" \
-v lib_vtls_srcs="$$sorted_lib_vtls_srcs" \
-v lib_vtls_hdrs="$$sorted_lib_vtls_hdrs" \
"$$awk_code" $(srcdir)/$(VC8_LIBTMPL) > $(VC8_LIBVCPROJ) || { exit 1; }; \
\
echo "generating '$(VC8_SRCVCPROJ)'"; \
awk -v proj_type=vcproj2 \
-v src_srcs="$$sorted_src_srcs" \
-v src_hdrs="$$sorted_src_hdrs" \
-v src_rc="$$win32_src_rc" \
-v src_x_srcs="$$sorted_src_x_srcs" \
-v src_x_hdrs="$$sorted_src_x_hdrs" \
"$$awk_code" $(srcdir)/$(VC8_SRCTMPL) > $(VC8_SRCVCPROJ) || { exit 1; }; \
\
echo "generating '$(VC9_LIBVCPROJ)'"; \
awk -v proj_type=vcproj2 \
-v lib_srcs="$$sorted_lib_srcs" \
-v lib_hdrs="$$sorted_lib_hdrs" \
-v lib_rc="$$win32_lib_rc" \
-v lib_vauth_srcs="$$sorted_lib_vauth_srcs" \
-v lib_vauth_hdrs="$$sorted_lib_vauth_hdrs" \
-v lib_vtls_srcs="$$sorted_lib_vtls_srcs" \
-v lib_vtls_hdrs="$$sorted_lib_vtls_hdrs" \
"$$awk_code" $(srcdir)/$(VC9_LIBTMPL) > $(VC9_LIBVCPROJ) || { exit 1; }; \
\
echo "generating '$(VC9_SRCVCPROJ)'"; \
awk -v proj_type=vcproj2 \
-v src_srcs="$$sorted_src_srcs" \
-v src_hdrs="$$sorted_src_hdrs" \
-v src_rc="$$win32_src_rc" \
-v src_x_srcs="$$sorted_src_x_srcs" \
-v src_x_hdrs="$$sorted_src_x_hdrs" \
"$$awk_code" $(srcdir)/$(VC9_SRCTMPL) > $(VC9_SRCVCPROJ) || { exit 1; }; \
\
echo "generating '$(VC10_LIBVCXPROJ)'"; \
awk -v proj_type=vcxproj \
-v lib_srcs="$$sorted_lib_srcs" \
-v lib_hdrs="$$sorted_lib_hdrs" \
-v lib_rc="$$win32_lib_rc" \
-v lib_vauth_srcs="$$sorted_lib_vauth_srcs" \
-v lib_vauth_hdrs="$$sorted_lib_vauth_hdrs" \
-v lib_vtls_srcs="$$sorted_lib_vtls_srcs" \
-v lib_vtls_hdrs="$$sorted_lib_vtls_hdrs" \
"$$awk_code" $(srcdir)/$(VC10_LIBTMPL) > $(VC10_LIBVCXPROJ) || { exit 1; }; \
\
echo "generating '$(VC10_SRCVCXPROJ)'"; \
awk -v proj_type=vcxproj \
-v src_srcs="$$sorted_src_srcs" \
-v src_hdrs="$$sorted_src_hdrs" \
-v src_rc="$$win32_src_rc" \
-v src_x_srcs="$$sorted_src_x_srcs" \
-v src_x_hdrs="$$sorted_src_x_hdrs" \
"$$awk_code" $(srcdir)/$(VC10_SRCTMPL) > $(VC10_SRCVCXPROJ) || { exit 1; }; \
\
echo "generating '$(VC11_LIBVCXPROJ)'"; \
awk -v proj_type=vcxproj \
-v lib_srcs="$$sorted_lib_srcs" \
-v lib_hdrs="$$sorted_lib_hdrs" \
-v lib_rc="$$win32_lib_rc" \
-v lib_vauth_srcs="$$sorted_lib_vauth_srcs" \
-v lib_vauth_hdrs="$$sorted_lib_vauth_hdrs" \
-v lib_vtls_srcs="$$sorted_lib_vtls_srcs" \
-v lib_vtls_hdrs="$$sorted_lib_vtls_hdrs" \
"$$awk_code" $(srcdir)/$(VC11_LIBTMPL) > $(VC11_LIBVCXPROJ) || { exit 1; }; \
\
echo "generating '$(VC11_SRCVCXPROJ)'"; \
awk -v proj_type=vcxproj \
-v src_srcs="$$sorted_src_srcs" \
-v src_hdrs="$$sorted_src_hdrs" \
-v src_rc="$$win32_src_rc" \
-v src_x_srcs="$$sorted_src_x_srcs" \
-v src_x_hdrs="$$sorted_src_x_hdrs" \
"$$awk_code" $(srcdir)/$(VC11_SRCTMPL) > $(VC11_SRCVCXPROJ) || { exit 1; }; \
\
echo "generating '$(VC12_LIBVCXPROJ)'"; \
awk -v proj_type=vcxproj \
-v lib_srcs="$$sorted_lib_srcs" \
-v lib_hdrs="$$sorted_lib_hdrs" \
-v lib_rc="$$win32_lib_rc" \
-v lib_vauth_srcs="$$sorted_lib_vauth_srcs" \
-v lib_vauth_hdrs="$$sorted_lib_vauth_hdrs" \
-v lib_vtls_srcs="$$sorted_lib_vtls_srcs" \
-v lib_vtls_hdrs="$$sorted_lib_vtls_hdrs" \
"$$awk_code" $(srcdir)/$(VC12_LIBTMPL) > $(VC12_LIBVCXPROJ) || { exit 1; }; \
\
echo "generating '$(VC12_SRCVCXPROJ)'"; \
awk -v proj_type=vcxproj \
-v src_srcs="$$sorted_src_srcs" \
-v src_hdrs="$$sorted_src_hdrs" \
-v src_rc="$$win32_src_rc" \
-v src_x_srcs="$$sorted_src_x_srcs" \
-v src_x_hdrs="$$sorted_src_x_hdrs" \
"$$awk_code" $(srcdir)/$(VC12_SRCTMPL) > $(VC12_SRCVCXPROJ) || { exit 1; }; \
\
echo "generating '$(VC14_LIBVCXPROJ)'"; \
awk -v proj_type=vcxproj \
-v lib_srcs="$$sorted_lib_srcs" \
-v lib_hdrs="$$sorted_lib_hdrs" \
-v lib_rc="$$win32_lib_rc" \
-v lib_vauth_srcs="$$sorted_lib_vauth_srcs" \
-v lib_vauth_hdrs="$$sorted_lib_vauth_hdrs" \
-v lib_vtls_srcs="$$sorted_lib_vtls_srcs" \
-v lib_vtls_hdrs="$$sorted_lib_vtls_hdrs" \
"$$awk_code" $(srcdir)/$(VC14_LIBTMPL) > $(VC14_LIBVCXPROJ) || { exit 1; }; \
\
echo "generating '$(VC14_SRCVCXPROJ)'"; \
awk -v proj_type=vcxproj \
-v src_srcs="$$sorted_src_srcs" \
-v src_hdrs="$$sorted_src_hdrs" \
-v src_rc="$$win32_src_rc" \
-v src_x_srcs="$$sorted_src_x_srcs" \
-v src_x_hdrs="$$sorted_src_x_hdrs" \
"$$awk_code" $(srcdir)/$(VC14_SRCTMPL) > $(VC14_SRCVCXPROJ) || { exit 1; };)
File diff suppressed because it is too large. Load diff
+49
View File
@@ -0,0 +1,49 @@
_ _ ____ _
___| | | | _ \| |
/ __| | | | |_) | |
| (__| |_| | _ <| |___
\___|\___/|_| \_\_____|
README
Curl is a command line tool for transferring data specified with URL
syntax. Find out how to use curl by reading the curl.1 man page or the
MANUAL document. Find out how to install Curl by reading the INSTALL
document.
libcurl is the library curl is using to do its job. It is readily
available to be used by your software. Read the libcurl.3 man page to
learn how!
You find answers to the most frequent questions we get in the FAQ document.
Study the COPYING file for distribution terms and similar. If you distribute
curl binaries or other binaries that involve libcurl, you might enjoy the
LICENSE-MIXING document.
CONTACT
If you have problems, questions, ideas or suggestions, please contact us
by posting to a suitable mailing list. See https://curl.haxx.se/mail/
All contributors to the project are listed in the THANKS document.
WEB SITE
Visit the curl web site for the latest news and downloads:
https://curl.haxx.se/
GIT
To download the very latest source off the GIT server do this:
git clone https://github.com/curl/curl.git
(you'll get a directory named curl created, filled with the source code)
NOTICE
Curl contains pieces of source code that is Copyright (c) 1998, 1999
Kungliga Tekniska Högskolan. This notice is included here to comply with the
distribution terms.
+32
View File
@@ -0,0 +1,32 @@
Curl and libcurl 7.52.1
Public curl releases: 162
Command line options: 204
curl_easy_setopt() options: 243
Public functions in libcurl: 61
Contributors: 1480
This release includes the following bugfixes:
o CVE-2016-9594: unititialized random [1]
o lib557: fix checksrc warnings
o lib: fix MSVC compiler warnings
o lib557.c: use a shorter MAXIMIZE representation [2]
o tests: run checksrc on debug builds
This release includes the following known bugs:
o see docs/KNOWN_BUGS (https://curl.haxx.se/docs/knownbugs.html)
This release would not have looked like this without help, code, reports and
advice from friends like these:
Daniel Stenberg, Kamil Dudka, Marcel Raad, Ray Satiro,
(4 contributors)
Thanks! (and sorry if I forgot to mention someone)
References to bug reports and discussions on issues:
[1] = https://curl.haxx.se/docs/adv_20161223.html
[2] = https://curl.haxx.se/mail/lib-2016-12/0098.html
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+449
View File
@@ -0,0 +1,449 @@
#!/bin/sh
#***************************************************************************
# _ _ ____ _
# Project ___| | | | _ \| |
# / __| | | | |_) | |
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
# Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
# are also available at https://curl.haxx.se/docs/copyright.html.
#
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
# copies of the Software, and permit persons to whom the Software is
# furnished to do so, under the terms of the COPYING file.
#
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
###########################################################################
#--------------------------------------------------------------------------
# die prints argument string to stdout and exits this shell script.
#
die(){
echo "buildconf: $@"
exit 1
}
#--------------------------------------------------------------------------
# findtool works as 'which' but we use a different name to make it more
# obvious we aren't using 'which'! ;-)
# Unlike 'which' does, the current directory is ignored.
#
findtool(){
file="$1"
if { echo "$file" | grep "/" >/dev/null 2>&1; } then
# when file is given with a path check it first
if test -f "$file"; then
echo "$file"
return
fi
fi
old_IFS=$IFS; IFS=':'
for path in $PATH
do
IFS=$old_IFS
# echo "checks for $file in $path" >&2
if test "$path" -a "$path" != '.' -a -f "$path/$file"; then
echo "$path/$file"
return
fi
done
IFS=$old_IFS
}
#--------------------------------------------------------------------------
# removethis() removes all files and subdirectories with the given name,
# inside and below the current subdirectory at invocation time.
#
removethis(){
if test "$#" = "1"; then
find . -depth -name $1 -print > buildconf.tmp.$$
while read fdname
do
if test -f "$fdname"; then
rm -f "$fdname"
elif test -d "$fdname"; then
rm -f -r "$fdname"
fi
done < buildconf.tmp.$$
rm -f buildconf.tmp.$$
fi
}
#--------------------------------------------------------------------------
# Ensure that buildconf runs from the subdirectory where configure.ac lives
#
if test ! -f configure.ac ||
test ! -f src/tool_main.c ||
test ! -f lib/urldata.h ||
test ! -f include/curl/curl.h ||
test ! -f m4/curl-functions.m4; then
echo "Can not run buildconf from outside of curl's source subdirectory!"
echo "Change to the subdirectory where buildconf is found, and try again."
exit 1
fi
#--------------------------------------------------------------------------
# autoconf 2.57 or newer. Unpatched version 2.67 does not generate proper
# configure script. Unpatched version 2.68 is simply unusable, we should
# disallow 2.68 usage.
#
need_autoconf="2.57"
ac_version=`${AUTOCONF:-autoconf} --version 2>/dev/null|head -n 1| sed -e 's/^[^0-9]*//' -e 's/[a-z]* *$//'`
if test -z "$ac_version"; then
echo "buildconf: autoconf not found."
echo " You need autoconf version $need_autoconf or newer installed."
exit 1
fi
old_IFS=$IFS; IFS='.'; set $ac_version; IFS=$old_IFS
if test "$1" = "2" -a "$2" -lt "57" || test "$1" -lt "2"; then
echo "buildconf: autoconf version $ac_version found."
echo " You need autoconf version $need_autoconf or newer installed."
echo " If you have a sufficient autoconf installed, but it"
echo " is not named 'autoconf', then try setting the"
echo " AUTOCONF environment variable."
exit 1
fi
if test "$1" = "2" -a "$2" -eq "67"; then
echo "buildconf: autoconf version $ac_version (BAD)"
echo " Unpatched version generates broken configure script."
elif test "$1" = "2" -a "$2" -eq "68"; then
echo "buildconf: autoconf version $ac_version (BAD)"
echo " Unpatched version generates unusable configure script."
else
echo "buildconf: autoconf version $ac_version (ok)"
fi
am4te_version=`${AUTOM4TE:-autom4te} --version 2>/dev/null|head -n 1| sed -e 's/autom4te\(.*\)/\1/' -e 's/^[^0-9]*//' -e 's/[a-z]* *$//'`
if test -z "$am4te_version"; then
echo "buildconf: autom4te not found. Weird autoconf installation!"
exit 1
fi
if test "$am4te_version" = "$ac_version"; then
echo "buildconf: autom4te version $am4te_version (ok)"
else
echo "buildconf: autom4te version $am4te_version (ERROR: does not match autoconf version)"
exit 1
fi
#--------------------------------------------------------------------------
# autoheader 2.50 or newer
#
ah_version=`${AUTOHEADER:-autoheader} --version 2>/dev/null|head -n 1| sed -e 's/^[^0-9]*//' -e 's/[a-z]* *$//'`
if test -z "$ah_version"; then
echo "buildconf: autoheader not found."
echo " You need autoheader version 2.50 or newer installed."
exit 1
fi
old_IFS=$IFS; IFS='.'; set $ah_version; IFS=$old_IFS
if test "$1" = "2" -a "$2" -lt "50" || test "$1" -lt "2"; then
echo "buildconf: autoheader version $ah_version found."
echo " You need autoheader version 2.50 or newer installed."
echo " If you have a sufficient autoheader installed, but it"
echo " is not named 'autoheader', then try setting the"
echo " AUTOHEADER environment variable."
exit 1
fi
echo "buildconf: autoheader version $ah_version (ok)"
#--------------------------------------------------------------------------
# automake 1.7 or newer
#
need_automake="1.7"
am_version=`${AUTOMAKE:-automake} --version 2>/dev/null|head -n 1| sed -e 's/^.* \([0-9]\)/\1/' -e 's/[a-z]* *$//' -e 's/\(.*\)\(-p.*\)/\1/'`
if test -z "$am_version"; then
echo "buildconf: automake not found."
echo " You need automake version $need_automake or newer installed."
exit 1
fi
old_IFS=$IFS; IFS='.'; set $am_version; IFS=$old_IFS
if test "$1" = "1" -a "$2" -lt "7" || test "$1" -lt "1"; then
echo "buildconf: automake version $am_version found."
echo " You need automake version $need_automake or newer installed."
echo " If you have a sufficient automake installed, but it"
echo " is not named 'automake', then try setting the"
echo " AUTOMAKE environment variable."
exit 1
fi
echo "buildconf: automake version $am_version (ok)"
acloc_version=`${ACLOCAL:-aclocal} --version 2>/dev/null|head -n 1| sed -e 's/^.* \([0-9]\)/\1/' -e 's/[a-z]* *$//' -e 's/\(.*\)\(-p.*\)/\1/'`
if test -z "$acloc_version"; then
echo "buildconf: aclocal not found. Weird automake installation!"
exit 1
fi
if test "$acloc_version" = "$am_version"; then
echo "buildconf: aclocal version $acloc_version (ok)"
else
echo "buildconf: aclocal version $acloc_version (ERROR: does not match automake version)"
exit 1
fi
#--------------------------------------------------------------------------
# GNU libtoolize preliminary check
#
want_lt_major=1
want_lt_minor=4
want_lt_patch=2
want_lt_version=1.4.2
# This approach that tries 'glibtoolize' first is intended for systems that
# have GNU libtool named as 'glibtoolize' and libtoolize not being GNU's.
libtoolize=`findtool glibtoolize 2>/dev/null`
if test ! -x "$libtoolize"; then
libtoolize=`findtool ${LIBTOOLIZE:-libtoolize}`
fi
if test -z "$libtoolize"; then
echo "buildconf: libtoolize not found."
echo " You need GNU libtoolize $want_lt_version or newer installed."
exit 1
fi
lt_pver=`$libtoolize --version 2>/dev/null|head -n 1`
lt_qver=`echo $lt_pver|sed -e "s/([^)]*)//g" -e "s/^[^0-9]*//g"`
lt_version=`echo $lt_qver|sed -e "s/[- ].*//" -e "s/\([a-z]*\)$//"`
if test -z "$lt_version"; then
echo "buildconf: libtoolize not found."
echo " You need GNU libtoolize $want_lt_version or newer installed."
exit 1
fi
old_IFS=$IFS; IFS='.'; set $lt_version; IFS=$old_IFS
lt_major=$1
lt_minor=$2
lt_patch=$3
if test -z "$lt_major"; then
lt_status="bad"
elif test "$lt_major" -gt "$want_lt_major"; then
lt_status="good"
elif test "$lt_major" -lt "$want_lt_major"; then
lt_status="bad"
elif test -z "$lt_minor"; then
lt_status="bad"
elif test "$lt_minor" -gt "$want_lt_minor"; then
lt_status="good"
elif test "$lt_minor" -lt "$want_lt_minor"; then
lt_status="bad"
elif test -z "$lt_patch"; then
lt_status="bad"
elif test "$lt_patch" -gt "$want_lt_patch"; then
lt_status="good"
elif test "$lt_patch" -lt "$want_lt_patch"; then
lt_status="bad"
else
lt_status="good"
fi
if test "$lt_status" != "good"; then
echo "buildconf: libtoolize version $lt_version found."
echo " You need GNU libtoolize $want_lt_version or newer installed."
exit 1
fi
echo "buildconf: libtoolize version $lt_version (ok)"
#--------------------------------------------------------------------------
# m4 check
#
m4=`(${M4:-m4} --version || ${M4:-gm4} --version) 2>/dev/null | head -n 1`;
m4_version=`echo $m4 | sed -e 's/^.* \([0-9]\)/\1/' -e 's/[a-z]* *$//'`
if { echo $m4 | grep "GNU" >/dev/null 2>&1; } then
echo "buildconf: GNU m4 version $m4_version (ok)"
else
if test -z "$m4"; then
echo "buildconf: m4 version not recognized. You need a GNU m4 installed!"
else
echo "buildconf: m4 version $m4 found. You need a GNU m4 installed!"
fi
exit 1
fi
#--------------------------------------------------------------------------
# perl check
#
PERL=`findtool ${PERL:-perl}`
if test -z "$PERL"; then
echo "buildconf: perl not found"
exit 1
fi
#--------------------------------------------------------------------------
# Remove files generated on previous buildconf/configure run.
#
for fname in .deps \
.libs \
*.la \
*.lo \
*.a \
*.o \
Makefile \
Makefile.in \
aclocal.m4 \
aclocal.m4.bak \
ares_build.h \
ares_config.h \
ares_config.h.in \
autom4te.cache \
compile \
config.guess \
curl_config.h \
curl_config.h.in \
config.log \
config.lt \
config.status \
config.sub \
configure \
configurehelp.pm \
curl-config \
curlbuild.h \
depcomp \
libcares.pc \
libcurl.pc \
libtool \
libtool.m4 \
libtool.m4.tmp \
ltmain.sh \
ltoptions.m4 \
ltsugar.m4 \
ltversion.m4 \
lt~obsolete.m4 \
missing \
install-sh \
stamp-h1 \
stamp-h2 \
stamp-h3 ; do
removethis "$fname"
done
#--------------------------------------------------------------------------
# run the correct scripts now
#
echo "buildconf: running libtoolize"
${libtoolize} --copy --force || die "libtoolize command failed"
# When using libtool 1.5.X (X < 26) we copy libtool.m4 to our local m4
# subdirectory and this local copy is patched to fix some warnings that
# are triggered when running aclocal and using autoconf 2.62 or later.
if test "$lt_major" = "1" && test "$lt_minor" = "5"; then
if test -z "$lt_patch" || test "$lt_patch" -lt "26"; then
echo "buildconf: copying libtool.m4 to local m4 subdir"
ac_dir=`${ACLOCAL:-aclocal} --print-ac-dir`
if test -f $ac_dir/libtool.m4; then
cp -f $ac_dir/libtool.m4 m4/libtool.m4
else
echo "buildconf: $ac_dir/libtool.m4 not found"
fi
if test -f m4/libtool.m4; then
echo "buildconf: renaming some variables in local m4/libtool.m4"
$PERL -i.tmp -pe \
's/lt_prog_compiler_pic_works/lt_cv_prog_compiler_pic_works/g; \
s/lt_prog_compiler_static_works/lt_cv_prog_compiler_static_works/g;' \
m4/libtool.m4
rm -f m4/libtool.m4.tmp
fi
fi
fi
if test -f m4/libtool.m4; then
echo "buildconf: converting all mv to mv -f in local m4/libtool.m4"
$PERL -i.tmp -pe 's/\bmv +([^-\s])/mv -f $1/g' m4/libtool.m4
rm -f m4/libtool.m4.tmp
fi
echo "buildconf: running aclocal"
${ACLOCAL:-aclocal} -I m4 $ACLOCAL_FLAGS || die "aclocal command failed"
echo "buildconf: converting all mv to mv -f in local aclocal.m4"
$PERL -i.bak -pe 's/\bmv +([^-\s])/mv -f $1/g' aclocal.m4
echo "buildconf: running autoheader"
${AUTOHEADER:-autoheader} || die "autoheader command failed"
echo "buildconf: running autoconf"
${AUTOCONF:-autoconf} || die "autoconf command failed"
if test -d ares; then
cd ares
echo "buildconf: running in ares"
./buildconf
cd ..
fi
echo "buildconf: running automake"
${AUTOMAKE:-automake} --add-missing --copy || die "automake command failed"
#--------------------------------------------------------------------------
# GNU libtool complementary check
#
# Depending on the libtool and automake versions being used, config.guess
# might not be installed in the subdirectory until automake has finished.
# So we can not attempt to use it until this very last buildconf stage.
#
if test ! -f ./config.guess; then
echo "buildconf: config.guess not found"
else
buildhost=`./config.guess 2>/dev/null|head -n 1`
case $buildhost in
*-*-darwin*)
need_lt_major=1
need_lt_minor=5
need_lt_patch=26
need_lt_check="yes"
;;
*-*-hpux*)
need_lt_major=1
need_lt_minor=5
need_lt_patch=24
need_lt_check="yes"
;;
esac
if test ! -z "$need_lt_check"; then
if test -z "$lt_major"; then
lt_status="bad"
elif test "$lt_major" -gt "$need_lt_major"; then
lt_status="good"
elif test "$lt_major" -lt "$need_lt_major"; then
lt_status="bad"
elif test -z "$lt_minor"; then
lt_status="bad"
elif test "$lt_minor" -gt "$need_lt_minor"; then
lt_status="good"
elif test "$lt_minor" -lt "$need_lt_minor"; then
lt_status="bad"
elif test -z "$lt_patch"; then
lt_status="bad"
elif test "$lt_patch" -gt "$need_lt_patch"; then
lt_status="good"
elif test "$lt_patch" -lt "$need_lt_patch"; then
lt_status="bad"
else
lt_status="good"
fi
if test "$lt_status" != "good"; then
need_lt_version="$need_lt_major.$need_lt_minor.$need_lt_patch"
echo "buildconf: libtool version $lt_version found."
echo " $buildhost requires GNU libtool $need_lt_version or newer installed."
rm -f configure
exit 1
fi
fi
fi
#--------------------------------------------------------------------------
# Finished successfully.
#
echo "buildconf: OK"
exit 0
+350
View File
@@ -0,0 +1,350 @@
@echo off
rem ***************************************************************************
rem * _ _ ____ _
rem * Project ___| | | | _ \| |
rem * / __| | | | |_) | |
rem * | (__| |_| | _ <| |___
rem * \___|\___/|_| \_\_____|
rem *
rem * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
rem *
rem * This software is licensed as described in the file COPYING, which
rem * you should have received as part of this distribution. The terms
rem * are also available at https://curl.haxx.se/docs/copyright.html.
rem *
rem * You may opt to use, copy, modify, merge, publish, distribute and/or sell
rem * copies of the Software, and permit persons to whom the Software is
rem * furnished to do so, under the terms of the COPYING file.
rem *
rem * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
rem * KIND, either express or implied.
rem *
rem ***************************************************************************
rem NOTES
rem
rem This batch file must be used to set up a git tree to build on systems where
rem there is no autotools support (i.e. DOS and Windows).
rem
:begin
rem Set our variables
if "%OS%" == "Windows_NT" setlocal
set MODE=GENERATE
rem Switch to this batch file's directory
cd /d "%~0\.." 1>NUL 2>&1
rem Check we are running from a curl git repository
if not exist GIT-INFO goto norepo
rem Detect programs. HAVE_<PROGNAME>
rem When not found the variable is set undefined. The undefined pattern
rem allows for statements like "if not defined HAVE_PERL (command)"
groff --version <NUL 1>NUL 2>&1
if errorlevel 1 (set HAVE_GROFF=) else (set HAVE_GROFF=Y)
nroff --version <NUL 1>NUL 2>&1
if errorlevel 1 (set HAVE_NROFF=) else (set HAVE_NROFF=Y)
perl --version <NUL 1>NUL 2>&1
if errorlevel 1 (set HAVE_PERL=) else (set HAVE_PERL=Y)
gzip --version <NUL 1>NUL 2>&1
if errorlevel 1 (set HAVE_GZIP=) else (set HAVE_GZIP=Y)
:parseArgs
if "%~1" == "" goto start
if /i "%~1" == "-clean" (
set MODE=CLEAN
) else if /i "%~1" == "-?" (
goto syntax
) else if /i "%~1" == "-h" (
goto syntax
) else if /i "%~1" == "-help" (
goto syntax
) else (
goto unknown
)
shift & goto parseArgs
:start
if "%MODE%" == "GENERATE" (
echo.
echo Generating prerequisite files
call :generate
if errorlevel 4 goto nogencurlbuild
if errorlevel 3 goto nogenhugehelp
if errorlevel 2 goto nogenmakefile
if errorlevel 1 goto warning
) else (
echo.
echo Removing prerequisite files
call :clean
if errorlevel 3 goto nocleancurlbuild
if errorlevel 2 goto nocleanhugehelp
if errorlevel 1 goto nocleanmakefile
)
goto success
rem Main generate function.
rem
rem Returns:
rem
rem 0 - success
rem 1 - success with simplified tool_hugehelp.c
rem 2 - failed to generate Makefile
rem 3 - failed to generate tool_hugehelp.c
rem 4 - failed to generate curlbuild.h
rem
:generate
if "%OS%" == "Windows_NT" setlocal
set BASIC_HUGEHELP=0
rem Create Makefile
echo * %CD%\Makefile
if exist Makefile.dist (
copy /Y Makefile.dist Makefile 1>NUL 2>&1
if errorlevel 1 (
if "%OS%" == "Windows_NT" endlocal
exit /B 2
)
)
rem Create tool_hugehelp.c
echo * %CD%\src\tool_hugehelp.c
call :genHugeHelp
if errorlevel 2 (
if "%OS%" == "Windows_NT" endlocal
exit /B 3
)
if errorlevel 1 (
set BASIC_HUGEHELP=1
)
cmd /c exit 0
rem Create curlbuild.h
echo * %CD%\include\curl\curlbuild.h
if exist include\curl\curlbuild.h.dist (
copy /Y include\curl\curlbuild.h.dist include\curl\curlbuild.h 1>NUL 2>&1
if errorlevel 1 (
if "%OS%" == "Windows_NT" endlocal
exit /B 4
)
)
rem Setup c-ares git tree
if exist ares\buildconf.bat (
echo.
echo Configuring c-ares build environment
cd ares
call buildconf.bat
cd ..
)
if "%BASIC_HUGEHELP%" == "1" (
if "%OS%" == "Windows_NT" endlocal
exit /B 1
)
if "%OS%" == "Windows_NT" endlocal
exit /B 0
rem Main clean function.
rem
rem Returns:
rem
rem 0 - success
rem 1 - failed to clean Makefile
rem 2 - failed to clean tool_hugehelp.c
rem 3 - failed to clean curlbuild.h
rem
:clean
rem Remove Makefile
echo * %CD%\Makefile
if exist Makefile (
del Makefile 2>NUL
if exist Makefile (
exit /B 1
)
)
rem Remove tool_hugehelp.c
echo * %CD%\src\tool_hugehelp.c
if exist src\tool_hugehelp.c (
del src\tool_hugehelp.c 2>NUL
if exist src\tool_hugehelp.c (
exit /B 2
)
)
rem Remove curlbuild.h
echo * %CD%\include\curl\curlbuild.h
if exist include\curl\curlbuild.h (
del include\curl\curlbuild.h 2>NUL
if exist include\curl\curlbuild.h (
exit /B 3
)
)
exit /B
rem Function to generate src\tool_hugehelp.c
rem
rem Returns:
rem
rem 0 - full tool_hugehelp.c generated
rem 1 - simplified tool_hugehelp.c
rem 2 - failure
rem
:genHugeHelp
if "%OS%" == "Windows_NT" setlocal
set LC_ALL=C
set ROFFCMD=
set BASIC=1
if defined HAVE_PERL (
if defined HAVE_GROFF (
set ROFFCMD=groff -mtty-char -Tascii -P-c -man
) else if defined HAVE_NROFF (
set ROFFCMD=nroff -c -Tascii -man
)
)
if defined ROFFCMD (
echo #include "tool_setup.h"> src\tool_hugehelp.c
echo #include "tool_hugehelp.h">> src\tool_hugehelp.c
if defined HAVE_GZIP (
echo #ifndef HAVE_LIBZ>> src\tool_hugehelp.c
)
%ROFFCMD% docs\curl.1 2>NUL | perl src\mkhelp.pl docs\MANUAL >> src\tool_hugehelp.c
if defined HAVE_GZIP (
echo #else>> src\tool_hugehelp.c
%ROFFCMD% docs\curl.1 2>NUL | perl src\mkhelp.pl -c docs\MANUAL >> src\tool_hugehelp.c
echo #endif /^* HAVE_LIBZ ^*/>> src\tool_hugehelp.c
)
set BASIC=0
) else (
if exist src\tool_hugehelp.c.cvs (
copy /Y src\tool_hugehelp.c.cvs src\tool_hugehelp.c 1>NUL 2>&1
) else (
echo #include "tool_setup.h"> src\tool_hugehelp.c
echo #include "tool_hugehelp.hd">> src\tool_hugehelp.c
echo.>> src\tool_hugehelp.c
echo void hugehelp(void^)>> src\tool_hugehelp.c
echo {>> src\tool_hugehelp.c
echo #ifdef USE_MANUAL>> src\tool_hugehelp.c
echo fputs("Built-in manual not included\n", stdout^);>> src\tool_hugehelp.c
echo #endif>> src\tool_hugehelp.c
echo }>> src\tool_hugehelp.c
)
)
findstr "/C:void hugehelp(void)" src\tool_hugehelp.c 1>NUL 2>&1
if errorlevel 1 (
if "%OS%" == "Windows_NT" endlocal
exit /B 2
)
if "%BASIC%" == "1" (
if "%OS%" == "Windows_NT" endlocal
exit /B 1
)
if "%OS%" == "Windows_NT" endlocal
exit /B 0
rem Function to clean-up local variables under DOS, Windows 3.x and
rem Windows 9x as setlocal isn't available until Windows NT
rem
:dosCleanup
set MODE=
set HAVE_GROFF=
set HAVE_NROFF=
set HAVE_PERL=
set HAVE_GZIP=
set BASIC_HUGEHELP=
set LC_ALL
set ROFFCMD=
set BASIC=
exit /B
:syntax
rem Display the help
echo.
echo Usage: buildconf [-clean]
echo.
echo -clean - Removes the files
goto error
:unknown
echo.
echo Error: Unknown argument '%1'
goto error
:norepo
echo.
echo Error: This batch file should only be used with a curl git repository
goto error
:nogenmakefile
echo.
echo Error: Unable to generate Makefile
goto error
:nogenhugehelp
echo.
echo Error: Unable to generate src\tool_hugehelp.c
goto error
:nogencurlbuild
echo.
echo Error: Unable to generate include\curl\curlbuild.h
goto error
:nocleanmakefile
echo.
echo Error: Unable to clean Makefile
goto error
:nocleanhugehelp
echo.
echo Error: Unable to clean src\tool_hugehelp.c
goto error
:nocleancurlbuild
echo.
echo Error: Unable to clean include\curl\curlbuild.h
goto error
:warning
echo.
echo Warning: The curl manual could not be integrated in the source. This means when
echo you build curl the manual will not be available (curl --man^). Integration of
echo the manual is not required and a summary of the options will still be available
echo (curl --help^). To integrate the manual your PATH is required to have
echo groff/nroff, perl and optionally gzip for compression.
goto success
:error
if "%OS%" == "Windows_NT" (
endlocal
) else (
call :dosCleanup
)
exit /B 1
:success
if "%OS%" == "Windows_NT" (
endlocal
) else (
call :dosCleanup
)
exit /B 0
+347
View File
@@ -0,0 +1,347 @@
#! /bin/sh
# Wrapper for compilers which do not understand '-c -o'.
scriptversion=2012-10-14.11; # UTC
# Copyright (C) 1999-2014 Free Software Foundation, Inc.
# Written by Tom Tromey <tromey@cygnus.com>.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# This file is maintained in Automake, please report
# bugs to <bug-automake@gnu.org> or send patches to
# <automake-patches@gnu.org>.
nl='
'
# We need space, tab and new line, in precisely that order. Quoting is
# there to prevent tools from complaining about whitespace usage.
IFS=" "" $nl"
file_conv=
# func_file_conv build_file lazy
# Convert a $build file to $host form and store it in $file
# Currently only supports Windows hosts. If the determined conversion
# type is listed in (the comma separated) LAZY, no conversion will
# take place.
func_file_conv ()
{
file=$1
case $file in
/ | /[!/]*) # absolute file, and not a UNC file
if test -z "$file_conv"; then
# lazily determine how to convert abs files
case `uname -s` in
MINGW*)
file_conv=mingw
;;
CYGWIN*)
file_conv=cygwin
;;
*)
file_conv=wine
;;
esac
fi
case $file_conv/,$2, in
*,$file_conv,*)
;;
mingw/*)
file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
;;
cygwin/*)
file=`cygpath -m "$file" || echo "$file"`
;;
wine/*)
file=`winepath -w "$file" || echo "$file"`
;;
esac
;;
esac
}
# func_cl_dashL linkdir
# Make cl look for libraries in LINKDIR
func_cl_dashL ()
{
func_file_conv "$1"
if test -z "$lib_path"; then
lib_path=$file
else
lib_path="$lib_path;$file"
fi
linker_opts="$linker_opts -LIBPATH:$file"
}
# func_cl_dashl library
# Do a library search-path lookup for cl
func_cl_dashl ()
{
lib=$1
found=no
save_IFS=$IFS
IFS=';'
for dir in $lib_path $LIB
do
IFS=$save_IFS
if $shared && test -f "$dir/$lib.dll.lib"; then
found=yes
lib=$dir/$lib.dll.lib
break
fi
if test -f "$dir/$lib.lib"; then
found=yes
lib=$dir/$lib.lib
break
fi
if test -f "$dir/lib$lib.a"; then
found=yes
lib=$dir/lib$lib.a
break
fi
done
IFS=$save_IFS
if test "$found" != yes; then
lib=$lib.lib
fi
}
# func_cl_wrapper cl arg...
# Adjust compile command to suit cl
func_cl_wrapper ()
{
# Assume a capable shell
lib_path=
shared=:
linker_opts=
for arg
do
if test -n "$eat"; then
eat=
else
case $1 in
-o)
# configure might choose to run compile as 'compile cc -o foo foo.c'.
eat=1
case $2 in
*.o | *.[oO][bB][jJ])
func_file_conv "$2"
set x "$@" -Fo"$file"
shift
;;
*)
func_file_conv "$2"
set x "$@" -Fe"$file"
shift
;;
esac
;;
-I)
eat=1
func_file_conv "$2" mingw
set x "$@" -I"$file"
shift
;;
-I*)
func_file_conv "${1#-I}" mingw
set x "$@" -I"$file"
shift
;;
-l)
eat=1
func_cl_dashl "$2"
set x "$@" "$lib"
shift
;;
-l*)
func_cl_dashl "${1#-l}"
set x "$@" "$lib"
shift
;;
-L)
eat=1
func_cl_dashL "$2"
;;
-L*)
func_cl_dashL "${1#-L}"
;;
-static)
shared=false
;;
-Wl,*)
arg=${1#-Wl,}
save_ifs="$IFS"; IFS=','
for flag in $arg; do
IFS="$save_ifs"
linker_opts="$linker_opts $flag"
done
IFS="$save_ifs"
;;
-Xlinker)
eat=1
linker_opts="$linker_opts $2"
;;
-*)
set x "$@" "$1"
shift
;;
*.cc | *.CC | *.cxx | *.CXX | *.[cC]++)
func_file_conv "$1"
set x "$@" -Tp"$file"
shift
;;
*.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO])
func_file_conv "$1" mingw
set x "$@" "$file"
shift
;;
*)
set x "$@" "$1"
shift
;;
esac
fi
shift
done
if test -n "$linker_opts"; then
linker_opts="-link$linker_opts"
fi
exec "$@" $linker_opts
exit 1
}
eat=
case $1 in
'')
echo "$0: No command. Try '$0 --help' for more information." 1>&2
exit 1;
;;
-h | --h*)
cat <<\EOF
Usage: compile [--help] [--version] PROGRAM [ARGS]
Wrapper for compilers which do not understand '-c -o'.
Remove '-o dest.o' from ARGS, run PROGRAM with the remaining
arguments, and rename the output as expected.
If you are trying to build a whole package this is not the
right script to run: please start by reading the file 'INSTALL'.
Report bugs to <bug-automake@gnu.org>.
EOF
exit $?
;;
-v | --v*)
echo "compile $scriptversion"
exit $?
;;
cl | *[/\\]cl | cl.exe | *[/\\]cl.exe )
func_cl_wrapper "$@" # Doesn't return...
;;
esac
ofile=
cfile=
for arg
do
if test -n "$eat"; then
eat=
else
case $1 in
-o)
# configure might choose to run compile as 'compile cc -o foo foo.c'.
# So we strip '-o arg' only if arg is an object.
eat=1
case $2 in
*.o | *.obj)
ofile=$2
;;
*)
set x "$@" -o "$2"
shift
;;
esac
;;
*.c)
cfile=$1
set x "$@" "$1"
shift
;;
*)
set x "$@" "$1"
shift
;;
esac
fi
shift
done
if test -z "$ofile" || test -z "$cfile"; then
# If no '-o' option was seen then we might have been invoked from a
# pattern rule where we don't need one. That is ok -- this is a
# normal compilation that the losing compiler can handle. If no
# '.c' file was seen then we are probably linking. That is also
# ok.
exec "$@"
fi
# Name of file we expect compiler to create.
cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'`
# Create the lock directory.
# Note: use '[/\\:.-]' here to ensure that we don't use the same name
# that we are using for the .o file. Also, base the name on the expected
# object file name, since that is what matters with a parallel build.
lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d
while true; do
if mkdir "$lockdir" >/dev/null 2>&1; then
break
fi
sleep 1
done
# FIXME: race condition here if user kills between mkdir and trap.
trap "rmdir '$lockdir'; exit 1" 1 2 15
# Run the compile.
"$@"
ret=$?
if test -f "$cofile"; then
test "$cofile" = "$ofile" || mv "$cofile" "$ofile"
elif test -f "${cofile}bj"; then
test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile"
fi
rmdir "$lockdir"
exit $ret
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:
+1462
View File
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+1825
View File
File diff suppressed because it is too large. Load diff
+43682
View File
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+178
View File
@@ -0,0 +1,178 @@
#! /bin/sh
#***************************************************************************
# _ _ ____ _
# Project ___| | | | _ \| |
# / __| | | | |_) | |
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
# Copyright (C) 2001 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
# are also available at https://curl.haxx.se/docs/copyright.html.
#
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
# copies of the Software, and permit persons to whom the Software is
# furnished to do so, under the terms of the COPYING file.
#
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
###########################################################################
prefix=/usr/local
exec_prefix=${prefix}
includedir=${prefix}/include
cppflag_curl_staticlib=
usage()
{
cat <<EOF
Usage: curl-config [OPTION]
Available values for OPTION include:
--built-shared says 'yes' if libcurl was built shared
--ca ca bundle install path
--cc compiler
--cflags pre-processor and compiler flags
--checkfor [version] check for (lib)curl of the specified version
--configure the arguments given to configure when building curl
--features newline separated list of enabled features
--help display this help and exit
--libs library linking information
--prefix curl install prefix
--protocols newline separated list of enabled protocols
--static-libs static libcurl library linking information
--version output version information
--vernum output the version information as a number (hexadecimal)
EOF
exit $1
}
if test $# -eq 0; then
usage 1
fi
while test $# -gt 0; do
case "$1" in
# this deals with options in the style
# --option=value and extracts the value part
# [not currently used]
-*=*) value=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
*) value= ;;
esac
case "$1" in
--built-shared)
echo yes
;;
--ca)
echo "/etc/ssl/certs/ca-certificates.crt"
;;
--cc)
echo "gcc"
;;
--prefix)
echo "$prefix"
;;
--feature|--features)
for feature in SSL IPv6 UnixSockets libz IDN NTLM NTLM_WB TLS-SRP HTTPS-proxy ""; do
test -n "$feature" && echo "$feature"
done
;;
--protocols)
for protocol in DICT FILE FTP FTPS GOPHER HTTP HTTPS IMAP IMAPS POP3 POP3S RTSP SMB SMBS SMTP SMTPS TELNET TFTP; do
echo "$protocol"
done
;;
--version)
echo libcurl 7.52.1
exit 0
;;
--checkfor)
checkfor=$2
cmajor=`echo $checkfor | cut -d. -f1`
cminor=`echo $checkfor | cut -d. -f2`
# when extracting the patch part we strip off everything after a
# dash as that's used for things like version 1.2.3-CVS
cpatch=`echo $checkfor | cut -d. -f3 | cut -d- -f1`
checknum=`echo "$cmajor*256*256 + $cminor*256 + ${cpatch:-0}" | bc`
numuppercase=`echo 073401 | tr 'a-f' 'A-F'`
nownum=`echo "obase=10; ibase=16; $numuppercase" | bc`
if test "$nownum" -ge "$checknum"; then
# silent success
exit 0
else
echo "requested version $checkfor is newer than existing 7.52.1"
exit 1
fi
;;
--vernum)
echo 073401
exit 0
;;
--help)
usage 0
;;
--cflags)
if test "X$cppflag_curl_staticlib" = "X-DCURL_STATICLIB"; then
CPPFLAG_CURL_STATICLIB="-DCURL_STATICLIB "
else
CPPFLAG_CURL_STATICLIB=""
fi
if test "X${prefix}/include" = "X/usr/include"; then
echo "$CPPFLAG_CURL_STATICLIB"
else
echo "${CPPFLAG_CURL_STATICLIB}-I${prefix}/include"
fi
;;
--libs)
if test "X${exec_prefix}/lib" != "X/usr/lib" -a "X${exec_prefix}/lib" != "X/usr/lib64"; then
CURLLIBDIR="-L${exec_prefix}/lib "
else
CURLLIBDIR=""
fi
if test "Xno" = "Xyes"; then
echo ${CURLLIBDIR}-lcurl -lidn2 -lssl -lcrypto -lssl -lcrypto -lz
else
echo ${CURLLIBDIR}-lcurl
fi
;;
--static-libs)
if test "Xyes" != "Xno" ; then
echo ${exec_prefix}/lib/libcurl.a -lidn2 -lssl -lcrypto -lssl -lcrypto -lz
else
echo "curl was built with static libraries disabled" >&2
exit 1
fi
;;
--configure)
echo ""
;;
*)
echo "unknown option: $1"
usage 1
;;
esac
shift
done
exit 0
+178
View File
@@ -0,0 +1,178 @@
#! /bin/sh
#***************************************************************************
# _ _ ____ _
# Project ___| | | | _ \| |
# / __| | | | |_) | |
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
# Copyright (C) 2001 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
# are also available at https://curl.haxx.se/docs/copyright.html.
#
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
# copies of the Software, and permit persons to whom the Software is
# furnished to do so, under the terms of the COPYING file.
#
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
###########################################################################
prefix=@prefix@
exec_prefix=@exec_prefix@
includedir=@includedir@
cppflag_curl_staticlib=@CPPFLAG_CURL_STATICLIB@
usage()
{
cat <<EOF
Usage: curl-config [OPTION]
Available values for OPTION include:
--built-shared says 'yes' if libcurl was built shared
--ca ca bundle install path
--cc compiler
--cflags pre-processor and compiler flags
--checkfor [version] check for (lib)curl of the specified version
--configure the arguments given to configure when building curl
--features newline separated list of enabled features
--help display this help and exit
--libs library linking information
--prefix curl install prefix
--protocols newline separated list of enabled protocols
--static-libs static libcurl library linking information
--version output version information
--vernum output the version information as a number (hexadecimal)
EOF
exit $1
}
if test $# -eq 0; then
usage 1
fi
while test $# -gt 0; do
case "$1" in
# this deals with options in the style
# --option=value and extracts the value part
# [not currently used]
-*=*) value=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
*) value= ;;
esac
case "$1" in
--built-shared)
echo @ENABLE_SHARED@
;;
--ca)
echo @CURL_CA_BUNDLE@
;;
--cc)
echo "@CC@"
;;
--prefix)
echo "$prefix"
;;
--feature|--features)
for feature in @SUPPORT_FEATURES@ ""; do
test -n "$feature" && echo "$feature"
done
;;
--protocols)
for protocol in @SUPPORT_PROTOCOLS@; do
echo "$protocol"
done
;;
--version)
echo libcurl @CURLVERSION@
exit 0
;;
--checkfor)
checkfor=$2
cmajor=`echo $checkfor | cut -d. -f1`
cminor=`echo $checkfor | cut -d. -f2`
# when extracting the patch part we strip off everything after a
# dash as that's used for things like version 1.2.3-CVS
cpatch=`echo $checkfor | cut -d. -f3 | cut -d- -f1`
checknum=`echo "$cmajor*256*256 + $cminor*256 + ${cpatch:-0}" | bc`
numuppercase=`echo @VERSIONNUM@ | tr 'a-f' 'A-F'`
nownum=`echo "obase=10; ibase=16; $numuppercase" | bc`
if test "$nownum" -ge "$checknum"; then
# silent success
exit 0
else
echo "requested version $checkfor is newer than existing @CURLVERSION@"
exit 1
fi
;;
--vernum)
echo @VERSIONNUM@
exit 0
;;
--help)
usage 0
;;
--cflags)
if test "X$cppflag_curl_staticlib" = "X-DCURL_STATICLIB"; then
CPPFLAG_CURL_STATICLIB="-DCURL_STATICLIB "
else
CPPFLAG_CURL_STATICLIB=""
fi
if test "X@includedir@" = "X/usr/include"; then
echo "$CPPFLAG_CURL_STATICLIB"
else
echo "${CPPFLAG_CURL_STATICLIB}-I@includedir@"
fi
;;
--libs)
if test "X@libdir@" != "X/usr/lib" -a "X@libdir@" != "X/usr/lib64"; then
CURLLIBDIR="-L@libdir@ "
else
CURLLIBDIR=""
fi
if test "X@REQUIRE_LIB_DEPS@" = "Xyes"; then
echo ${CURLLIBDIR}-lcurl @LIBCURL_LIBS@
else
echo ${CURLLIBDIR}-lcurl
fi
;;
--static-libs)
if test "X@ENABLE_STATIC@" != "Xno" ; then
echo @libdir@/libcurl.@libext@ @LDFLAGS@ @LIBCURL_LIBS@
else
echo "curl was built with static libraries disabled" >&2
exit 1
fi
;;
--configure)
echo @CONFIGURE_OPTIONS@
;;
*)
echo "unknown option: $1"
usage 1
;;
esac
shift
done
exit 0
+791
View File
@@ -0,0 +1,791 @@
#! /bin/sh
# depcomp - compile a program generating dependencies as side-effects
scriptversion=2013-05-30.07; # UTC
# Copyright (C) 1999-2014 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>.
case $1 in
'')
echo "$0: No command. Try '$0 --help' for more information." 1>&2
exit 1;
;;
-h | --h*)
cat <<\EOF
Usage: depcomp [--help] [--version] PROGRAM [ARGS]
Run PROGRAMS ARGS to compile a file, generating dependencies
as side-effects.
Environment variables:
depmode Dependency tracking mode.
source Source file read by 'PROGRAMS ARGS'.
object Object file output by 'PROGRAMS ARGS'.
DEPDIR directory where to store dependencies.
depfile Dependency file to output.
tmpdepfile Temporary file to use when outputting dependencies.
libtool Whether libtool is used (yes/no).
Report bugs to <bug-automake@gnu.org>.
EOF
exit $?
;;
-v | --v*)
echo "depcomp $scriptversion"
exit $?
;;
esac
# Get the directory component of the given path, and save it in the
# global variables '$dir'. Note that this directory component will
# be either empty or ending with a '/' character. This is deliberate.
set_dir_from ()
{
case $1 in
*/*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;;
*) dir=;;
esac
}
# Get the suffix-stripped basename of the given path, and save it the
# global variable '$base'.
set_base_from ()
{
base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'`
}
# If no dependency file was actually created by the compiler invocation,
# we still have to create a dummy depfile, to avoid errors with the
# Makefile "include basename.Plo" scheme.
make_dummy_depfile ()
{
echo "#dummy" > "$depfile"
}
# Factor out some common post-processing of the generated depfile.
# Requires the auxiliary global variable '$tmpdepfile' to be set.
aix_post_process_depfile ()
{
# If the compiler actually managed to produce a dependency file,
# post-process it.
if test -f "$tmpdepfile"; then
# Each line is of the form 'foo.o: dependency.h'.
# Do two passes, one to just change these to
# $object: dependency.h
# and one to simply output
# dependency.h:
# which is needed to avoid the deleted-header problem.
{ sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile"
sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile"
} > "$depfile"
rm -f "$tmpdepfile"
else
make_dummy_depfile
fi
}
# A tabulation character.
tab=' '
# A newline character.
nl='
'
# Character ranges might be problematic outside the C locale.
# These definitions help.
upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ
lower=abcdefghijklmnopqrstuvwxyz
digits=0123456789
alpha=${upper}${lower}
if test -z "$depmode" || test -z "$source" || test -z "$object"; then
echo "depcomp: Variables source, object and depmode must be set" 1>&2
exit 1
fi
# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po.
depfile=${depfile-`echo "$object" |
sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`}
tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
rm -f "$tmpdepfile"
# Avoid interferences from the environment.
gccflag= dashmflag=
# Some modes work just like other modes, but use different flags. We
# parameterize here, but still list the modes in the big case below,
# to make depend.m4 easier to write. Note that we *cannot* use a case
# here, because this file can only contain one case statement.
if test "$depmode" = hp; then
# HP compiler uses -M and no extra arg.
gccflag=-M
depmode=gcc
fi
if test "$depmode" = dashXmstdout; then
# This is just like dashmstdout with a different argument.
dashmflag=-xM
depmode=dashmstdout
fi
cygpath_u="cygpath -u -f -"
if test "$depmode" = msvcmsys; then
# This is just like msvisualcpp but w/o cygpath translation.
# Just convert the backslash-escaped backslashes to single forward
# slashes to satisfy depend.m4
cygpath_u='sed s,\\\\,/,g'
depmode=msvisualcpp
fi
if test "$depmode" = msvc7msys; then
# This is just like msvc7 but w/o cygpath translation.
# Just convert the backslash-escaped backslashes to single forward
# slashes to satisfy depend.m4
cygpath_u='sed s,\\\\,/,g'
depmode=msvc7
fi
if test "$depmode" = xlc; then
# IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information.
gccflag=-qmakedep=gcc,-MF
depmode=gcc
fi
case "$depmode" in
gcc3)
## gcc 3 implements dependency tracking that does exactly what
## we want. Yay! Note: for some reason libtool 1.4 doesn't like
## it if -MD -MP comes after the -MF stuff. Hmm.
## Unfortunately, FreeBSD c89 acceptance of flags depends upon
## the command line argument order; so add the flags where they
## appear in depend2.am. Note that the slowdown incurred here
## affects only configure: in makefiles, %FASTDEP% shortcuts this.
for arg
do
case $arg in
-c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;;
*) set fnord "$@" "$arg" ;;
esac
shift # fnord
shift # $arg
done
"$@"
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
mv "$tmpdepfile" "$depfile"
;;
gcc)
## Note that this doesn't just cater to obsosete pre-3.x GCC compilers.
## but also to in-use compilers like IMB xlc/xlC and the HP C compiler.
## (see the conditional assignment to $gccflag above).
## There are various ways to get dependency output from gcc. Here's
## why we pick this rather obscure method:
## - Don't want to use -MD because we'd like the dependencies to end
## up in a subdir. Having to rename by hand is ugly.
## (We might end up doing this anyway to support other compilers.)
## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
## -MM, not -M (despite what the docs say). Also, it might not be
## supported by the other compilers which use the 'gcc' depmode.
## - Using -M directly means running the compiler twice (even worse
## than renaming).
if test -z "$gccflag"; then
gccflag=-MD,
fi
"$@" -Wp,"$gccflag$tmpdepfile"
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
echo "$object : \\" > "$depfile"
# The second -e expression handles DOS-style file names with drive
# letters.
sed -e 's/^[^:]*: / /' \
-e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
## This next piece of magic avoids the "deleted header file" problem.
## The problem is that when a header file which appears in a .P file
## is deleted, the dependency causes make to die (because there is
## typically no way to rebuild the header). We avoid this by adding
## dummy dependencies for each header file. Too bad gcc doesn't do
## this for us directly.
## Some versions of gcc put a space before the ':'. On the theory
## that the space means something, we add a space to the output as
## well. hp depmode also adds that space, but also prefixes the VPATH
## to the object. Take care to not repeat it in the output.
## Some versions of the HPUX 10.20 sed can't process this invocation
## correctly. Breaking it into two sed invocations is a workaround.
tr ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \
| sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
hp)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
sgi)
if test "$libtool" = yes; then
"$@" "-Wp,-MDupdate,$tmpdepfile"
else
"$@" -MDupdate "$tmpdepfile"
fi
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files
echo "$object : \\" > "$depfile"
# Clip off the initial element (the dependent). Don't try to be
# clever and replace this with sed code, as IRIX sed won't handle
# lines with more than a fixed number of characters (4096 in
# IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines;
# the IRIX cc adds comments like '#:fec' to the end of the
# dependency line.
tr ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \
| tr "$nl" ' ' >> "$depfile"
echo >> "$depfile"
# The second pass generates a dummy entry for each header file.
tr ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
>> "$depfile"
else
make_dummy_depfile
fi
rm -f "$tmpdepfile"
;;
xlc)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
aix)
# The C for AIX Compiler uses -M and outputs the dependencies
# in a .u file. In older versions, this file always lives in the
# current directory. Also, the AIX compiler puts '$object:' at the
# start of each line; $object doesn't have directory information.
# Version 6 uses the directory in both cases.
set_dir_from "$object"
set_base_from "$object"
if test "$libtool" = yes; then
tmpdepfile1=$dir$base.u
tmpdepfile2=$base.u
tmpdepfile3=$dir.libs/$base.u
"$@" -Wc,-M
else
tmpdepfile1=$dir$base.u
tmpdepfile2=$dir$base.u
tmpdepfile3=$dir$base.u
"$@" -M
fi
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
exit $stat
fi
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
do
test -f "$tmpdepfile" && break
done
aix_post_process_depfile
;;
tcc)
# tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26
# FIXME: That version still under development at the moment of writing.
# Make that this statement remains true also for stable, released
# versions.
# It will wrap lines (doesn't matter whether long or short) with a
# trailing '\', as in:
#
# foo.o : \
# foo.c \
# foo.h \
#
# It will put a trailing '\' even on the last line, and will use leading
# spaces rather than leading tabs (at least since its commit 0394caf7
# "Emit spaces for -MD").
"$@" -MD -MF "$tmpdepfile"
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
# Each non-empty line is of the form 'foo.o : \' or ' dep.h \'.
# We have to change lines of the first kind to '$object: \'.
sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile"
# And for each line of the second kind, we have to emit a 'dep.h:'
# dummy dependency, to avoid the deleted-header problem.
sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile"
rm -f "$tmpdepfile"
;;
## The order of this option in the case statement is important, since the
## shell code in configure will try each of these formats in the order
## listed in this file. A plain '-MD' option would be understood by many
## compilers, so we must ensure this comes after the gcc and icc options.
pgcc)
# Portland's C compiler understands '-MD'.
# Will always output deps to 'file.d' where file is the root name of the
# source file under compilation, even if file resides in a subdirectory.
# The object file name does not affect the name of the '.d' file.
# pgcc 10.2 will output
# foo.o: sub/foo.c sub/foo.h
# and will wrap long lines using '\' :
# foo.o: sub/foo.c ... \
# sub/foo.h ... \
# ...
set_dir_from "$object"
# Use the source, not the object, to determine the base name, since
# that's sadly what pgcc will do too.
set_base_from "$source"
tmpdepfile=$base.d
# For projects that build the same source file twice into different object
# files, the pgcc approach of using the *source* file root name can cause
# problems in parallel builds. Use a locking strategy to avoid stomping on
# the same $tmpdepfile.
lockdir=$base.d-lock
trap "
echo '$0: caught signal, cleaning up...' >&2
rmdir '$lockdir'
exit 1
" 1 2 13 15
numtries=100
i=$numtries
while test $i -gt 0; do
# mkdir is a portable test-and-set.
if mkdir "$lockdir" 2>/dev/null; then
# This process acquired the lock.
"$@" -MD
stat=$?
# Release the lock.
rmdir "$lockdir"
break
else
# If the lock is being held by a different process, wait
# until the winning process is done or we timeout.
while test -d "$lockdir" && test $i -gt 0; do
sleep 1
i=`expr $i - 1`
done
fi
i=`expr $i - 1`
done
trap - 1 2 13 15
if test $i -le 0; then
echo "$0: failed to acquire lock after $numtries attempts" >&2
echo "$0: check lockdir '$lockdir'" >&2
exit 1
fi
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
# Each line is of the form `foo.o: dependent.h',
# or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
# Do two passes, one to just change these to
# `$object: dependent.h' and one to simply `dependent.h:'.
sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
# Some versions of the HPUX 10.20 sed can't process this invocation
# correctly. Breaking it into two sed invocations is a workaround.
sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \
| sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
hp2)
# The "hp" stanza above does not work with aCC (C++) and HP's ia64
# compilers, which have integrated preprocessors. The correct option
# to use with these is +Maked; it writes dependencies to a file named
# 'foo.d', which lands next to the object file, wherever that
# happens to be.
# Much of this is similar to the tru64 case; see comments there.
set_dir_from "$object"
set_base_from "$object"
if test "$libtool" = yes; then
tmpdepfile1=$dir$base.d
tmpdepfile2=$dir.libs/$base.d
"$@" -Wc,+Maked
else
tmpdepfile1=$dir$base.d
tmpdepfile2=$dir$base.d
"$@" +Maked
fi
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile1" "$tmpdepfile2"
exit $stat
fi
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2"
do
test -f "$tmpdepfile" && break
done
if test -f "$tmpdepfile"; then
sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile"
# Add 'dependent.h:' lines.
sed -ne '2,${
s/^ *//
s/ \\*$//
s/$/:/
p
}' "$tmpdepfile" >> "$depfile"
else
make_dummy_depfile
fi
rm -f "$tmpdepfile" "$tmpdepfile2"
;;
tru64)
# The Tru64 compiler uses -MD to generate dependencies as a side
# effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'.
# At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
# dependencies in 'foo.d' instead, so we check for that too.
# Subdirectories are respected.
set_dir_from "$object"
set_base_from "$object"
if test "$libtool" = yes; then
# Libtool generates 2 separate objects for the 2 libraries. These
# two compilations output dependencies in $dir.libs/$base.o.d and
# in $dir$base.o.d. We have to check for both files, because
# one of the two compilations can be disabled. We should prefer
# $dir$base.o.d over $dir.libs/$base.o.d because the latter is
# automatically cleaned when .libs/ is deleted, while ignoring
# the former would cause a distcleancheck panic.
tmpdepfile1=$dir$base.o.d # libtool 1.5
tmpdepfile2=$dir.libs/$base.o.d # Likewise.
tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504
"$@" -Wc,-MD
else
tmpdepfile1=$dir$base.d
tmpdepfile2=$dir$base.d
tmpdepfile3=$dir$base.d
"$@" -MD
fi
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
exit $stat
fi
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
do
test -f "$tmpdepfile" && break
done
# Same post-processing that is required for AIX mode.
aix_post_process_depfile
;;
msvc7)
if test "$libtool" = yes; then
showIncludes=-Wc,-showIncludes
else
showIncludes=-showIncludes
fi
"$@" $showIncludes > "$tmpdepfile"
stat=$?
grep -v '^Note: including file: ' "$tmpdepfile"
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
echo "$object : \\" > "$depfile"
# The first sed program below extracts the file names and escapes
# backslashes for cygpath. The second sed program outputs the file
# name when reading, but also accumulates all include files in the
# hold buffer in order to output them again at the end. This only
# works with sed implementations that can handle large buffers.
sed < "$tmpdepfile" -n '
/^Note: including file: *\(.*\)/ {
s//\1/
s/\\/\\\\/g
p
}' | $cygpath_u | sort -u | sed -n '
s/ /\\ /g
s/\(.*\)/'"$tab"'\1 \\/p
s/.\(.*\) \\/\1:/
H
$ {
s/.*/'"$tab"'/
G
p
}' >> "$depfile"
echo >> "$depfile" # make sure the fragment doesn't end with a backslash
rm -f "$tmpdepfile"
;;
msvc7msys)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
#nosideeffect)
# This comment above is used by automake to tell side-effect
# dependency tracking mechanisms from slower ones.
dashmstdout)
# Important note: in order to support this mode, a compiler *must*
# always write the preprocessed file to stdout, regardless of -o.
"$@" || exit $?
# Remove the call to Libtool.
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
# Remove '-o $object'.
IFS=" "
for arg
do
case $arg in
-o)
shift
;;
$object)
shift
;;
*)
set fnord "$@" "$arg"
shift # fnord
shift # $arg
;;
esac
done
test -z "$dashmflag" && dashmflag=-M
# Require at least two characters before searching for ':'
# in the target name. This is to cope with DOS-style filenames:
# a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise.
"$@" $dashmflag |
sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile"
rm -f "$depfile"
cat < "$tmpdepfile" > "$depfile"
# Some versions of the HPUX 10.20 sed can't process this sed invocation
# correctly. Breaking it into two sed invocations is a workaround.
tr ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
| sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
dashXmstdout)
# This case only exists to satisfy depend.m4. It is never actually
# run, as this mode is specially recognized in the preamble.
exit 1
;;
makedepend)
"$@" || exit $?
# Remove any Libtool call
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
# X makedepend
shift
cleared=no eat=no
for arg
do
case $cleared in
no)
set ""; shift
cleared=yes ;;
esac
if test $eat = yes; then
eat=no
continue
fi
case "$arg" in
-D*|-I*)
set fnord "$@" "$arg"; shift ;;
# Strip any option that makedepend may not understand. Remove
# the object too, otherwise makedepend will parse it as a source file.
-arch)
eat=yes ;;
-*|$object)
;;
*)
set fnord "$@" "$arg"; shift ;;
esac
done
obj_suffix=`echo "$object" | sed 's/^.*\././'`
touch "$tmpdepfile"
${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
rm -f "$depfile"
# makedepend may prepend the VPATH from the source file name to the object.
# No need to regex-escape $object, excess matching of '.' is harmless.
sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile"
# Some versions of the HPUX 10.20 sed can't process the last invocation
# correctly. Breaking it into two sed invocations is a workaround.
sed '1,2d' "$tmpdepfile" \
| tr ' ' "$nl" \
| sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
| sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile" "$tmpdepfile".bak
;;
cpp)
# Important note: in order to support this mode, a compiler *must*
# always write the preprocessed file to stdout.
"$@" || exit $?
# Remove the call to Libtool.
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
# Remove '-o $object'.
IFS=" "
for arg
do
case $arg in
-o)
shift
;;
$object)
shift
;;
*)
set fnord "$@" "$arg"
shift # fnord
shift # $arg
;;
esac
done
"$@" -E \
| sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
-e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
| sed '$ s: \\$::' > "$tmpdepfile"
rm -f "$depfile"
echo "$object : \\" > "$depfile"
cat < "$tmpdepfile" >> "$depfile"
sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
msvisualcpp)
# Important note: in order to support this mode, a compiler *must*
# always write the preprocessed file to stdout.
"$@" || exit $?
# Remove the call to Libtool.
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
IFS=" "
for arg
do
case "$arg" in
-o)
shift
;;
$object)
shift
;;
"-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
set fnord "$@"
shift
shift
;;
*)
set fnord "$@" "$arg"
shift
shift
;;
esac
done
"$@" -E 2>/dev/null |
sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile"
rm -f "$depfile"
echo "$object : \\" > "$depfile"
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile"
echo "$tab" >> "$depfile"
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile"
rm -f "$tmpdepfile"
;;
msvcmsys)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
none)
exec "$@"
;;
*)
echo "Unknown depmode $depmode" 1>&2
exit 1
;;
esac
exit 0
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:
+106
View File
@@ -0,0 +1,106 @@
libcurl bindings
================
Creative people have written bindings or interfaces for various environments
and programming languages. Using one of these allows you to take advantage of
curl powers from within your favourite language or system.
This is a list of all known interfaces as of this writing.
The bindings listed below are not part of the curl/libcurl distribution
archives, but must be downloaded and installed separately.
[Ada95](http://www.almroth.com/adacurl/index.html) Written by Andreas Almroth
[Basic](http://scriptbasic.com/) ScriptBasic bindings written by Peter Verhas
[C++](http://curlpp.org/) Written by Jean-Philippe Barrette-LaPierre
[Ch](http://chcurl.sourceforge.net/) Written by Stephen Nestinger and Jonathan Rogado
Cocoa: [BBHTTP](https://github.com/brunodecarvalho/BBHTTP) written by Bruno de Carvalho
[curlhandle](http://curlhandle.sourceforge.net/) Written by Dan Wood
[D](http://dlang.org/library/std/net/curl.html) Written by Kenneth Bogert
[Dylan](http://dylanlibs.sourceforge.net/) Written by Chris Double
[Eiffel](https://room.eiffel.com/library/curl) Written by Eiffel Software
[Euphoria](http://rays-web.com/eulibcurl.htm) Written by Ray Smith
[Falcon](http://www.falconpl.org/index.ftd?page_id=prjs&prj_id=curl)
[Ferite](http://www.ferite.org/) Written by Paul Querna
[Gambas](http://gambas.sourceforge.net/)
[glib/GTK+](http://atterer.net/glibcurl/) Written by Richard Atterer
[Guile](http://www.lonelycactus.com/guile-curl.html) Written by Michael L. Gran
[Harbour](https://github.com/vszakats/harbour-core/tree/master/contrib/hbcurl) Written by Viktor Szakáts
[Haskell](http://hackage.haskell.org/cgi-bin/hackage-scripts/package/curl) Written by Galois, Inc
[Java](https://github.com/pjlegato/curl-java)
[Julia](https://github.com/forio/Curl.jl) Written by Paul Howe
[Lisp](http://common-lisp.net/project/cl-curl/) Written by Liam Healy
Lua: [luacurl](http://luacurl.luaforge.net/) by Alexander Marinov, [Lua-cURL](http://luaforge.net/projects/lua-curl/) by Jürgen Hötzel
[Mono](http://forge.novell.com/modules/xfmod/project/?libcurl-mono) Written by Jeffrey Phillips
[.NET](https://sourceforge.net/projects/libcurl-net/) libcurl-net by Jeffrey Phillips
[node.js](https://github.com/JCMais/node-libcurl) node-libcurl by Jonathan Cardoso Machado
[Object-Pascal](http://www.tekool.com/opcurl) Free Pascal, Delphi and Kylix binding written by Christophe Espern.
[O'Caml](https://sourceforge.net/projects/ocurl/) Written by Lars Nilsson
[Pascal](http://houston.quik.com/jkp/curlpas/) Free Pascal, Delphi and Kylix binding written by Jeffrey Pohlmeyer.
[Perl](https://github.com/szbalint/WWW--Curl) Maintained by Cris Bailiff and Bálint Szilakszi
[PHP](https://php.net/curl) Originally written by Sterling Hughes
[PostgreSQL](http://gborg.postgresql.org/project/pgcurl/projdisplay.php) Written by Gian Paolo Ciceri
[Python](http://pycurl.sourceforge.net/) PycURL by Kjetil Jacobsen
[R](http://cran.r-project.org/package=curl)
[Rexx](http://rexxcurl.sourceforge.net/) Written Mark Hessling
RPG, support for ILE/RPG on OS/400 is included in source distribution
Ruby: [curb](http://curb.rubyforge.org/) written by Ross Bamford, [ruby-curl-multi](http://curl-multi.rubyforge.org/) written by Kristjan Petursson and Keith Rarick
[Rust](https://github.com/carllerche/curl-rust) curl-rust - by Carl Lerche
[Scheme](http://www.metapaper.net/lisovsky/web/curl/) Bigloo binding by Kirill Lisovsky
[S-Lang](http://www.jedsoft.org/slang/modules/curl.html) by John E Davis
[Smalltalk](http://www.squeaksource.com/CurlPlugin/) Written by Danil Osipchuk
[SP-Forth](http://www.forth.org.ru/~ac/lib/lin/curl/) Written by ygrek
[SPL](http://www.clifford.at/spl/) Written by Clifford Wolf
[Tcl](http://mirror.yellow5.com/tclcurl/) Tclcurl by Andrés García
[Visual Basic](https://sourceforge.net/projects/libcurl-vb/) libcurl-vb by Jeffrey Phillips
[Visual Foxpro](http://www.ctl32.com.ar/libcurl.asp) by Carlos Alloatti
[Q](http://q-lang.sourceforge.net/) The libcurl module is part of the default install
[wxWidgets](http://wxcode.sourceforge.net/components/wxcurl/) Written by Casey O'Donnell
[XBLite](http://perso.wanadoo.fr/xblite/libraries.html) Written by David Szafranski
[Xojo](https://github.com/charonn0/RB-libcURL) Written by Andrew Lambert
+247
View File
@@ -0,0 +1,247 @@
_ _ ____ _
___| | | | _ \| |
/ __| | | | |_) | |
| (__| |_| | _ <| |___
\___|\___/|_| \_\_____|
BUGS
1. Bugs
1.1 There are still bugs
1.2 Where to report
1.3 What to report
1.4 libcurl problems
1.5 Who will fix the problems
1.6 How to get a stack trace
1.7 Bugs in libcurl bindings
2. Bug fixing procedure
2.1 What happens on first filing
2.2 First response
2.3 Not reproducible
2.4 Unresponsive
2.5 Lack of time/interest
2.6 KNOWN_BUGS
2.7 TODO
2.8 Closing off stalled bugs
==============================================================================
1.1 There are still bugs
Curl and libcurl have grown substantially since the beginning. At the time
of writing (January 2013), there are about 83,000 lines of source code, and
by the time you read this it has probably grown even more.
Of course there are lots of bugs left. And lots of misfeatures.
To help us make curl the stable and solid product we want it to be, we need
bug reports and bug fixes.
1.2 Where to report
If you can't fix a bug yourself and submit a fix for it, try to report an as
detailed report as possible to a curl mailing list to allow one of us to
have a go at a solution. You can optionally also post your bug/problem at
curl's bug tracking system over at
https://github.com/curl/curl/issues
Please read the rest of this document below first before doing that!
If you feel you need to ask around first, find a suitable mailing list and
post there. The lists are available on https://curl.haxx.se/mail/
1.3 What to report
When reporting a bug, you should include all information that will help us
understand what's wrong, what you expected to happen and how to repeat the
bad behavior. You therefore need to tell us:
- your operating system's name and version number
- what version of curl you're using (curl -V is fine)
- versions of the used libraries that libcurl is built to use
- what URL you were working with (if possible), at least which protocol
and anything and everything else you think matters. Tell us what you
expected to happen, tell use what did happen, tell us how you could make it
work another way. Dig around, try out, test. Then include all the tiny bits
and pieces in your report. You will benefit from this yourself, as it will
enable us to help you quicker and more accurately.
Since curl deals with networks, it often helps us if you include a protocol
debug dump with your bug report. The output you get by using the -v or
--trace options.
If curl crashed, causing a core dump (in unix), there is hardly any use to
send that huge file to anyone of us. Unless we have an exact same system
setup as you, we can't do much with it. Instead we ask you to get a stack
trace and send that (much smaller) output to us instead!
The address and how to subscribe to the mailing lists are detailed in the
MANUAL file.
1.4 libcurl problems
When you've written your own application with libcurl to perform transfers,
it is even more important to be specific and detailed when reporting bugs.
Tell us the libcurl version and your operating system. Tell us the name and
version of all relevant sub-components like for example the SSL library
you're using and what name resolving your libcurl uses. If you use SFTP or
SCP, the libssh2 version is relevant etc.
Showing us a real source code example repeating your problem is the best way
to get our attention and it will greatly increase our chances to understand
your problem and to work on a fix (if we agree it truly is a problem).
Lots of problems that appear to be libcurl problems are actually just abuses
of the libcurl API or other malfunctions in your applications. It is advised
that you run your problematic program using a memory debug tool like
valgrind or similar before you post memory-related or "crashing" problems to
us.
1.5 Who will fix the problems
If the problems or bugs you describe are considered to be bugs, we want to
have the problems fixed.
There are no developers in the curl project that are paid to work on bugs.
All developers that take on reported bugs do this on a voluntary basis. We
do it out of an ambition to keep curl and libcurl excellent products and out
of pride.
But please do not assume that you can just lump over something to us and it
will then magically be fixed after some given time. Most often we need
feedback and help to understand what you've experienced and how to repeat a
problem. Then we may only be able to assist YOU to debug the problem and to
track down the proper fix.
We get reports from many people every month and each report can take a
considerable amount of time to really go to the bottom with.
1.6 How to get a stack trace
First, you must make sure that you compile all sources with -g and that you
don't 'strip' the final executable. Try to avoid optimizing the code as
well, remove -O, -O2 etc from the compiler options.
Run the program until it cores.
Run your debugger on the core file, like '<debugger> curl core'. <debugger>
should be replaced with the name of your debugger, in most cases that will
be 'gdb', but 'dbx' and others also occur.
When the debugger has finished loading the core file and presents you a
prompt, enter 'where' (without the quotes) and press return.
The list that is presented is the stack trace. If everything worked, it is
supposed to contain the chain of functions that were called when curl
crashed. Include the stack trace with your detailed bug report. It'll help a
lot.
1.7 Bugs in libcurl bindings
There will of course pop up bugs in libcurl bindings. You should then
primarily approach the team that works on that particular binding and see
what you can do to help them fix the problem.
If you suspect that the problem exists in the underlying libcurl, then
please convert your program over to plain C and follow the steps outlined
above.
2. Bug fixing procedure
2.1 What happens on first filing
When a new issue is posted in the issue tracker or on the mailing list, the
team of developers first need to see the report. Maybe they took the day
off, maybe they're off in the woods hunting. Have patience. Allow at least a
few days before expecting someone to have responded.
In the issue tracker you can expect that some labels will be set on the
issue to help categorize it.
2.2 First response
If your issue/bug report wasn't perfect at once (and few are), chances are
that someone will ask follow-up questions. Which version did you use? Which
options did you use? How often does the problem occur? How can we reproduce
this problem? Which protocols does it involve? Or perhaps much more specific
and deep diving questions. It all depends on your specific issue.
You should then respond to these follow-up questions and provide more info
about the problem, so that we can help you figure it out. Or maybe you can
help us figure it out. An active back-and-forth communication is important
and the key for finding a cure and landing a fix.
2.3 Not reproducible
For problems that we can't reproduce and can't understand even after having
gotten all the info we need and having studied the source code over again,
are really hard to solve so then we may require further work from you who
actually see or experience the problem.
2.4 Unresponsive
If the problem haven't been understood or reproduced, and there's nobody
responding to follow-up questions or questions asking for clarifications or
for discussing possible ways to move forward with the task, we take that as
a strong suggestion that the bug is not important.
Unimportant issues will be closed as inactive sooner or later as they can't
be fixed. The inactivity period (waiting for responses) should not be
shorter than two weeks but may extend months.
2.5 Lack of time/interest
Bugs that are filed and are understood can unfortunately end up in the
"nobody cares enough about it to work on it" category. Such bugs are
perfectly valid problems that *should* get fixed but apparently aren't. We
try to mark such bugs as "KNOWN_BUGS material" after a time of inactivity
and if no activity is noticed after yet some time those bugs are added to
KNOWN_BUGS and are closed in the issue tracker.
2.6 KNOWN_BUGS
This is a list of known bugs. Bugs we know exist and that have been pointed
out but that haven't yet been fixed. The reasons for why they haven't been
fixed can involve anything really, but the primary reason is that nobody has
considered these problems to be important enough to spend the necesary time
and effort to have them fixed.
The KNOWN_BUGS are always up for grabs and we will always love the ones who
bring one of them back to live and offers solutions to them.
The KNOWN_BUGS document has a sibling document known as TODO.
2.7 TODO
Issues that are filed or reported that aren't really bugs but more missing
features or ideas for future improvements and so on are marked as
'enhancement' or 'feature-request' and will be added to the TODO document
instead and the issue is closed. We don't keep TODO items in the issue
tracker.
The TODO document is full of ideas and suggestions of what we can add or fix
one day. You're always encouraged and free to grab one of those items and
take up a discussion with the curl development team on how that could be
implemented or provided in the project so that you can work on ticking it
odd that document.
If the issue is rather a bug and not a missing feature or functionality, it
is listed in KNOWN_BUGS instead.
2.8 Closing off stalled bugs
The issue and pull request trackers on https://github.com/curl/curl will
only hold "active" entries (using a non-precise defintion of what active
actually is, but they're at least not completely dead). Those that are
abandonded or in other ways dormant will be closed and sometimes added to
TODO and KNOWN_BUGS instead.
This way, we only have "active" issues open on github. Irrelevant issues and
pull requests will not distract developes or casual visitors.
+124
View File
@@ -0,0 +1,124 @@
# checksrc
This is the tool we use within the curl project to scan C source code and
check that it adheres to our [Source Code Style guide](CODE_STYLE.md).
## Usage
checksrc.pl [options] [file1] [file2] ...
## Command line options
`-W[file]` whitelists that file and excludes it from being checked. Helpful
when, for example, one of the files is generated.
`-D[dir]` directory name to prepend to file names when accessing them.
`-h` shows the help output, that also lists all recognized warnings
## What does checksrc warn for?
checksrc does not check and verify the code against the entire style guide,
but the script is instead an effort to detect the most common mistakes and
syntax mistakes that contributors make before they get accustomed to our code
style. Heck, many of us regulars do the mistakes too and this script helps us
keep the code in shape.
checksrc.pl -h
Lists how to use the script and it lists all existing warnings it has and
problems it detects. At the time of this writing, the existing checksrc
warnings are:
- `BADCOMMAND`: There's a bad !checksrc! instruction in the code. See the
**Ignore certain warnings** section below for details.
- `BANNEDFUNC`: A banned function was used. The functions sprintf, vsprintf,
strcat, strncat, gets are **never** allowed in curl source code.
- `BRACEELSE`: '} else' on the same line. The else is supposed to be on the
following line.
- `BRACEPOS`: wrong position for an open brace (`{`).
- `COMMANOSPACE`: a comma without following space
- `COPYRIGHT`: the file is missing a copyright statement!
- `CPPCOMMENTS`: `//` comment detected, that's not C89 compliant
- `FOPENMODE`: `fopen()` needs a macro for the mode string, use it
- `INDENTATION`: detected a wrong start column for code. Note that this warning
only checks some specific places and will certainly miss many bad
indentations.
- `LONGLINE`: A line is longer than 79 columns.
- `PARENBRACE`: `){` was used without sufficient space in between.
- `RETURNNOSPACE`: `return` was used without space between the keyword and the
following value.
- `SPACEAFTERPAREN`: there was a space after open parenthesis, `( text`.
- `SPACEBEFORECLOSE`: there was a space before a close parenthesis, `text )`.
- `SPACEBEFORECOMMA`: there was a space before a comma, `one , two`.
- `SPACEBEFOREPAREN`: there was a space before an open parenthesis, `if (`,
where one was not expected
- `SPACESEMILCOLON`: there was a space before semicolon, ` ;`.
- `TABS`: TAB characters are not allowed!
- `TRAILINGSPACE`: Trailing white space on the line
- `UNUSEDIGNORE`: a checksrc inlined warning ignore was asked for but not used,
that's an ignore that should be removed or changed to get used.
## Ignore certain warnings
Due to the nature of the source code and the flaws of the checksrc tool, there
is sometimes a need to ignore specific warnings. checksrc allows a few
different ways to do this.
### Inline ignore
You can control what to ignore within a specific source file by providing
instructions to checksrc in the source code itself. You need a magic marker
that is `!checksrc!` followed by the instruction. The instruction can ask to
ignore a specific warning N number of times or you ignore all of them until
you mark the end of the ignored section.
Inline ignores are only done for that single specific source code file.
Example
/* !checksrc! disable LONGLINE all */
This will ignore the warning for overly long lines until it is re-enabled with:
/* !checksrc! enable LONGLINE */
If the enabling isn't performed before the end of the file, it will be enabled
automatically for the next file.
You can also opt to ignore just N violations so that if you have a single long
line you just can't shorten and is agreed to be fine anyway:
/* !checksrc! disable LONGLINE 1 */
... and the warning for long lines will be enabled again automatically after
it has ignored that single warning. The number `1` can of course be changed to
any other integer number. It can be used to make sure only the exact intended
instances are ignored and nothing extra.
### Directory wide ignore patterns
This is a method we've transitioned away from. Use inline ignores as far as
possible.
Make a `checksrc.whitelist` file in the directory of the source code with the
false positive, and include the full offending line into this file.
@@ -0,0 +1,32 @@
Contributor Code of Conduct
===========================
As contributors and maintainers of this project, we pledge to respect all
people who contribute through reporting issues, posting feature requests,
updating documentation, submitting pull requests or patches, and other
activities.
We are committed to making participation in this project a harassment-free
experience for everyone, regardless of level of experience, gender, gender
identity and expression, sexual orientation, disability, personal appearance,
body size, race, ethnicity, age, or religion.
Examples of unacceptable behavior by participants include the use of sexual
language or imagery, derogatory comments or personal attacks, trolling, public
or private harassment, insults, or other unprofessional conduct.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct. Project maintainers who do not
follow the Code of Conduct may be removed from the project team.
This code of conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community.
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by opening an issue or contacting one or more of the project
maintainers.
This Code of Conduct is adapted from the [Contributor
Covenant](http://contributor-covenant.org), version 1.1.0, available at
[http://contributor-covenant.org/version/1/1/0/](http://contributor-covenant.org/version/1/1/0/)
@@ -0,0 +1,238 @@
# curl C code style
Source code that has a common style is easier to read than code that uses
different styles in different places. It helps making the code feel like one
single code base. Easy-to-read is a very important property of code and helps
making it easier to review when new things are added and it helps debugging
code when developers are trying to figure out why things go wrong. A unified
style is more important than individual contributors having their own personal
tastes satisfied.
Our C code has a few style rules. Most of them are verified and upheld by the
`lib/checksrc.pl` script. Invoked with `make checksrc` or even by default by
the build system when built after `./configure --enable-debug` has been used.
It is normally not a problem for anyone to follow the guidelines, as you just
need to copy the style already used in the source code and there are no
particularly unusual rules in our set of rules.
We also work hard on writing code that are warning-free on all the major
platforms and in general on as many platforms as possible. Code that obviously
will cause warnings will not be accepted as-is.
## Naming
Try using a non-confusing naming scheme for your new functions and variable
names. It doesn't necessarily have to mean that you should use the same as in
other places of the code, just that the names should be logical,
understandable and be named according to what they're used for. File-local
functions should be made static. We like lower case names.
See the [INTERNALS](INTERNALS.md) document on how we name non-exported
library-global symbols.
## Indenting
We use only spaces for indentation, never TABs. We use two spaces for each new
open brace.
if(something_is_true) {
while(second_statement == fine) {
moo();
}
}
## Comments
Since we write C89 code, `//` comments are not allowed. They weren't
introduced in the C standard until C99. We use only `/*` and `*/` comments:
/* this is a comment */
## Long lines
Source code in curl may never be wider than 79 columns and there are two
reasons for maintaining this even in the modern era of very large and high
resolution screens:
1. Narrower columns are easier to read than very wide ones. There's a reason
newspapers have used columns for decades or centuries.
2. Narrower columns allow developers to easier show multiple pieces of code
next to each other in different windows. I often have two or three source
code windows next to each other on the same screen - as well as multiple
terminal and debugging windows.
## Braces
In if/while/do/for expressions, we write the open brace on the same line as
the keyword and we then set the closing brace on the same indentation level as
the initial keyword. Like this:
if(age < 40) {
/* clearly a youngster */
}
You may omit the braces if they would contain only a one-line statement:
if(!x)
continue;
For functions the opening brace should be on a separate line:
int main(int argc, char **argv)
{
return 1;
}
## 'else' on the following line
When adding an `else` clause to a conditional expression using braces, we add
it on a new line after the closing brace. Like this:
if(age < 40) {
/* clearly a youngster */
}
else {
/* probably grumpy */
}
## No space before parentheses
When writing expressions using if/while/do/for, there shall be no space
between the keyword and the open parenthesis. Like this:
while(1) {
/* loop forever */
}
## Use boolean conditions
Rather than test a conditional value such as a bool against TRUE or FALSE, a
pointer against NULL or != NULL and an int against zero or not zero in
if/while conditions we prefer:
result = do_something();
if(!result) {
/* something went wrong */
return result;
}
## No assignments in conditions
To increase readability and reduce complexity of conditionals, we avoid
assigning variables within if/while conditions. We frown upon this style:
if((ptr = malloc(100)) == NULL)
return NULL;
and instead we encourage the above version to be spelled out more clearly:
ptr = malloc(100);
if(!ptr)
return NULL;
## New block on a new line
We never write multiple statements on the same source line, even for very
short if() conditions.
if(a)
return TRUE;
else if(b)
return FALSE;
and NEVER:
if(a) return TRUE;
else if(b) return FALSE;
## Space around operators
Please use spaces on both sides of operators in C expressions. Postfix `(),
[], ->, ., ++, --` and Unary `+, - !, ~, &` operators excluded they should
have no space.
Examples:
bla = func();
who = name[0];
age += 1;
true = !false;
size += -2 + 3 * (a + b);
ptr->member = a++;
struct.field = b--;
ptr = &address;
contents = *pointer;
complement = ~bits;
empty = (!*string) ? TRUE : FALSE;
## Column alignment
Some statements cannot be completed on a single line because the line would
be too long, the statement too hard to read, or due to other style guidelines
above. In such a case the statement will span multiple lines.
If a continuation line is part of an expression or sub-expression then you
should align on the appropriate column so that it's easy to tell what part of
the statement it is. Operators should not start continuation lines. In other
cases follow the 2-space indent guideline. Here are some examples from libcurl:
~~~c
if(Curl_pipeline_wanted(handle->multi, CURLPIPE_HTTP1) &&
(handle->set.httpversion != CURL_HTTP_VERSION_1_0) &&
(handle->set.httpreq == HTTPREQ_GET ||
handle->set.httpreq == HTTPREQ_HEAD))
/* didn't ask for HTTP/1.0 and a GET or HEAD */
return TRUE;
~~~
~~~c
case CURLOPT_KEEP_SENDING_ON_ERROR:
data->set.http_keep_sending_on_error = (0 != va_arg(param, long)) ?
TRUE : FALSE;
break;
~~~
~~~c
data->set.http_disable_hostname_check_before_authentication =
(0 != va_arg(param, long)) ? TRUE : FALSE;
~~~
~~~c
if(option) {
result = parse_login_details(option, strlen(option),
(userp ? &user : NULL),
(passwdp ? &passwd : NULL),
NULL);
}
~~~
~~~c
DEBUGF(infof(data, "Curl_pp_readresp_ %d bytes of trailing "
"server response left\n",
(int)clipamount));
~~~
## Platform dependent code
Use `#ifdef HAVE_FEATURE` to do conditional code. We avoid checking for
particular operating systems or hardware in the #ifdef lines. The HAVE_FEATURE
shall be generated by the configure script for unix-like systems and they are
hard-coded in the config-[system].h files for the others.
We also encourage use of macros/functions that possibly are empty or defined
to constants when libcurl is built without that feature, to make the code
seamless. Like this style where the `magic()` function works differently
depending on a build-time conditional:
#ifdef HAVE_MAGIC
void magic(int a)
{
return a + 2;
}
#else
#define magic(x) 1
#endif
int content = magic(3);
@@ -0,0 +1,247 @@
# Contributing to the curl project
This document is intended to offer guidelines on how to best contribute to the
curl project. This concerns new features as well as corrections to existing
flaws or bugs.
## Learning curl
### Join the Community
Skip over to [https://curl.haxx.se/mail/](https://curl.haxx.se/mail/) and join
the appropriate mailing list(s). Read up on details before you post
questions. Read this file before you start sending patches! We prefer
questions sent to and discussions being held on the mailing list(s), not sent
to individuals.
Before posting to one of the curl mailing lists, please read up on the
[mailing list etiquette](https://curl.haxx.se/mail/etiquette.html).
We also hang out on IRC in #curl on irc.freenode.net
If you're at all interested in the code side of things, consider clicking
'watch' on the [curl repo on github](https://github.com/curl/curl) to get
notified on pull requests and new issues posted there.
### License and copyright
When contributing with code, you agree to put your changes and new code under
the same license curl and libcurl is already using unless stated and agreed
otherwise.
If you add a larger piece of code, you can opt to make that file or set of
files to use a different license as long as they don't enforce any changes to
the rest of the package and they make sense. Such "separate parts" can not be
GPL licensed (as we don't want copyleft to affect users of libcurl) but they
must use "GPL compatible" licenses (as we want to allow users to use libcurl
properly in GPL licensed environments).
When changing existing source code, you do not alter the copyright of the
original file(s). The copyright will still be owned by the original creator(s)
or those who have been assigned copyright by the original author(s).
By submitting a patch to the curl project, you are assumed to have the right
to the code and to be allowed by your employer or whatever to hand over that
patch/code to us. We will credit you for your changes as far as possible, to
give credit but also to keep a trace back to who made what changes. Please
always provide us with your full real name when contributing!
### What To Read
Source code, the man pages, the [INTERNALS
document](https://curl.haxx.se/dev/internals.html),
[TODO](https://curl.haxx.se/docs/todo.html),
[KNOWN_BUGS](https://curl.haxx.se/docs/knownbugs.html) and the [most recent
changes](https://curl.haxx.se/dev/sourceactivity.html) in git. Just lurking on
the [curl-library mailing
list](https://curl.haxx.se/mail/list.cgi?list=curl-library) will give you a
lot of insights on what's going on right now. Asking there is a good idea too.
## Write a good patch
### Follow code style
When writing C code, follow the
[CODE_STYLE](https://curl.haxx.se/dev/code-style.html) already established in
the project. Consistent style makes code easier to read and mistakes less
likely to happen. Run `make checksrc` before you submit anything, to make sure
you follow the basic style. That script doesn't verify everything, but if it
complains you know you have work to do.
### Non-clobbering All Over
When you write new functionality or fix bugs, it is important that you don't
fiddle all over the source files and functions. Remember that it is likely
that other people have done changes in the same source files as you have and
possibly even in the same functions. If you bring completely new
functionality, try writing it in a new source file. If you fix bugs, try to
fix one bug at a time and send them as separate patches.
### Write Separate Changes
It is annoying when you get a huge patch from someone that is said to fix 511
odd problems, but discussions and opinions don't agree with 510 of them - or
509 of them were already fixed in a different way. Then the person merging
this change needs to extract the single interesting patch from somewhere
within the huge pile of source, and that gives a lot of extra work.
Preferably, each fix that correct a problem should be in its own patch/commit
with its own description/commit message stating exactly what they correct so
that all changes can be selectively applied by the maintainer or other
interested parties.
Also, separate changes enable bisecting much better when we track problems
and regression in the future.
### Patch Against Recent Sources
Please try to get the latest available sources to make your patches against.
It makes the lives of the developers so much easier. The very best is if you
get the most up-to-date sources from the git repository, but the latest
release archive is quite OK as well!
### Documentation
Writing docs is dead boring and one of the big problems with many open source
projects. Someone's gotta do it. It makes it a lot easier if you submit a
small description of your fix or your new features with every contribution so
that it can be swiftly added to the package documentation.
The documentation is always made in man pages (nroff formatted) or plain
ASCII files. All HTML files on the web site and in the release archives are
generated from the nroff/ASCII versions.
### Test Cases
Since the introduction of the test suite, we can quickly verify that the main
features are working as they're supposed to. To maintain this situation and
improve it, all new features and functions that are added need to be tested
in the test suite. Every feature that is added should get at least one valid
test case that verifies that it works as documented. If every submitter also
posts a few test cases, it won't end up as a heavy burden on a single person!
If you don't have test cases or perhaps you have done something that is very
hard to write tests for, do explain exactly how you have otherwise tested and
verified your changes.
## Sharing Your Changes
### How to get your changes into the main sources
Ideally you file a [pull request on
github](https://github.com/curl/curl/pulls), but you can also send your plain
patch to [the curl-library mailing
list](https://curl.haxx.se/mail/list.cgi?list=curl-library).
Either way, your change will be reviewed and discussed there and you will be
expected to correct flaws pointed out and update accordingly, or the change
risk stalling and eventually just get deleted without action. As a submitter
of a change, you are the owner of that change until it has been merged.
Respond on the list or on github about the change and answer questions and/or
fix nits/flaws. This is very important. We will take lack of replies as a
sign that you're not very anxious to get your patch accepted and we tend to
simply drop such changes.
### About pull requests
With github it is easy to send a [pull
request](https://github.com/curl/curl/pulls) to the curl project to have
changes merged.
We prefer pull requests to mailed patches, as it makes it a proper git commit
that is easy to merge and they are easy to track and not that easy to loose
in a flood of many emails, like they sometimes do on the mailing lists.
When you adjust your pull requests after review, consider squashing the
commits so that we can review the full updated version more easily.
### Making quality patches
Make the patch against as recent sources as possible.
If you've followed the tips in this document and your patch still hasn't been
incorporated or responded to after some weeks, consider resubmitting it to
the list or better yet: change it to a pull request.
### Write good commit messages
A short guide to how to write commit messages in the curl project.
---- start ----
[area]: [short line describing the main effect]
-- empty line --
[full description, no wider than 72 columns that describe as much as
possible as to why this change is made, and possibly what things
it fixes and everything else that is related]
-- empty line --
[Bug: URL to source of the report or more related discussion]
[Reported-by: John Doe - credit the reporter]
[whatever-else-by: credit all helpers, finders, doers]
---- stop ----
Don't forget to use commit --author="" if you commit someone else's work,
and make sure that you have your own user and email setup correctly in git
before you commit
### Write Access to git Repository
If you are a very frequent contributor, you may be given push access to the
git repository and then you'll be able to push your changes straight into the
git repo instead of sending changes as pull requests or by mail as patches.
Just ask if this is what you'd want. You will be required to have posted
several high quality patches first, before you can be granted push access.
### How To Make a Patch with git
You need to first checkout the repository:
git clone https://github.com/curl/curl.git
You then proceed and edit all the files you like and you commit them to your
local repository:
git commit [file]
As usual, group your commits so that you commit all changes that at once that
constitutes a logical change.
Once you have done all your commits and you're happy with what you see, you
can make patches out of your changes that are suitable for mailing:
git format-patch remotes/origin/master
This creates files in your local directory named NNNN-[name].patch for each
commit.
Now send those patches off to the curl-library list. You can of course opt to
do that with the 'git send-email' command.
### How To Make a Patch without git
Keep a copy of the unmodified curl sources. Make your changes in a separate
source tree. When you think you have something that you want to offer the
curl community, use GNU diff to generate patches.
If you have modified a single file, try something like:
diff -u unmodified-file.c my-changed-one.c > my-fixes.diff
If you have modified several files, possibly in different directories, you
can use diff recursively:
diff -ur curl-original-dir curl-modified-sources-dir > my-fixes.diff
The GNU diff and GNU patch tools exist for virtually all platforms, including
all kinds of Unixes and Windows:
For unix-like operating systems:
- [https://savannah.gnu.org/projects/patch/](https://savannah.gnu.org/projects/patch/)
- [https://www.gnu.org/software/diffutils/](https://www.gnu.org/software/diffutils/)
For Windows:
- [http://gnuwin32.sourceforge.net/packages/patch.htm](http://gnuwin32.sourceforge.net/packages/patch.htm)
- [http://gnuwin32.sourceforge.net/packages/diffutils.htm](http://gnuwin32.sourceforge.net/packages/diffutils.htm)
File diff suppressed because it is too large. Load diff
+206
View File
@@ -0,0 +1,206 @@
_ _ ____ _
___| | | | _ \| |
/ __| | | | |_) | |
| (__| |_| | _ <| |___
\___|\___/|_| \_\_____|
FEATURES
curl tool
- config file support
- multiple URLs in a single command line
- range "globbing" support: [0-13], {one,two,three}
- multiple file upload on a single command line
- custom maximum transfer rate
- redirectable stderr
- metalink support (*13)
libcurl
- full URL syntax with no length limit
- custom maximum download time
- custom least download speed acceptable
- custom output result after completion
- guesses protocol from host name unless specified
- uses .netrc
- progress bar with time statistics while downloading
- "standard" proxy environment variables support
- compiles on win32 (reported builds on 40+ operating systems)
- selectable network interface for outgoing traffic
- IPv6 support on unix and Windows
- persistent connections
- socks 4 + 5 support, with or without local name resolving
- supports user name and password in proxy environment variables
- operations through proxy "tunnel" (using CONNECT)
- support for large files (>2GB and >4GB) during upload and download
- replaceable memory functions (malloc, free, realloc, etc)
- asynchronous name resolving (*6)
- both a push and a pull style interface
- international domain names (*11)
HTTP
- HTTP/1.1 compliant (optionally uses 1.0)
- GET
- PUT
- HEAD
- POST
- Pipelining
- multipart formpost (RFC1867-style)
- authentication: Basic, Digest, NTLM (*9) and Negotiate (SPNEGO) (*3)
to server and proxy
- resume (both GET and PUT)
- follow redirects
- maximum amount of redirects to follow
- custom HTTP request
- cookie get/send fully parsed
- reads/writes the netscape cookie file format
- custom headers (replace/remove internally generated headers)
- custom user-agent string
- custom referrer string
- range
- proxy authentication
- time conditions
- via http-proxy
- retrieve file modification date
- Content-Encoding support for deflate and gzip
- "Transfer-Encoding: chunked" support in uploads
- data compression (*12)
- HTTP/2 (*5)
HTTPS (*1)
- (all the HTTP features)
- using client certificates
- verify server certificate
- via http-proxy
- select desired encryption
- force usage of a specific SSL version (SSLv2 (*7), SSLv3 (*10) or TLSv1)
FTP
- download
- authentication
- Kerberos 5 (*14)
- active/passive using PORT, EPRT, PASV or EPSV
- single file size information (compare to HTTP HEAD)
- 'type=' URL support
- dir listing
- dir listing names-only
- upload
- upload append
- upload via http-proxy as HTTP PUT
- download resume
- upload resume
- custom ftp commands (before and/or after the transfer)
- simple "range" support
- via http-proxy
- all operations can be tunneled through a http-proxy
- customizable to retrieve file modification date
- no dir depth limit
FTPS (*1)
- implicit ftps:// support that use SSL on both connections
- explicit "AUTH TLS" and "AUTH SSL" usage to "upgrade" plain ftp://
connection to use SSL for both or one of the connections
SCP (*8)
- both password and public key auth
SFTP (*8)
- both password and public key auth
- with custom commands sent before/after the transfer
TFTP
- download
- upload
TELNET
- connection negotiation
- custom telnet options
- stdin/stdout I/O
LDAP (*2)
- full LDAP URL support
DICT
- extended DICT URL support
FILE
- URL support
- upload
- resume
SMB
- SMBv1 over TCP and SSL
- download
- upload
- authentication with NTLMv1
SMTP
- authentication: Plain, Login, CRAM-MD5, Digest-MD5, NTLM (*9), Kerberos 5
(*4) and External.
- send e-mails
- mail from support
- mail size support
- mail auth support for trusted server-to-server relaying
- multiple recipients
- via http-proxy
SMTPS (*1)
- implicit smtps:// support
- explicit "STARTTLS" usage to "upgrade" plain smtp:// connections to use SSL
- via http-proxy
POP3
- authentication: Clear Text, APOP and SASL
- SASL based authentication: Plain, Login, CRAM-MD5, Digest-MD5, NTLM (*9),
Kerberos 5 (*4) and External.
- list e-mails
- retrieve e-mails
- enhanced command support for: CAPA, DELE, TOP, STAT, UIDL and NOOP via
custom requests
- via http-proxy
POP3S (*1)
- implicit pop3s:// support
- explicit "STLS" usage to "upgrade" plain pop3:// connections to use SSL
- via http-proxy
IMAP
- authentication: Clear Text and SASL
- SASL based authentication: Plain, Login, CRAM-MD5, Digest-MD5, NTLM (*9),
Kerberos 5 (*4) and External.
- list the folders of a mailbox
- select a mailbox with support for verifying the UIDVALIDITY
- fetch e-mails with support for specifying the UID and SECTION
- upload e-mails via the append command
- enhanced command support for: EXAMINE, CREATE, DELETE, RENAME, STATUS,
STORE, COPY and UID via custom requests
- via http-proxy
IMAPS (*1)
- implicit imaps:// support
- explicit "STARTTLS" usage to "upgrade" plain imap:// connections to use SSL
- via http-proxy
FOOTNOTES
=========
*1 = requires OpenSSL, GnuTLS, NSS, yassl, axTLS, PolarSSL, WinSSL (native
Windows), Secure Transport (native iOS/OS X) or GSKit (native IBM i)
*2 = requires OpenLDAP
*3 = requires a GSS-API implementation (such as Heimdal or MIT Kerberos) or
SSPI (native Windows)
*4 = requires a GSS-API implementation, however, only Windows SSPI is
currently supported
*5 = requires nghttp2 and possibly a recent TLS library
*6 = requires c-ares
*7 = requires OpenSSL, NSS, GSKit, WinSSL or Secure Transport; GnuTLS, for
example, only supports SSLv3 and TLSv1
*8 = requires libssh2
*9 = requires OpenSSL, GnuTLS, mbedTLS, NSS, yassl, Secure Transport or SSPI
(native Windows)
*10 = requires any of the SSL libraries in (*1) above other than axTLS, which
does not support SSLv3
*11 = requires libidn or Windows
*12 = requires libz
*13 = requires libmetalink, and either an Apple or Microsoft operating
system, or OpenSSL, or GnuTLS, or NSS
*14 = requires a GSS-API implementation (such as Heimdal or MIT Kerberos)
+278
View File
@@ -0,0 +1,278 @@
How curl Became Like This
=========================
Towards the end of 1996, Daniel Stenberg was spending time writing an IRC bot
for an Amiga related channel on EFnet. He then came up with the idea to make
currency-exchange calculations available to Internet Relay Chat (IRC)
users. All the necessary data are published on the Web; he just needed to
automate their retrieval.
Daniel simply adopted an existing command-line open-source tool, httpget, that
Brazilian Rafael Sagula had written and recently release version 0.1 of. After
a few minor adjustments, it did just what he needed.
1997
----
HttpGet 1.0 was released on April 8th 1997 with brand new HTTP proxy support.
We soon found and fixed support for getting currencies over GOPHER. Once FTP
download support was added, the name of the project was changed and urlget 2.0
was released in August 1997. The http-only days were already passed.
1998
----
The project slowly grew bigger. When upload capabilities were added and the
name once again was misleading, a second name change was made and on March 20,
1998 curl 4 was released. (The version numbering from the previous names was
kept.)
(Unrelated to this project a company called Curl Corporation registered a US
trademark on the name "CURL" on May 18 1998. That company had then already
registered the curl.com domain back in November of the previous year. All this
was revealed to us much later.)
SSL support was added, powered by the SSLeay library.
August, first announcement of curl on freshmeat.net.
October, with the curl 4.9 release and the introduction of cookie support,
curl was no longer released under the GPL license. Now we're at 4000 lines of
code, we switched over to the MPL license to restrict the effects of
"copyleft".
November, configure script and reported successful compiles on several
major operating systems. The never-quite-understood -F option was added and
curl could now simulate quite a lot of a browser. TELNET support was added.
Curl 5 was released in December 1998 and introduced the first ever curl man
page. People started making Linux RPM packages out of it.
1999
----
January, DICT support added.
OpenSSL took over where SSLeay was abandoned.
May, first Debian package.
August, LDAP:// and FILE:// support added. The curl web site gets 1300 visits
weekly. Moved site to curl.haxx.nu.
Released curl 6.0 in September. 15000 lines of code.
December 28, added the project on Sourceforge and started using its services
for managing the project.
2000
----
Spring 2000, major internal overhaul to provide a suitable library interface.
The first non-beta release was named 7.1 and arrived in August. This offered
the easy interface and turned out to be the beginning of actually getting
other software and programs to get based on and powered by libcurl. Almost
20000 lines of code.
June 2000: the curl site moves to "curl.haxx.se"
August, the curl web site gets 4000 visits weekly.
The PHP guys adopted libcurl already the same month, when the first ever third
party libcurl binding showed up. CURL has been a supported module in PHP since
the release of PHP 4.0.2. This would soon get followers. More than 16
different bindings exist at the time of this writing.
September, kerberos4 support was added.
In November started the work on a test suite for curl. It was later re-written
from scratch again. The libcurl major SONAME number was set to 1.
2001
----
January, Daniel released curl 7.5.2 under a new license again: MIT (or
MPL). The MIT license is extremely liberal and can be used combined with GPL
in other projects. This would finally put an end to the "complaints" from
people involved in GPLed projects that previously were prohibited from using
libcurl while it was released under MPL only. (Due to the fact that MPL is
deemed "GPL incompatible".)
curl supports HTTP 1.1 starting with the release of 7.7, March 22 2001. This
also introduced libcurl's ability to do persistent connections. 24000 lines of
code. The libcurl major SONAME number was bumped to 2 due to this overhaul.
The first experimental ftps:// support was added in March 2001.
August. curl is bundled in Mac OS X, 10.1. It was already becoming more and
more of a standard utility of Linux distributions and a regular in the BSD
ports collections. The curl web site gets 8000 visits weekly. Curl Corporation
contacted Daniel to discuss "the name issue". After Daniel's reply, they have
never since got in touch again.
September, libcurl 7.9 introduces cookie jar and curl_formadd(). During the
forthcoming 7.9.x releases, we introduced the multi interface slowly and
without much whistles.
2002
----
June, the curl web site gets 13000 visits weekly. curl and libcurl is
35000 lines of code. Reported successful compiles on more than 40 combinations
of CPUs and operating systems.
To estimate number of users of the curl tool or libcurl library is next to
impossible. Around 5000 downloaded packages each week from the main site gives
a hint, but the packages are mirrored extensively, bundled with numerous OS
distributions and otherwise retrieved as part of other software.
September, with the release of curl 7.10 it is released under the MIT license
only.
2003
----
January. Started working on the distributed curl tests. The autobuilds.
February, the curl site averages at 20000 visits weekly. At any given moment,
there's an average of 3 people browsing the curl.haxx.se site.
Multiple new authentication schemes are supported: Digest (May), NTLM (June)
and Negotiate (June).
November: curl 7.10.8 is released. 45000 lines of code. ~55000 unique visitors
to the curl.haxx.se site. Five official web mirrors.
December, full-fledged SSL for FTP is supported.
2004
----
January: curl 7.11.0 introduced large file support.
June: curl 7.12.0 introduced IDN support. 10 official web mirrors.
This release bumped the major SONAME to 3 due to the removal of the
curl_formparse() function
August: Curl and libcurl 7.12.1
Public curl release number: 82
Releases counted from the very beginning: 109
Available command line options: 96
Available curl_easy_setopt() options: 120
Number of public functions in libcurl: 36
Amount of public web site mirrors: 12
Number of known libcurl bindings: 26
2005
----
April. GnuTLS can now optionally be used for the secure layer when curl is
built.
April: Added the multi_socket() API
September: TFTP support was added.
More than 100,000 unique visitors of the curl web site. 25 mirrors.
December: security vulnerability: libcurl URL Buffer Overflow
2006
----
January. We dropped support for Gopher. We found bugs in the implementation
that turned out having been introduced years ago, so with the conclusion that
nobody had found out in all this time we removed it instead of fixing it.
March: security vulnerability: libcurl TFTP Packet Buffer Overflow
September: The major SONAME number for libcurl was bumped to 4 due to the
removal of ftp third party transfer support.
November: Added SCP and SFTP support
2007
----
February: Added support for the Mozilla NSS library to do the SSL/TLS stuff
July: security vulnerability: libcurl GnuTLS insufficient cert verification
2008
----
November:
Command line options: 128
curl_easy_setopt() options: 158
Public functions in libcurl: 58
Known libcurl bindings: 37
Contributors: 683
145,000 unique visitors. >100 GB downloaded.
2009
----
March: security vulnerability: libcurl Arbitrary File Access
August: security vulnerability: libcurl embedded zero in cert name
December: Added support for IMAP, POP3 and SMTP
2010
----
January: Added support for RTSP
February: security vulnerability: libcurl data callback excessive length
March: The project switched over to use git (hosted by github) instead of CVS
for source code control
May: Added support for RTMP
Added support for PolarSSL to do the SSL/TLS stuff
August:
Public curl releases: 117
Command line options: 138
curl_easy_setopt() options: 180
Public functions in libcurl: 58
Known libcurl bindings: 39
Contributors: 808
Gopher support added (re-added actually)
2012
----
July: Added support for Schannel (native Windows TLS backend) and Darwin SSL
(Native Mac OS X and iOS TLS backend).
Supports metalink
October: SSH-agent support.
2013
----
February: Cleaned up internals to always uses the "multi" non-blocking
approach internally and only expose the blocking API with a wrapper.
September: First small steps on supporting HTTP/2 with nghttp2.
October: Removed krb4 support.
December: Happy eyeballs.
2014
----
March: first real release supporting HTTP/2
September: Web site had 245,000 unique visitors and served 236GB data
@@ -0,0 +1,104 @@
# HTTP Cookies
## Cookie overview
Cookies are `name=contents` pairs that a HTTP server tells the client to
hold and then the client sends back those to the server on subsequent
requests to the same domains and paths for which the cookies were set.
Cookies are either "session cookies" which typically are forgotten when the
session is over which is often translated to equal when browser quits, or
the cookies aren't session cookies they have expiration dates after which
the client will throw them away.
Cookies are set to the client with the Set-Cookie: header and are sent to
servers with the Cookie: header.
For a very long time, the only spec explaining how to use cookies was the
original [Netscape spec from 1994](https://curl.haxx.se/rfc/cookie_spec.html).
In 2011, [RFC6265](https://www.ietf.org/rfc/rfc6265.txt) was finally
published and details how cookies work within HTTP.
## Cookies saved to disk
Netscape once created a file format for storing cookies on disk so that they
would survive browser restarts. curl adopted that file format to allow
sharing the cookies with browsers, only to see browsers move away from that
format. Modern browsers no longer use it, while curl still does.
The netscape cookie file format stores one cookie per physical line in the
file with a bunch of associated meta data, each field separated with
TAB. That file is called the cookiejar in curl terminology.
When libcurl saves a cookiejar, it creates a file header of its own in which
there is a URL mention that will link to the web version of this document.
## Cookies with curl the command line tool
curl has a full cookie "engine" built in. If you just activate it, you can
have curl receive and send cookies exactly as mandated in the specs.
Command line options:
`-b, --cookie`
tell curl a file to read cookies from and start the cookie engine, or if it
isn't a file it will pass on the given string. -b name=var works and so does
-b cookiefile.
`-j, --junk-session-cookies`
when used in combination with -b, it will skip all "session cookies" on load
so as to appear to start a new cookie session.
`-c, --cookie-jar`
tell curl to start the cookie engine and write cookies to the given file
after the request(s)
## Cookies with libcurl
libcurl offers several ways to enable and interface the cookie engine. These
options are the ones provided by the native API. libcurl bindings may offer
access to them using other means.
`CURLOPT_COOKIE`
Is used when you want to specify the exact contents of a cookie header to
send to the server.
`CURLOPT_COOKIEFILE`
Tell libcurl to activate the cookie engine, and to read the initial set of
cookies from the given file. Read-only.
`CURLOPT_COOKIEJAR`
Tell libcurl to activate the cookie engine, and when the easy handle is
closed save all known cookies to the given cookiejar file. Write-only.
`CURLOPT_COOKIELIST`
Provide detailed information about a single cookie to add to the internal
storage of cookies. Pass in the cookie as a HTTP header with all the details
set, or pass in a line from a netscape cookie file. This option can also be
used to flush the cookies etc.
`CURLINFO_COOKIELIST`
Extract cookie information from the internal cookie storage as a linked
list.
## Cookies with javascript
These days a lot of the web is built up by javascript. The webbrowser loads
complete programs that render the page you see. These javascript programs
can also set and access cookies.
Since curl and libcurl are plain HTTP clients without any knowledge of or
capability to handle javascript, such cookies will not be detected or used.
Often, if you want to mimic what a browser does on such web sites, you can
record web browser HTTP traffic when using such a site and then repeat the
cookie operations using curl or libcurl.
+126
View File
@@ -0,0 +1,126 @@
HTTP/2 with curl
================
[HTTP/2 Spec](https://www.rfc-editor.org/rfc/rfc7540.txt)
[http2 explained](https://daniel.haxx.se/http2/)
Build prerequisites
-------------------
- nghttp2
- OpenSSL, libressl, BoringSSL, NSS, GnutTLS, mbedTLS, wolfSSL or SChannel
with a new enough version.
[nghttp2](https://nghttp2.org/)
-------------------------------
libcurl uses this 3rd party library for the low level protocol handling
parts. The reason for this is that HTTP/2 is much more complex at that layer
than HTTP/1.1 (which we implement on our own) and that nghttp2 is an already
existing and well functional library.
We require at least version 1.0.0.
Over an http:// URL
-------------------
If `CURLOPT_HTTP_VERSION` is set to `CURL_HTTP_VERSION_2_0`, libcurl will
include an upgrade header in the initial request to the host to allow
upgrading to HTTP/2.
Possibly we can later introduce an option that will cause libcurl to fail if
not possible to upgrade. Possibly we introduce an option that makes libcurl
use HTTP/2 at once over http://
Over an https:// URL
--------------------
If `CURLOPT_HTTP_VERSION` is set to `CURL_HTTP_VERSION_2_0`, libcurl will use
ALPN (or NPN) to negotiate which protocol to continue with. Possibly introduce
an option that will cause libcurl to fail if not possible to use HTTP/2.
`CURL_HTTP_VERSION_2TLS` was added in 7.47.0 as a way to ask libcurl to prefer
HTTP/2 for HTTPS but stick to 1.1 by default for plain old HTTP connections.
ALPN is the TLS extension that HTTP/2 is expected to use. The NPN extension is
for a similar purpose, was made prior to ALPN and is used for SPDY so early
HTTP/2 servers are implemented using NPN before ALPN support is widespread.
`CURLOPT_SSL_ENABLE_ALPN` and `CURLOPT_SSL_ENABLE_NPN` are offered to allow
applications to explicitly disable ALPN or NPN.
SSL libs
--------
The challenge is the ALPN and NPN support and all our different SSL
backends. You may need a fairly updated SSL library version for it to provide
the necessary TLS features. Right now we support:
- OpenSSL: ALPN and NPN
- libressl: ALPN and NPN
- BoringSSL: ALPN and NPN
- NSS: ALPN and NPN
- GnuTLS: ALPN
- mbedTLS: ALPN
- SChannel: ALPN
- wolfSSL: ALPN
Multiplexing
------------
Starting in 7.43.0, libcurl fully supports HTTP/2 multiplexing, which is the
term for doing multiple independent transfers over the same physical TCP
connection.
To take advantage of multiplexing, you need to use the multi interface and set
`CURLMOPT_PIPELINING` to `CURLPIPE_MULTIPLEX`. With that bit set, libcurl will
attempt to re-use existing HTTP/2 connections and just add a new stream over
that when doing subsequent parallel requests.
While libcurl sets up a connection to a HTTP server there is a period during
which it doesn't know if it can pipeline or do multiplexing and if you add new
transfers in that period, libcurl will default to start new connections for
those transfers. With the new option `CURLOPT_PIPEWAIT` (added in 7.43.0), you
can ask that a transfer should rather wait and see in case there's a
connection for the same host in progress that might end up being possible to
multiplex on. It favours keeping the number of connections low to the cost of
slightly longer time to first byte transferred.
Applications
------------
We hide HTTP/2's binary nature and convert received HTTP/2 traffic to headers
in HTTP 1.1 style. This allows applications to work unmodified.
curl tool
---------
curl offers the `--http2` command line option to enable use of HTTP/2.
curl offers the `--http2-prior-knowledge` command line option to enable use of
HTTP/2 without HTTP/1.1 Upgrade.
Since 7.47.0, the curl tool enables HTTP/2 by default for HTTPS connections.
curl tool limitations
---------------------
The command line tool won't do any HTTP/2 multiplexing even though libcurl
supports it, simply because the curl tool is not written to take advantage of
the libcurl API that's necessary for this (the multi interface). We have an
outstanding TODO item for this and **you** can help us make it happen.
The command line tool also doesn't support HTTP/2 server push for the same
reason it doesn't do multiplexing: it needs to use the multi interface for
that so that multiplexing is supported.
HTTP Alternative Services
-------------------------
Alt-Svc is an extension with a corresponding frame (ALTSVC) in HTTP/2 that
tells the client about an alternative "route" to the same content for the same
origin server that you get the response from. A browser or long-living client
can use that hint to create a new connection asynchronously. For libcurl, we
may introduce a way to bring such clues to the application and/or let a
subsequent request use the alternate route automatically.
[Detailed in RFC 7838](https://tools.ietf.org/html/rfc7838)
+9
View File
@@ -0,0 +1,9 @@
_ _ ____ _
___| | | | _ \| |
/ __| | | | |_) | |
| (__| |_| | _ <| |___
\___|\___/|_| \_\_____|
How To Compile
see INSTALL.md
+513
View File
@@ -0,0 +1,513 @@
# how to install curl and libcurl
## Installing Binary Packages
Lots of people download binary distributions of curl and libcurl. This
document does not describe how to install curl or libcurl using such a binary
package. This document describes how to compile, build and install curl and
libcurl from source code.
## Building from git
If you get your code off a git repository instead of a release tarball, see
the `GIT-INFO` file in the root directory for specific instructions on how to
proceed.
# Unix
A normal Unix installation is made in three or four steps (after you've
unpacked the source archive):
./configure
make
make test (optional)
make install
You probably need to be root when doing the last command.
Get a full listing of all available configure options by invoking it like:
./configure --help
If you want to install curl in a different file hierarchy than `/usr/local`,
specify that when running configure:
./configure --prefix=/path/to/curl/tree
If you have write permission in that directory, you can do 'make install'
without being root. An example of this would be to make a local install in
your own home directory:
./configure --prefix=$HOME
make
make install
The configure script always tries to find a working SSL library unless
explicitly told not to. If you have OpenSSL installed in the default search
path for your compiler/linker, you don't need to do anything special. If you
have OpenSSL installed in /usr/local/ssl, you can run configure like:
./configure --with-ssl
If you have OpenSSL installed somewhere else (for example, /opt/OpenSSL) and
you have pkg-config installed, set the pkg-config path first, like this:
env PKG_CONFIG_PATH=/opt/OpenSSL/lib/pkgconfig ./configure --with-ssl
Without pkg-config installed, use this:
./configure --with-ssl=/opt/OpenSSL
If you insist on forcing a build without SSL support, even though you may
have OpenSSL installed in your system, you can run configure like this:
./configure --without-ssl
If you have OpenSSL installed, but with the libraries in one place and the
header files somewhere else, you have to set the LDFLAGS and CPPFLAGS
environment variables prior to running configure. Something like this should
work:
CPPFLAGS="-I/path/to/ssl/include" LDFLAGS="-L/path/to/ssl/lib" ./configure
If you have shared SSL libs installed in a directory where your run-time
linker doesn't find them (which usually causes configure failures), you can
provide the -R option to ld on some operating systems to set a hard-coded
path to the run-time linker:
LDFLAGS=-R/usr/local/ssl/lib ./configure --with-ssl
## More Options
To force a static library compile, disable the shared library creation by
running configure like:
./configure --disable-shared
To tell the configure script to skip searching for thread-safe functions, add
an option like:
./configure --disable-thread
If you're a curl developer and use gcc, you might want to enable more debug
options with the `--enable-debug` option.
curl can be built to use a whole range of libraries to provide various useful
services, and configure will try to auto-detect a decent default. But if you
want to alter it, you can select how to deal with each individual library.
## Select TLS backend
The default OpenSSL configure check will also detect and use BoringSSL or
libressl.
- GnuTLS: `--without-ssl --with-gnutls`.
- Cyassl: `--without-ssl --with-cyassl`
- NSS: `--without-ssl --with-nss`
- PolarSSL: `--without-ssl --with-polarssl`
- mbedTLS: `--without-ssl --with-mbedtls`
- axTLS: `--without-ssl --with-axtls`
- schannel: `--without-ssl --with-winssl`
- secure transport: `--with-winssl --with-darwinssl`
# Windows
## Building Windows DLLs and C run-time (CRT) linkage issues
As a general rule, building a DLL with static CRT linkage is highly
discouraged, and intermixing CRTs in the same app is something to avoid at
any cost.
Reading and comprehending Microsoft Knowledge Base articles KB94248 and
KB140584 is a must for any Windows developer. Especially important is full
understanding if you are not going to follow the advice given above.
- [How To Use the C Run-Time](https://support.microsoft.com/kb/94248/en-us)
- [How to link with the correct C Run-Time CRT library](https://support.microsoft.com/kb/140584/en-us)
- [Potential Errors Passing CRT Objects Across DLL Boundaries](https://msdn.microsoft.com/en-us/library/ms235460)
If your app is misbehaving in some strange way, or it is suffering from
memory corruption, before asking for further help, please try first to
rebuild every single library your app uses as well as your app using the
debug multithreaded dynamic C runtime.
If you get linkage errors read section 5.7 of the FAQ document.
## MingW32
Make sure that MinGW32's bin dir is in the search path, for example:
set PATH=c:\mingw32\bin;%PATH%
then run `mingw32-make mingw32` in the root dir. There are other
make targets available to build libcurl with more features, use:
- `mingw32-make mingw32-zlib` to build with Zlib support;
- `mingw32-make mingw32-ssl-zlib` to build with SSL and Zlib enabled;
- `mingw32-make mingw32-ssh2-ssl-zlib` to build with SSH2, SSL, Zlib;
- `mingw32-make mingw32-ssh2-ssl-sspi-zlib` to build with SSH2, SSL, Zlib
and SSPI support.
If you have any problems linking libraries or finding header files, be sure
to verify that the provided "Makefile.m32" files use the proper paths, and
adjust as necessary. It is also possible to override these paths with
environment variables, for example:
set ZLIB_PATH=c:\zlib-1.2.8
set OPENSSL_PATH=c:\openssl-1.0.2c
set LIBSSH2_PATH=c:\libssh2-1.6.0
It is also possible to build with other LDAP SDKs than MS LDAP; currently
it is possible to build with native Win32 OpenLDAP, or with the Novell CLDAP
SDK. If you want to use these you need to set these vars:
set LDAP_SDK=c:\openldap
set USE_LDAP_OPENLDAP=1
or for using the Novell SDK:
set USE_LDAP_NOVELL=1
If you want to enable LDAPS support then set LDAPS=1.
## Cygwin
Almost identical to the unix installation. Run the configure script in the
curl source tree root with `sh configure`. Make sure you have the sh
executable in /bin/ or you'll see the configure fail toward the end.
Run `make`
## Borland C++ compiler
Ensure that your build environment is properly set up to use the compiler and
associated tools. PATH environment variable must include the path to bin
subdirectory of your compiler installation, eg: `c:\Borland\BCC55\bin`
It is advisable to set environment variable BCCDIR to the base path of the
compiler installation.
set BCCDIR=c:\Borland\BCC55
In order to build a plain vanilla version of curl and libcurl run the
following command from curl's root directory:
make borland
To build curl and libcurl with zlib and OpenSSL support set environment
variables `ZLIB_PATH` and `OPENSSL_PATH` to the base subdirectories of the
already built zlib and OpenSSL libraries and from curl's root directory run
command:
make borland-ssl-zlib
libcurl library will be built in 'lib' subdirectory while curl tool is built
in 'src' subdirectory. In order to use libcurl library it is advisable to
modify compiler's configuration file bcc32.cfg located in
`c:\Borland\BCC55\bin` to reflect the location of libraries include paths for
example the '-I' line could result in something like:
-I"c:\Borland\BCC55\include;c:\curl\include;c:\openssl\inc32"
bcc3.cfg `-L` line could also be modified to reflect the location of of
libcurl library resulting for example:
-L"c:\Borland\BCC55\lib;c:\curl\lib;c:\openssl\out32"
In order to build sample program `simple.c` from the docs\examples
subdirectory run following command from mentioned subdirectory:
bcc32 simple.c libcurl.lib cw32mt.lib
In order to build sample program simplessl.c an SSL enabled libcurl is
required, as well as the OpenSSL libeay32.lib and ssleay32.lib libraries.
## Disabling Specific Protocols in Windows builds
The configure utility, unfortunately, is not available for the Windows
environment, therefore, you cannot use the various disable-protocol options of
the configure utility on this platform.
However, you can use the following defines to disable specific
protocols:
- `HTTP_ONLY` disables all protocols except HTTP
- `CURL_DISABLE_FTP` disables FTP
- `CURL_DISABLE_LDAP` disables LDAP
- `CURL_DISABLE_TELNET` disables TELNET
- `CURL_DISABLE_DICT` disables DICT
- `CURL_DISABLE_FILE` disables FILE
- `CURL_DISABLE_TFTP` disables TFTP
- `CURL_DISABLE_HTTP` disables HTTP
- `CURL_DISABLE_IMAP` disables IMAP
- `CURL_DISABLE_POP3` disables POP3
- `CURL_DISABLE_SMTP` disables SMTP
If you want to set any of these defines you have the following options:
- Modify lib/config-win32.h
- Modify lib/curl_setup.h
- Modify lib/Makefile.vc6
- Modify the "Preprocessor Definitions" in the libcurl project
Note: The pre-processor settings can be found using the Visual Studio IDE
under "Project -> Settings -> C/C++ -> General" in VC6 and "Project ->
Properties -> Configuration Properties -> C/C++ -> Preprocessor" in later
versions.
## Using BSD-style lwIP instead of Winsock TCP/IP stack in Win32 builds
In order to compile libcurl and curl using BSD-style lwIP TCP/IP stack it is
necessary to make definition of preprocessor symbol USE_LWIPSOCK visible to
libcurl and curl compilation processes. To set this definition you have the
following alternatives:
- Modify lib/config-win32.h and src/config-win32.h
- Modify lib/Makefile.vc6
- Modify the "Preprocessor Definitions" in the libcurl project
Note: The pre-processor settings can be found using the Visual Studio IDE
under "Project -> Settings -> C/C++ -> General" in VC6 and "Project ->
Properties -> Configuration Properties -> C/C++ -> Preprocessor" in later
versions.
Once that libcurl has been built with BSD-style lwIP TCP/IP stack support, in
order to use it with your program it is mandatory that your program includes
lwIP header file `<lwip/opt.h>` (or another lwIP header that includes this)
before including any libcurl header. Your program does not need the
`USE_LWIPSOCK` preprocessor definition which is for libcurl internals only.
Compilation has been verified with [lwIP
1.4.0](http://download.savannah.gnu.org/releases/lwip/lwip-1.4.0.zip) and
[contrib-1.4.0](http://download.savannah.gnu.org/releases/lwip/contrib-1.4.0.zip).
This BSD-style lwIP TCP/IP stack support must be considered experimental given
that it has been verified that lwIP 1.4.0 still needs some polish, and libcurl
might yet need some additional adjustment, caveat emptor.
## Important static libcurl usage note
When building an application that uses the static libcurl library on Windows,
you must add `-DCURL_STATICLIB` to your `CFLAGS`. Otherwise the linker will
look for dynamic import symbols.
## Legacy Windows and SSL
WinSSL (specifically SChannel from Windows SSPI), is the native SSL library in
Windows. However, WinSSL in Windows <= XP is unable to connect to servers that
no longer support the legacy handshakes and algorithms used by those
versions. If you will be using curl in one of those earlier versions of
Windows you should choose another SSL backend such as OpenSSL.
# Apple iOS and Mac OS X
On modern Apple operating systems, curl can be built to use Apple's SSL/TLS
implementation, Secure Transport, instead of OpenSSL. To build with Secure
Transport for SSL/TLS, use the configure option `--with-darwinssl`. (It is not
necessary to use the option `--without-ssl`.) This feature requires iOS 5.0 or
later, or OS X 10.5 ("Leopard") or later.
When Secure Transport is in use, the curl options `--cacert` and `--capath`
and their libcurl equivalents, will be ignored, because Secure Transport uses
the certificates stored in the Keychain to evaluate whether or not to trust
the server. This, of course, includes the root certificates that ship with the
OS. The `--cert` and `--engine` options, and their libcurl equivalents, are
currently unimplemented in curl with Secure Transport.
For OS X users: In OS X 10.8 ("Mountain Lion"), Apple made a major overhaul to
the Secure Transport API that, among other things, added support for the newer
TLS 1.1 and 1.2 protocols. To get curl to support TLS 1.1 and 1.2, you must
build curl on Mountain Lion or later, or by using the equivalent SDK. If you
set the `MACOSX_DEPLOYMENT_TARGET` environmental variable to an earlier
version of OS X prior to building curl, then curl will use the new Secure
Transport API on Mountain Lion and later, and fall back on the older API when
the same curl binary is executed on older cats. For example, running these
commands in curl's directory in the shell will build the code such that it
will run on cats as old as OS X 10.6 ("Snow Leopard") (using bash):
export MACOSX_DEPLOYMENT_TARGET="10.6"
./configure --with-darwinssl
make
# Cross compile
Download and unpack the curl package.
'cd' to the new directory. (e.g. `cd curl-7.12.3`)
Set environment variables to point to the cross-compile toolchain and call
configure with any options you need. Be sure and specify the `--host` and
`--build` parameters at configuration time. The following script is an
example of cross-compiling for the IBM 405GP PowerPC processor using the
toolchain from MonteVista for Hardhat Linux.
#! /bin/sh
export PATH=$PATH:/opt/hardhat/devkit/ppc/405/bin
export CPPFLAGS="-I/opt/hardhat/devkit/ppc/405/target/usr/include"
export AR=ppc_405-ar
export AS=ppc_405-as
export LD=ppc_405-ld
export RANLIB=ppc_405-ranlib
export CC=ppc_405-gcc
export NM=ppc_405-nm
./configure --target=powerpc-hardhat-linux
--host=powerpc-hardhat-linux
--build=i586-pc-linux-gnu
--prefix=/opt/hardhat/devkit/ppc/405/target/usr/local
--exec-prefix=/usr/local
You may also need to provide a parameter like `--with-random=/dev/urandom` to
configure as it cannot detect the presence of a random number generating
device for a target system. The `--prefix` parameter specifies where curl
will be installed. If `configure` completes successfully, do `make` and `make
install` as usual.
In some cases, you may be able to simplify the above commands to as little as:
./configure --host=ARCH-OS
# REDUCING SIZE
There are a number of configure options that can be used to reduce the size of
libcurl for embedded applications where binary size is an important factor.
First, be sure to set the CFLAGS variable when configuring with any relevant
compiler optimization flags to reduce the size of the binary. For gcc, this
would mean at minimum the -Os option, and potentially the `-march=X`,
`-mdynamic-no-pic` and `-flto` options as well, e.g.
./configure CFLAGS='-Os' LDFLAGS='-Wl,-Bsymbolic'...
Note that newer compilers often produce smaller code than older versions
due to improved optimization.
Be sure to specify as many `--disable-` and `--without-` flags on the
configure command-line as you can to disable all the libcurl features that you
know your application is not going to need. Besides specifying the
`--disable-PROTOCOL` flags for all the types of URLs your application will not
use, here are some other flags that can reduce the size of the library:
- `--disable-ares` (disables support for the C-ARES DNS library)
- `--disable-cookies` (disables support for HTTP cookies)
- `--disable-crypto-auth` (disables HTTP cryptographic authentication)
- `--disable-ipv6` (disables support for IPv6)
- `--disable-manual` (disables support for the built-in documentation)
- `--disable-proxy` (disables support for HTTP and SOCKS proxies)
- `--disable-unix-sockets` (disables support for UNIX sockets)
- `--disable-verbose` (eliminates debugging strings and error code strings)
- `--disable-versioned-symbols` (disables support for versioned symbols)
- `--enable-hidden-symbols` (eliminates unneeded symbols in the shared library)
- `--without-libidn` (disables support for the libidn DNS library)
- `--without-librtmp` (disables support for RTMP)
- `--without-ssl` (disables support for SSL/TLS)
- `--without-zlib` (disables support for on-the-fly decompression)
The GNU compiler and linker have a number of options that can reduce the
size of the libcurl dynamic libraries on some platforms even further.
Specify them by providing appropriate CFLAGS and LDFLAGS variables on the
configure command-line, e.g.
CFLAGS="-Os -ffunction-sections -fdata-sections
-fno-unwind-tables -fno-asynchronous-unwind-tables -flto"
LDFLAGS="-Wl,-s -Wl,-Bsymbolic -Wl,--gc-sections"
Be sure also to strip debugging symbols from your binaries after compiling
using 'strip' (or the appropriate variant if cross-compiling). If space is
really tight, you may be able to remove some unneeded sections of the shared
library using the -R option to objcopy (e.g. the .comment section).
Using these techniques it is possible to create a basic HTTP-only shared
libcurl library for i386 Linux platforms that is only 113 KiB in size, and an
FTP-only library that is 113 KiB in size (as of libcurl version 7.50.3, using
gcc 5.4.0).
You may find that statically linking libcurl to your application will result
in a lower total size than dynamically linking.
Note that the curl test harness can detect the use of some, but not all, of
the `--disable` statements suggested above. Use will cause tests relying on
those features to fail. The test harness can be manually forced to skip the
relevant tests by specifying certain key words on the runtests.pl command
line. Following is a list of appropriate key words:
- `--disable-cookies` !cookies
- `--disable-manual` !--manual
- `--disable-proxy` !HTTP\ proxy !proxytunnel !SOCKS4 !SOCKS5
# PORTS
This is a probably incomplete list of known hardware and operating systems
that curl has been compiled for. If you know a system curl compiles and
runs on, that isn't listed, please let us know!
- Alpha DEC OSF 4
- Alpha Digital UNIX v3.2
- Alpha FreeBSD 4.1, 4.5
- Alpha Linux 2.2, 2.4
- Alpha NetBSD 1.5.2
- Alpha OpenBSD 3.0
- Alpha OpenVMS V7.1-1H2
- Alpha Tru64 v5.0 5.1
- AVR32 Linux
- ARM Android 1.5, 2.1, 2.3, 3.2, 4.x
- ARM INTEGRITY
- ARM iOS
- Cell Linux
- Cell Cell OS
- HP-PA HP-UX 9.X 10.X 11.X
- HP-PA Linux
- HP3000 MPE/iX
- MicroBlaze uClinux
- MIPS IRIX 6.2, 6.5
- MIPS Linux
- OS/400
- Pocket PC/Win CE 3.0
- Power AIX 3.2.5, 4.2, 4.3.1, 4.3.2, 5.1, 5.2
- PowerPC Darwin 1.0
- PowerPC INTEGRITY
- PowerPC Linux
- PowerPC Mac OS 9
- PowerPC Mac OS X
- SH4 Linux 2.6.X
- SH4 OS21
- SINIX-Z v5
- Sparc Linux
- Sparc Solaris 2.4, 2.5, 2.5.1, 2.6, 7, 8, 9, 10
- Sparc SunOS 4.1.X
- StrongARM (and other ARM) RISC OS 3.1, 4.02
- StrongARM/ARM7/ARM9 Linux 2.4, 2.6
- StrongARM NetBSD 1.4.1
- Symbian OS (P.I.P.S.) 9.x
- TPF
- Ultrix 4.3a
- UNICOS 9.0
- i386 BeOS
- i386 DOS
- i386 eCos 1.3.1
- i386 Esix 4.1
- i386 FreeBSD
- i386 HURD
- i386 Haiku OS
- i386 Linux 1.3, 2.0, 2.2, 2.3, 2.4, 2.6
- i386 Mac OS X
- i386 MINIX 3.1
- i386 NetBSD
- i386 Novell NetWare
- i386 OS/2
- i386 OpenBSD
- i386 QNX 6
- i386 SCO unix
- i386 Solaris 2.7
- i386 Windows 95, 98, ME, NT, 2000, XP, 2003
- i486 ncr-sysv4.3.03 (NCR MP-RAS)
- ia64 Linux 2.3.99
- m68k AmigaOS 3
- m68k Linux
- m68k uClinux
- m68k OpenBSD
- m88k dg-dgux5.4R3.00
- s390 Linux
- x86_64 Linux
- XScale/PXA250 Linux 2.4
- Nios II uClinux
File diff suppressed because it is too large. Load diff
+622
View File
@@ -0,0 +1,622 @@
_ _ ____ _
___| | | | _ \| |
/ __| | | | |_) | |
| (__| |_| | _ <| |___
\___|\___/|_| \_\_____|
Known Bugs
These are problems and bugs known to exist at the time of this release. Feel
free to join in and help us correct one or more of these! Also be sure to
check the changelog of the current development status, as one or more of these
problems may have been fixed or changed somewhat since this was written!
1. HTTP
1.1 CURLFORM_CONTENTLEN in an array
1.2 Disabling HTTP Pipelining
1.3 STARTTRANSFER time is wrong for HTTP POSTs
1.4 multipart formposts file name encoding
1.5 Expect-100 meets 417
1.6 Unnecessary close when 401 received waiting for 100
1.8 DNS timing is wrong for HTTP redirects
1.9 HTTP/2 frames while in the connection pool kill reuse
1.10 Strips trailing dot from host name
1.11 CURLOPT_SEEKFUNCTION not called with CURLFORM_STREAM
1.12 HTTP/2 server push enabled when no pushes can be accepted
2. TLS
2.1 Hangs with PolarSSL
2.2 CURLINFO_SSL_VERIFYRESULT has limited support
2.3 DER in keychain
2.4 GnuTLS backend skips really long certificate fields
3. Email protocols
3.1 IMAP SEARCH ALL truncated response
3.2 No disconnect command
3.3 SMTP to multiple recipients
3.4 POP3 expects "CRLF.CRLF" eob for some single-line responses
4. Command line
4.1 -J with %-encoded file nameas
4.2 -J with -C - fails
4.3 --retry and transfer timeouts
5. Build and portability issues
5.1 Windows Borland compiler
5.2 curl-config --libs contains private details
5.3 libidn and old iconv
5.4 AIX shared build with c-ares fails
5.5 can't handle Unicode arguments in Windows
5.6 cmake support gaps
5.7 Visual Studio project gaps
5.8 configure finding libs in wrong directory
5.9 Utilize Requires.private directives in libcurl.pc
5.10 Fix the gcc typechecks
6. Authentication
6.1 NTLM authentication and unicode
6.2 MIT Kerberos for Windows build
6.3 NTLM in system context uses wrong name
6.4 Negotiate and Kerberos V5 need a fake user name
7. FTP
7.1 FTP without or slow 220 response
7.2 FTP with CONNECT and slow server
7.3 FTP with NOBODY and FAILONERROR
7.4 FTP with ACCT
7.5 ASCII FTP
7.6 FTP with NULs in URL parts
7.7 FTP and empty path parts in the URL
7.8 Premature transfer end but healthy control channel
8. TELNET
8.1 TELNET and time limtiations don't work
8.2 Microsoft telnet server
9. SFTP and SCP
9.1 SFTP doesn't do CURLOPT_POSTQUOTE correct
10. SOCKS
10.1 SOCKS proxy connections are done blocking
10.2 SOCKS don't support timeouts
10.3 FTPS over SOCKS
10.4 active FTP over a SOCKS
11. Internals
11.1 Curl leaks .onion hostnames in DNS
11.2 error buffer not set if connection to multiple addresses fails
11.3 c-ares deviates from stock resolver on http://1346569778
12. LDAP and OpenLDAP
12.1 OpenLDAP hangs after returning results
13. TCP/IP
13.1 --interface for ipv6 binds to unusable IP address
==============================================================================
1. HTTP
1.1 CURLFORM_CONTENTLEN in an array
It is not possible to pass a 64-bit value using CURLFORM_CONTENTLEN with
CURLFORM_ARRAY, when compiled on 32-bit platforms that support 64-bit
integers. This is because the underlying structure 'curl_forms' uses a dual
purpose char* for storing these values in via casting. For more information
see the now closed related issue:
https://github.com/curl/curl/issues/608
1.2 Disabling HTTP Pipelining
Disabling HTTP Pipelining when there are ongoing transfers can lead to
heap corruption and crash. https://curl.haxx.se/bug/view.cgi?id=1411
1.3 STARTTRANSFER time is wrong for HTTP POSTs
Wrong STARTTRANSFER timer accounting for POST requests Timer works fine with
GET requests, but while using POST the time for CURLINFO_STARTTRANSFER_TIME
is wrong. While using POST CURLINFO_STARTTRANSFER_TIME minus
CURLINFO_PRETRANSFER_TIME is near to zero every time.
https://github.com/curl/curl/issues/218
https://curl.haxx.se/bug/view.cgi?id=1213
1.4 multipart formposts file name encoding
When creating multipart formposts. The file name part can be encoded with
something beyond ascii but currently libcurl will only pass in the verbatim
string the app provides. There are several browsers that already do this
encoding. The key seems to be the updated draft to RFC2231:
https://tools.ietf.org/html/draft-reschke-rfc2231-in-http-02
1.5 Expect-100 meets 417
If an upload using Expect: 100-continue receives an HTTP 417 response, it
ought to be automatically resent without the Expect:. A workaround is for
the client application to redo the transfer after disabling Expect:.
https://curl.haxx.se/mail/archive-2008-02/0043.html
1.6 Unnecessary close when 401 received waiting for 100
libcurl closes the connection if an HTTP 401 reply is received while it is
waiting for the the 100-continue response.
https://curl.haxx.se/mail/lib-2008-08/0462.html
1.8 DNS timing is wrong for HTTP redirects
When extracting timing information after HTTP redirects, only the last
transfer's results are returned and not the totals:
https://github.com/curl/curl/issues/522
1.9 HTTP/2 frames while in the connection pool kill reuse
If the server sends HTTP/2 frames (like for example an HTTP/2 PING frame) to
curl while the connection is held in curl's connection pool, the socket will
be found readable when considered for reuse and that makes curl think it is
dead and then it will be closed and a new connection gets created instead.
This is *best* fixed by adding monitoring to connections while they are kept
in the pool so that pings can be responded to appropriately.
1.10 Strips trailing dot from host name
When given a URL wit a trailing dot for the host name part:
"https://example.com./", libcurl will strip off the dot and use the name
without a dot internally and send it dot-less in HTTP Host: headers and in
the TLS SNI field.
The HTTP part violates RFC 7230 section 5.4 but the SNI part is accordance
with RFC 6066 section 3.
URLs using these trailing dots are very rare in the wild and we have not seen
or gotten any real-world problems with such URLs reported. The popular
browsers seem to have stayed with not stripping the dot for both uses (thus
they violate RFC 6066 instead of RFC 7230).
Daniel took the discussion to the HTTPbis mailing list in March 2016:
https://lists.w3.org/Archives/Public/ietf-http-wg/2016JanMar/0430.html but
there was not major rush or interest to fix this. The impression I get is
that most HTTP people rather not rock the boat now and instead prioritize web
compatibility rather than to strictly adhere to these RFCs.
Our current approach allows a knowing client to send a custom HTTP header
with the dot added.
It can also be noted that while adding a trailing dot to the host name in
most (all?) cases will make the name resolve to the same set of IP addresses,
many HTTP servers will not happily accept the trailing dot there unless that
has been specificly configured to be a fine virtual host.
If URLs with trailing dots for host names become more popular or even just
used more than for just plain fun experiments, I'm sure we will have reason
to go back and reconsider.
See https://github.com/curl/curl/issues/716 for the discussion.
1.11 CURLOPT_SEEKFUNCTION not called with CURLFORM_STREAM
I'm using libcurl to POST form data using a FILE* with the CURLFORM_STREAM
option of curl_formadd(). I've noticed that if the connection drops at just
the right time, the POST is reattempted without the data from the file. It
seems like the file stream position isn't getting reset to the beginning of
the file. I found the CURLOPT_SEEKFUNCTION option and set that with a
function that performs an fseek() on the FILE*. However, setting that didn't
seem to fix the issue or even get called. See
https://github.com/curl/curl/issues/768
1.12 HTTP/2 server push enabled when no pushes can be accepted
If the easy interface is used, we can't accept any server pushes so we should
switch off them already in the h2 settings as otherwise we risk wasting
bandwidth when the server tries to send pushes libcurl will never accept.
See https://github.com/curl/curl/issues/927
2. TLS
2.1 Hangs with PolarSSL
"curl_easy_perform hangs with imap and PolarSSL"
https://github.com/curl/curl/issues/334
Most likely, a fix similar to commit c111178bd4 (for mbedTLS) is
necessary. Or if we just wait a little longer we'll rip out all support for
PolarSSL instead...
2.2 CURLINFO_SSL_VERIFYRESULT has limited support
CURLINFO_SSL_VERIFYRESULT is only implemented for the OpenSSL and NSS
backends, so relying on this information in a generic app is flaky.
2.3 DER in keychain
Curl doesn't recognize certificates in DER format in keychain, but it works
with PEM. https://curl.haxx.se/bug/view.cgi?id=1065
2.4 GnuTLS backend skips really long certificate fields
libcurl calls gnutls_x509_crt_get_dn() with a fixed buffer size and if the
field is too long in the cert, it'll just return an error and the field will
be displayed blank.
3. Email protocols
3.1 IMAP SEARCH ALL truncated response
IMAP "SEARCH ALL" truncates output on large boxes. "A quick search of the
code reveals that pingpong.c contains some truncation code, at line 408, when
it deems the server response to be too large truncating it to 40 characters"
https://curl.haxx.se/bug/view.cgi?id=1366
3.2 No disconnect command
The disconnect commands (LOGOUT and QUIT) may not be sent by IMAP, POP3 and
SMTP if a failure occurs during the authentication phase of a connection.
3.3 SMTP to multiple recipients
When sending data to multiple recipients, curl will abort and return failure
if one of the recipients indicate failure (on the "RCPT TO"
command). Ordinary mail programs would proceed and still send to the ones
that can receive data. This is subject for change in the future.
https://curl.haxx.se/bug/view.cgi?id=1116
3.4 POP3 expects "CRLF.CRLF" eob for some single-line responses
You have to tell libcurl not to expect a body, when dealing with one line
response commands. Please see the POP3 examples and test cases which show
this for the NOOP and DELE commands. https://curl.haxx.se/bug/?i=740
4. Command line
4.1 -J with %-encoded file nameas
-J/--remote-header-name doesn't decode %-encoded file names. RFC6266 details
how it should be done. The can of worm is basically that we have no charset
handling in curl and ascii >=128 is a challenge for us. Not to mention that
decoding also means that we need to check for nastiness that is attempted,
like "../" sequences and the like. Probably everything to the left of any
embedded slashes should be cut off.
https://curl.haxx.se/bug/view.cgi?id=1294
4.2 -J with -C - fails
When using -J (with -O), automatically resumed downloading together with "-C
-" fails. Without -J the same command line works! This happens because the
resume logic is worked out before the target file name (and thus its
pre-transfer size) has been figured out!
https://curl.haxx.se/bug/view.cgi?id=1169
4.3 --retry and transfer timeouts
If using --retry and the transfer timeouts (possibly due to using -m or
-y/-Y) the next attempt doesn't resume the transfer properly from what was
downloaded in the previous attempt but will truncate and restart at the
original position where it was at before the previous failed attempt. See
https://curl.haxx.se/mail/lib-2008-01/0080.html and Mandriva bug report
https://qa.mandriva.com/show_bug.cgi?id=22565
5. Build and portability issues
5.1 Windows Borland compiler
When building with the Windows Borland compiler, it fails because the "tlib"
tool doesn't support hyphens (minus signs) in file names and we have such in
the build. https://curl.haxx.se/bug/view.cgi?id=1222
5.2 curl-config --libs contains private details
"curl-config --libs" will include details set in LDFLAGS when configure is
run that might be needed only for building libcurl. Further, curl-config
--cflags suffers from the same effects with CFLAGS/CPPFLAGS.
5.3 libidn and old iconv
Test case 165 might fail on a system which has libidn present, but with an
old iconv version (2.1.3 is a known bad version), since it doesn't recognize
the charset when named ISO8859-1. Changing the name to ISO-8859-1 makes the
test pass, but instead makes it fail on Solaris hosts that use its native
iconv.
5.4 AIX shared build with c-ares fails
curl version 7.12.2 fails on AIX if compiled with --enable-ares. The
workaround is to combine --enable-ares with --disable-shared
5.5 can't handle Unicode arguments in Windows
If a URL or filename can't be encoded using the user's current codepage then
it can only be encoded properly in the Unicode character set. Windows uses
UTF-16 encoding for Unicode and stores it in wide characters, however curl
and libcurl are not equipped for that at the moment. And, except for Cygwin,
Windows can't use UTF-8 as a locale.
https://curl.haxx.se/bug/?i=345
https://curl.haxx.se/bug/?i=731
5.6 cmake support gaps
The cmake build setup lacks several features that the autoconf build
offers. This includes:
- symbol hiding when the shared library is built
- use of correct soname for the shared library build
- support for several TLS backends are missing
- the unit tests cause link failures in regular non-static builds
- no nghttp2 check
5.7 Visual Studio project gaps
The Visual Studio projects lack some features that the autoconf and nmake
builds offer, such as the following:
- support for zlib and nghttp2
- use of static runtime libraries
- add the test suite components
In addition to this the following could be implemented:
- support for other development IDEs
- add PATH environment variables for third-party DLLs
5.8 configure finding libs in wrong directory
When the configure script checks for third-party libraries, it adds those
directories to the LDFLAGS variable and then tries linking to see if it
works. When successful, the found directory is kept in the LDFLAGS variable
when the script continues to execute and do more tests and possibly check for
more libraries.
This can make subsequent checks for libraries wrongly detect another
installation in a directory that was previously added to LDFLAGS by another
library check!
A possibly better way to do these checks would be to keep the pristine LDFLAGS
even after successful checks and instead add those verified paths to a
separate variable that only after all library checks have been performed gets
appended to LDFLAGS.
5.9 Utilize Requires.private directives in libcurl.pc
https://github.com/curl/curl/issues/864
5.10 Fix the gcc typechecks
Issue #846 identifies a problem with the gcc-typechecks and how the types are
documented and checked for CURLINFO_CERTINFO but our attempts to fix the
issue were futile and needs more attention.
https://github.com/curl/curl/issues/846
6. Authentication
6.1 NTLM authentication and unicode
NTLM authentication involving unicode user name or password only works
properly if built with UNICODE defined together with the WinSSL/schannel
backend. The original problem was mentioned in:
https://curl.haxx.se/mail/lib-2009-10/0024.html
https://curl.haxx.se/bug/view.cgi?id=896
The WinSSL/schannel version verified to work as mentioned in
https://curl.haxx.se/mail/lib-2012-07/0073.html
6.2 MIT Kerberos for Windows build
libcurl fails to build with MIT Kerberos for Windows (KfW) due to KfW's
library header files exporting symbols/macros that should be kept private to
the KfW library. See ticket #5601 at http://krbdev.mit.edu/rt/
6.3 NTLM in system context uses wrong name
NTLM authentication using SSPI (on Windows) when (lib)curl is running in
"system context" will make it use wrong(?) user name - at least when compared
to what winhttp does. See https://curl.haxx.se/bug/view.cgi?id=535
6.4 Negotiate and Kerberos V5 need a fake user name
In order to get Negotiate (SPNEGO) authentication to work in HTTP or Kerberos
V5 in the e-mail protocols, you need to provide a (fake) user name (this
concerns both curl and the lib) because the code wrongly only considers
authentication if there's a user name provided by setting
conn->bits.user_passwd in url.c https://curl.haxx.se/bug/view.cgi?id=440 How?
https://curl.haxx.se/mail/lib-2004-08/0182.html A possible solution is to
either modify this variable to be set or introduce a variable such as
new conn->bits.want_authentication which is set when any of the authentication
options are set.
7. FTP
7.1 FTP without or slow 220 response
If a connection is made to a FTP server but the server then just never sends
the 220 response or otherwise is dead slow, libcurl will not acknowledge the
connection timeout during that phase but only the "real" timeout - which may
surprise users as it is probably considered to be the connect phase to most
people. Brought up (and is being misunderstood) in:
https://curl.haxx.se/bug/view.cgi?id=856
7.2 FTP with CONNECT and slow server
When doing FTP over a socks proxy or CONNECT through HTTP proxy and the multi
interface is used, libcurl will fail if the (passive) TCP connection for the
data transfer isn't more or less instant as the code does not properly wait
for the connect to be confirmed. See test case 564 for a first shot at a test
case.
7.3 FTP with NOBODY and FAILONERROR
It seems sensible to be able to use CURLOPT_NOBODY and CURLOPT_FAILONERROR
with FTP to detect if a file exists or not, but it is not working:
https://curl.haxx.se/mail/lib-2008-07/0295.html
7.4 FTP with ACCT
When doing an operation over FTP that requires the ACCT command (but not when
logging in), the operation will fail since libcurl doesn't detect this and
thus fails to issue the correct command:
https://curl.haxx.se/bug/view.cgi?id=635
7.5 ASCII FTP
FTP ASCII transfers do not follow RFC959. They don't convert the data
accordingly (not for sending nor for receiving). RFC 959 section 3.1.1.1
clearly describes how this should be done:
The sender converts the data from an internal character representation to
the standard 8-bit NVT-ASCII representation (see the Telnet
specification). The receiver will convert the data from the standard
form to his own internal form.
Since 7.15.4 at least line endings are converted.
7.6 FTP with NULs in URL parts
FTP URLs passed to curl may contain NUL (0x00) in the RFC 1738 <user>,
<password>, and <fpath> components, encoded as "%00". The problem is that
curl_unescape does not detect this, but instead returns a shortened C string.
From a strict FTP protocol standpoint, NUL is a valid character within RFC
959 <string>, so the way to handle this correctly in curl would be to use a
data structure other than a plain C string, one that can handle embedded NUL
characters. From a practical standpoint, most FTP servers would not
meaningfully support NUL characters within RFC 959 <string>, anyway (e.g.,
Unix pathnames may not contain NUL).
7.7 FTP and empty path parts in the URL
libcurl ignores empty path parts in FTP URLs, whereas RFC1738 states that
such parts should be sent to the server as 'CWD ' (without an argument). The
only exception to this rule, is that we knowingly break this if the empty
part is first in the path, as then we use the double slashes to indicate that
the user wants to reach the root dir (this exception SHALL remain even when
this bug is fixed).
7.8 Premature transfer end but healthy control channel
When 'multi_done' is called before the transfer has been completed the normal
way, it is considered a "premature" transfer end. In this situation, libcurl
closes the connection assuming it doesn't know the state of the connection so
it can't be reused for subsequent requests.
With FTP however, this isn't necessarily true but there are a bunch of
situations (listed in the ftp_done code) where it *could* keep the connection
alive even in this situation - but the current code doesn't. Fixing this would
allow libcurl to reuse FTP connections better.
8. TELNET
8.1 TELNET and time limtiations don't work
When using telnet, the time limitation options don't work.
https://curl.haxx.se/bug/view.cgi?id=846
8.2 Microsoft telnet server
There seems to be a problem when connecting to the Microsoft telnet server.
https://curl.haxx.se/bug/view.cgi?id=649
9. SFTP and SCP
9.1 SFTP doesn't do CURLOPT_POSTQUOTE correct
When libcurl sends CURLOPT_POSTQUOTE commands when connected to a SFTP server
using the multi interface, the commands are not being sent correctly and
instead the connection is "cancelled" (the operation is considered done)
prematurely. There is a half-baked (busy-looping) patch provided in the bug
report but it cannot be accepted as-is. See
https://curl.haxx.se/bug/view.cgi?id=748
10. SOCKS
10.1 SOCKS proxy connections are done blocking
Both SOCKS5 and SOCKS4 proxy connections are done blocking, which is very bad
when used with the multi interface.
10.2 SOCKS don't support timeouts
The SOCKS4 connection codes don't properly acknowledge (connect) timeouts.
According to bug #1556528, even the SOCKS5 connect code does not do it right:
https://curl.haxx.se/bug/view.cgi?id=604
When connecting to a SOCK proxy, the (connect) timeout is not properly
acknowledged after the actual TCP connect (during the SOCKS "negotiate"
phase).
10.3 FTPS over SOCKS
libcurl doesn't support FTPS over a SOCKS proxy.
10.4 active FTP over a SOCKS
libcurl doesn't support active FTP over a SOCKS proxy
11. Internals
11.1 Curl leaks .onion hostnames in DNS
Curl sends DNS requests for hostnames with a .onion TLD. This leaks
information about what the user is attempting to access, and violates this
requirement of RFC7686: https://tools.ietf.org/html/rfc7686
Issue: https://github.com/curl/curl/issues/543
11.2 error buffer not set if connection to multiple addresses fails
If you ask libcurl to resolve a hostname like example.com to IPv6 addresses
only. But you only have IPv4 connectivity. libcurl will correctly fail with
CURLE_COULDNT_CONNECT. But the error buffer set by CURLOPT_ERRORBUFFER
remains empty. Issue: https://github.com/curl/curl/issues/544
11.3 c-ares deviates from stock resolver on http://1346569778
When using the socket resolvers, that URL becomes:
* Rebuilt URL to: http://1346569778/
* Trying 80.67.6.50...
but with c-ares it instead says "Could not resolve: 1346569778 (Domain name
not found)"
See https://github.com/curl/curl/issues/893
12. LDAP and OpenLDAP
12.1 OpenLDAP hangs after returning results
By configuration defaults, openldap automatically chase referrals on
secondary socket descriptors. The OpenLDAP backend is asynchronous and thus
should monitor all socket descriptors involved. Currently, these secondary
descriptors are not monitored, causing openldap library to never receive
data from them.
As a temporary workaround, disable referrals chasing by configuration.
The fix is not easy: proper automatic referrals chasing requires a
synchronous bind callback and monitoring an arbitrary number of socket
descriptors for a single easy handle (currently limited to 5).
Generic LDAP is synchronous: OK.
See https://github.com/curl/curl/issues/622 and
https://curl.haxx.se/mail/lib-2016-01/0101.html
13. TCP/IP
13.1 --interface for ipv6 binds to unusable IP address
Since IPv6 provides a lot of addresses with different scope, binding to an
IPv6 address needs to take the proper care so that it doesn't bind to a
locally scoped address as that is bound to fail.
https://github.com/curl/curl/issues/686
Loaded 100 of 3962 files, more files were not shown because too many files have changed in this diff. Show more