Revert "Remove old folders that are now submodules"

This reverts commit d7d3e24297.
This commit is contained in:
Théophile Diot 2023-06-28 10:10:27 -04:00
parent 2e1e9a08cb
commit a253f4a59c
No known key found for this signature in database
GPG Key ID: E752C80DB72BB014
1903 changed files with 722170 additions and 0 deletions

View File

@ -0,0 +1 @@
*.t linguist-language=Text

View File

@ -0,0 +1,54 @@
reindex
.libs
*.swp
*.slo
*.la
*.swo
*.lo
*~
*.o
print.txt
.rsync
*.tar.gz
dist
build[78]
build
tags
update-readme
*.tmp
test/Makefile
test/blib
test.sh
t.sh
t/t.sh
test/t/servroot/
releng
reset
*.t_
genmobi.sh
*.mobi
misc/chunked
src/headers.c
src/headers.h
src/module.c
src/module.h
src/util.c
src/util.h
go
ctags
src/in.c
src/in.h
src/out.c
src/out.h
build[89]
build1[0-9]
buildroot/
work/
all
t/servroot
analyze
cov
nginx
*.plist
a.patch
Makefile

View File

@ -0,0 +1,55 @@
sudo: required
dist: bionic
os: linux
language: c
compiler:
- gcc
addons:
apt:
packages:
- axel
- cpanminus
env:
global:
- LUAJIT_PREFIX=/opt/luajit21
- LUAJIT_LIB=$LUAJIT_PREFIX/lib
- LUAJIT_INC=$LUAJIT_PREFIX/include/luajit-2.1
- LD_LIBRARY_PATH=$LUAJIT_LIB:$LD_LIBRARY_PATH
matrix:
- NGINX_VERSION=1.19.3
- NGINX_VERSION=1.19.9
- NGINX_VERSION=1.23.0 WITHOUT_PCRE2=1
before_install:
- sudo apt-get update -y
- sudo apt-get install -y ca-certificates
- sudo cpanm -v --notest Test::Nginx > build.log 2>&1 || (cat build.log && exit 1)
install:
- git clone https://github.com/openresty/echo-nginx-module.git ../echo-nginx-module
- git clone https://github.com/openresty/lua-nginx-module.git ../lua-nginx-module
- git clone https://github.com/openresty/lua-resty-core.git ../lua-resty-core
- git clone https://github.com/openresty/lua-resty-lrucache.git ../lua-resty-lrucache
- git clone https://github.com/openresty/nginx-eval-module.git ../eval-nginx-module
- git clone https://github.com/openresty/openresty.git ../openresty
- git clone https://github.com/openresty/no-pool-nginx.git ../no-pool-nginx
- git clone https://github.com/openresty/nginx-devel-utils.git
- git clone -b v2.1-agentzh https://github.com/openresty/luajit2.git luajit2
before_script:
- cd luajit2/
- make -j$JOBS CCDEBUG=-g Q= PREFIX=$LUAJIT_PREFIX CC=$CC XCFLAGS='-DLUA_USE_APICHECK -DLUA_USE_ASSERT -msse4.2' > build.log 2>&1 || (cat build.log && exit 1)
- sudo make install PREFIX=$LUAJIT_PREFIX > build.log 2>&1 || (cat build.log && exit 1)
- cd ..
script:
- export PATH=$PWD/work/nginx/sbin:$PWD/nginx-devel-utils:$PATH
- export NGX_BUILD_CC=$CC
- sh util/build.sh $NGINX_VERSION > build.log 2>&1 || (cat build.log && exit 1)
- prove -I. -r t

View File

@ -0,0 +1,555 @@
Name
====
**ngx_headers_more** - Set and clear input and output headers...more than "add"!
*This module is not distributed with the Nginx source.* See [the installation instructions](#installation).
Table of Contents
=================
* [Name](#name)
* [Version](#version)
* [Synopsis](#synopsis)
* [Description](#description)
* [Directives](#directives)
* [more_set_headers](#more_set_headers)
* [more_clear_headers](#more_clear_headers)
* [more_set_input_headers](#more_set_input_headers)
* [more_clear_input_headers](#more_clear_input_headers)
* [Limitations](#limitations)
* [Installation](#installation)
* [Compatibility](#compatibility)
* [Community](#community)
* [English Mailing List](#english-mailing-list)
* [Chinese Mailing List](#chinese-mailing-list)
* [Bugs and Patches](#bugs-and-patches)
* [Source Repository](#source-repository)
* [Changes](#changes)
* [Test Suite](#test-suite)
* [TODO](#todo)
* [Getting involved](#getting-involved)
* [Authors](#authors)
* [Copyright & License](#copyright--license)
* [See Also](#see-also)
Version
=======
This document describes headers-more-nginx-module [v0.33](https://github.com/openresty/headers-more-nginx-module/tags) released on 3 November 2017.
Synopsis
========
```nginx
# set the Server output header
more_set_headers 'Server: my-server';
# set and clear output headers
location /bar {
more_set_headers 'X-MyHeader: blah' 'X-MyHeader2: foo';
more_set_headers -t 'text/plain text/css' 'Content-Type: text/foo';
more_set_headers -s '400 404 500 503' -s 413 'Foo: Bar';
more_clear_headers 'Content-Type';
# your proxy_pass/memcached_pass/or any other config goes here...
}
# set output headers
location /type {
more_set_headers 'Content-Type: text/plain';
# ...
}
# set input headers
location /foo {
set $my_host 'my dog';
more_set_input_headers 'Host: $my_host';
more_set_input_headers -t 'text/plain' 'X-Foo: bah';
# now $host and $http_host have their new values...
# ...
}
# replace input header X-Foo *only* if it already exists
more_set_input_headers -r 'X-Foo: howdy';
```
Description
===========
This module allows you to add, set, or clear any output
or input header that you specify.
This is an enhanced version of the standard
[headers](http://nginx.org/en/docs/http/ngx_http_headers_module.html) module because it provides more utilities like
resetting or clearing "builtin headers" like `Content-Type`,
`Content-Length`, and `Server`.
It also allows you to specify an optional HTTP status code
criteria using the `-s` option and an optional content
type criteria using the `-t` option while modifying the
output headers with the [more_set_headers](#more_set_headers) and
[more_clear_headers](#more_clear_headers) directives. For example,
```nginx
more_set_headers -s 404 -t 'text/html' 'X-Foo: Bar';
```
You can also specify multiple MIME types to filter out in a single `-t` option.
For example,
```nginx
more_set_headers -t 'text/html text/plain' 'X-Foo: Bar';
```
Never use other parameters like `charset=utf-8` in the `-t` option values; they will not
work as you would expect.
Input headers can be modified as well. For example
```nginx
location /foo {
more_set_input_headers 'Host: foo' 'User-Agent: faked';
# now $host, $http_host, $user_agent, and
# $http_user_agent all have their new values.
}
```
The option `-t` is also available in the
[more_set_input_headers](#more_set_input_headers) and
[more_clear_input_headers](#more_clear_input_headers) directives (for request header filtering) while the `-s` option
is not allowed.
Unlike the standard [headers](http://nginx.org/en/docs/http/ngx_http_headers_module.html) module, this module's directives will by
default apply to all the status codes, including `4xx` and `5xx`.
[Back to TOC](#table-of-contents)
Directives
==========
[Back to TOC](#table-of-contents)
more_set_headers
----------------
**syntax:** *more_set_headers [-t <content-type list>]... [-s <status-code list>]... <new-header>...*
**default:** *no*
**context:** *http, server, location, location if*
**phase:** *output-header-filter*
Replaces (if any) or adds (if not any) the specified output headers when the response status code matches the codes specified by the `-s` option *AND* the response content type matches the types specified by the `-t` option.
If either `-s` or `-t` is not specified or has an empty list value, then no match is required. Therefore, the following directive set the `Server` output header to the custom value for *any* status code and *any* content type:
```nginx
more_set_headers "Server: my_server";
```
Existing response headers with the same name are always overridden. If you want to add headers incrementally, use the standard [add_header](http://nginx.org/en/docs/http/ngx_http_headers_module.html#add_header) directive instead.
A single directive can set/add multiple output headers. For example
```nginx
more_set_headers 'Foo: bar' 'Baz: bah';
```
Multiple occurrences of the options are allowed in a single directive. Their values will be merged together. For instance
```nginx
more_set_headers -s 404 -s '500 503' 'Foo: bar';
```
is equivalent to
```nginx
more_set_headers -s '404 500 503' 'Foo: bar';
```
The new header should be the one of the forms:
1. `Name: Value`
1. `Name: `
1. `Name`
The last two effectively clear the value of the header `Name`.
Nginx variables are allowed in header values. For example:
```nginx
set $my_var "dog";
more_set_headers "Server: $my_var";
```
But variables won't work in header keys due to performance considerations.
Multiple set/clear header directives are allowed in a single location, and they're executed sequentially.
Directives inherited from an upper level scope (say, http block or server blocks) are executed before the directives in the location block.
Note that although `more_set_headers` is allowed in *location* if blocks, it is *not* allowed in the *server* if blocks, as in
```nginx
? # This is NOT allowed!
? server {
? if ($args ~ 'download') {
? more_set_headers 'Foo: Bar';
? }
? ...
? }
```
Behind the scene, use of this directive and its friend [more_clear_headers](#more_clear_headers) will (lazily) register an ouput header filter that modifies `r->headers_out` the way you specify.
[Back to TOC](#table-of-contents)
more_clear_headers
------------------
**syntax:** *more_clear_headers [-t <content-type list>]... [-s <status-code list>]... <new-header>...*
**default:** *no*
**context:** *http, server, location, location if*
**phase:** *output-header-filter*
Clears the specified output headers.
In fact,
```nginx
more_clear_headers -s 404 -t 'text/plain' Foo Baz;
```
is exactly equivalent to
```nginx
more_set_headers -s 404 -t 'text/plain' "Foo: " "Baz: ";
```
or
```nginx
more_set_headers -s 404 -t 'text/plain' Foo Baz
```
See [more_set_headers](#more_set_headers) for more details.
The wildcard character, `*`, can also be used at the end of the header name to specify a pattern. For example, the following directive
effectively clears *any* output headers starting by "`X-Hidden-`":
```nginx
more_clear_headers 'X-Hidden-*';
```
The `*` wildcard support was first introduced in [v0.09](#v009).
[Back to TOC](#table-of-contents)
more_set_input_headers
----------------------
**syntax:** *more_set_input_headers [-r] [-t <content-type list>]... <new-header>...*
**default:** *no*
**context:** *http, server, location, location if*
**phase:** *rewrite tail*
Very much like [more_set_headers](#more_set_headers) except that it operates on input headers (or request headers) and it only supports the `-t` option.
Note that using the `-t` option in this directive means filtering by the `Content-Type` *request* header, rather than the response header.
Behind the scene, use of this directive and its friend [more_clear_input_headers](#more_clear_input_headers) will (lazily)
register a `rewrite phase` handler that modifies `r->headers_in` the way you specify. Note that it always run at the *end* of
the `rewrite` phase so that it runs *after* the standard [rewrite module](http://nginx.org/en/docs/http/ngx_http_rewrite_module.html)
and works in subrequests as well.
If the `-r` option is specified, then the headers will be replaced to the new values *only if* they already exist.
[Back to TOC](#table-of-contents)
more_clear_input_headers
------------------------
**syntax:** *more_clear_input_headers [-t <content-type list>]... <new-header>...*
**default:** *no*
**context:** *http, server, location, location if*
**phase:** *rewrite tail*
Clears the specified input headers.
In fact,
```nginx
more_clear_input_headers -t 'text/plain' Foo Baz;
```
is exactly equivalent to
```nginx
more_set_input_headers -t 'text/plain' "Foo: " "Baz: ";
```
or
```nginx
more_set_input_headers -t 'text/plain' Foo Baz
```
To remove request headers "Foo" and "Baz" for all incoming requests regardless of the content type, we can write
```nginx
more_clear_input_headers "Foo" "Baz";
```
See [more_set_input_headers](#more_set_input_headers) for more details.
The wildcard character, `*`, can also be used at the end of the header name to specify a pattern. For example, the following directive
effectively clears *any* input headers starting by "`X-Hidden-`":
```nginx
more_clear_input_headers 'X-Hidden-*';
```
[Back to TOC](#table-of-contents)
Limitations
===========
* Unlike the standard [headers](http://nginx.org/en/docs/http/ngx_http_headers_module.html) module, this module does not automatically take care of the constraint among the `Expires`, `Cache-Control`, and `Last-Modified` headers. You have to get them right yourself or use the [headers](http://nginx.org/en/docs/http/ngx_http_headers_module.html) module together with this module.
* You cannot remove the `Connection` response header using this module because the `Connection` response header is generated by the standard `ngx_http_header_filter_module` in the Nginx core, whose output header filter runs always *after* the filter of this module. The only way to actually remove the `Connection` header is to patch the Nginx core, that is, editing the C function `ngx_http_header_filter` in the `src/http/ngx_http_header_filter_module.c` file.
[Back to TOC](#table-of-contents)
Installation
============
Grab the nginx source code from [nginx.org](http://nginx.org/), for example,
the version 1.17.8 (see [nginx compatibility](#compatibility)), and then build the source with this module:
```bash
wget 'http://nginx.org/download/nginx-1.17.8.tar.gz'
tar -xzvf nginx-1.17.8.tar.gz
cd nginx-1.17.8/
# Here we assume you would install you nginx under /opt/nginx/.
./configure --prefix=/opt/nginx \
--add-module=/path/to/headers-more-nginx-module
make
make install
```
Download the latest version of the release tarball of this module from [headers-more-nginx-module file list](https://github.com/openresty/headers-more-nginx-module/tags).
Starting from NGINX 1.9.11, you can also compile this module as a dynamic module, by using the `--add-dynamic-module=PATH` option instead of `--add-module=PATH` on the
`./configure` command line above. And then you can explicitly load the module in your `nginx.conf` via the [load_module](http://nginx.org/en/docs/ngx_core_module.html#load_module)
directive, for example,
```nginx
load_module /path/to/modules/ngx_http_headers_more_filter_module.so;
```
Also, this module is included and enabled by default in the [OpenResty bundle](http://openresty.org).
[Back to TOC](#table-of-contents)
Compatibility
=============
The following versions of Nginx should work with this module:
* **1.21.x** (last tested: 1.21.4)
* **1.19.x** (last tested: 1.19.9)
* **1.17.x** (last tested: 1.17.8)
* **1.16.x**
* **1.15.x** (last tested: 1.15.8)
* **1.14.x**
* **1.13.x** (last tested: 1.13.6)
* **1.12.x**
* **1.11.x** (last tested: 1.11.2)
* **1.10.x**
* **1.9.x** (last tested: 1.9.15)
* **1.8.x**
* **1.7.x** (last tested: 1.7.10)
* **1.6.x** (last tested: 1.6.2)
* **1.5.x** (last tested: 1.5.8)
* **1.4.x** (last tested: 1.4.4)
* **1.3.x** (last tested: 1.3.7)
* **1.2.x** (last tested: 1.2.9)
* **1.1.x** (last tested: 1.1.5)
* **1.0.x** (last tested: 1.0.11)
* **0.9.x** (last tested: 0.9.4)
* **0.8.x** (last tested: 0.8.54)
* **0.7.x >= 0.7.44** (last tested: 0.7.68)
Earlier versions of Nginx like 0.6.x and 0.5.x will *not* work.
If you find that any particular version of Nginx above 0.7.44 does not work with this module, please consider [reporting a bug](#report-bugs).
[Back to TOC](#table-of-contents)
Community
=========
[Back to TOC](#table-of-contents)
English Mailing List
--------------------
The [openresty-en](https://groups.google.com/group/openresty-en) mailing list is for English speakers.
[Back to TOC](#table-of-contents)
Chinese Mailing List
--------------------
The [openresty](https://groups.google.com/group/openresty) mailing list is for Chinese speakers.
[Back to TOC](#table-of-contents)
Bugs and Patches
================
Please submit bug reports, wishlists, or patches by
1. creating a ticket on the [GitHub Issue Tracker](https://github.com/chaoslawful/lua-nginx-module/issues),
1. or posting to the [OpenResty community](#community).
[Back to TOC](#table-of-contents)
Source Repository
=================
Available on github at [openresty/headers-more-nginx-module](https://github.com/openresty/headers-more-nginx-module).
[Back to TOC](#table-of-contents)
Changes
=======
The changes of every release of this module can be obtained from the OpenResty bundle's change logs:
<http://openresty.org/#Changes>
[Back to TOC](#table-of-contents)
Test Suite
==========
This module comes with a Perl-driven test suite. The [test cases](https://github.com/openresty/headers-more-nginx-module/tree/master/t/) are
[declarative](https://github.com/openresty/headers-more-nginx-module/blob/master/t/sanity.t) too. Thanks to the [Test::Nginx](http://search.cpan.org/perldoc?Test::Nginx) module in the Perl world.
To run it on your side:
```bash
$ PATH=/path/to/your/nginx-with-headers-more-module:$PATH prove -r t
```
To run the test suite with valgrind's memcheck, use the following commands:
```bash
$ export PATH=/path/to/your/nginx-with-headers-more-module:$PATH
$ TEST_NGINX_USE_VALGRIND=1 prove -r t
```
You need to terminate any Nginx processes before running the test suite if you have changed the Nginx server binary.
Because a single nginx server (by default, `localhost:1984`) is used across all the test scripts (`.t` files), it's meaningless to run the test suite in parallel by specifying `-jN` when invoking the `prove` utility.
Some parts of the test suite requires modules [proxy](http://nginx.org/en/docs/http/ngx_http_proxy_module.html), [rewrite](http://nginx.org/en/docs/http/ngx_http_rewrite_module.html), and [echo](https://github.com/openresty/echo-nginx-module) to be enabled as well when building Nginx.
[Back to TOC](#table-of-contents)
TODO
====
* Support variables in new headers' keys.
[Back to TOC](#table-of-contents)
Getting involved
================
You'll be very welcomed to submit patches to the [author](#author) or just ask for a commit bit to the [source repository](#source-repository) on GitHub.
[Back to TOC](#table-of-contents)
Authors
=======
* Yichun "agentzh" Zhang (章亦春) *&lt;agentzh@gmail.com&gt;*, OpenResty Inc.
* Bernd Dorn ( <http://www.lovelysystems.com/> )
This wiki page is also maintained by the author himself, and everybody is encouraged to improve this page as well.
[Back to TOC](#table-of-contents)
Copyright & License
===================
The code base is borrowed directly from the standard [headers](http://nginx.org/en/docs/http/ngx_http_headers_module.html) module in Nginx 0.8.24. This part of code is copyrighted by Igor Sysoev.
Copyright (c) 2009-2017, Yichun "agentzh" Zhang (章亦春) <agentzh@gmail.com>, OpenResty Inc.
Copyright (c) 2010-2013, Bernd Dorn.
This module is licensed under the terms of the BSD license.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
[Back to TOC](#table-of-contents)
See Also
========
* The original thread on the Nginx mailing list that inspires this module's development: ["A question about add_header replication"](http://forum.nginx.org/read.php?2,11206,11738).
* The orginal announcement thread on the Nginx mailing list: ["The "headers_more" module: Set and clear output headers...more than 'add'!"](http://forum.nginx.org/read.php?2,23460).
* The original [blog post](http://agentzh.blogspot.com/2009/11/headers-more-module-scripting-input-and.html) about this module's initial development.
* The [echo module](https://github.com/openresty/echo-nginx-module) for Nginx module's automated testing.
* The standard [headers](http://nginx.org/en/docs/http/ngx_http_headers_module.html) module.
[Back to TOC](#table-of-contents)

View File

@ -0,0 +1,32 @@
ngx_addon_name=ngx_http_headers_more_filter_module
HEADERS_MORE_SRCS=" \
$ngx_addon_dir/src/ngx_http_headers_more_filter_module.c \
$ngx_addon_dir/src/ngx_http_headers_more_headers_out.c \
$ngx_addon_dir/src/ngx_http_headers_more_headers_in.c \
$ngx_addon_dir/src/ngx_http_headers_more_util.c \
"
HEADERS_MORE_DEPS=" \
$ngx_addon_dir/src/ddebug.h \
$ngx_addon_dir/src/ngx_http_headers_more_filter_module.h \
$ngx_addon_dir/src/ngx_http_headers_more_headers_in.h \
$ngx_addon_dir/src/ngx_http_headers_more_headers_out.h \
$ngx_addon_dir/src/ngx_http_headers_more_headers_in.h \
$ngx_addon_dir/src/ngx_http_headers_more_util.h \
"
if test -n "$ngx_module_link"; then
ngx_module_type=HTTP_AUX_FILTER
ngx_module_name=$ngx_addon_name
ngx_module_incs=
ngx_module_deps="$HEADERS_MORE_DEPS"
ngx_module_srcs="$HEADERS_MORE_SRCS"
ngx_module_libs=
. auto/module
else
HTTP_AUX_FILTER_MODULES="$HTTP_AUX_FILTER_MODULES $ngx_addon_name"
NGX_ADDON_SRCS="$NGX_ADDON_SRCS $HEADERS_MORE_SRCS"
NGX_ADDON_DEPS="$NGX_ADDON_DEPS $HEADERS_MORE_DEPS"
fi

View File

@ -0,0 +1,124 @@
#ifndef DDEBUG_H
#define DDEBUG_H
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>
#include <nginx.h>
#if defined(DDEBUG) && (DDEBUG)
# if (NGX_HAVE_VARIADIC_MACROS)
# define dd(...) fprintf(stderr, "headers-more *** %s: ", __func__); \
fprintf(stderr, __VA_ARGS__); \
fprintf(stderr, " at %s line %d.\n", __FILE__, __LINE__)
# else
#include <stdarg.h>
#include <stdio.h>
#include <stdarg.h>
static ngx_inline void
dd(const char * fmt, ...) {
}
# endif
# if DDEBUG > 1
# define dd_enter() dd_enter_helper(r, __func__)
# if defined(nginx_version) && nginx_version >= 8011
# define dd_main_req_count r->main->count
# else
# define dd_main_req_count 0
# endif
static ngx_inline void
dd_enter_helper(ngx_http_request_t *r, const char *func)
{
ngx_http_posted_request_t *pr;
fprintf(stderr, "headers-more *** enter %s %.*s %.*s?%.*s c:%d m:%p r:%p ar:%p pr:%p",
func,
(int) r->method_name.len, r->method_name.data,
(int) r->uri.len, r->uri.data,
(int) r->args.len, r->args.data,
(int) dd_main_req_count, r->main,
r, r->connection->data, r->parent);
if (r->posted_requests) {
fprintf(stderr, " posted:");
for (pr = r->posted_requests; pr; pr = pr->next) {
fprintf(stderr, "%p,", pr);
}
}
fprintf(stderr, "\n");
}
# else
# define dd_enter()
# endif
#else
# if (NGX_HAVE_VARIADIC_MACROS)
# define dd(...)
# define dd_enter()
# else
#include <stdarg.h>
static ngx_inline void
dd(const char * fmt, ...) {
}
static ngx_inline void
dd_enter() {
}
# endif
#endif
#if defined(DDEBUG) && (DDEBUG)
#define dd_check_read_event_handler(r) \
dd("r->read_event_handler = %s", \
r->read_event_handler == ngx_http_block_reading ? \
"ngx_http_block_reading" : \
r->read_event_handler == ngx_http_test_reading ? \
"ngx_http_test_reading" : \
r->read_event_handler == ngx_http_request_empty_handler ? \
"ngx_http_request_empty_handler" : "UNKNOWN")
#define dd_check_write_event_handler(r) \
dd("r->write_event_handler = %s", \
r->write_event_handler == ngx_http_handler ? \
"ngx_http_handler" : \
r->write_event_handler == ngx_http_core_run_phases ? \
"ngx_http_core_run_phases" : \
r->write_event_handler == ngx_http_request_empty_handler ? \
"ngx_http_request_empty_handler" : "UNKNOWN")
#else
#define dd_check_read_event_handler(r)
#define dd_check_write_event_handler(r)
#endif
#endif /* DDEBUG_H */

View File

@ -0,0 +1,348 @@
/*
* Copyright (C) Yichun Zhang (agentzh)
*/
#ifndef DDEBUG
#define DDEBUG 0
#endif
#include "ddebug.h"
#include "ngx_http_headers_more_filter_module.h"
#include "ngx_http_headers_more_headers_out.h"
#include "ngx_http_headers_more_headers_in.h"
#include "ngx_http_headers_more_util.h"
#include <ngx_config.h>
/* config handlers */
static void *ngx_http_headers_more_create_loc_conf(ngx_conf_t *cf);
static char *ngx_http_headers_more_merge_loc_conf(ngx_conf_t *cf,
void *parent, void *child);
static void *ngx_http_headers_more_create_main_conf(ngx_conf_t *cf);
static ngx_int_t ngx_http_headers_more_post_config(ngx_conf_t *cf);
/* post-read-phase handler */
static ngx_int_t ngx_http_headers_more_handler(ngx_http_request_t *r);
/* filter handlers */
static ngx_int_t ngx_http_headers_more_filter_init(ngx_conf_t *cf);
ngx_uint_t ngx_http_headers_more_location_hash = 0;
static ngx_command_t ngx_http_headers_more_filter_commands[] = {
{ ngx_string("more_set_headers"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
|NGX_CONF_1MORE,
ngx_http_headers_more_set_headers,
NGX_HTTP_LOC_CONF_OFFSET,
0,
NULL},
{ ngx_string("more_clear_headers"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
|NGX_CONF_1MORE,
ngx_http_headers_more_clear_headers,
NGX_HTTP_LOC_CONF_OFFSET,
0,
NULL},
{ ngx_string("more_set_input_headers"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
|NGX_CONF_1MORE,
ngx_http_headers_more_set_input_headers,
NGX_HTTP_LOC_CONF_OFFSET,
0,
NULL},
{ ngx_string("more_clear_input_headers"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
|NGX_CONF_1MORE,
ngx_http_headers_more_clear_input_headers,
NGX_HTTP_LOC_CONF_OFFSET,
0,
NULL},
ngx_null_command
};
static ngx_http_module_t ngx_http_headers_more_filter_module_ctx = {
NULL, /* preconfiguration */
ngx_http_headers_more_post_config, /* postconfiguration */
ngx_http_headers_more_create_main_conf, /* create main configuration */
NULL, /* init main configuration */
NULL, /* create server configuration */
NULL, /* merge server configuration */
ngx_http_headers_more_create_loc_conf, /* create location configuration */
ngx_http_headers_more_merge_loc_conf /* merge location configuration */
};
ngx_module_t ngx_http_headers_more_filter_module = {
NGX_MODULE_V1,
&ngx_http_headers_more_filter_module_ctx, /* module context */
ngx_http_headers_more_filter_commands, /* module directives */
NGX_HTTP_MODULE, /* module type */
NULL, /* init master */
NULL, /* init module */
NULL, /* init process */
NULL, /* init thread */
NULL, /* exit thread */
NULL, /* exit process */
NULL, /* exit master */
NGX_MODULE_V1_PADDING
};
static ngx_http_output_header_filter_pt ngx_http_next_header_filter;
static volatile ngx_cycle_t *ngx_http_headers_more_prev_cycle = NULL;
static ngx_int_t
ngx_http_headers_more_filter(ngx_http_request_t *r)
{
ngx_int_t rc;
ngx_uint_t i;
ngx_http_headers_more_loc_conf_t *conf;
ngx_http_headers_more_cmd_t *cmd;
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"headers more header filter, uri \"%V\"", &r->uri);
conf = ngx_http_get_module_loc_conf(r, ngx_http_headers_more_filter_module);
if (conf->cmds) {
cmd = conf->cmds->elts;
for (i = 0; i < conf->cmds->nelts; i++) {
if (cmd[i].is_input) {
continue;
}
rc = ngx_http_headers_more_exec_cmd(r, &cmd[i]);
if (rc != NGX_OK) {
return rc;
}
}
}
return ngx_http_next_header_filter(r);
}
static ngx_int_t
ngx_http_headers_more_filter_init(ngx_conf_t *cf)
{
ngx_http_next_header_filter = ngx_http_top_header_filter;
ngx_http_top_header_filter = ngx_http_headers_more_filter;
return NGX_OK;
}
static void *
ngx_http_headers_more_create_loc_conf(ngx_conf_t *cf)
{
ngx_http_headers_more_loc_conf_t *conf;
conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_headers_more_loc_conf_t));
if (conf == NULL) {
return NULL;
}
/*
* set by ngx_pcalloc():
*
* conf->cmds = NULL;
*/
return conf;
}
static char *
ngx_http_headers_more_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
{
ngx_uint_t i;
ngx_uint_t orig_len;
ngx_http_headers_more_cmd_t *prev_cmd, *cmd;
ngx_http_headers_more_loc_conf_t *prev = parent;
ngx_http_headers_more_loc_conf_t *conf = child;
if (conf->cmds == NULL || conf->cmds->nelts == 0) {
conf->cmds = prev->cmds;
} else if (prev->cmds && prev->cmds->nelts) {
orig_len = conf->cmds->nelts;
(void) ngx_array_push_n(conf->cmds, prev->cmds->nelts);
cmd = conf->cmds->elts;
for (i = 0; i < orig_len; i++) {
cmd[conf->cmds->nelts - 1 - i] = cmd[orig_len - 1 - i];
}
prev_cmd = prev->cmds->elts;
for (i = 0; i < prev->cmds->nelts; i++) {
cmd[i] = prev_cmd[i];
}
}
return NGX_CONF_OK;
}
static ngx_int_t
ngx_http_headers_more_post_config(ngx_conf_t *cf)
{
int multi_http_blocks;
ngx_int_t rc;
ngx_http_handler_pt *h;
ngx_http_core_main_conf_t *cmcf;
ngx_http_headers_more_main_conf_t *hmcf;
ngx_http_headers_more_location_hash =
ngx_http_headers_more_hash_literal("location");
hmcf = ngx_http_conf_get_module_main_conf(cf,
ngx_http_headers_more_filter_module);
if (ngx_http_headers_more_prev_cycle != ngx_cycle) {
ngx_http_headers_more_prev_cycle = ngx_cycle;
multi_http_blocks = 0;
} else {
multi_http_blocks = 1;
}
if (multi_http_blocks || hmcf->requires_filter) {
rc = ngx_http_headers_more_filter_init(cf);
if (rc != NGX_OK) {
return rc;
}
}
if (!hmcf->requires_handler) {
return NGX_OK;
}
cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
h = ngx_array_push(&cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers);
if (h == NULL) {
return NGX_ERROR;
}
*h = ngx_http_headers_more_handler;
return NGX_OK;
}
static ngx_int_t
ngx_http_headers_more_handler(ngx_http_request_t *r)
{
ngx_int_t rc;
ngx_uint_t i;
ngx_http_headers_more_loc_conf_t *conf;
ngx_http_headers_more_main_conf_t *hmcf;
ngx_http_headers_more_cmd_t *cmd;
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"headers more rewrite handler, uri \"%V\"", &r->uri);
hmcf = ngx_http_get_module_main_conf(r,
ngx_http_headers_more_filter_module);
if (!hmcf->postponed_to_phase_end) {
ngx_http_core_main_conf_t *cmcf;
ngx_http_phase_handler_t tmp;
ngx_http_phase_handler_t *ph;
ngx_http_phase_handler_t *cur_ph;
ngx_http_phase_handler_t *last_ph;
hmcf->postponed_to_phase_end = 1;
cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
ph = cmcf->phase_engine.handlers;
cur_ph = &ph[r->phase_handler];
last_ph = &ph[cur_ph->next - 1];
if (cur_ph < last_ph) {
dd("swaping the contents of cur_ph and last_ph...");
tmp = *cur_ph;
memmove(cur_ph, cur_ph + 1,
(last_ph - cur_ph) * sizeof (ngx_http_phase_handler_t));
*last_ph = tmp;
r->phase_handler--; /* redo the current ph */
return NGX_DECLINED;
}
}
dd("running phase handler...");
conf = ngx_http_get_module_loc_conf(r, ngx_http_headers_more_filter_module);
if (conf->cmds) {
if (r->http_version < NGX_HTTP_VERSION_10) {
return NGX_DECLINED;
}
cmd = conf->cmds->elts;
for (i = 0; i < conf->cmds->nelts; i++) {
if (!cmd[i].is_input) {
continue;
}
rc = ngx_http_headers_more_exec_input_cmd(r, &cmd[i]);
if (rc != NGX_OK) {
return rc;
}
}
}
return NGX_DECLINED;
}
static void *
ngx_http_headers_more_create_main_conf(ngx_conf_t *cf)
{
ngx_http_headers_more_main_conf_t *hmcf;
hmcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_headers_more_main_conf_t));
if (hmcf == NULL) {
return NULL;
}
/* set by ngx_pcalloc:
* hmcf->postponed_to_phase_end = 0;
* hmcf->requires_filter = 0;
* hmcf->requires_handler = 0;
*/
return hmcf;
}

View File

@ -0,0 +1,80 @@
/*
* Copyright (c) Yichun Zhang (agentzh)
*/
#ifndef NGX_HTTP_HEADERS_MORE_FILTER_MODULE_H
#define NGX_HTTP_HEADERS_MORE_FILTER_MODULE_H
#include <ngx_core.h>
#include <ngx_http.h>
#include <assert.h>
typedef enum {
ngx_http_headers_more_opcode_set,
ngx_http_headers_more_opcode_clear
} ngx_http_headers_more_opcode_t;
typedef struct {
ngx_array_t *types; /* of ngx_str_t */
ngx_array_t *statuses; /* of ngx_uint_t */
ngx_array_t *headers; /* of ngx_http_header_val_t */
ngx_flag_t is_input;
} ngx_http_headers_more_cmd_t;
typedef struct {
ngx_array_t *cmds; /* of ngx_http_headers_more_cmd_t */
} ngx_http_headers_more_loc_conf_t;
typedef struct {
ngx_int_t postponed_to_phase_end;
ngx_int_t requires_filter;
ngx_int_t requires_handler;
} ngx_http_headers_more_main_conf_t;
typedef struct ngx_http_headers_more_header_val_s
ngx_http_headers_more_header_val_t;
typedef ngx_int_t (*ngx_http_headers_more_set_header_pt)(ngx_http_request_t *r,
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value);
typedef struct {
ngx_str_t name;
ngx_uint_t offset;
ngx_http_headers_more_set_header_pt handler;
} ngx_http_headers_more_set_header_t;
struct ngx_http_headers_more_header_val_s {
ngx_http_complex_value_t value;
ngx_uint_t hash;
ngx_str_t key;
ngx_http_headers_more_set_header_pt handler;
ngx_uint_t offset;
ngx_flag_t replace;
ngx_flag_t wildcard;
};
extern ngx_module_t ngx_http_headers_more_filter_module;
#ifndef ngx_str_set
#define ngx_str_set(str, text) \
(str)->len = sizeof(text) - 1; (str)->data = (u_char *) text
#endif
#define ngx_http_headers_more_assert(a) assert(a)
#endif /* NGX_HTTP_HEADERS_MORE_FILTER_MODULE_H */

View File

@ -0,0 +1,954 @@
/*
* Copyright (C) Yichun Zhang (agentzh)
*/
#ifndef DDEBUG
#define DDEBUG 0
#endif
#include "ddebug.h"
#include "ngx_http_headers_more_headers_in.h"
#include "ngx_http_headers_more_util.h"
#include <ctype.h>
static char *ngx_http_headers_more_parse_directive(ngx_conf_t *cf,
ngx_command_t *ngx_cmd, void *conf,
ngx_http_headers_more_opcode_t opcode);
static int ngx_http_headers_more_check_type(ngx_http_request_t *r,
ngx_array_t *types);
static ngx_int_t ngx_http_set_header(ngx_http_request_t *r,
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value);
static ngx_int_t ngx_http_set_header_helper(ngx_http_request_t *r,
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value,
ngx_table_elt_t **output_header);
static ngx_int_t ngx_http_set_builtin_header(ngx_http_request_t *r,
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value);
static ngx_int_t ngx_http_set_user_agent_header(ngx_http_request_t *r,
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value);
static ngx_int_t ngx_http_set_content_length_header(ngx_http_request_t *r,
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value);
static ngx_int_t ngx_http_clear_builtin_header(ngx_http_request_t *r,
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value);
static ngx_int_t ngx_http_clear_content_length_header(ngx_http_request_t *r,
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value);
static ngx_int_t ngx_http_set_host_header(ngx_http_request_t *r,
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value);
static ngx_int_t ngx_http_set_connection_header(ngx_http_request_t *r,
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value);
static ngx_int_t ngx_http_set_builtin_multi_header(ngx_http_request_t *r,
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value);
static ngx_int_t ngx_http_headers_more_validate_host(ngx_str_t *host,
ngx_pool_t *pool, ngx_uint_t alloc);
static ngx_http_headers_more_set_header_t ngx_http_headers_more_set_handlers[]
= {
{ ngx_string("Host"),
offsetof(ngx_http_headers_in_t, host),
ngx_http_set_host_header },
{ ngx_string("Connection"),
offsetof(ngx_http_headers_in_t, connection),
ngx_http_set_connection_header },
{ ngx_string("If-Modified-Since"),
offsetof(ngx_http_headers_in_t, if_modified_since),
ngx_http_set_builtin_header },
#if defined(nginx_version) && nginx_version >= 9002
{ ngx_string("If-Unmodified-Since"),
offsetof(ngx_http_headers_in_t, if_unmodified_since),
ngx_http_set_builtin_header },
#endif
#if defined(nginx_version) && nginx_version >= 1003003
{ ngx_string("If-Match"),
offsetof(ngx_http_headers_in_t, if_match),
ngx_http_set_builtin_header },
{ ngx_string("If-None-Match"),
offsetof(ngx_http_headers_in_t, if_none_match),
ngx_http_set_builtin_header },
#endif
{ ngx_string("User-Agent"),
offsetof(ngx_http_headers_in_t, user_agent),
ngx_http_set_user_agent_header },
{ ngx_string("Referer"),
offsetof(ngx_http_headers_in_t, referer),
ngx_http_set_builtin_header },
{ ngx_string("Content-Length"),
offsetof(ngx_http_headers_in_t, content_length),
ngx_http_set_content_length_header },
{ ngx_string("Content-Type"),
offsetof(ngx_http_headers_in_t, content_type),
ngx_http_set_builtin_header },
{ ngx_string("Range"),
offsetof(ngx_http_headers_in_t, range),
ngx_http_set_builtin_header },
{ ngx_string("If-Range"),
offsetof(ngx_http_headers_in_t, if_range),
ngx_http_set_builtin_header },
{ ngx_string("Transfer-Encoding"),
offsetof(ngx_http_headers_in_t, transfer_encoding),
ngx_http_set_builtin_header },
{ ngx_string("Expect"),
offsetof(ngx_http_headers_in_t, expect),
ngx_http_set_builtin_header },
#if defined(nginx_version) && nginx_version >= 1003013
{ ngx_string("Upgrade"),
offsetof(ngx_http_headers_in_t, upgrade),
ngx_http_set_builtin_header },
#endif
#if (NGX_HTTP_GZIP)
{ ngx_string("Accept-Encoding"),
offsetof(ngx_http_headers_in_t, accept_encoding),
ngx_http_set_builtin_header },
{ ngx_string("Via"), offsetof(ngx_http_headers_in_t, via),
ngx_http_set_builtin_header },
#endif
{ ngx_string("Authorization"),
offsetof(ngx_http_headers_in_t, authorization),
ngx_http_set_builtin_header },
{ ngx_string("Keep-Alive"),
offsetof(ngx_http_headers_in_t, keep_alive),
ngx_http_set_builtin_header },
#if (NGX_HTTP_X_FORWARDED_FOR)
{ ngx_string("X-Forwarded-For"),
offsetof(ngx_http_headers_in_t, x_forwarded_for),
ngx_http_set_builtin_multi_header },
#endif
#if (NGX_HTTP_REALIP)
{ ngx_string("X-Real-IP"),
offsetof(ngx_http_headers_in_t, x_real_ip),
ngx_http_set_builtin_header },
#endif
#if (NGX_HTTP_DAV)
{ ngx_string("Depth"), offsetof(ngx_http_headers_in_t, depth),
ngx_http_set_builtin_header },
{ ngx_string("Destination"), offsetof(ngx_http_headers_in_t, destination),
ngx_http_set_builtin_header },
{ ngx_string("Overwrite"), offsetof(ngx_http_headers_in_t, overwrite),
ngx_http_set_builtin_header },
{ ngx_string("Date"), offsetof(ngx_http_headers_in_t, date),
ngx_http_set_builtin_header },
#endif
#if defined(nginx_version) && nginx_version >= 1023000
{ ngx_string("Cookie"),
offsetof(ngx_http_headers_in_t, cookie),
ngx_http_set_builtin_multi_header },
#else
{ ngx_string("Cookie"),
offsetof(ngx_http_headers_in_t, cookies),
ngx_http_set_builtin_multi_header },
#endif
{ ngx_null_string, 0, ngx_http_set_header }
};
ngx_int_t
ngx_http_headers_more_exec_input_cmd(ngx_http_request_t *r,
ngx_http_headers_more_cmd_t *cmd)
{
ngx_str_t value;
ngx_http_headers_more_header_val_t *h;
ngx_uint_t i;
if (!cmd->headers) {
return NGX_OK;
}
if (cmd->types && !ngx_http_headers_more_check_type(r, cmd->types)) {
return NGX_OK;
}
h = cmd->headers->elts;
for (i = 0; i < cmd->headers->nelts; i++) {
if (ngx_http_complex_value(r, &h[i].value, &value) != NGX_OK) {
return NGX_ERROR;
}
if (value.len) {
value.len--; /* remove the trailing '\0' added by
ngx_http_headers_more_parse_header */
}
if (h[i].handler(r, &h[i], &value) != NGX_OK) {
return NGX_ERROR;
}
}
return NGX_OK;
}
static ngx_int_t
ngx_http_set_header(ngx_http_request_t *r,
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value)
{
return ngx_http_set_header_helper(r, hv, value, NULL);
}
static ngx_int_t
ngx_http_set_header_helper(ngx_http_request_t *r,
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value,
ngx_table_elt_t **output_header)
{
ngx_table_elt_t *h, *matched;
ngx_list_part_t *part;
ngx_uint_t i;
ngx_uint_t rc;
dd_enter();
matched = NULL;
retry:
part = &r->headers_in.headers.part;
h = part->elts;
for (i = 0; /* void */; i++) {
dd("i: %d, part: %p", (int) i, part);
if (i >= part->nelts) {
if (part->next == NULL) {
break;
}
part = part->next;
h = part->elts;
i = 0;
}
if (!hv->wildcard
&& h[i].key.len == hv->key.len
&& ngx_strncasecmp(h[i].key.data, hv->key.data,
h[i].key.len) == 0)
{
goto matched;
}
if (hv->wildcard
&& value->len == 0
&& h[i].key.len >= hv->key.len - 1
&& ngx_strncasecmp(h[i].key.data, hv->key.data,
hv->key.len - 1) == 0)
{
goto matched;
}
/* not matched */
continue;
matched:
if (value->len == 0 || (matched && matched != &h[i])) {
h[i].hash = 0;
rc = ngx_http_headers_more_rm_header_helper(
&r->headers_in.headers, part, i);
ngx_http_headers_more_assert(
!(r->headers_in.headers.part.next == NULL
&& r->headers_in.headers.last
!= &r->headers_in.headers.part));
if (rc == NGX_OK) {
if (output_header) {
*output_header = NULL;
}
goto retry;
}
return NGX_ERROR;
}
h[i].value = *value;
if (output_header) {
*output_header = &h[i];
dd("setting existing builtin input header");
}
if (matched == NULL) {
matched = &h[i];
}
}
if (matched) {
return NGX_OK;
}
if (value->len == 0 || hv->replace) {
return NGX_OK;
}
if (r->headers_in.headers.last == NULL) {
/* must be 400 bad request */
return NGX_OK;
}
h = ngx_list_push(&r->headers_in.headers);
if (h == NULL) {
return NGX_ERROR;
}
dd("created new header for %.*s", (int) hv->key.len, hv->key.data);
if (value->len == 0) {
h->hash = 0;
} else {
h->hash = hv->hash;
}
h->key = hv->key;
h->value = *value;
#if defined(nginx_version) && nginx_version >= 1023000
h->next = NULL;
#endif
h->lowcase_key = ngx_pnalloc(r->pool, h->key.len);
if (h->lowcase_key == NULL) {
return NGX_ERROR;
}
ngx_strlow(h->lowcase_key, h->key.data, h->key.len);
if (output_header) {
*output_header = h;
while (r != r->main) {
r->parent->headers_in = r->headers_in;
r = r->parent;
}
}
return NGX_OK;
}
static ngx_int_t
ngx_http_set_builtin_header(ngx_http_request_t *r,
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value)
{
ngx_table_elt_t *h, **old;
dd("entered set_builtin_header (input)");
if (hv->offset) {
old = (ngx_table_elt_t **) ((char *) &r->headers_in + hv->offset);
} else {
old = NULL;
}
dd("old builtin ptr ptr: %p", old);
if (old) {
dd("old builtin ptr: %p", *old);
}
if (old == NULL || *old == NULL) {
dd("set normal header");
return ngx_http_set_header_helper(r, hv, value, old);
}
h = *old;
if (value->len == 0) {
h->hash = 0;
h->value = *value;
return ngx_http_set_header_helper(r, hv, value, old);
}
h->hash = hv->hash;
h->value = *value;
return NGX_OK;
}
static ngx_int_t
ngx_http_set_host_header(ngx_http_request_t *r,
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value)
{
ngx_str_t host;
if (value->len) {
host= *value;
if (ngx_http_headers_more_validate_host(&host, r->pool, 0) != NGX_OK) {
return NGX_ERROR;
}
r->headers_in.server = host;
} else {
r->headers_in.server = *value;
}
return ngx_http_set_builtin_header(r, hv, value);
}
static ngx_int_t
ngx_http_set_content_length_header(ngx_http_request_t *r,
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value)
{
off_t len;
if (value->len == 0) {
return ngx_http_clear_content_length_header(r, hv, value);
}
len = ngx_atosz(value->data, value->len);
if (len == NGX_ERROR) {
return NGX_ERROR;
}
dd("reset headers_in.content_length_n to %d", (int) len);
r->headers_in.content_length_n = len;
return ngx_http_set_builtin_header(r, hv, value);
}
static ngx_int_t
ngx_http_clear_content_length_header(ngx_http_request_t *r,
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value)
{
r->headers_in.content_length_n = -1;
return ngx_http_clear_builtin_header(r, hv, value);
}
static ngx_int_t
ngx_http_clear_builtin_header(ngx_http_request_t *r,
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value)
{
value->len = 0;
return ngx_http_set_builtin_header(r, hv, value);
}
char *
ngx_http_headers_more_set_input_headers(ngx_conf_t *cf,
ngx_command_t *cmd, void *conf)
{
return ngx_http_headers_more_parse_directive(cf, cmd, conf,
ngx_http_headers_more_opcode_set);
}
char *
ngx_http_headers_more_clear_input_headers(ngx_conf_t *cf,
ngx_command_t *cmd, void *conf)
{
return ngx_http_headers_more_parse_directive(cf, cmd, conf,
ngx_http_headers_more_opcode_clear);
}
static int
ngx_http_headers_more_check_type(ngx_http_request_t *r, ngx_array_t *types)
{
ngx_uint_t i;
ngx_str_t *t;
ngx_str_t actual_type;
if (r->headers_in.content_type == NULL) {
return 0;
}
actual_type = r->headers_in.content_type->value;
if (actual_type.len == 0) {
return 0;
}
dd("headers_in->content_type: %.*s",
(int) actual_type.len,
actual_type.data);
t = types->elts;
for (i = 0; i < types->nelts; i++) {
dd("...comparing with type [%.*s]", (int) t[i].len, t[i].data);
if (actual_type.len == t[i].len
&& ngx_strncmp(actual_type.data, t[i].data, t[i].len) == 0)
{
return 1;
}
}
return 0;
}
static char *
ngx_http_headers_more_parse_directive(ngx_conf_t *cf, ngx_command_t *ngx_cmd,
void *conf, ngx_http_headers_more_opcode_t opcode)
{
ngx_http_headers_more_loc_conf_t *hlcf = conf;
ngx_uint_t i;
ngx_http_headers_more_cmd_t *cmd;
ngx_str_t *arg;
ngx_flag_t ignore_next_arg;
ngx_str_t *cmd_name;
ngx_int_t rc;
ngx_flag_t replace = 0;
ngx_http_headers_more_header_val_t *h;
ngx_http_headers_more_main_conf_t *hmcf;
if (hlcf->cmds == NULL) {
hlcf->cmds = ngx_array_create(cf->pool, 1,
sizeof(ngx_http_headers_more_cmd_t));
if (hlcf->cmds == NULL) {
return NGX_CONF_ERROR;
}
}
cmd = ngx_array_push(hlcf->cmds);
if (cmd == NULL) {
return NGX_CONF_ERROR;
}
cmd->headers = ngx_array_create(cf->pool, 1,
sizeof(ngx_http_headers_more_header_val_t));
if (cmd->headers == NULL) {
return NGX_CONF_ERROR;
}
cmd->types = ngx_array_create(cf->pool, 1, sizeof(ngx_str_t));
if (cmd->types == NULL) {
return NGX_CONF_ERROR;
}
cmd->statuses = NULL;
arg = cf->args->elts;
cmd_name = &arg[0];
ignore_next_arg = 0;
for (i = 1; i < cf->args->nelts; i++) {
if (ignore_next_arg) {
ignore_next_arg = 0;
continue;
}
if (arg[i].len == 0) {
continue;
}
if (arg[i].data[0] != '-') {
rc = ngx_http_headers_more_parse_header(cf, cmd_name,
&arg[i], cmd->headers,
opcode,
ngx_http_headers_more_set_handlers);
if (rc != NGX_OK) {
return NGX_CONF_ERROR;
}
continue;
}
if (arg[i].len == 2) {
if (arg[i].data[1] == 't') {
if (i == cf->args->nelts - 1) {
ngx_log_error(NGX_LOG_ERR, cf->log, 0,
"%V: option -t takes an argument.",
cmd_name);
return NGX_CONF_ERROR;
}
rc = ngx_http_headers_more_parse_types(cf->log, cmd_name,
&arg[i + 1],
cmd->types);
if (rc != NGX_OK) {
return NGX_CONF_ERROR;
}
ignore_next_arg = 1;
continue;
}
if (arg[i].data[1] == 'r') {
dd("Found replace flag");
replace = 1;
continue;
}
}
ngx_log_error(NGX_LOG_ERR, cf->log, 0,
"%V: invalid option name: \"%V\"", cmd_name, &arg[i]);
return NGX_CONF_ERROR;
}
dd("Found %d types, and %d headers",
(int) cmd->types->nelts,
(int) cmd->headers->nelts);
if (cmd->headers->nelts == 0) {
ngx_pfree(cf->pool, cmd->headers);
cmd->headers = NULL;
} else {
h = cmd->headers->elts;
for (i = 0; i < cmd->headers->nelts; i++) {
h[i].replace = replace;
}
}
if (cmd->types->nelts == 0) {
ngx_pfree(cf->pool, cmd->types);
cmd->types = NULL;
}
cmd->is_input = 1;
hmcf = ngx_http_conf_get_module_main_conf(cf,
ngx_http_headers_more_filter_module);
hmcf->requires_handler = 1;
return NGX_CONF_OK;
}
/* borrowed the code from ngx_http_request.c:ngx_http_process_user_agent */
static ngx_int_t
ngx_http_set_user_agent_header(ngx_http_request_t *r,
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value)
{
u_char *user_agent, *msie;
/* clear existing settings */
r->headers_in.msie = 0;
r->headers_in.msie6 = 0;
r->headers_in.opera = 0;
r->headers_in.gecko = 0;
r->headers_in.chrome = 0;
r->headers_in.safari = 0;
r->headers_in.konqueror = 0;
if (value->len == 0) {
return ngx_http_set_builtin_header(r, hv, value);
}
/* check some widespread browsers */
user_agent = value->data;
msie = ngx_strstrn(user_agent, "MSIE ", 5 - 1);
if (msie && msie + 7 < user_agent + value->len) {
r->headers_in.msie = 1;
if (msie[6] == '.') {
switch (msie[5]) {
case '4':
case '5':
r->headers_in.msie6 = 1;
break;
case '6':
if (ngx_strstrn(msie + 8, "SV1", 3 - 1) == NULL) {
r->headers_in.msie6 = 1;
}
break;
}
}
}
if (ngx_strstrn(user_agent, "Opera", 5 - 1)) {
r->headers_in.opera = 1;
r->headers_in.msie = 0;
r->headers_in.msie6 = 0;
}
if (!r->headers_in.msie && !r->headers_in.opera) {
if (ngx_strstrn(user_agent, "Gecko/", 6 - 1)) {
r->headers_in.gecko = 1;
} else if (ngx_strstrn(user_agent, "Chrome/", 7 - 1)) {
r->headers_in.chrome = 1;
} else if (ngx_strstrn(user_agent, "Safari/", 7 - 1)
&& ngx_strstrn(user_agent, "Mac OS X", 8 - 1))
{
r->headers_in.safari = 1;
} else if (ngx_strstrn(user_agent, "Konqueror", 9 - 1)) {
r->headers_in.konqueror = 1;
}
}
return ngx_http_set_builtin_header(r, hv, value);
}
static ngx_int_t
ngx_http_set_connection_header(ngx_http_request_t *r,
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value)
{
r->headers_in.connection_type = 0;
if (value->len == 0) {
return ngx_http_set_builtin_header(r, hv, value);
}
if (ngx_strcasestrn(value->data, "close", 5 - 1)) {
r->headers_in.connection_type = NGX_HTTP_CONNECTION_CLOSE;
r->headers_in.keep_alive_n = -1;
} else if (ngx_strcasestrn(value->data, "keep-alive", 10 - 1)) {
r->headers_in.connection_type = NGX_HTTP_CONNECTION_KEEP_ALIVE;
}
return ngx_http_set_builtin_header(r, hv, value);
}
static ngx_int_t
ngx_http_set_builtin_multi_header(ngx_http_request_t *r,
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value)
{
#if defined(nginx_version) && nginx_version >= 1023000
ngx_table_elt_t **headers, **ph, *h;
int nelts;
if (r->headers_out.status == 400 || r->headers_in.headers.last == NULL) {
/* must be a 400 Bad Request */
return NGX_OK;
}
headers = (ngx_table_elt_t **) ((char *) &r->headers_in + hv->offset);
if (*headers) {
nelts = 0;
for (h = *headers; h; h = h->next) {
nelts++;
}
*headers = NULL;
dd("clear multi-value headers: %d", nelts);
}
if (ngx_http_set_header_helper(r, hv, value, &h) == NGX_ERROR) {
return NGX_ERROR;
}
if (value->len == 0) {
return NGX_OK;
}
dd("new multi-value header: %p", h);
if (*headers) {
for (ph = headers; *ph; ph = &(*ph)->next) { /* void */ }
*ph = h;
} else {
*headers = h;
}
h->next = NULL;
return NGX_OK;
#else
ngx_array_t *headers;
ngx_table_elt_t **v, *h;
if (r->headers_out.status == 400 || r->headers_in.headers.last == NULL) {
/* must be a 400 Bad Request */
return NGX_OK;
}
headers = (ngx_array_t *) ((char *) &r->headers_in + hv->offset);
if (headers->nelts > 0) {
ngx_array_destroy(headers);
if (ngx_array_init(headers, r->pool, 2,
sizeof(ngx_table_elt_t *))
!= NGX_OK)
{
return NGX_ERROR;
}
dd("clear multi-value headers: %d", (int) headers->nelts);
}
#if 1
if (headers->nalloc == 0) {
if (ngx_array_init(headers, r->pool, 2,
sizeof(ngx_table_elt_t *))
!= NGX_OK)
{
return NGX_ERROR;
}
}
#endif
h = NULL;
if (ngx_http_set_header_helper(r, hv, value, &h) == NGX_ERROR) {
return NGX_ERROR;
}
if (value->len == 0) {
return NGX_OK;
}
dd("new cookie header: %p", h);
v = ngx_array_push(headers);
if (v == NULL) {
return NGX_ERROR;
}
*v = h;
return NGX_OK;
#endif
}
static ngx_int_t
ngx_http_headers_more_validate_host(ngx_str_t *host, ngx_pool_t *pool,
ngx_uint_t alloc)
{
u_char *h, ch;
size_t i, dot_pos, host_len;
enum {
sw_usual = 0,
sw_literal,
sw_rest
} state;
dot_pos = host->len;
host_len = host->len;
h = host->data;
state = sw_usual;
for (i = 0; i < host->len; i++) {
ch = h[i];
switch (ch) {
case '.':
if (dot_pos == i - 1) {
return NGX_DECLINED;
}
dot_pos = i;
break;
case ':':
if (state == sw_usual) {
host_len = i;
state = sw_rest;
}
break;
case '[':
if (i == 0) {
state = sw_literal;
}
break;
case ']':
if (state == sw_literal) {
host_len = i + 1;
state = sw_rest;
}
break;
case '\0':
return NGX_DECLINED;
default:
if (ngx_path_separator(ch)) {
return NGX_DECLINED;
}
if (ch >= 'A' && ch <= 'Z') {
alloc = 1;
}
break;
}
}
if (dot_pos == host_len - 1) {
host_len--;
}
if (host_len == 0) {
return NGX_DECLINED;
}
if (alloc) {
host->data = ngx_pnalloc(pool, host_len);
if (host->data == NULL) {
return NGX_ERROR;
}
ngx_strlow(host->data, h, host_len);
}
host->len = host_len;
return NGX_OK;
}

View File

@ -0,0 +1,26 @@
/*
* Copyright (c) Yichun Zhang (agentzh)
*/
#ifndef NGX_HTTP_HEADERS_MORE_INPUT_HEADERS_H
#define NGX_HTTP_HEADERS_MORE_INPUT_HEADERS_H
#include "ngx_http_headers_more_filter_module.h"
/* output header setters and clearers */
ngx_int_t ngx_http_headers_more_exec_input_cmd(ngx_http_request_t *r,
ngx_http_headers_more_cmd_t *cmd);
char *ngx_http_headers_more_set_input_headers(ngx_conf_t *cf,
ngx_command_t *cmd, void *conf);
char *ngx_http_headers_more_clear_input_headers(ngx_conf_t *cf,
ngx_command_t *cmd, void *conf);
#endif /* NGX_HTTP_HEADERS_MORE_INPUT_HEADERS_H */

View File

@ -0,0 +1,757 @@
/*
* Copyright (C) Yichun Zhang (agentzh)
*/
#ifndef DDEBUG
#define DDEBUG 0
#endif
#include "ddebug.h"
#include "ngx_http_headers_more_headers_out.h"
#include "ngx_http_headers_more_util.h"
#include <ctype.h>
static char *
ngx_http_headers_more_parse_directive(ngx_conf_t *cf, ngx_command_t *ngx_cmd,
void *conf, ngx_http_headers_more_opcode_t opcode);
static ngx_flag_t ngx_http_headers_more_check_type(ngx_http_request_t *r,
ngx_array_t *types);
static ngx_flag_t ngx_http_headers_more_check_status(ngx_http_request_t *r,
ngx_array_t *statuses);
static ngx_int_t ngx_http_set_header(ngx_http_request_t *r,
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value);
static ngx_int_t ngx_http_set_header_helper(ngx_http_request_t *r,
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value,
ngx_table_elt_t **output_header, ngx_flag_t no_create);
static ngx_int_t ngx_http_set_builtin_header(ngx_http_request_t *r,
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value);
static ngx_int_t ngx_http_set_accept_ranges_header(ngx_http_request_t *r,
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value);
static ngx_int_t ngx_http_set_content_length_header(ngx_http_request_t *r,
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value);
static ngx_int_t ngx_http_set_content_type_header(ngx_http_request_t *r,
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value);
static ngx_int_t ngx_http_clear_builtin_header(ngx_http_request_t *r,
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value);
static ngx_int_t ngx_http_clear_content_length_header(ngx_http_request_t *r,
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value);
static ngx_int_t ngx_http_set_builtin_multi_header(ngx_http_request_t *r,
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value);
static ngx_http_headers_more_set_header_t ngx_http_headers_more_set_handlers[]
= {
{ ngx_string("Server"),
offsetof(ngx_http_headers_out_t, server),
ngx_http_set_builtin_header },
{ ngx_string("Date"),
offsetof(ngx_http_headers_out_t, date),
ngx_http_set_builtin_header },
{ ngx_string("Content-Encoding"),
offsetof(ngx_http_headers_out_t, content_encoding),
ngx_http_set_builtin_header },
{ ngx_string("Location"),
offsetof(ngx_http_headers_out_t, location),
ngx_http_set_builtin_header },
{ ngx_string("Refresh"),
offsetof(ngx_http_headers_out_t, refresh),
ngx_http_set_builtin_header },
{ ngx_string("Last-Modified"),
offsetof(ngx_http_headers_out_t, last_modified),
ngx_http_set_builtin_header },
{ ngx_string("Content-Range"),
offsetof(ngx_http_headers_out_t, content_range),
ngx_http_set_builtin_header },
{ ngx_string("Accept-Ranges"),
offsetof(ngx_http_headers_out_t, accept_ranges),
ngx_http_set_accept_ranges_header },
{ ngx_string("WWW-Authenticate"),
offsetof(ngx_http_headers_out_t, www_authenticate),
ngx_http_set_builtin_header },
{ ngx_string("Expires"),
offsetof(ngx_http_headers_out_t, expires),
ngx_http_set_builtin_header },
{ ngx_string("E-Tag"),
offsetof(ngx_http_headers_out_t, etag),
ngx_http_set_builtin_header },
{ ngx_string("Content-Length"),
offsetof(ngx_http_headers_out_t, content_length),
ngx_http_set_content_length_header },
{ ngx_string("Content-Type"),
0,
ngx_http_set_content_type_header },
{ ngx_string("Cache-Control"),
offsetof(ngx_http_headers_out_t, cache_control),
ngx_http_set_builtin_multi_header },
{ ngx_null_string, 0, ngx_http_set_header }
};
ngx_int_t
ngx_http_headers_more_exec_cmd(ngx_http_request_t *r,
ngx_http_headers_more_cmd_t *cmd)
{
ngx_str_t value;
ngx_http_headers_more_header_val_t *h;
ngx_uint_t i;
if (!cmd->headers) {
return NGX_OK;
}
if (cmd->types && !ngx_http_headers_more_check_type(r, cmd->types)) {
return NGX_OK;
}
if (cmd->statuses
&& !ngx_http_headers_more_check_status(r, cmd->statuses))
{
return NGX_OK;
}
h = cmd->headers->elts;
for (i = 0; i < cmd->headers->nelts; i++) {
if (ngx_http_complex_value(r, &h[i].value, &value) != NGX_OK) {
return NGX_ERROR;
}
if (value.len) {
value.len--; /* remove the trailing '\0' added by
ngx_http_headers_more_parse_header */
}
if (h[i].handler(r, &h[i], &value) != NGX_OK) {
return NGX_ERROR;
}
}
return NGX_OK;
}
static ngx_int_t
ngx_http_set_header(ngx_http_request_t *r,
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value)
{
return ngx_http_set_header_helper(r, hv, value, NULL, 0);
}
static ngx_int_t
ngx_http_set_header_helper(ngx_http_request_t *r,
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value,
ngx_table_elt_t **output_header, ngx_flag_t no_create)
{
ngx_table_elt_t *h;
ngx_list_part_t *part;
ngx_uint_t i;
ngx_flag_t matched = 0;
dd_enter();
#if 1
if (r->headers_out.location
&& r->headers_out.location->value.len
&& r->headers_out.location->value.data[0] == '/')
{
/* XXX ngx_http_core_find_config_phase, for example,
* may not initialize the "key" and "hash" fields
* for a nasty optimization purpose, and
* we have to work-around it here */
r->headers_out.location->hash = ngx_http_headers_more_location_hash;
ngx_str_set(&r->headers_out.location->key, "Location");
}
#endif
part = &r->headers_out.headers.part;
h = part->elts;
for (i = 0; /* void */; i++) {
if (i >= part->nelts) {
if (part->next == NULL) {
break;
}
part = part->next;
h = part->elts;
i = 0;
}
if (h[i].hash == 0) {
continue;
}
if (!hv->wildcard
&& h[i].key.len == hv->key.len
&& ngx_strncasecmp(h[i].key.data, hv->key.data,
h[i].key.len) == 0)
{
goto matched;
}
if (hv->wildcard
&& h[i].key.len >= hv->key.len - 1
&& ngx_strncasecmp(h[i].key.data, hv->key.data,
hv->key.len - 1) == 0)
{
goto matched;
}
/* not matched */
continue;
matched:
if (value->len == 0 || matched) {
dd("clearing normal header for %.*s", (int) hv->key.len,
hv->key.data);
h[i].value.len = 0;
h[i].hash = 0;
} else {
h[i].value = *value;
h[i].hash = hv->hash;
}
if (output_header) {
*output_header = &h[i];
}
matched = 1;
}
if (matched){
return NGX_OK;
}
if ((hv->wildcard || no_create) && value->len == 0) {
return NGX_OK;
}
/* XXX we still need to create header slot even if the value
* is empty because some builtin headers like Last-Modified
* relies on this to get cleared */
h = ngx_list_push(&r->headers_out.headers);
if (h == NULL) {
return NGX_ERROR;
}
if (value->len == 0) {
h->hash = 0;
} else {
h->hash = hv->hash;
}
h->key = hv->key;
h->value = *value;
h->lowcase_key = ngx_pnalloc(r->pool, h->key.len);
if (h->lowcase_key == NULL) {
return NGX_ERROR;
}
ngx_strlow(h->lowcase_key, h->key.data, h->key.len);
if (output_header) {
*output_header = h;
}
return NGX_OK;
}
static ngx_int_t
ngx_http_set_builtin_header(ngx_http_request_t *r,
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value)
{
ngx_table_elt_t *h, **old;
dd_enter();
if (hv->offset) {
old = (ngx_table_elt_t **) ((char *) &r->headers_out + hv->offset);
} else {
old = NULL;
}
if (old == NULL || *old == NULL) {
return ngx_http_set_header_helper(r, hv, value, old, 0);
}
h = *old;
if (value->len == 0) {
dd("clearing the builtin header");
h->hash = 0;
h->value = *value;
return NGX_OK;
}
h->hash = hv->hash;
h->key = hv->key;
h->value = *value;
return NGX_OK;
}
static ngx_int_t
ngx_http_set_builtin_multi_header(ngx_http_request_t *r,
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value)
{
#if defined(nginx_version) && nginx_version >= 1023000
ngx_table_elt_t **headers, *h, *ho, **ph;
headers = (ngx_table_elt_t **) ((char *) &r->headers_out + hv->offset);
if (*headers) {
for (h = (*headers)->next; h; h = h->next) {
h->hash = 0;
h->value.len = 0;
}
h = *headers;
h->value = *value;
if (value->len == 0) {
h->hash = 0;
} else {
h->hash = hv->hash;
}
return NGX_OK;
}
for (ph = headers; *ph; ph = &(*ph)->next) { /* void */ }
ho = ngx_list_push(&r->headers_out.headers);
if (ho == NULL) {
return NGX_ERROR;
}
ho->value = *value;
ho->hash = hv->hash;
ngx_str_set(&ho->key, "Cache-Control");
ho->next = NULL;
*ph = ho;
return NGX_OK;
#else
ngx_array_t *pa;
ngx_table_elt_t *ho, **ph;
ngx_uint_t i;
pa = (ngx_array_t *) ((char *) &r->headers_out + hv->offset);
if (pa->elts == NULL) {
if (ngx_array_init(pa, r->pool, 2, sizeof(ngx_table_elt_t *))
!= NGX_OK)
{
return NGX_ERROR;
}
}
/* override old values (if any) */
if (pa->nelts > 0) {
ph = pa->elts;
for (i = 1; i < pa->nelts; i++) {
ph[i]->hash = 0;
ph[i]->value.len = 0;
}
ph[0]->value = *value;
if (value->len == 0) {
ph[0]->hash = 0;
} else {
ph[0]->hash = hv->hash;
}
return NGX_OK;
}
ph = ngx_array_push(pa);
if (ph == NULL) {
return NGX_ERROR;
}
ho = ngx_list_push(&r->headers_out.headers);
if (ho == NULL) {
return NGX_ERROR;
}
ho->value = *value;
ho->hash = hv->hash;
ngx_str_set(&ho->key, "Cache-Control");
*ph = ho;
return NGX_OK;
#endif
}
static ngx_int_t
ngx_http_set_content_type_header(ngx_http_request_t *r,
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value)
{
u_char *p, *last, *end;
r->headers_out.content_type_len = value->len;
r->headers_out.content_type = *value;
r->headers_out.content_type_hash = hv->hash;
r->headers_out.content_type_lowcase = NULL;
p = value->data;
end = p + value->len;
for (; p != end; p++) {
if (*p != ';') {
continue;
}
last = p;
while (*++p == ' ') { /* void */ }
if (p == end) {
break;
}
if (ngx_strncasecmp(p, (u_char *) "charset=", 8) != 0) {
continue;
}
p += 8;
r->headers_out.content_type_len = last - value->data;
if (*p == '"') {
p++;
}
last = end;
if (*(last - 1) == '"') {
last--;
}
r->headers_out.charset.len = last - p;
r->headers_out.charset.data = p;
break;
}
value->len = 0;
return ngx_http_set_header_helper(r, hv, value, NULL, 1);
}
static ngx_int_t
ngx_http_set_content_length_header(ngx_http_request_t *r,
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value)
{
off_t len;
if (value->len == 0) {
return ngx_http_clear_content_length_header(r, hv, value);
}
len = ngx_atosz(value->data, value->len);
if (len == NGX_ERROR) {
return NGX_ERROR;
}
r->headers_out.content_length_n = len;
return ngx_http_set_builtin_header(r, hv, value);
}
static ngx_int_t
ngx_http_set_accept_ranges_header(ngx_http_request_t *r,
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value)
{
if (value->len == 0) {
r->allow_ranges = 0;
}
return ngx_http_set_builtin_header(r, hv, value);
}
static ngx_int_t
ngx_http_clear_content_length_header(ngx_http_request_t *r,
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value)
{
r->headers_out.content_length_n = -1;
return ngx_http_clear_builtin_header(r, hv, value);
}
static ngx_int_t
ngx_http_clear_builtin_header(ngx_http_request_t *r,
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value)
{
dd_enter();
value->len = 0;
return ngx_http_set_builtin_header(r, hv, value);
}
char *
ngx_http_headers_more_set_headers(ngx_conf_t *cf,
ngx_command_t *cmd, void *conf)
{
return ngx_http_headers_more_parse_directive(cf, cmd, conf,
ngx_http_headers_more_opcode_set);
}
char *
ngx_http_headers_more_clear_headers(ngx_conf_t *cf,
ngx_command_t *cmd, void *conf)
{
return ngx_http_headers_more_parse_directive(cf, cmd, conf,
ngx_http_headers_more_opcode_clear);
}
static ngx_flag_t
ngx_http_headers_more_check_type(ngx_http_request_t *r, ngx_array_t *types)
{
ngx_uint_t i;
ngx_str_t *t;
dd("headers_out->content_type: %.*s (len %d)",
(int) r->headers_out.content_type.len,
r->headers_out.content_type.data,
(int) r->headers_out.content_type.len);
t = types->elts;
for (i = 0; i < types->nelts; i++) {
dd("...comparing with type [%.*s]", (int) t[i].len, t[i].data);
if (r->headers_out.content_type_len == t[i].len
&& ngx_strncmp(r->headers_out.content_type.data,
t[i].data, t[i].len) == 0)
{
return 1;
}
}
return 0;
}
static ngx_flag_t
ngx_http_headers_more_check_status(ngx_http_request_t *r, ngx_array_t *statuses)
{
ngx_uint_t i;
ngx_uint_t *status;
dd("headers_out.status = %d", (int) r->headers_out.status);
status = statuses->elts;
for (i = 0; i < statuses->nelts; i++) {
dd("...comparing with specified status %d", (int) status[i]);
if (r->headers_out.status == status[i]) {
return 1;
}
}
return 0;
}
static char *
ngx_http_headers_more_parse_directive(ngx_conf_t *cf, ngx_command_t *ngx_cmd,
void *conf, ngx_http_headers_more_opcode_t opcode)
{
ngx_http_headers_more_loc_conf_t *hlcf = conf;
ngx_uint_t i;
ngx_http_headers_more_cmd_t *cmd;
ngx_str_t *arg;
ngx_flag_t ignore_next_arg;
ngx_str_t *cmd_name;
ngx_int_t rc;
ngx_http_headers_more_main_conf_t *hmcf;
if (hlcf->cmds == NULL) {
hlcf->cmds = ngx_array_create(cf->pool, 1,
sizeof(ngx_http_headers_more_cmd_t));
if (hlcf->cmds == NULL) {
return NGX_CONF_ERROR;
}
}
cmd = ngx_array_push(hlcf->cmds);
if (cmd == NULL) {
return NGX_CONF_ERROR;
}
cmd->headers =
ngx_array_create(cf->pool, 1,
sizeof(ngx_http_headers_more_header_val_t));
if (cmd->headers == NULL) {
return NGX_CONF_ERROR;
}
cmd->types = ngx_array_create(cf->pool, 1, sizeof(ngx_str_t));
if (cmd->types == NULL) {
return NGX_CONF_ERROR;
}
cmd->statuses = ngx_array_create(cf->pool, 1, sizeof(ngx_uint_t));
if (cmd->statuses == NULL) {
return NGX_CONF_ERROR;
}
arg = cf->args->elts;
cmd_name = &arg[0];
ignore_next_arg = 0;
for (i = 1; i < cf->args->nelts; i++) {
if (ignore_next_arg) {
ignore_next_arg = 0;
continue;
}
if (arg[i].len == 0) {
continue;
}
if (arg[i].data[0] != '-') {
rc = ngx_http_headers_more_parse_header(cf, cmd_name,
&arg[i], cmd->headers,
opcode,
ngx_http_headers_more_set_handlers);
if (rc != NGX_OK) {
return NGX_CONF_ERROR;
}
continue;
}
if (arg[i].len == 2) {
if (arg[i].data[1] == 't') {
if (i == cf->args->nelts - 1) {
ngx_log_error(NGX_LOG_ERR, cf->log, 0,
"%V: option -t takes an argument.",
cmd_name);
return NGX_CONF_ERROR;
}
rc = ngx_http_headers_more_parse_types(cf->log, cmd_name,
&arg[i + 1],
cmd->types);
if (rc != NGX_OK) {
return NGX_CONF_ERROR;
}
ignore_next_arg = 1;
continue;
} else if (arg[i].data[1] == 's') {
if (i == cf->args->nelts - 1) {
ngx_log_error(NGX_LOG_ERR, cf->log, 0,
"%V: option -s takes an argument.",
cmd_name);
return NGX_CONF_ERROR;
}
rc = ngx_http_headers_more_parse_statuses(cf->log, cmd_name,
&arg[i + 1],
cmd->statuses);
if (rc != NGX_OK) {
return NGX_CONF_ERROR;
}
ignore_next_arg = 1;
continue;
}
}
ngx_log_error(NGX_LOG_ERR, cf->log, 0,
"%V: invalid option name: \"%V\"", cmd_name, &arg[i]);
return NGX_CONF_ERROR;
}
dd("Found %d statuses, %d types, and %d headers",
(int) cmd->statuses->nelts, (int) cmd->types->nelts,
(int) cmd->headers->nelts);
if (cmd->headers->nelts == 0) {
cmd->headers = NULL;
}
if (cmd->types->nelts == 0) {
cmd->types = NULL;
}
if (cmd->statuses->nelts == 0) {
cmd->statuses = NULL;
}
cmd->is_input = 0;
hmcf = ngx_http_conf_get_module_main_conf(cf,
ngx_http_headers_more_filter_module);
hmcf->requires_filter = 1;
return NGX_CONF_OK;
}

View File

@ -0,0 +1,26 @@
/*
* Copyright (c) Yichun Zhang (agentzh)
*/
#ifndef NGX_HTTP_HEADERS_MORE_OUTPUT_HEADERS_H
#define NGX_HTTP_HEADERS_MORE_OUTPUT_HEADERS_H
#include "ngx_http_headers_more_filter_module.h"
/* output header setters and clearers */
ngx_int_t ngx_http_headers_more_exec_cmd(ngx_http_request_t *r,
ngx_http_headers_more_cmd_t *cmd);
char *ngx_http_headers_more_set_headers(ngx_conf_t *cf,
ngx_command_t *cmd, void *conf);
char *ngx_http_headers_more_clear_headers(ngx_conf_t *cf,
ngx_command_t *cmd, void *conf);
#endif /* NGX_HTTP_HEADERS_MORE_OUTPUT_HEADERS_H */

View File

@ -0,0 +1,382 @@
/*
* Copyright (C) Yichun Zhang (agentzh)
*/
#ifndef DDEBUG
#define DDEBUG 0
#endif
#include "ddebug.h"
#include "ngx_http_headers_more_util.h"
#include <ctype.h>
ngx_int_t
ngx_http_headers_more_parse_header(ngx_conf_t *cf, ngx_str_t *cmd_name,
ngx_str_t *raw_header, ngx_array_t *headers,
ngx_http_headers_more_opcode_t opcode,
ngx_http_headers_more_set_header_t *handlers)
{
ngx_http_headers_more_header_val_t *hv;
ngx_uint_t i;
ngx_str_t key = ngx_null_string;
ngx_str_t value = ngx_null_string;
ngx_flag_t seen_end_of_key;
ngx_http_compile_complex_value_t ccv;
u_char *p;
hv = ngx_array_push(headers);
if (hv == NULL) {
return NGX_ERROR;
}
seen_end_of_key = 0;
for (i = 0; i < raw_header->len; i++) {
if (key.len == 0) {
if (isspace(raw_header->data[i])) {
continue;
}
key.data = raw_header->data;
key.len = 1;
continue;
}
if (!seen_end_of_key) {
if (raw_header->data[i] == ':'
|| isspace(raw_header->data[i]))
{
seen_end_of_key = 1;
continue;
}
key.len++;
continue;
}
if (value.len == 0) {
if (raw_header->data[i] == ':'
|| isspace(raw_header->data[i]))
{
continue;
}
value.data = &raw_header->data[i];
value.len = 1;
continue;
}
value.len++;
}
if (key.len == 0) {
ngx_log_error(NGX_LOG_ERR, cf->log, 0,
"%V: no key found in the header argument: %V",
cmd_name, raw_header);
return NGX_ERROR;
}
hv->wildcard = (key.data[key.len - 1] == '*');
if (hv->wildcard && key.len<2){
ngx_log_error(NGX_LOG_ERR, cf->log, 0,
"%V: wildcard key too short: %V",
cmd_name, raw_header);
return NGX_ERROR;
}
hv->hash = ngx_hash_key_lc(key.data, key.len);
hv->key = key;
hv->offset = 0;
for (i = 0; handlers[i].name.len; i++) {
if (hv->key.len != handlers[i].name.len
|| ngx_strncasecmp(hv->key.data, handlers[i].name.data,
handlers[i].name.len) != 0)
{
dd("hv key comparison: %s <> %s", handlers[i].name.data,
hv->key.data);
continue;
}
hv->offset = handlers[i].offset;
hv->handler = handlers[i].handler;
break;
}
if (handlers[i].name.len == 0 && handlers[i].handler) {
hv->offset = handlers[i].offset;
hv->handler = handlers[i].handler;
}
if (opcode == ngx_http_headers_more_opcode_clear) {
value.len = 0;
}
if (value.len == 0) {
ngx_memzero(&hv->value, sizeof(ngx_http_complex_value_t));
return NGX_OK;
}
/* Nginx request header value requires to be a null-terminated
* C string */
p = ngx_palloc(cf->pool, value.len + 1);
if (p == NULL) {
return NGX_ERROR;
}
ngx_memcpy(p, value.data, value.len);
p[value.len] = '\0';
value.data = p;
value.len++; /* we should also compile the trailing '\0' */
/* compile the header value as a complex value */
ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
ccv.cf = cf;
ccv.value = &value;
ccv.complex_value = &hv->value;
if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
return NGX_ERROR;
}
return NGX_OK;
}
ngx_int_t
ngx_http_headers_more_parse_statuses(ngx_log_t *log, ngx_str_t *cmd_name,
ngx_str_t *value, ngx_array_t *statuses)
{
u_char *p, *last;
ngx_uint_t *s = NULL;
p = value->data;
last = p + value->len;
for (; p != last; p++) {
if (s == NULL) {
if (isspace(*p)) {
continue;
}
s = ngx_array_push(statuses);
if (s == NULL) {
return NGX_ERROR;
}
if (*p >= '0' && *p <= '9') {
*s = *p - '0';
} else {
ngx_log_error(NGX_LOG_ERR, log, 0,
"%V: invalid digit \"%c\" found in "
"the status code list \"%V\"",
cmd_name, *p, value);
return NGX_ERROR;
}
continue;
}
if (isspace(*p)) {
dd("Parsed status %d", (int) *s);
s = NULL;
continue;
}
if (*p >= '0' && *p <= '9') {
*s *= 10;
*s += *p - '0';
} else {
ngx_log_error(NGX_LOG_ERR, log, 0,
"%V: invalid digit \"%c\" found in "
"the status code list \"%V\"",
cmd_name, *p, value);
return NGX_ERROR;
}
}
if (s) {
dd("Parsed status %d", (int) *s);
}
return NGX_OK;
}
ngx_int_t
ngx_http_headers_more_parse_types(ngx_log_t *log, ngx_str_t *cmd_name,
ngx_str_t *value, ngx_array_t *types)
{
u_char *p, *last;
ngx_str_t *t = NULL;
p = value->data;
last = p + value->len;
for (; p != last; p++) {
if (t == NULL) {
if (isspace(*p) || *p == ';') {
continue;
}
t = ngx_array_push(types);
if (t == NULL) {
return NGX_ERROR;
}
t->len = 1;
t->data = p;
continue;
}
if (isspace(*p) || *p == ';') {
t = NULL;
continue;
}
t->len++;
}
return NGX_OK;
}
ngx_int_t
ngx_http_headers_more_rm_header_helper(ngx_list_t *l, ngx_list_part_t *cur,
ngx_uint_t i)
{
ngx_table_elt_t *data;
ngx_list_part_t *new, *part;
dd("list rm item: part %p, i %d, nalloc %d", cur, (int) i,
(int) l->nalloc);
data = cur->elts;
dd("cur: nelts %d, nalloc %d", (int) cur->nelts,
(int) l->nalloc);
if (i == 0) {
cur->elts = (char *) cur->elts + l->size;
cur->nelts--;
if (cur == l->last) {
if (cur->nelts == 0) {
#if 1
part = &l->part;
if (part == cur) {
cur->elts = (char *) cur->elts - l->size;
/* do nothing */
} else {
while (part->next != cur) {
if (part->next == NULL) {
return NGX_ERROR;
}
part = part->next;
}
l->last = part;
part->next = NULL;
dd("part nelts: %d", (int) part->nelts);
l->nalloc = part->nelts;
}
#endif
} else {
l->nalloc--;
}
return NGX_OK;
}
if (cur->nelts == 0) {
part = &l->part;
if (part == cur) {
ngx_http_headers_more_assert(cur->next != NULL);
dd("remove 'cur' from the list by rewriting 'cur': "
"l->last: %p, cur: %p, cur->next: %p, part: %p",
l->last, cur, cur->next, part);
if (l->last == cur->next) {
dd("last is cur->next");
l->part = *(cur->next);
l->last = part;
l->nalloc = part->nelts;
} else {
l->part = *(cur->next);
}
} else {
dd("remove 'cur' from the list");
while (part->next != cur) {
if (part->next == NULL) {
return NGX_ERROR;
}
part = part->next;
}
part->next = cur->next;
}
return NGX_OK;
}
return NGX_OK;
}
if (i == cur->nelts - 1) {
cur->nelts--;
if (cur == l->last) {
l->nalloc = cur->nelts;
}
return NGX_OK;
}
new = ngx_palloc(l->pool, sizeof(ngx_list_part_t));
if (new == NULL) {
return NGX_ERROR;
}
new->elts = &data[i + 1];
new->nelts = cur->nelts - i - 1;
new->next = cur->next;
cur->nelts = i;
cur->next = new;
if (cur == l->last) {
l->last = new;
l->nalloc = new->nelts;
}
return NGX_OK;
}

View File

@ -0,0 +1,52 @@
/*
* Copyright (c) Yichun Zhang (agentzh)
*/
#ifndef NGX_HTTP_HEADERS_MORE_UTIL_H
#define NGX_HTTP_HEADERS_MORE_UTIL_H
#include "ngx_http_headers_more_filter_module.h"
#define ngx_http_headers_more_hash_literal(s) \
ngx_http_headers_more_hash_str((u_char *) s, sizeof(s) - 1)
static ngx_inline ngx_uint_t
ngx_http_headers_more_hash_str(u_char *src, size_t n)
{
ngx_uint_t key;
key = 0;
while (n--) {
key = ngx_hash(key, *src);
src++;
}
return key;
}
extern ngx_uint_t ngx_http_headers_more_location_hash;
ngx_int_t ngx_http_headers_more_parse_header(ngx_conf_t *cf,
ngx_str_t *cmd_name, ngx_str_t *raw_header, ngx_array_t *headers,
ngx_http_headers_more_opcode_t opcode,
ngx_http_headers_more_set_header_t *handlers);
ngx_int_t ngx_http_headers_more_parse_statuses(ngx_log_t *log,
ngx_str_t *cmd_name, ngx_str_t *value, ngx_array_t *statuses);
ngx_int_t ngx_http_headers_more_parse_types(ngx_log_t *log,
ngx_str_t *cmd_name, ngx_str_t *value, ngx_array_t *types);
ngx_int_t ngx_http_headers_more_rm_header_helper(ngx_list_t *l,
ngx_list_part_t *cur, ngx_uint_t i);
#endif /* NGX_HTTP_HEADERS_MORE_UTIL_H */

View File

@ -0,0 +1,416 @@
# vi:filetype=
use Test::Nginx::Socket; # 'no_plan';
repeat_each(2);
plan tests => 56 * repeat_each();
no_diff;
run_tests();
__DATA__
=== TEST 1: set Server
--- config
#more_set_headers 'Last-Modified: x';
more_clear_headers 'Last-Modified';
--- request
GET /index.html
--- response_headers
! Last-Modified
--- response_body_like: It works!
=== TEST 2: variables in the Ranges header
--- config
location /index.html {
set $rfrom 1;
set $rto 3;
more_set_input_headers 'Range: bytes=$rfrom - $rto';
#more_set_input_headers 'Range: bytes=1 - 3';
#echo $http_range;
}
--- request
GET /index.html
--- error_code: 206
--- response_body chomp
htm
=== TEST 3: mime type overriding (inlined types)
--- config
more_clear_headers 'X-Powered-By' 'X-Runtime' 'ETag';
types {
text/html html htm shtml;
text/css css;
}
--- user_files
>>> a.css
hello
--- request
GET /a.css
--- error_code: 200
--- response_headers
Content-Type: text/css
--- response_body
hello
=== TEST 4: mime type overriding (included types file)
--- config
more_clear_headers 'X-Powered-By' 'X-Runtime' 'ETag';
include mime.types;
--- user_files
>>> a.css
hello
>>> ../conf/mime.types
types {
text/html html htm shtml;
text/css css;
}
--- request
GET /a.css
--- error_code: 200
--- response_headers
Content-Type: text/css
--- response_body
hello
=== TEST 5: empty variable as the header value
--- config
location /foo {
more_set_headers 'X-Foo: $arg_foo';
echo hi;
}
--- request
GET /foo
--- response_headers
! X-Foo
--- response_body
hi
=== TEST 6: range bug
--- config
location /index.html {
more_clear_input_headers "Range*" ;
more_clear_input_headers "Content-Range*" ;
more_set_input_headers 'Range: bytes=1-5';
more_set_headers 'Content-Range: bytes 1-5/1000';
}
--- request
GET /index.html
--- more_headers
Range: bytes=1-3
--- raw_response_headers_like: Content-Range: bytes 1-5/1000$
--- response_body chop
html>
--- error_code: 206
--- SKIP
=== TEST 7: Allow-Ranges
--- config
location /index.html {
more_clear_headers 'Accept-Ranges';
}
--- request
GET /index.html
--- response_headers
! Accept-Ranges
--- response_body_like: It works
=== TEST 8: clear hand-written Allow-Ranges headers
--- config
location /index.html {
more_set_headers 'Accept-Ranges: bytes';
more_clear_headers 'Accept-Ranges';
}
--- request
GET /index.html
--- response_headers
! Accept-Ranges
--- response_body_like: It works
=== TEST 9: clear first, then add
--- config
location /bug {
more_clear_headers 'Foo';
more_set_headers 'Foo: a';
echo hello;
}
--- request
GET /bug
--- raw_response_headers_like eval
".*Foo: a.*"
--- response_body
hello
=== TEST 10: first add, then clear, then add again
--- config
location /bug {
more_set_headers 'Foo: a';
more_clear_headers 'Foo';
more_set_headers 'Foo: b';
echo hello;
}
--- request
GET /bug
--- raw_response_headers_like eval
".*Foo: b.*"
--- response_body
hello
=== TEST 11: override charset
--- config
location /foo {
charset iso-8859-1;
default_type "text/html";
echo hiya;
}
location /bug {
more_set_headers "Content-Type: text/html; charset=UTF-8";
proxy_pass http://127.0.0.1:$server_port/foo;
}
--- request
GET /bug
--- response_body
hiya
--- response_headers
Content-Type: text/html; charset=UTF-8
=== TEST 12: set multi-value header to a single value
--- config
location /main {
set $footer '';
proxy_pass http://127.0.0.1:$server_port/foo;
more_set_headers 'Foo: b';
header_filter_by_lua '
ngx.var.footer = ngx.header.Foo
';
echo_after_body $footer;
}
location /foo {
echo foo;
add_header Foo a;
add_header Foo c;
}
--- request
GET /main
--- response_headers
Foo: b
--- response_body
foo
b
=== TEST 13: set multi values to cache-control and override it with multiple values (to reproduce a bug)
--- config
location /lua {
content_by_lua '
ngx.header.cache_control = { "private", "no-store", "foo", "bar", "baz" }
ngx.send_headers()
ngx.say("Cache-Control: ", ngx.var.sent_http_cache_control)
';
more_clear_headers Cache-Control;
add_header Cache-Control "blah";
}
--- request
GET /lua
--- response_headers
Cache-Control: blah
--- response_body
Cache-Control: blah
=== TEST 14: set 20+ headers
--- config
location /test {
more_clear_input_headers "Authorization";
echo $http_a1;
echo $http_authorization;
echo $http_a2;
echo $http_a3;
echo $http_a23;
echo $http_a24;
echo $http_a25;
}
--- request
GET /test
--- more_headers eval
my $i = 1;
my $s;
while ($i <= 25) {
$s .= "A$i: $i\n";
if ($i == 22) {
$s .= "Authorization: blah\n";
}
$i++;
}
#warn $s;
$s
--- response_body
1
2
3
23
24
25
=== TEST 15: github #20: segfault caused by the nasty optimization in the nginx core (set)
--- config
location = /t/ {
more_set_headers "Foo: 1";
proxy_pass http://127.0.0.1:$server_port;
}
--- request
GET /t
--- more_headers
Foo: bar
Bah: baz
--- response_body_like: 301 Moved Permanently
--- error_code: 301
--- no_error_log
[error]
=== TEST 16: github #20: segfault caused by the nasty optimization in the nginx core (clear)
--- config
location = /t/ {
more_clear_headers Foo;
proxy_pass http://127.0.0.1:$server_port;
}
--- request
GET /t
--- more_headers
Foo: bar
Bah: baz
--- response_body_like: 301 Moved Permanently
--- error_code: 301
--- no_error_log
[error]
=== TEST 17: Content-Type response headers with a charset param (correct -t values)
--- config
location = /t {
more_set_headers -t 'text/html' 'X-Foo: Bar';
proxy_pass http://127.0.0.1:$server_port/fake;
}
location = /fake {
default_type text/html;
charset utf-8;
echo ok;
}
--- request
GET /t
--- response_headers
X-Foo: Bar
--- response_body
ok
=== TEST 18: Content-Type response headers with a charset param (WRONG -t values)
--- config
location = /t {
more_set_headers -t 'text/html; charset=utf-8' 'X-Foo: Bar';
proxy_pass http://127.0.0.1:$server_port/fake;
}
location = /fake {
default_type text/html;
charset utf-8;
echo ok;
}
--- request
GET /t
--- response_headers
X-Foo: Bar
--- response_body
ok
=== TEST 19: for bad requests (bad request method letter case)
--- config
error_page 400 = /err;
location = /err {
more_set_input_headers "Foo: bar";
echo ok;
}
--- raw_request
GeT / HTTP/1.1
--- response_body
ok
--- no_check_leak
=== TEST 20: for bad requests (bad request method names)
--- config
error_page 400 = /err;
location = /err {
more_set_input_headers "Foo: bar";
echo ok;
}
--- raw_request
GET x HTTP/1.1
--- response_body
ok
--- no_check_leak
=== TEST 21: override Cache-Control header sent by proxy module
--- config
location = /back {
content_by_lua_block {
ngx.header['Cache-Control'] = 'max-age=0, no-cache'
ngx.send_headers()
ngx.say("Cache-Control: ", ngx.var.sent_http_cache_control)
}
}
location = /t {
more_set_headers "Cache-Control: max-age=1800";
proxy_pass http://127.0.0.1:$server_port/back;
}
--- request
GET /t
--- response_headers
Cache-Control: max-age=1800
--- response_body
Cache-Control: max-age=0, no-cache

View File

@ -0,0 +1,338 @@
# vi:filetype=
use lib 'lib';
use Test::Nginx::Socket; # 'no_plan';
plan tests => 60;
no_diff;
run_tests();
__DATA__
=== TEST 1: set Server
--- config
location /foo {
echo hi;
more_set_headers 'Server: Foo';
}
--- request
GET /foo
--- response_headers
Server: Foo
--- response_body
hi
=== TEST 2: clear Server
--- config
location /foo {
echo hi;
more_clear_headers 'Server: ';
}
--- request
GET /foo
--- response_headers
! Server
--- response_body
hi
=== TEST 3: set Content-Type
--- config
location /foo {
default_type 'text/plan';
more_set_headers 'Content-Type: text/css';
echo hi;
}
--- request
GET /foo
--- response_headers
Content-Type: text/css
--- response_body
hi
=== TEST 4: set Content-Type
--- config
location /foo {
default_type 'text/plan';
more_set_headers 'Content-Type: text/css';
return 404;
}
--- request
GET /foo
--- response_headers
Content-Type: text/css
--- response_body_like: 404 Not Found
--- error_code: 404
=== TEST 5: clear Content-Type
--- config
location /foo {
default_type 'text/plain';
more_clear_headers 'Content-Type: ';
return 404;
}
--- request
GET /foo
--- response_headers
! Content-Type
--- response_body_like: 404 Not Found
--- error_code: 404
=== TEST 6: clear Content-Type (colon not required)
--- config
location /foo {
default_type 'text/plain';
more_set_headers 'Content-Type: Hello';
more_clear_headers 'Content-Type';
return 404;
}
--- request
GET /foo
--- response_headers
! Content-Type
--- response_body_like: 404 Not Found
--- error_code: 404
=== TEST 7: clear Content-Type (value ignored)
--- config
location /foo {
default_type 'text/plain';
more_set_headers 'Content-Type: Hello';
more_clear_headers 'Content-Type: blah';
return 404;
}
--- request
GET /foo
--- response_headers
! Content-Type
--- response_body_like: 404 Not Found
--- error_code: 404
=== TEST 8: clear Content-Type (case insensitive)
--- config
location /foo {
default_type 'text/plain';
more_set_headers 'Content-Type: Hello';
more_clear_headers 'content-type: blah';
return 404;
}
--- request
GET /foo
--- response_headers
! Content-Type
--- response_body_like: 404 Not Found
--- error_code: 404
=== TEST 9: clear Content-Type using set empty
--- config
location /foo {
default_type 'text/plain';
more_set_headers 'Content-Type: Hello';
more_set_headers 'content-type:';
return 404;
}
--- request
GET /foo
--- response_headers
! Content-Type
--- response_body_like: 404 Not Found
--- error_code: 404
=== TEST 10: clear Content-Type using setting key only
--- config
location /foo {
default_type 'text/plain';
more_set_headers 'Content-Type: Hello';
more_set_headers 'content-type';
return 404;
}
--- request
GET /foo
--- response_headers
! Content-Type
--- response_body_like: 404 Not Found
--- error_code: 404
=== TEST 11: set content-length
--- config
location /len {
more_set_headers 'Content-Length: 2';
echo hello;
}
--- request
GET /len
--- response_headers
Content-Length: 2
--- response_body chop
he
=== TEST 12: set content-length multiple times
--- config
location /len {
more_set_headers 'Content-Length: 2';
more_set_headers 'Content-Length: 4';
echo hello;
}
--- request
GET /len
--- response_headers
Content-Length: 4
--- response_body chop
hell
=== TEST 13: clear content-length
--- config
location /len {
more_set_headers 'Content-Length: 4';
more_set_headers 'Content-Length:';
echo hello;
}
--- request
GET /len
--- response_headers
! Content-Length
--- response_body
hello
=== TEST 14: clear content-length (another way)
--- config
location /len {
more_set_headers 'Content-Length: 4';
more_clear_headers 'Content-Length';
echo hello;
}
--- request
GET /len
--- response_headers
! Content-Length
--- response_body
hello
=== TEST 15: clear content-type
--- config
location /len {
default_type 'text/plain';
more_set_headers 'Content-Type:';
echo hello;
}
--- request
GET /len
--- response_headers
! Content-Type
--- response_body
hello
=== TEST 16: clear content-type (the other way)
--- config
location /len {
default_type 'text/plain';
more_clear_headers 'Content-Type:';
echo hello;
}
--- request
GET /len
--- response_headers
! Content-Type
--- response_body
hello
=== TEST 17: set Charset
--- config
location /len {
default_type 'text/plain';
more_set_headers 'Charset: gbk';
echo hello;
}
--- request
GET /len
--- response_headers
Charset: gbk
--- response_body
hello
=== TEST 18: clear Charset
--- config
location /len {
default_type 'text/plain';
more_set_headers 'Charset: gbk';
more_clear_headers 'Charset';
echo hello;
}
--- request
GET /len
--- response_headers
! Charset
--- response_body
hello
=== TEST 19: clear Charset (the other way: using set)
--- config
location /len {
default_type 'text/plain';
more_set_headers 'Charset: gbk';
more_set_headers 'Charset: ';
echo hello;
}
--- request
GET /len
--- response_headers
! Charset
--- response_body
hello
=== TEST 20: set Vary
--- config
location /foo {
more_set_headers 'Vary: gbk';
echo hello;
}
location /len {
default_type 'text/plain';
more_set_headers 'Vary: hello';
proxy_pass http://127.0.0.1:$server_port/foo;
}
--- request
GET /len
--- response_headers
Vary: hello
--- response_body
hello

View File

@ -0,0 +1,36 @@
# vi:filetype=
use lib 'lib';
use Test::Nginx::Socket; # 'no_plan';
repeat_each(3);
plan tests => repeat_each() * 2 * blocks();
#no_long_string();
#no_diff;
run_tests();
__DATA__
=== TEST 1: set request header at client side
--- config
location /foo {
eval_subrequest_in_memory off;
eval_override_content_type text/plain;
eval $res {
echo -n 1;
}
#echo "[$res]";
if ($res = '1') {
more_set_input_headers 'Foo: Bar';
echo "OK";
break;
}
echo "NOT OK";
}
--- request
GET /foo
--- response_body
OK

View File

@ -0,0 +1,137 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use lib 'lib';
use Test::Nginx::Socket;
#worker_connections(1014);
#master_process_enabled(1);
#log_level('warn');
repeat_each(2);
plan tests => repeat_each() * (4 * blocks());
#no_diff();
no_long_string();
run_tests();
__DATA__
=== TEST 1: clear the Connection req header
--- config
location /req-header {
more_clear_input_headers Connection;
echo "connection: $http_connection";
}
--- request
GET /req-header
--- stap
F(ngx_http_headers_more_exec_input_cmd) {
printf("rewrite: conn type: %d\n", $r->headers_in->connection_type)
}
F(ngx_http_core_content_phase) {
printf("content: conn type: %d\n", $r->headers_in->connection_type)
}
--- stap_out
rewrite: conn type: 1
content: conn type: 0
--- response_body
connection:
--- no_error_log
[error]
=== TEST 2: set custom Connection req header (close)
--- config
location /req-header {
more_set_input_headers "Connection: CLOSE";
echo "connection: $http_connection";
}
--- request
GET /req-header
--- stap
F(ngx_http_headers_more_exec_input_cmd) {
printf("rewrite: conn type: %d\n", $r->headers_in->connection_type)
}
F(ngx_http_core_content_phase) {
printf("content: conn type: %d\n", $r->headers_in->connection_type)
}
--- stap_out
rewrite: conn type: 1
content: conn type: 1
--- response_body
connection: CLOSE
--- no_error_log
[error]
=== TEST 3: set custom Connection req header (keep-alive)
--- config
location /req-header {
more_set_input_headers "Connection: keep-alive";
echo "connection: $http_connection";
}
--- request
GET /req-header
--- stap
F(ngx_http_headers_more_exec_input_cmd) {
printf("rewrite: conn type: %d\n", $r->headers_in->connection_type)
}
F(ngx_http_core_content_phase) {
printf("content: conn type: %d\n", $r->headers_in->connection_type)
}
--- stap_out
rewrite: conn type: 1
content: conn type: 2
--- response_body
connection: keep-alive
--- no_error_log
[error]
=== TEST 4: set custom Connection req header (bad)
--- config
location /req-header {
more_set_input_headers "Connection: bad";
echo "connection: $http_connection";
}
--- request
GET /req-header
--- stap
F(ngx_http_headers_more_exec_input_cmd) {
printf("rewrite: conn type: %d\n", $r->headers_in->connection_type)
}
F(ngx_http_core_content_phase) {
printf("content: conn type: %d\n", $r->headers_in->connection_type)
}
--- stap_out
rewrite: conn type: 1
content: conn type: 0
--- response_body
connection: bad
--- no_error_log
[error]

View File

@ -0,0 +1,183 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use lib 'lib';
use Test::Nginx::Socket;
#worker_connections(1014);
#master_process_enabled(1);
#log_level('warn');
repeat_each(2);
plan tests => repeat_each() * (4 * blocks());
#no_diff();
no_long_string();
run_tests();
__DATA__
=== TEST 1: clear cookie (with existing cookies)
--- config
location /t {
more_clear_input_headers Cookie;
echo "Cookie foo: $cookie_foo";
echo "Cookie baz: $cookie_baz";
echo "Cookie: $http_cookie";
}
--- request
GET /t
--- more_headers
Cookie: foo=bar
Cookie: baz=blah
--- stap
F(ngx_http_headers_more_exec_input_cmd) {
printf("rewrite: cookies: %d\n", $r->headers_in->cookies->nelts)
}
F(ngx_http_core_content_phase) {
printf("content: cookies: %d\n", $r->headers_in->cookies->nelts)
}
--- stap_out
rewrite: cookies: 2
content: cookies: 0
--- response_body
Cookie foo:
Cookie baz:
Cookie:
--- no_error_log
[error]
=== TEST 2: clear cookie (without existing cookies)
--- config
location /t {
more_clear_input_headers Cookie;
echo "Cookie foo: $cookie_foo";
echo "Cookie baz: $cookie_baz";
echo "Cookie: $http_cookie";
}
--- request
GET /t
--- stap
F(ngx_http_headers_more_exec_input_cmd) {
printf("rewrite: cookies: %d\n", $r->headers_in->cookies->nelts)
}
F(ngx_http_core_content_phase) {
printf("content: cookies: %d\n", $r->headers_in->cookies->nelts)
}
--- stap_out
rewrite: cookies: 0
content: cookies: 0
--- response_body
Cookie foo:
Cookie baz:
Cookie:
--- no_error_log
[error]
=== TEST 3: set one custom cookie (with existing cookies)
--- config
location /t {
more_set_input_headers "Cookie: boo=123";
echo "Cookie foo: $cookie_foo";
echo "Cookie baz: $cookie_baz";
echo "Cookie boo: $cookie_boo";
echo "Cookie: $http_cookie";
}
--- request
GET /t
--- more_headers
Cookie: foo=bar
Cookie: baz=blah
--- stap
F(ngx_http_headers_more_exec_input_cmd) {
printf("rewrite: cookies: %d\n", $r->headers_in->cookies->nelts)
}
F(ngx_http_core_content_phase) {
printf("content: cookies: %d\n", $r->headers_in->cookies->nelts)
}
--- stap_out
rewrite: cookies: 2
content: cookies: 1
--- response_body
Cookie foo:
Cookie baz:
Cookie boo: 123
Cookie: boo=123
--- no_error_log
[error]
=== TEST 4: set one custom cookie (without existing cookies)
--- config
location /t {
more_set_input_headers "Cookie: boo=123";
echo "Cookie foo: $cookie_foo";
echo "Cookie baz: $cookie_baz";
echo "Cookie boo: $cookie_boo";
echo "Cookie: $http_cookie";
}
--- request
GET /t
--- stap
F(ngx_http_headers_more_exec_input_cmd) {
printf("rewrite: cookies: %d\n", $r->headers_in->cookies->nelts)
}
F(ngx_http_core_content_phase) {
printf("content: cookies: %d\n", $r->headers_in->cookies->nelts)
}
--- stap_out
rewrite: cookies: 0
content: cookies: 1
--- response_body
Cookie foo:
Cookie baz:
Cookie boo: 123
Cookie: boo=123
--- no_error_log
[error]
=== TEST 5: for bad requests causing segfaults when setting & getting multi-value headers
--- config
error_page 400 = /err;
location = /err {
more_set_input_headers "Cookie: foo=bar";
echo -n $cookie_foo;
echo ok;
}
--- raw_request
GeT / HTTP/1.1
--- response_body
ok
--- no_error_log
[warn]
[error]
--- no_check_leak

View File

@ -0,0 +1,628 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use lib 'lib';
use Test::Nginx::Socket;
#worker_connections(1014);
#master_process_enabled(1);
#log_level('warn');
repeat_each(2);
plan tests => repeat_each() * (4 * blocks());
#no_diff();
no_long_string();
run_tests();
__DATA__
=== TEST 1: clear Opera user-agent
--- config
location /t {
more_clear_input_headers User-Agent;
echo "User-Agent: $http_user_agent";
}
--- request
GET /t
--- more_headers
User-Agent: Opera/9.80 (Macintosh; Intel Mac OS X 10.7.4; U; en) Presto/2.10.229 Version/11.62
--- stap
F(ngx_http_headers_more_exec_input_cmd) {
printf("rewrite: opera: %d\n", $r->headers_in->opera)
}
F(ngx_http_core_content_phase) {
printf("content: opera: %d\n", $r->headers_in->opera)
}
--- stap_out
rewrite: opera: 1
content: opera: 0
--- response_body
User-Agent:
--- no_error_log
[error]
=== TEST 2: clear MSIE 4 user-agent
--- config
location /t {
more_clear_input_headers User-Agent;
echo "User-Agent: $http_user_agent";
}
--- request
GET /t
--- more_headers
User-Agent: Mozilla/4.0 (compatible; MSIE 4.01; Windows NT 5.0)
--- stap
F(ngx_http_headers_more_exec_input_cmd) {
printf("rewrite: msie=%d msie6=%d\n",
$r->headers_in->msie,
$r->headers_in->msie6)
}
F(ngx_http_core_content_phase) {
printf("content: msie=%d msie6=%d\n",
$r->headers_in->msie,
$r->headers_in->msie6)
}
--- stap_out
rewrite: msie=1 msie6=1
content: msie=0 msie6=0
--- response_body
User-Agent:
--- no_error_log
[error]
=== TEST 3: set custom MSIE 4 user-agent
--- config
location /t {
more_set_input_headers "User-Agent: Mozilla/4.0 (compatible; MSIE 4.01; Windows NT 5.0)";
echo "User-Agent: $http_user_agent";
}
--- request
GET /t
--- stap
F(ngx_http_headers_more_exec_input_cmd) {
printf("rewrite: msie=%d msie6=%d\n",
$r->headers_in->msie,
$r->headers_in->msie6)
}
F(ngx_http_core_content_phase) {
printf("content: msie=%d msie6=%d\n",
$r->headers_in->msie,
$r->headers_in->msie6)
}
--- stap_out
rewrite: msie=0 msie6=0
content: msie=1 msie6=1
--- response_body
User-Agent: Mozilla/4.0 (compatible; MSIE 4.01; Windows NT 5.0)
--- no_error_log
[error]
=== TEST 4: clear MSIE 5 user-agent
--- config
location /t {
more_clear_input_headers User-Agent;
echo "User-Agent: $http_user_agent";
}
--- request
GET /t
--- more_headers
User-Agent: Mozilla/4.0 (compatible; MSIE 5.01; Windows 95; MSIECrawler)
--- stap
F(ngx_http_headers_more_exec_input_cmd) {
printf("rewrite: msie=%d msie6=%d\n",
$r->headers_in->msie,
$r->headers_in->msie6)
}
F(ngx_http_core_content_phase) {
printf("content: msie=%d msie6=%d\n",
$r->headers_in->msie,
$r->headers_in->msie6)
}
--- stap_out
rewrite: msie=1 msie6=1
content: msie=0 msie6=0
--- response_body
User-Agent:
--- no_error_log
[error]
=== TEST 5: set custom MSIE 5 user-agent
--- config
location /t {
more_set_input_headers "User-Agent: Mozilla/4.0 (compatible; MSIE 5.01; Windows 95; MSIECrawler)";
echo "User-Agent: $http_user_agent";
}
--- request
GET /t
--- stap
F(ngx_http_headers_more_exec_input_cmd) {
printf("rewrite: msie=%d msie6=%d\n",
$r->headers_in->msie,
$r->headers_in->msie6)
}
F(ngx_http_core_content_phase) {
printf("content: msie=%d msie6=%d\n",
$r->headers_in->msie,
$r->headers_in->msie6)
}
--- stap_out
rewrite: msie=0 msie6=0
content: msie=1 msie6=1
--- response_body
User-Agent: Mozilla/4.0 (compatible; MSIE 5.01; Windows 95; MSIECrawler)
--- no_error_log
[error]
=== TEST 6: clear MSIE 6 (without SV1) user-agent
--- config
location /t {
more_clear_input_headers User-Agent;
echo "User-Agent: $http_user_agent";
}
--- request
GET /t
--- more_headers
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Google Wireless Transcoder;)
--- stap
F(ngx_http_headers_more_exec_input_cmd) {
printf("rewrite: msie=%d msie6=%d\n",
$r->headers_in->msie,
$r->headers_in->msie6)
}
F(ngx_http_core_content_phase) {
printf("content: msie=%d msie6=%d\n",
$r->headers_in->msie,
$r->headers_in->msie6)
}
--- stap_out
rewrite: msie=1 msie6=1
content: msie=0 msie6=0
--- response_body
User-Agent:
--- no_error_log
[error]
=== TEST 7: set custom MSIE 6 (without SV1) user-agent
--- config
location /t {
more_set_input_headers "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Google Wireless Transcoder;)";
echo "User-Agent: $http_user_agent";
}
--- request
GET /t
--- stap
F(ngx_http_headers_more_exec_input_cmd) {
printf("rewrite: msie=%d msie6=%d\n",
$r->headers_in->msie,
$r->headers_in->msie6)
}
F(ngx_http_core_content_phase) {
printf("content: msie=%d msie6=%d\n",
$r->headers_in->msie,
$r->headers_in->msie6)
}
--- stap_out
rewrite: msie=0 msie6=0
content: msie=1 msie6=1
--- response_body
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Google Wireless Transcoder;)
--- no_error_log
[error]
=== TEST 8: clear MSIE 6 (with SV1) user-agent
--- config
location /t {
more_clear_input_headers User-Agent;
echo "User-Agent: $http_user_agent";
}
--- request
GET /t
--- more_headers
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; InfoPath.1)
--- stap
F(ngx_http_headers_more_exec_input_cmd) {
printf("rewrite: msie=%d msie6=%d\n",
$r->headers_in->msie,
$r->headers_in->msie6)
}
F(ngx_http_core_content_phase) {
printf("content: msie=%d msie6=%d\n",
$r->headers_in->msie,
$r->headers_in->msie6)
}
--- stap_out
rewrite: msie=1 msie6=0
content: msie=0 msie6=0
--- response_body
User-Agent:
--- no_error_log
[error]
=== TEST 9: set custom MSIE 6 (with SV1) user-agent
--- config
location /t {
more_set_input_headers "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; InfoPath.1)";
echo "User-Agent: $http_user_agent";
}
--- request
GET /t
--- stap
F(ngx_http_headers_more_exec_input_cmd) {
printf("rewrite: msie=%d msie6=%d\n",
$r->headers_in->msie,
$r->headers_in->msie6)
}
F(ngx_http_core_content_phase) {
printf("content: msie=%d msie6=%d\n",
$r->headers_in->msie,
$r->headers_in->msie6)
}
--- stap_out
rewrite: msie=0 msie6=0
content: msie=1 msie6=0
--- response_body
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; InfoPath.1)
--- no_error_log
[error]
=== TEST 10: set custom MSIE 7 user-agent
--- config
location /t {
more_set_input_headers "User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; winfx; .NET CLR 1.1.4322; .NET CLR 2.0.50727; Zune 2.0)";
echo "User-Agent: $http_user_agent";
}
--- request
GET /t
--- stap
F(ngx_http_headers_more_exec_input_cmd) {
printf("rewrite: msie=%d msie6=%d\n",
$r->headers_in->msie,
$r->headers_in->msie6)
}
F(ngx_http_core_content_phase) {
printf("content: msie=%d msie6=%d\n",
$r->headers_in->msie,
$r->headers_in->msie6)
}
--- stap_out
rewrite: msie=0 msie6=0
content: msie=1 msie6=0
--- response_body
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; winfx; .NET CLR 1.1.4322; .NET CLR 2.0.50727; Zune 2.0)
--- no_error_log
[error]
=== TEST 11: clear Gecko user-agent
--- config
location /t {
more_clear_input_headers User-Agent;
echo "User-Agent: $http_user_agent";
}
--- request
GET /t
--- more_headers
User-Agent: Mozilla/5.0 (Android; Mobile; rv:13.0) Gecko/13.0 Firefox/13.0
--- stap
F(ngx_http_headers_more_exec_input_cmd) {
printf("rewrite: gecko: %d\n", $r->headers_in->gecko)
}
F(ngx_http_core_content_phase) {
printf("content: gecko: %d\n", $r->headers_in->gecko)
}
--- stap_out
rewrite: gecko: 1
content: gecko: 0
--- response_body
User-Agent:
--- no_error_log
[error]
=== TEST 12: set custom Gecko user-agent
--- config
location /t {
more_set_input_headers "User-Agent: Mozilla/5.0 (Android; Mobile; rv:13.0) Gecko/13.0 Firefox/13.0";
echo "User-Agent: $http_user_agent";
}
--- request
GET /t
--- stap
F(ngx_http_headers_more_exec_input_cmd) {
printf("rewrite: gecko: %d\n", $r->headers_in->gecko)
}
F(ngx_http_core_content_phase) {
printf("content: gecko: %d\n", $r->headers_in->gecko)
}
--- stap_out
rewrite: gecko: 0
content: gecko: 1
--- response_body
User-Agent: Mozilla/5.0 (Android; Mobile; rv:13.0) Gecko/13.0 Firefox/13.0
--- no_error_log
[error]
=== TEST 13: clear Chrome user-agent
--- config
location /t {
more_clear_input_headers User-Agent;
echo "User-Agent: $http_user_agent";
}
--- request
GET /t
--- more_headers
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.151 Safari/535.19
--- stap
F(ngx_http_headers_more_exec_input_cmd) {
printf("rewrite: chrome: %d\n", $r->headers_in->chrome)
}
F(ngx_http_core_content_phase) {
printf("content: chrome: %d\n", $r->headers_in->chrome)
}
--- stap_out
rewrite: chrome: 1
content: chrome: 0
--- response_body
User-Agent:
--- no_error_log
[error]
=== TEST 14: set custom Chrome user-agent
--- config
location /t {
more_set_input_headers "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.151 Safari/535.19";
echo "User-Agent: $http_user_agent";
}
--- request
GET /t
--- stap
F(ngx_http_headers_more_exec_input_cmd) {
printf("rewrite: chrome: %d\n", $r->headers_in->chrome)
}
F(ngx_http_core_content_phase) {
printf("content: chrome: %d\n", $r->headers_in->chrome)
}
--- stap_out
rewrite: chrome: 0
content: chrome: 1
--- response_body
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.151 Safari/535.19
--- no_error_log
[error]
=== TEST 15: clear Safari (Mac OS X) user-agent
--- config
location /t {
more_clear_input_headers User-Agent;
echo "User-Agent: $http_user_agent";
}
--- request
GET /t
--- more_headers
User-Agent: Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/125.2 (KHTML, like Gecko) Safari/125.8
--- stap
F(ngx_http_headers_more_exec_input_cmd) {
printf("rewrite: safari: %d\n", $r->headers_in->safari)
}
F(ngx_http_core_content_phase) {
printf("content: safari: %d\n", $r->headers_in->safari)
}
--- stap_out
rewrite: safari: 1
content: safari: 0
--- response_body
User-Agent:
--- no_error_log
[error]
=== TEST 16: set custom Safari user-agent
--- config
location /t {
more_set_input_headers "User-Agent: Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/125.2 (KHTML, like Gecko) Safari/125.8";
echo "User-Agent: $http_user_agent";
}
--- request
GET /t
--- stap
F(ngx_http_headers_more_exec_input_cmd) {
printf("rewrite: safari: %d\n", $r->headers_in->safari)
}
F(ngx_http_core_content_phase) {
printf("content: safari: %d\n", $r->headers_in->safari)
}
--- stap_out
rewrite: safari: 0
content: safari: 1
--- response_body
User-Agent: Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/125.2 (KHTML, like Gecko) Safari/125.8
--- no_error_log
[error]
=== TEST 17: clear Konqueror user-agent
--- config
location /t {
more_clear_input_headers User-Agent;
echo "User-Agent: $http_user_agent";
}
--- request
GET /t
--- more_headers
User-Agent: Mozilla/5.0 (compatible; Konqueror/3.5; Linux) KHTML/3.5.10 (like Gecko) (Kubuntu)
--- stap
F(ngx_http_headers_more_exec_input_cmd) {
printf("rewrite: konqueror: %d\n", $r->headers_in->konqueror)
}
F(ngx_http_core_content_phase) {
printf("content: konqueror: %d\n", $r->headers_in->konqueror)
}
--- stap_out
rewrite: konqueror: 1
content: konqueror: 0
--- response_body
User-Agent:
--- no_error_log
[error]
=== TEST 18: set custom Konqueror user-agent
--- config
location /t {
more_set_input_headers "User-Agent: Mozilla/5.0 (compatible; Konqueror/3.5; Linux) KHTML/3.5.10 (like Gecko) (Kubuntu)";
echo "User-Agent: $http_user_agent";
}
--- request
GET /t
--- stap
F(ngx_http_headers_more_exec_input_cmd) {
printf("rewrite: konqueror: %d\n", $r->headers_in->konqueror)
}
F(ngx_http_core_content_phase) {
printf("content: konqueror: %d\n", $r->headers_in->konqueror)
}
--- stap_out
rewrite: konqueror: 0
content: konqueror: 1
--- response_body
User-Agent: Mozilla/5.0 (compatible; Konqueror/3.5; Linux) KHTML/3.5.10 (like Gecko) (Kubuntu)
--- no_error_log
[error]

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,25 @@
# vi:filetype=perl
use lib 'lib';
use Test::Nginx::Socket;
plan tests => 3;
no_diff;
run_tests();
__DATA__
=== TEST 1: simple set (1 arg)
--- config
location /foo {
deny all;
more_set_headers 'X-Foo: Blah';
}
--- request
GET /foo
--- response_headers
X-Foo: Blah
--- response_body_like: 403 Forbidden
--- error_code: 403

View File

@ -0,0 +1,567 @@
# vi:filetype=
use lib 'lib';
use Test::Nginx::Socket;
repeat_each(2);
plan tests => repeat_each() * 113;
#master_on();
#workers(2);
log_level("warn");
no_diff;
run_tests();
__DATA__
=== TEST 1: simple set (1 arg)
--- config
location /foo {
echo hi;
more_set_headers 'X-Foo: Blah';
}
--- request
GET /foo
--- response_headers
X-Foo: Blah
--- response_body
hi
=== TEST 2: simple set (2 args)
--- config
location /foo {
echo hi;
more_set_headers 'X-Foo: Blah' 'X-Bar: hi';
}
--- request
GET /foo
--- response_headers
X-Foo: Blah
X-Bar: hi
--- response_body
hi
=== TEST 3: two sets in a single location
--- config
location /two {
echo hi;
more_set_headers 'X-Foo: Blah'
more_set_headers 'X-Bar: hi';
}
--- request
GET /two
--- response_headers
X-Foo: Blah
X-Bar: hi
--- response_body
hi
=== TEST 4: two sets in a single location (for 404 too)
--- config
location /two {
more_set_headers 'X-Foo: Blah'
more_set_headers 'X-Bar: hi';
return 404;
}
--- request
GET /two
--- response_headers
X-Foo: Blah
X-Bar: hi
--- response_body_like: 404 Not Found
--- error_code: 404
=== TEST 5: set a header then clears it (500)
--- config
location /two {
more_set_headers 'X-Foo: Blah';
more_set_headers 'X-Foo:';
return 500;
}
--- request
GET /two
--- response_headers
! X-Foo
! X-Bar
--- response_body_like: 500 Internal Server Error
--- error_code: 500
=== TEST 6: set a header only when 500 (matched)
--- config
location /bad {
more_set_headers -s 500 'X-Mine: Hiya';
more_set_headers -s 404 'X-Yours: Blah';
return 500;
}
--- request
GET /bad
--- response_headers
X-Mine: Hiya
! X-Yours
--- response_body_like: 500 Internal Server Error
--- error_code: 500
=== TEST 7: set a header only when 500 (not matched with 200)
--- config
location /bad {
more_set_headers -s 500 'X-Mine: Hiya';
more_set_headers -s 404 'X-Yours: Blah';
echo hello;
}
--- request
GET /bad
--- response_headers
! X-Mine
! X-Yours
--- response_body
hello
--- error_code: 200
=== TEST 8: set a header only when 500 (not matched with 404)
--- config
location /bad {
more_set_headers -s 500 'X-Mine: Hiya';
more_set_headers -s 404 'X-Yours: Blah';
return 404;
}
--- request
GET /bad
--- response_headers
! X-Mine
X-Yours: Blah
--- response_body_like: 404 Not Found
--- error_code: 404
=== TEST 9: more conditions
--- config
location /bad {
more_set_headers -s '503 404' 'X-Mine: Hiya';
more_set_headers -s ' 404 413 ' 'X-Yours: Blah';
return 503;
}
--- request
GET /bad
--- response_headers
X-Mine: Hiya
! X-Yours
--- response_body_like: 503 Service
--- error_code: 503
=== TEST 10: more conditions
--- config
location /bad {
more_set_headers -s '503 404' 'X-Mine: Hiya';
more_set_headers -s ' 404 413 ' 'X-Yours: Blah';
return 404;
}
--- request
GET /bad
--- response_headers
X-Mine: Hiya
X-Yours: Blah
--- response_body_like: 404 Not Found
--- error_code: 404
=== TEST 11: more conditions
--- config
location /bad {
more_set_headers -s '503 404' 'X-Mine: Hiya';
more_set_headers -s ' 404 413 ' 'X-Yours: Blah';
return 413;
}
--- request
GET /bad
--- response_headers
! X-Mine
X-Yours: Blah
--- response_body_like: 413 Request Entity Too Large
--- error_code: 413
=== TEST 12: simple -t
--- config
location /bad {
default_type 'text/css';
more_set_headers -t 'text/css' 'X-CSS: yes';
echo hi;
}
--- request
GET /bad
--- response_headers
X-CSS: yes
--- response_body
hi
=== TEST 13: simple -t (not matched)
--- config
location /bad {
default_type 'text/plain';
more_set_headers -t 'text/css' 'X-CSS: yes';
echo hi;
}
--- request
GET /bad
--- response_headers
! X-CSS
--- response_body
hi
=== TEST 14: multiple -t (not matched)
--- config
location /bad {
default_type 'text/plain';
more_set_headers -t 'text/javascript' -t 'text/css' 'X-CSS: yes';
echo hi;
}
--- request
GET /bad
--- response_headers
! X-CSS
--- response_body
hi
=== TEST 15: multiple -t (matched)
--- config
location /bad {
default_type 'text/plain';
more_set_headers -t 'text/javascript' -t 'text/plain' 'X-CSS: yes';
echo hi;
}
--- request
GET /bad
--- response_headers
X-CSS: yes
--- response_body
hi
=== TEST 16: multiple -t (matched)
--- config
location /bad {
default_type 'text/javascript';
more_set_headers -t 'text/javascript' -t 'text/plain' 'X-CSS: yes';
echo hi;
}
--- request
GET /bad
--- response_headers
X-CSS: yes
--- response_body
hi
=== TEST 17: multiple -t (matched) with extra spaces
--- config
location /bad {
default_type 'text/javascript';
more_set_headers -t ' text/javascript ' -t 'text/plain' 'X-CSS: yes';
echo hi;
}
--- request
GET /bad
--- response_headers
X-CSS: yes
--- response_body
hi
=== TEST 18: multiple -t merged
--- config
location /bad {
default_type 'text/javascript';
more_set_headers -t ' text/javascript text/plain' 'X-CSS: yes';
echo hi;
}
--- request
GET /bad
--- response_headers
X-CSS: yes
--- response_body
hi
=== TEST 19: multiple -t merged (2)
--- config
location /bad {
default_type 'text/plain';
more_set_headers -t ' text/javascript text/plain' 'X-CSS: yes';
echo hi;
}
--- request
GET /bad
--- response_headers
X-CSS: yes
--- response_body
hi
=== TEST 20: multiple -s option in a directive (not matched)
--- config
location /bad {
more_set_headers -s 404 -s 500 'X-status: howdy';
echo hi;
}
--- request
GET /bad
--- response_headers
! X-status
--- response_body
hi
=== TEST 21: multiple -s option in a directive (matched 404)
--- config
location /bad {
more_set_headers -s 404 -s 500 'X-status: howdy';
return 404;
}
--- request
GET /bad
--- response_headers
X-status: howdy
--- response_body_like: 404 Not Found
--- error_code: 404
=== TEST 22: multiple -s option in a directive (matched 500)
--- config
location /bad {
more_set_headers -s 404 -s 500 'X-status: howdy';
return 500;
}
--- request
GET /bad
--- response_headers
X-status: howdy
--- response_body_like: 500 Internal Server Error
--- error_code: 500
=== TEST 23: -s mixed with -t
--- config
location /bad {
default_type 'text/html';
more_set_headers -s 404 -s 200 -t 'text/html' 'X-status: howdy2';
return 404;
}
--- request
GET /bad
--- response_headers
X-status: howdy2
--- response_body_like: 404 Not Found
--- error_code: 404
=== TEST 24: -s mixed with -t
--- config
location /bad {
default_type 'text/html';
more_set_headers -s 404 -s 200 -t 'text/plain' 'X-status: howdy2';
return 404;
}
--- request
GET /bad
--- response_headers
! X-status
--- response_body_like: 404 Not Found
--- error_code: 404
=== TEST 25: -s mixed with -t
--- config
location /bad {
default_type 'text/html';
more_set_headers -s 404 -s 200 -t 'text/html' 'X-status: howdy2';
echo hi;
}
--- request
GET /bad
--- response_headers
X-status: howdy2
--- response_body
hi
--- error_code: 200
=== TEST 26: -s mixed with -t
--- config
location /bad {
default_type 'text/html';
more_set_headers -s 500 -s 200 -t 'text/html' 'X-status: howdy2';
return 404;
}
--- request
GET /bad
--- response_headers
! X-status
--- response_body_like: 404 Not Found
--- error_code: 404
=== TEST 27: merge from the upper level
--- config
more_set_headers -s 404 -t 'text/html' 'X-status2: howdy3';
location /bad {
default_type 'text/html';
more_set_headers -s 500 -s 200 -t 'text/html' 'X-status: howdy2';
return 404;
}
--- request
GET /bad
--- response_headers
X-status2: howdy3
! X-status
--- response_body_like: 404 Not Found
--- error_code: 404
=== TEST 28: merge from the upper level
--- config
more_set_headers -s 404 -t 'text/html' 'X-status2: howdy3';
location /bad {
default_type 'text/html';
more_set_headers -s 500 -s 200 -t 'text/html' 'X-status: howdy2';
echo yeah;
}
--- request
GET /bad
--- response_headers
! X-status2
X-status: howdy2
--- response_body
yeah
--- error_code: 200
=== TEST 29: override settings by inheritance
--- config
more_set_headers -s 404 -t 'text/html' 'X-status: yeah';
location /bad {
default_type 'text/html';
more_set_headers -s 404 -t 'text/html' 'X-status: nope';
return 404;
}
--- request
GET /bad
--- response_headers
X-status: nope
--- response_body_like: 404 Not Found
--- error_code: 404
=== TEST 30: append settings by inheritance
--- config
more_set_headers -s 404 -t 'text/html' 'X-status: yeah';
location /bad {
default_type 'text/html';
more_set_headers -s 404 -t 'text/html' 'X-status2: nope';
return 404;
}
--- request
GET /bad
--- response_headers
X-status: yeah
X-status2: nope
--- response_body_like: 404 Not Found
--- error_code: 404
=== TEST 31: clear headers with wildcard
--- config
location = /backend {
add_header X-Hidden-One "i am hidden";
add_header X-Hidden-Two "me 2";
echo hi;
}
location /hello {
more_clear_headers 'X-Hidden-*';
proxy_pass http://127.0.0.1:$server_port/backend;
}
--- request
GET /hello
--- response_headers
! X-Hidden-One
! X-Hidden-Two
--- response_body
hi
=== TEST 32: clear duplicate headers
--- config
location = /backend {
add_header pragma no-cache;
add_header pragma no-cache;
echo hi;
}
location /hello {
more_clear_headers 'pragma';
proxy_pass http://127.0.0.1:$server_port/backend;
}
--- request
GET /hello
--- response_headers
!pragma
--- response_body
hi
=== TEST 33: HTTP 0.9 (set)
--- config
location /foo {
more_set_headers 'X-Foo: howdy';
echo ok;
}
--- raw_request eval
"GET /foo\r\n"
--- response_headers
! X-Foo
--- response_body
ok
--- http09

View File

@ -0,0 +1,68 @@
# vi:filetype=
use lib 'lib';
use Test::Nginx::Socket; # 'no_plan';
plan tests => blocks() * 3;
no_diff;
run_tests();
__DATA__
=== TEST 1: vars in input header directives
--- config
location /main {
echo_location /foo;
echo "main: $http_user_agent";
}
location /foo {
set $val 'dog';
more_set_input_headers 'User-Agent: $val';
proxy_pass http://127.0.0.1:$server_port/proxy;
}
location /proxy {
echo "sub: $http_user_agent";
}
--- request
GET /main
--- more_headers
User-Agent: my-sock
--- response_body
sub: dog
main: dog
--- response_headers
! Host
--- skip_nginx: 3: < 0.7.46
=== TEST 2: vars in input header directives
--- config
location /main {
#more_set_input_headers 'User-Agent: cat';
echo_location /foo;
echo "main: $http_user_agent";
}
location /foo {
set $val 'dog';
more_set_input_headers 'User-Agent: $val';
proxy_pass http://127.0.0.1:$server_port/proxy;
#echo $http_user_agent;
}
location /proxy {
echo "sub: $http_user_agent";
}
--- request
GET /main
--- response_body
sub: dog
main: dog
--- response_headers
! Host
--- skip_nginx: 3: < 0.7.46

View File

@ -0,0 +1,174 @@
# vi:filetype=
use lib 'lib';
use Test::Nginx::Socket;
repeat_each(2);
plan tests => repeat_each() * (blocks() * 4 + 2);
#master_on();
#workers(2);
log_level("warn");
no_diff;
run_tests();
__DATA__
=== TEST 1: used output filter
--- config
location /foo {
echo hi;
more_set_headers "Foo: bar";
}
--- request
GET /foo
--- response_headers
Foo: bar
--- response_body
hi
--- error_log
headers more header filter
--- no_error_log
[error]
--- log_level: debug
=== TEST 2: unused output filter (none)
--- config
location /foo {
echo hi;
}
--- request
GET /foo
--- response_body
hi
--- no_error_log
headers more header filter
[error]
--- log_level: debug
=== TEST 3: unused output filter (with more_set_input_headers only)
--- config
location /foo {
more_set_input_headers "Foo: bar";
echo hi;
}
--- request
GET /foo
--- response_body
hi
--- no_error_log
headers more header filter
[error]
--- log_level: debug
=== TEST 4: used rewrite handler
--- config
location /foo {
more_set_input_headers "Foo: bar";
echo hi;
}
--- request
GET /foo
--- response_body
hi
--- error_log
headers more rewrite handler
--- no_error_log
[error]
--- log_level: debug
=== TEST 5: unused rewrite handler (none)
--- config
location /foo {
#more_set_input_headers "Foo: bar";
echo hi;
}
--- request
GET /foo
--- response_body
hi
--- no_error_log
headers more rewrite handler
[error]
--- log_level: debug
=== TEST 6: unused rewrite handler (with output header filters)
--- config
location /foo {
#more_set_input_headers "Foo: bar";
echo hi;
more_set_headers "Foo: bar";
}
--- request
GET /foo
--- response_headers
Foo: bar
--- response_body
hi
--- no_error_log
headers more rewrite handler
[error]
--- log_level: debug
=== TEST 7: multiple http {} blocks (filter)
This test case won't run with nginx 1.9.3+ since duplicate http {} blocks
have been prohibited since then.
--- SKIP
--- config
location /foo {
echo hi;
more_set_headers 'Foo: bar';
}
--- post_main_config
http {
}
--- request
GET /foo
--- response_body
hi
--- response_headers
Foo: bar
--- no_error_log
[error]
--- error_log
headers more header filter
--- log_level: debug
=== TEST 8: multiple http {} blocks (handler)
This test case won't run with nginx 1.9.3+ since duplicate http {} blocks
have been prohibited since then.
--- SKIP
--- config
location /foo {
more_set_input_headers 'Foo: bar';
echo $http_foo;
}
--- post_main_config
http {
}
--- request
GET /foo
--- response_body
bar
--- no_error_log
headers more header handler
[error]
--- log_level: debug

View File

@ -0,0 +1,58 @@
# vi:ft=
use lib 'lib';
use Test::Nginx::Socket; # 'no_plan';
plan tests => 9;
no_diff;
run_tests();
__DATA__
=== TEST 1: vars
--- config
location /foo {
echo hi;
set $val 'hello, world';
more_set_headers 'X-Foo: $val';
}
--- request
GET /foo
--- response_headers
X-Foo: hello, world
--- response_body
hi
=== TEST 2: vars in both key and val
--- config
location /foo {
echo hi;
set $val 'hello, world';
more_set_headers '$val: $val';
}
--- request
GET /foo
--- response_headers
$val: hello, world
--- response_body
hi
=== TEST 3: vars in input header directives
--- config
location /foo {
set $val 'dog';
more_set_input_headers 'Host: $val';
echo $host;
}
--- request
GET /foo
--- response_body
dog
--- response_headers
Host:

View File

@ -0,0 +1,38 @@
#!/bin/bash
# this file is mostly meant to be used by the author himself.
root=`pwd`
version=$1
home=~
force=$2
pcre2_opt=""
if [ "$WITHOUT_PCRE2" = "1" ]; then
pcre2_opt="--without-pcre2"
fi
#--with-cc=gcc46 \
ngx-build $force $version \
--with-ld-opt="-L$PCRE_LIB -Wl,-rpath,$PCRE_LIB:$LIBDRIZZLE_LIB" \
--without-mail_pop3_module \
--without-mail_imap_module \
--without-mail_smtp_module \
--without-http_upstream_ip_hash_module \
--without-http_empty_gif_module \
--without-http_memcached_module \
--without-http_referer_module \
--without-http_autoindex_module \
--without-http_auth_basic_module \
--without-http_userid_module \
$pcre2_opt \
--with-http_realip_module \
--with-http_dav_module \
--add-module=$root/../eval-nginx-module \
--add-module=$root/../lua-nginx-module \
--add-module=$root/../echo-nginx-module \
--add-module=$root $opts \
--with-debug
#--add-module=$root/../ndk-nginx-module \
#--without-http_ssi_module # we cannot disable ssi because echo_location_async depends on it (i dunno why?!)

View File

@ -0,0 +1,135 @@
{
<insert_a_suppression_name_here>
Memcheck:Leak
fun:malloc
fun:ngx_alloc
obj:*
}
{
<insert_a_suppression_name_here>
Memcheck:Leak
fun:malloc
fun:ngx_alloc
fun:ngx_calloc
fun:ngx_event_process_init
}
{
<insert_a_suppression_name_here>
Memcheck:Leak
fun:malloc
fun:ngx_alloc
fun:ngx_event_process_init
}
{
<insert_a_suppression_name_here>
Memcheck:Param
epoll_ctl(event)
fun:epoll_ctl
}
{
<insert_a_suppression_name_here>
Memcheck:Cond
fun:memcpy
fun:ngx_vslprintf
fun:ngx_log_error_core
fun:ngx_http_charset_header_filter
}
{
nginx-core-process-init
Memcheck:Leak
fun:malloc
fun:ngx_alloc
fun:ngx_event_process_init
}
{
nginx-core-crc32-init
Memcheck:Leak
fun:malloc
fun:ngx_alloc
fun:ngx_crc32_table_init
fun:main
}
{
palloc_large_for_init_request
Memcheck:Leak
fun:malloc
fun:ngx_alloc
fun:ngx_palloc_large
fun:ngx_palloc
fun:ngx_pcalloc
fun:ngx_http_init_request
fun:ngx_epoll_process_events
fun:ngx_process_events_and_timers
}
{
palloc_large_for_create_temp_buf
Memcheck:Leak
fun:malloc
fun:ngx_alloc
fun:ngx_palloc_large
fun:ngx_palloc
fun:ngx_create_temp_buf
fun:ngx_http_init_request
fun:ngx_epoll_process_events
fun:ngx_process_events_and_timers
}
{
accept_create_pool
Memcheck:Leak
fun:memalign
fun:posix_memalign
fun:ngx_memalign
fun:ngx_create_pool
fun:ngx_event_accept
fun:ngx_epoll_process_events
fun:ngx_process_events_and_timers
}
{
create_pool_for_init_req
Memcheck:Leak
fun:memalign
fun:posix_memalign
fun:ngx_memalign
fun:ngx_create_pool
fun:ngx_http_init_request
fun:ngx_epoll_process_events
fun:ngx_process_events_and_timers
}
{
<insert_a_suppression_name_here>
Memcheck:Addr8
fun:getenv
fun:gcov_exit
fun:exit
fun:ngx_master_process_exit
}
{
<insert_a_suppression_name_here>
Memcheck:Cond
fun:index
fun:expand_dynamic_string_token
fun:_dl_map_object
fun:map_doit
fun:_dl_catch_error
fun:do_preload
fun:dl_main
}
{
<insert_a_suppression_name_here>
Memcheck:Leak
match-leak-kinds: definite
fun:malloc
fun:ngx_alloc
fun:ngx_set_environment
fun:ngx_single_process_cycle
}
{
<insert_a_suppression_name_here>
Memcheck:Leak
match-leak-kinds: definite
fun:malloc
fun:ngx_alloc
fun:ngx_set_environment
fun:ngx_worker_process_init
fun:ngx_worker_process_cycle
}

3
src/deps/src/lbase64/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
*.out
*.swp
*.swo

View File

@ -0,0 +1,25 @@
language: python
sudo: false
env:
- LUA="lua 5.1"
- LUA="lua 5.2"
- LUA="lua 5.3"
- LUA="lua 5.4"
- LUA="luajit 2.0"
- LUA="luajit 2.1"
before_install:
- pip install hererocks
- hererocks env --$LUA -rlatest # Use latest LuaRocks, install into 'env' directory.
- source env/bin/activate # Add directory with all installed binaries to PATH.notifications:
notifications:
email: false
install:
- luarocks install luacheck
script:
- luacheck --no-unused-args *.lua
- lua test.lua

View File

@ -0,0 +1,48 @@
[![Build Status](https://travis-ci.org/iskolbin/lbase64.svg?branch=master)](https://travis-ci.org/iskolbin/lbase64)
[![license](https://img.shields.io/badge/license-public%20domain-blue.svg)]()
[![MIT Licence](https://badges.frapsoft.com/os/mit/mit.svg?v=103)](https://opensource.org/licenses/mit-license.php)
Lua base64 encoder/decoder
==========================
Pure Lua [base64](https://en.wikipedia.org/wiki/Base64) encoder/decoder. Works with
Lua 5.1+ and LuaJIT. Fallbacks to pure Lua bit operations if bit/bit32/native bit
operators are not available.
```lua
local base64 = require'base64'
local str = 'Man is distinguished, not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure.'
local b64str = 'TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2YgdGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGludWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4='
local encoded = base64.encode( str )
local decoded = base64.decode( b64str )
assert( str == decoded )
assert( b64str == encoded )
```
base64.encode( str, encoder = DEFAULT, usecache = false )
---------------------------------------------------------
Encodes `str` string using `encoder` table. By default uses table with `+` as
char for 62, `/` as char for 63 and `=` as padding char. You can specify custom
encoder. For this you could use `base64.makeencoder`. If you are encoding large
chunks of text (or another highly redundant data) it's possible to highly
increase performace (for text approx. x2 gain) by using `usecache = true`. For
binary data like images using cache decreasing performance.
base64.decode( str, decoder = DEFAULT, usecache = false )
---------------------------------------------------------
Decodes `str` string using `decoder` table. Default decoder uses same chars as
default encoder.
base64.makeencoder( s62 = '+', s63 = '/', spad = '=' )
------------------------------------------------------
Make custom encoding table
base64.makedecoder( s62 = '+', s63 = '/', spad = '=' )
------------------------------------------------------
Make custom decoding table
Install
-------
```bash
luarocks install base64
```

View File

@ -0,0 +1,201 @@
--[[
base64 -- v1.5.3 public domain Lua base64 encoder/decoder
no warranty implied; use at your own risk
Needs bit32.extract function. If not present it's implemented using BitOp
or Lua 5.3 native bit operators. For Lua 5.1 fallbacks to pure Lua
implementation inspired by Rici Lake's post:
http://ricilake.blogspot.co.uk/2007/10/iterating-bits-in-lua.html
author: Ilya Kolbin (iskolbin@gmail.com)
url: github.com/iskolbin/lbase64
COMPATIBILITY
Lua 5.1+, LuaJIT
LICENSE
See end of file for license information.
--]]
local base64 = {}
local extract = _G.bit32 and _G.bit32.extract -- Lua 5.2/Lua 5.3 in compatibility mode
if not extract then
if _G.bit then -- LuaJIT
local shl, shr, band = _G.bit.lshift, _G.bit.rshift, _G.bit.band
extract = function( v, from, width )
return band( shr( v, from ), shl( 1, width ) - 1 )
end
elseif _G._VERSION == "Lua 5.1" then
extract = function( v, from, width )
local w = 0
local flag = 2^from
for i = 0, width-1 do
local flag2 = flag + flag
if v % flag2 >= flag then
w = w + 2^i
end
flag = flag2
end
return w
end
else -- Lua 5.3+
extract = load[[return function( v, from, width )
return ( v >> from ) & ((1 << width) - 1)
end]]()
end
end
function base64.makeencoder( s62, s63, spad )
local encoder = {}
for b64code, char in pairs{[0]='A','B','C','D','E','F','G','H','I','J',
'K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y',
'Z','a','b','c','d','e','f','g','h','i','j','k','l','m','n',
'o','p','q','r','s','t','u','v','w','x','y','z','0','1','2',
'3','4','5','6','7','8','9',s62 or '+',s63 or'/',spad or'='} do
encoder[b64code] = char:byte()
end
return encoder
end
function base64.makedecoder( s62, s63, spad )
local decoder = {}
for b64code, charcode in pairs( base64.makeencoder( s62, s63, spad )) do
decoder[charcode] = b64code
end
return decoder
end
local DEFAULT_ENCODER = base64.makeencoder()
local DEFAULT_DECODER = base64.makedecoder()
local char, concat = string.char, table.concat
function base64.encode( str, encoder, usecaching )
encoder = encoder or DEFAULT_ENCODER
local t, k, n = {}, 1, #str
local lastn = n % 3
local cache = {}
for i = 1, n-lastn, 3 do
local a, b, c = str:byte( i, i+2 )
local v = a*0x10000 + b*0x100 + c
local s
if usecaching then
s = cache[v]
if not s then
s = char(encoder[extract(v,18,6)], encoder[extract(v,12,6)], encoder[extract(v,6,6)], encoder[extract(v,0,6)])
cache[v] = s
end
else
s = char(encoder[extract(v,18,6)], encoder[extract(v,12,6)], encoder[extract(v,6,6)], encoder[extract(v,0,6)])
end
t[k] = s
k = k + 1
end
if lastn == 2 then
local a, b = str:byte( n-1, n )
local v = a*0x10000 + b*0x100
t[k] = char(encoder[extract(v,18,6)], encoder[extract(v,12,6)], encoder[extract(v,6,6)], encoder[64])
elseif lastn == 1 then
local v = str:byte( n )*0x10000
t[k] = char(encoder[extract(v,18,6)], encoder[extract(v,12,6)], encoder[64], encoder[64])
end
return concat( t )
end
function base64.decode( b64, decoder, usecaching )
decoder = decoder or DEFAULT_DECODER
local pattern = '[^%w%+%/%=]'
if decoder then
local s62, s63
for charcode, b64code in pairs( decoder ) do
if b64code == 62 then s62 = charcode
elseif b64code == 63 then s63 = charcode
end
end
pattern = ('[^%%w%%%s%%%s%%=]'):format( char(s62), char(s63) )
end
b64 = b64:gsub( pattern, '' )
local cache = usecaching and {}
local t, k = {}, 1
local n = #b64
local padding = b64:sub(-2) == '==' and 2 or b64:sub(-1) == '=' and 1 or 0
for i = 1, padding > 0 and n-4 or n, 4 do
local a, b, c, d = b64:byte( i, i+3 )
local s
if usecaching then
local v0 = a*0x1000000 + b*0x10000 + c*0x100 + d
s = cache[v0]
if not s then
local v = decoder[a]*0x40000 + decoder[b]*0x1000 + decoder[c]*0x40 + decoder[d]
s = char( extract(v,16,8), extract(v,8,8), extract(v,0,8))
cache[v0] = s
end
else
local v = decoder[a]*0x40000 + decoder[b]*0x1000 + decoder[c]*0x40 + decoder[d]
s = char( extract(v,16,8), extract(v,8,8), extract(v,0,8))
end
t[k] = s
k = k + 1
end
if padding == 1 then
local a, b, c = b64:byte( n-3, n-1 )
local v = decoder[a]*0x40000 + decoder[b]*0x1000 + decoder[c]*0x40
t[k] = char( extract(v,16,8), extract(v,8,8))
elseif padding == 2 then
local a, b = b64:byte( n-3, n-2 )
local v = decoder[a]*0x40000 + decoder[b]*0x1000
t[k] = char( extract(v,16,8))
end
return concat( t )
end
return base64
--[[
------------------------------------------------------------------------------
This software is available under 2 licenses -- choose whichever you prefer.
------------------------------------------------------------------------------
ALTERNATIVE A - MIT License
Copyright (c) 2018 Ilya Kolbin
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
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.
------------------------------------------------------------------------------
ALTERNATIVE B - Public Domain (www.unlicense.org)
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
software, either in source code form or as a compiled binary, for any purpose,
commercial or non-commercial, and by any means.
In jurisdictions that recognize copyright laws, the author or authors of this
software dedicate any and all copyright interest in the software to the public
domain. We make this dedication for the benefit of the public at large and to
the detriment of our heirs and successors. We intend this dedication to be an
overt act of relinquishment in perpetuity of all present and future rights to
this software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS 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.
------------------------------------------------------------------------------
--]]

View File

@ -0,0 +1,76 @@
local base64 = require'base64'
local N = 10000000
local st = {}
local letters = ' abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890'
.. 'абвгдеёжзийклмнопрстуфхцшщчъыьэюя'
.. 'АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦШЩЧЪЫЬЭЮЯ'
local nletters = #letters
for i = 1, N do
local j = math.random( nletters )
st[i] = letters:sub( j, j )
end
local s = table.concat( st )
local t = os.clock()
local encoded = base64.encode( s )
local encodetime = os.clock() - t
t = os.clock()
local decoded = base64.decode( encoded )
local decodetime = os.clock() - t
assert( s == decoded )
print('Common text')
print(('Encoding: %d bytes/sec'):format( math.floor(N/encodetime)))
print(('Decoding: %d bytes/sec'):format( math.floor(N/decodetime)))
collectgarbage()
t = os.clock()
encoded = base64.encode( s, nil, true )
encodetime = os.clock() - t
t = os.clock()
decoded = base64.decode( encoded, nil, true )
assert( s == decoded )
decodetime = os.clock() - t
print('Common text (cache)')
print(('Encoding: %d bytes/sec'):format( math.floor(N/encodetime)))
print(('Decoding: %d bytes/sec'):format( math.floor(N/decodetime)))
collectgarbage()
local lt = {}
for i = 0, 255 do
lt[i] = string.char(i)
end
nletters = #lt
for i = 1, N do
local j = math.random( nletters )
st[i] = lt[j]
end
s = table.concat( st )
t = os.clock()
encoded = base64.encode( s, nil )
encodetime = os.clock() - t
t = os.clock()
decoded = base64.decode( encoded )
decodetime = os.clock() - t
assert( s == decoded )
print('Binary')
print(('Encoding: %d bytes/sec'):format( math.floor(N/encodetime)))
print(('Decoding: %d bytes/sec'):format( math.floor(N/decodetime)))
collectgarbage()
t = os.clock()
encoded = base64.encode( s, nil, true )
encodetime = os.clock() - t
t = os.clock()
decoded = base64.decode( encoded, nil, true )
assert( s == decoded )
decodetime = os.clock() - t
print('Binary (cache)')
print(('Encoding: %d bytes/sec'):format( math.floor(N/encodetime)))
print(('Decoding: %d bytes/sec'):format( math.floor(N/decodetime)))
collectgarbage()

View File

@ -0,0 +1,20 @@
package = "base64"
version = "1.5-1"
source = {
url = "git+https://github.com/iskolbin/lbase64",
tag = "v1.5.1",
}
description = {
summary = "Pure Lua base64 encoder/decoder",
detailed = [[
Pure Lua [base64](https://en.wikipedia.org/wiki/Base64) encoder/decoder. Works with Lua 5.1+ and LuaJIT. Fallbacks to pure Lua bit operations if bit/bit32/native bit operators are not available.]],
homepage = "https://github.com/iskolbin/lbase64",
license = "MIT/Public Domain"
}
dependencies = {}
build = {
type = "builtin",
modules = {
base64 = "base64.lua",
}
}

View File

@ -0,0 +1,20 @@
package = "base64"
version = "1.5-2"
source = {
url = "git://github.com/iskolbin/lbase64",
tag = "v1.5.2",
}
description = {
summary = "Pure Lua base64 encoder/decoder",
detailed = [[
Pure Lua [base64](https://en.wikipedia.org/wiki/Base64) encoder/decoder. Works with Lua 5.1+ and LuaJIT. Fallbacks to pure Lua bit operations if bit/bit32/native bit operators are not available.]],
homepage = "https://github.com/iskolbin/lbase64",
license = "MIT/Public Domain"
}
dependencies = {}
build = {
type = "builtin",
modules = {
base64 = "base64.lua",
}
}

View File

@ -0,0 +1,20 @@
package = "base64"
version = "1.5-3"
source = {
url = "git://github.com/iskolbin/lbase64",
tag = "v1.5.3",
}
description = {
summary = "Pure Lua base64 encoder/decoder",
detailed = [[
Pure Lua base64 encoder/decoder. Works with Lua 5.1+ and LuaJIT. Fallbacks to pure Lua bit operations if bit/bit32/native bit operators are not available.]],
homepage = "https://github.com/iskolbin/lbase64",
license = "MIT/Public Domain"
}
dependencies = {}
build = {
type = "builtin",
modules = {
base64 = "base64.lua",
}
}

View File

@ -0,0 +1,47 @@
local base64 = require('base64')
local function test( s, b64 )
assert( base64.encode( s ) == b64 )
assert( base64.decode( b64 ) == s )
assert( base64.decode( base64.encode( s )) == s )
assert( base64.encode( s, nil, true ) == b64 )
assert( base64.decode( b64, nil, true ) == s )
assert( base64.decode( base64.encode( s, nil, true ), nil, true ) == s )
end
test( 'any carnal pleasure.', 'YW55IGNhcm5hbCBwbGVhc3VyZS4=' )
test( 'any carnal pleasure', 'YW55IGNhcm5hbCBwbGVhc3VyZQ==' )
test( 'any carnal pleasur', 'YW55IGNhcm5hbCBwbGVhc3Vy' )
test( 'Man is distinguished, not only by his reason, but by this singular passion from other animals, which is a ' ..
'lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, ' ..
'exceeds the short vehemence of any carnal pleasure.', 'TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb' ..
'24sIGJ1dCBieSB0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2YgdGhlIG1pbmQsIHRoY' ..
'XQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGludWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd' ..
'2xlZGdlLCBleGNlZWRzIHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4=' )
test( 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et ' ..
'dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea ' ..
'commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat ' ..
'nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit ' ..
'anim id est laborum.', 'TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyIGFkaXBpc2NpbmcgZWxpdCwgc2VkIGRvIGVp' ..
'dXNtb2QgdGVtcG9yIGluY2lkaWR1bnQgdXQgbGFib3JlIGV0IGRvbG9yZSBtYWduYSBhbGlxdWEuIFV0IGVuaW0gYWQgbWluaW0gdmVuaWFtLCBx' ..
'dWlzIG5vc3RydWQgZXhlcmNpdGF0aW9uIHVsbGFtY28gbGFib3JpcyBuaXNpIHV0IGFsaXF1aXAgZXggZWEgY29tbW9kbyBjb25zZXF1YXQuIER1' ..
'aXMgYXV0ZSBpcnVyZSBkb2xvciBpbiByZXByZWhlbmRlcml0IGluIHZvbHVwdGF0ZSB2ZWxpdCBlc3NlIGNpbGx1bSBkb2xvcmUgZXUgZnVnaWF0' ..
'IG51bGxhIHBhcmlhdHVyLiBFeGNlcHRldXIgc2ludCBvY2NhZWNhdCBjdXBpZGF0YXQgbm9uIHByb2lkZW50LCBzdW50IGluIGN1bHBhIHF1aSBv' ..
'ZmZpY2lhIGRlc2VydW50IG1vbGxpdCBhbmltIGlkIGVzdCBsYWJvcnVtLg==')
test( '«В чащах юга жил бы цитрус? Да, но фальшивый экземпляр!»',
'wqvQkiDRh9Cw0YnQsNGFINGO0LPQsCDQttC40Lsg0LHRiyDR' ..
'htC40YLRgNGD0YE/INCU0LAsINC90L4g0YTQsNC70YzRiNC40LLRi9C5INGN0LrQt9C10LzQv9C70Y/RgCHCuw==')
test( '«В чащах юга жил бы цитрус? Да, фальшивый экземпляр!»',
'wqvQkiDRh9Cw0YnQsNGFINGO0LPQsCDQttC40Lsg0LHRiyDRhtC' ..
'40YLRgNGD0YE/INCU0LAsINGE0LDQu9GM0YjQuNCy0YvQuSDRjdC60LfQtdC80L/Qu9GP0YAhwrs=')
test( '\137\080\078\071\013\010\026\010\000\000\000\013\073\072\068\082\000\000\000\032\000\000\000\032\001\003\000' ..
'\000\000\073\180\232\183\000\000\000\006\080\076\084\069\255\255\255\000\000\000\085\194\211\126\000\000\000\018' ..
'\073\068\065\084\008\215\099\248\015\004\196\016\084\006\196\218\011\000\237\189\063\193\243\000\141\059\000\000' ..
'\000\000\073\069\078\068\174\066\096\130', 'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgAQMAAABJtOi3AAAABlBMVEX///8AAABVwtN+' ..
'AAAAEklEQVQI12P4DwTEEFQGxNoLAO29P8HzAI07AAAAAElFTkSuQmCC' )
assert( base64.decode('YW55IGNhcm5hbCBwbGVhc3VyZS4=\n\r\\' ) == 'any carnal pleasure.' )
assert( base64.decode('wйqеvнQсуkкiеDнRгhш9щCзwх0ъфYыnвQаsпNрGоFллIдNжGэOё0яLчPQsCDQttC40Lsg0LHRiyDRhtC' ..
'40YLRgNGD0YE/INсCмUи0тLьAбsюIЙКNЕG\n\n\n\n\r\rE0LDQu9GM0YjQuNCy0YvQuSDRjdC60LfQtdC80L/Qu9GP0YAhwrs=') ==
'«В чащах юга жил бы цитрус? Да, фальшивый экземпляр!»' )

View File

@ -0,0 +1,5 @@
BasedOnStyle: LLVM
IndentWidth: 4
BinPackArguments: false
BinPackParameters: false
IndentCaseLabels: true

View File

@ -0,0 +1,26 @@
name: Run Clang AddressSanitizer
on:
push:
pull_request:
schedule:
- cron: '13 20 * * SUN'
jobs:
addresssanitizer:
name: Clang AddressSanitizer
runs-on: ubuntu-latest
env:
ASAN_OPTIONS: strict_string_checks=1:detect_stack_use_after_return=1:check_initialization_order=1:strict_init_order=1:detect_invalid_pointer_pairs=2
CC: clang
CXX: clang++
CFLAGS: -fsanitize=address -Wall -Wextra -Wpedantic -Wformat=2 -Walloca -Wvla -Wimplicit-fallthrough -Wcast-qual -Wconversion -Wshadow -Wundef -Wstrict-prototypes -Wswitch-enum -fstack-protector -D_FORTIFY_SOURCE=2
CXXFLAGS: -fsanitize=address
LDFLAGS: -fsanitize=address
steps:
- uses: actions/checkout@v2
with:
submodules: true
- run: sudo apt install clang libipc-run3-perl
- run: ./bootstrap
- run: ./configure
- run: make
- run: make check

View File

@ -0,0 +1,19 @@
name: Run Clang Static Analysis
on:
push:
pull_request:
schedule:
- cron: '3 20 * * SUN'
jobs:
clang-analyzer:
name: Clang static analysis
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: sudo apt install clang-tools libipc-run3-perl
- run: ./bootstrap
- run: scan-build ./configure
env:
CFLAGS: -std=c99 -Wall -Wextra -Werror -Wno-unused-function -Wno-unused-parameter -Wno-unknown-pragmas
- run: cd src; scan-build --status-bugs make; cd ..
- run: cd bin; scan-build --status-bugs make; cd ..

View File

@ -0,0 +1,40 @@
name: "Code scanning - action"
on:
push:
pull_request:
schedule:
- cron: '0 7 * * 2'
jobs:
CodeQL-Build:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v2
with:
# We must fetch at least the immediate parents so that if this is
# a pull request then we can checkout the head.
fetch-depth: 2
submodules: true
# If this run was triggered by a pull request event, then checkout
# the head of the pull request instead of the merge commit.
- run: git checkout HEAD^2
if: ${{ github.event_name == 'pull_request' }}
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
- run: sudo apt install libipc-run3-perl libipc-system-simple-perl libfile-slurp-perl libfile-which-perl pandoc
- run: |
./bootstrap
./configure
make
make safedist
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1

View File

@ -0,0 +1,48 @@
name: Run tests
on:
push:
pull_request:
schedule:
- cron: '3 20 * * SUN'
jobs:
test-autoconf:
strategy:
matrix:
os: [ubuntu-latest, macos-latest]
cc: [gcc, clang]
posix: ['', -D_POSIX_C_SOURCE=200112L]
name: Autotools build on ${{matrix.os}} using ${{matrix.cc}} ${{matrix.posix}}
runs-on: ${{ matrix.os }}
env:
CC: ${{ matrix.cc }}
VERBOSE: 1
steps:
- uses: actions/checkout@v2
with:
submodules: true
- run: sudo apt install libipc-run3-perl
if: ${{ matrix.os == 'ubuntu-latest' }}
- run: brew install autoconf automake libtool
if: ${{ matrix.os == 'macos-latest' }}
- run: ./bootstrap
- run: ./configure
env:
# -Wno-unknown-pragmas because we have some Clang specific pragmas
# which aren't interesting to cause failures for.
CFLAGS: -std=c99 -Wall -Wextra -Werror -Wno-unused-function -Wno-unused-parameter -Wno-unknown-pragmas ${{ matrix.posix }}
- run: make
- run: make check
test-cmake:
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
name: CMake build on ${{matrix.os}}
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v2
with:
submodules: true
- run: cmake -DBUILD_TESTING=ON .
- run: cmake --build .
- run: ctest -V . -C Debug

45
src/deps/src/libmaxminddb/.gitignore vendored Normal file
View File

@ -0,0 +1,45 @@
*.a
*.la
*.lo
*.o
*.so
*.swp
*/.deps
*/.libs
*~
.\#*
.gh-pages
/INSTALL
/autom4te.cache
/bin/country_lookup
/bin/mmdbdump
/bin/mmdblookup
/compile
/config.*
/configure
/depcomp
/include/maxminddb_config.h
/install-sh
/libmaxminddb-*
/libtool
/ltmain.sh
/man
/missing
/src/libmaxminddb.pc
/src/test-data-pool
/t/*.log
/t/*.trs
/t/*_t
/t/*-t
/test-driver
\#*\#
aclocal.m4
stamp-h*
CMakeCache.txt
CMakeFiles/
CTestTestfile.cmake
cmake_install.cmake
Makefile
Makefile.in
Testing/
install_manifest.txt

9
src/deps/src/libmaxminddb/.gitmodules vendored Normal file
View File

@ -0,0 +1,9 @@
[submodule "maxmind-db"]
path = maxmind-db
url = https://github.com/maxmind/MaxMind-DB.git
[submodule "t/libtap"]
path = t/libtap
url = https://github.com/zorgnax/libtap.git
[submodule "t/maxmind-db"]
path = t/maxmind-db
url = https://github.com/maxmind/MaxMind-DB.git

View File

@ -0,0 +1,11 @@
--blank-lines-before-packages=0
--iterations=2
--no-outdent-long-comments
-bar
-boc
-ci=4
-i=4
-l=78
-nolq
-se
-wbb="% + - * / x != == >= <= =~ !~ < > | & >= < = **= += *= &= <<= &&= -= /= |= >>= ||= .= %= ^= x="

View File

View File

@ -0,0 +1,121 @@
cmake_minimum_required (VERSION 3.9)
project(maxminddb
LANGUAGES C
VERSION 1.7.1
)
set(MAXMINDDB_SOVERSION 0.0.7)
set(CMAKE_C_STANDARD 99)
set(CMAKE_C_EXTENSIONS OFF)
if (WIN32)
option(MSVC_STATIC_RUNTIME "When ON the library will be built by using MT/MTd run-time libraries" OFF)
endif()
option(BUILD_SHARED_LIBS "Build shared libraries (.dll/.so) instead of static ones (.lib/.a)" OFF)
option(BUILD_TESTING "Build test programs" ON)
include(GNUInstallDirs)
include(CheckTypeSize)
check_type_size("unsigned __int128" UINT128)
check_type_size("unsigned int __attribute__((mode(TI)))" UINT128_USING_MODE)
if(HAVE_UINT128)
set(MMDB_UINT128_USING_MODE 0)
set(MMDB_UINT128_IS_BYTE_ARRAY 0)
elseif(HAVE_UINT128_USING_MODE)
set(MMDB_UINT128_USING_MODE 1)
set(MMDB_UINT128_IS_BYTE_ARRAY 0)
else()
set(MMDB_UINT128_USING_MODE 0)
set(MMDB_UINT128_IS_BYTE_ARRAY 1)
endif()
include (TestBigEndian)
TEST_BIG_ENDIAN(IS_BIG_ENDIAN)
if (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
endif()
configure_file(${PROJECT_SOURCE_DIR}/include/maxminddb_config.h.cmake.in
${PROJECT_SOURCE_DIR}/include/maxminddb_config.h)
add_library(maxminddb
src/maxminddb.c
src/data-pool.c
)
add_library(maxminddb::maxminddb ALIAS maxminddb)
set_target_properties(maxminddb PROPERTIES VERSION ${MAXMINDDB_SOVERSION})
target_compile_definitions(maxminddb PUBLIC PACKAGE_VERSION="${PROJECT_VERSION}")
if(NOT IS_BIG_ENDIAN)
target_compile_definitions(maxminddb PRIVATE MMDB_LITTLE_ENDIAN=1)
endif()
if(MSVC)
target_compile_definitions(maxminddb PRIVATE _CRT_SECURE_NO_WARNINGS)
endif()
if(WIN32)
target_link_libraries(maxminddb ws2_32)
if(BUILD_SHARED_LIBS)
set_target_properties(maxminddb PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON)
endif()
if(MSVC_STATIC_RUNTIME)
# On MSVC, when MSVC_STATIC_RUNTIME is ON, MT (Release) and MTd (Debug)
# run-time libraries will be used instead of MD/MDd. The default is OFF so
# MD/MDd are used when nothing related is passed.
#
# Adapted from https://gitlab.kitware.com/cmake/community/-/wikis/FAQ#make-override-files
set(CMAKE_USER_MAKE_RULES_OVERRIDE
${CMAKE_CURRENT_SOURCE_DIR}/c_flag_overrides.cmake)
set(CMAKE_USER_MAKE_RULES_OVERRIDE_CXX
${CMAKE_CURRENT_SOURCE_DIR}/cxx_flag_overrides.cmake)
endif()
endif()
target_include_directories(maxminddb PUBLIC
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}>
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
)
set(MAXMINDB_HEADERS
include/maxminddb.h
include/maxminddb_config.h
)
set_target_properties(maxminddb PROPERTIES PUBLIC_HEADER "${MAXMINDB_HEADERS}")
install(TARGETS maxminddb
EXPORT maxminddb)
# This is required to work with FetchContent
install(EXPORT maxminddb
FILE maxminddb-config.cmake
NAMESPACE maxminddb::
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/maxminddb)
# We always want to build mmdblookup
add_subdirectory(bin)
if (BUILD_TESTING)
enable_testing()
add_subdirectory(t)
endif()
# Generate libmaxminddb.pc file for pkg-config
# Set the required variables as same with autotools
set(prefix ${CMAKE_INSTALL_PREFIX})
set(exec_prefix \${prefix})
set(libdir \${exec_prefix}/lib)
set(includedir \${prefix}/include)
set(PACKAGE_VERSION ${maxminddb_VERSION})
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/src/libmaxminddb.pc.in
${CMAKE_CURRENT_BINARY_DIR}/src/libmaxminddb.pc
@ONLY)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/src/libmaxminddb.pc
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)

View File

@ -0,0 +1,384 @@
## 1.7.1 - 2022-09-30
* The external symbols test now only runs on Linux. It assumes a Linux
environment. Reported by Carlo Cabrera. GitHub #304.
## 1.7.0 - 2022-09-28
* `FD_CLOEXEC` is now set on platforms that do not support `O_CLOEXEC`.
Reported by rittneje. GitHub #273.
* When building with Visual Studio, you may now build a static runtime with
CMake by setting `MSVC_STATIC_RUNTIME` to `ON`. Pull request by Rafael
Santiago. GitHub #269.
* The CMake build now works on iOS. Pull request by SpaceIm. GitHub #271.
* The CMake build now uses the correct library directory on Linux systems
using alternate directory structures. Pull request by Satadru Pramanik.
GitHub #284.
* File size check now correctly compares the size to `SSIZE_MAX`. Reported
by marakew. GitHub #301.
## 1.6.0 - 2021-04-29
* This release includes several improvements to the CMake build. In
particular:
* C99 support is now properly enabled, fixing builds on older `gcc`
versions. Pull request by Jan Včelák. GitHub #257.
* `CMAKE_SHARED_LIBRARY_PREFIX` and `CMAKE_STATIC_LIBRARY_PREFIX` are
no longer explicitly set and now use the default values for the platform.
Pull request by Jan Včelák. GitHub #258.
* `target_include_directories` now works as expected. Pull request by Jan
Včelák. GitHub #259.
* DLLs are now installed on Windows when `libmaxminddb` is built as a
shared library. Pull request by Jan Včelák. GitHub #261.
* When built as a dynamic library on Windows, all symbols are now exported.
Pull request by Jan Včelák. GitHub #262.
## 1.5.2 - 2021-02-18
* With `libmaxminddb` on Windows and `mmdblookup` generally, there were
instances where the return value of `calloc` was not checked, which could
lead to issues in low memory situations or when resource limits had been
set. Reported by cve-reporting. GitHub #252.
## 1.5.1 - 2021-02-18
* The formatting of the manpages has been improved and the script that
generates them now supports `lowdown` in addition to `pandoc`. Pull request
by Faidon Liambotis. GitHub #248.
## 1.5.0 - 2021-01-05
* A CMake build script has been added for Windows builds. The Visual
Studio project files in `projects` are now considered deprecated and will
be removed in a future release.
## 1.4.3 - 2020-08-06
* On Windows, always call `CreateFileW` instead of `CreateFile`.
`CreateFile` could be mapped to `CreateFileA` and not work as expected.
Pull request by Sandu Liviu Catalin. GitHub #228.
* Fixed use of uninitialized memory in `dump_entry_data_list()` that could
cause a heap buffer overflow in `mmdblookup`. As part of this fix, most
uses of `malloc` were replaced with `calloc`. Reported by azhou. GitHub
#236.
## 1.4.2 - 2019-11-02
* The 1.4.0 release introduced a change that increased the size of `MMDB_s`,
unintentionally causing an ABI break. This release reverts the relevant
commit.
## 1.4.1 - 2019-11-01
* The man page links for function calls were not generated correctly in
1.4.0. This has been corrected.
## 1.4.0 - 2019-11-01
* A negative array index may now be used with `MMDB_get_value`,
`MMDB_vget_value`, and `MMDB_aget_value`. This specifies the element
from the end of the array. For instance, `-1` would refer to the
last element of the array. PR by Kyle Box. GitHub #205.
* On Windows, the file name passed to `MMDB_open` is now expected to be
UTF-8 encoded. This allows Unicode characters to be used in file names.
As part of this change, `mmdblookup` on Windows now converts its
arguments to UTF-8. PR by Gerald Combs. GitHub #189 & #191.
* Fix a memory leak that occurred when freeing an `MMDB_s` where the
database had no languages defined in the metadata. If you are using an
official MaxMind database, this leak does not affect you. Pull request
by Kókai Péter. GitHub #180.
* Add `--disable-binaries` option to `configure`. Pull request by Fabrice
Fontaine. GitHub #166.
* Previous releases incorrectly included `*.Po` files in the `t` directory.
This has been corrected. Reported by Daniel Macks. GitHub #168.
* The internal use of the `MMDB_s` now has the `const` modifier. Public
functions that accepted an `MMDB_s` as an argument now also declare it as
`const`. Pull request by Kurt Johnson. GitHub #199.
* `mmdblookup` now displays the prefix length for the record when using
the verbose flag. GitHub #172.
## 1.3.2 - 2018-01-17
* Allocate memory for `MMDB_entry_data_list_s` structs in separate chunks
rather than one large chunk. This simplifies accessing memory in
`MMDB_get_entry_data_list()` and increases performance. It builds on the
changes in 1.3.0 and 1.3.1.
* We no longer export `data_pool_*` symbols. These are internal functions
but we were previously exporting them. Pull request by Faidon Liambotis.
GitHub #162.
* Build with POSIX.1-2008 by default if the system supports it. This allows
use of `open()` with `O_CLOEXEC`. We retain support for systems that
provide only POSIX.1-2001.
* Open the database with the `O_CLOEXEC` flag if the system provides it.
This avoids cases where we could leak fds when called in multi-threaded
programs that `fork()` and `exec()`. Original report and PR by Brandon L
Black.
* Added a test to ensure we export only intended symbols (e.g. MMDB_*).
## 1.3.1 - 2017-11-24
* Fix build problems related to `rpl_malloc()`. Pull request by Rainer
Gerhards. GitHub #152.
* Fix a race to set and read data in a field on the `MMDB_s` struct
(`ipv4_start_node`). GitHub #153.
* Fix cases of invalid memory access when using
`MMDB_get_entry_data_list()`. This was introduced in 1.3.0 and occurred
when performing large lookups. GitHub #153.
## 1.3.0 - 2017-11-10
* Perform fewer memory allocations in `MMDB_get_entry_data_list()`. This
significantly improves its performance. GitHub #147.
* Fix `mmdblookup`'s build epoch reporting on some systems. Big endian
systems with a 32-bit `time_t` no longer show a database build date of
1970-01-01 00:00:00. Pull request by Rainer Jung. GitHub #143.
## 1.2.1 - 2017-05-15
* Use autoconf to check the system's endianness rather than trying to do this
with compiler-defined macros like `__BYTE_ORDER__`. Apparently this didn't
work properly on a Sparc system. GitHub #120.
* Several compiler warnings on Visual C++ were fixed. Pull request by Marcel
Raad. GitHub #130.
* Fix segmentation faults found in `MMDB_open()` using afl-fuzz. This
occurred on corrupt databases that had a data pointer large enough to
cause an integer overflow when doing bound checking. Reported by Ryan
Whitworth. GitHub #140.
* Add --disable-tests option to `configure`. Pull request by Fabrice
Fontaine. GitHub #136.
## 1.2.0 - 2016-03-23
* Four additional fields were added to the end of the `MMDB_search_node_s`
struct returned by `MMDB_read_node`. These fields allow the user to iterate
through the search tree without making undocumented assumptions about how
this library works internally and without knowing the specific details of
the database format. GitHub #110.
## 1.1.5 - 2016-03-20
* Previously, reading a database with a pointer in the metadata would cause an
`MMDB_INVALID_METADATA_ERROR` to be returned. This was due to an invalid
offset being used when calculating the pointer. The `data_section` and
`metadata_section` fields now both point to the beginning of the data
section. Previously, `data_section` pointed to the beginning of the data
separator. This will not affect anyone using only documented fields from
`MMDB_s`.
* `MMDB_lookup_sockaddr` will set `mmdb_error` to
`MMDB_IPV6_LOOKUP_IN_IPV4_DATABASE_ERROR` if an IPv6 `sockaddr` is looked up
in an IPv4-only database. Previously only `MMDB_lookup_string` would set
this error code.
* When resolving an address, this library now relies on `getaddrinfo` to
determine the address family rather than trying to guess it itself.
## 1.1.4 - 2016-01-06
* Packaging fixes. The 1.1.3 tarball release contained a lot of extra junk in
the t/ directory.
## 1.1.3 - 2016-01-05
* Added several additional checks to make sure that we don't attempt to read
past the end of the databases's data section. Implemented by Tobias
Stoeckmann. GitHub #103.
* When searching for the database metadata, there was a bug that caused the
code to think it had found valid metadata when none existed. In addition,
this could lead to an attempt to read past the end of the database
entirely. Finally, if there are multiple metadata markers in the database,
we treat the final one as the start of the metdata, instead of the first.
Implemented by Tobias Stoeckmann. GitHub #102.
* Don't attempt to mmap a file that is too large to be mmapped on the
system. Implemented by Tobias Stoeckmann. GitHub #101.
* Added a missing out of memory check when reading a file's
metadata. Implemented by Tobias Stoeckmann. GitHub #101.
* Added several additional checks to make sure that we never attempt to
`malloc` more than `SIZE_MAX` memory, which would lead to integer
overflow. This could only happen with pathological databases. Implemented by
Tobias Stoeckmann. GitHub #101.
## 1.1.2 - 2015-11-16
* IMPORTANT: This release includes a number of important security fixes. Among
these fixes is improved validation of the database metadata. Unfortunately,
MaxMind GeoIP2 and GeoLite2 databases created earlier than January 28, 2014
had an invalid data type for the `record_size` in the metadata. Previously
these databases worked on little endian machines with libmaxminddb but did
not work on big endian machines. Due to increased safety checks when reading
the file, these databases will no longer work on any platform. If you are
using one of these databases, we recommend that you upgrade to the latest
GeoLite2 or GeoIP2 database
* Added pkg-config support. If your system supports it, then running `make
install` now installs a `libmaxminddb.pc` file for pkgconfig. Implemented by
Jan Vcelak.
* Several segmentation faults found with afl-fuzz were fixed. These were
caused by missing bounds checking and missing data type verification checks.
* `MMDB_get_entry_data_list` will now fail on data structures with a depth
greater than 512 and data structures that are cyclic. This should not
affect any known MaxMind DB in production. All databases produced by
MaxMind have a depth of less than five.
## 1.1.1 - 2015-07-22
* Added `maxminddb-compat-util.h` as a source file to dist.
## 1.1.0 - 2015-07-21
* Previously, when there was an error in `MMDB_open()`, `errno` would
generally be overwritten during cleanup, preventing a useful value from
being returned to the caller. This was changed so that the `errno` value
from the function call that caused the error is restored before returning to
the caller. In particular, this is important for `MMDB_IO_ERROR` errors as
checking `errno` is often the only way to determine what actually failed.
* If `mmap()` fails due to running out of memory space, an
`MMDB_OUT_OF_MEMORY_ERROR` is now returned from `MMDB_open` rather than an
`MMDB_IO_ERROR`.
* On Windows, the `CreateFileMappingA()` handle was not properly closed if
opening the database succeeded. Fixed by Bly Hostetler. GitHub #75 & #76.
* On Windows, we were not checking the return value of `CreateFileMappingA()`
properly for errors. Fixed by Bly Hotetler. GitHub #78.
* Several warnings from Clang's scan-build were fixed. GitHub #86.
* All headers are now installed in `$(includedir)`. GitHub #89.
* We no longer install `maxminddb-compat-util.h`. This header was intended for
internal use only.
## 1.0.4 - 2015-01-02
* If you used a non-integer string as an array index when doing a lookup with
`MMDB_get_value()`, `MMDB_vget_value()`, or `MMDB_aget_value()`, the first
element of the array would be returned rather than an error. A
`MMDB_LOOKUP_PATH_DOES_NOT_MATCH_DATA_ERROR` error will now be returned.
GitHub #61.
* If a number larger than `LONG_MAX` was used in the same functions,
`LONG_MAX` would have been used in the lookup. Now a
`MMDB_INVALID_LOOKUP_PATH_ERROR` error will be returned.
* Visual Studio build files were added for unit tests and some compatibility
issues with the tests were fixed.
* Visual Studio project was updated to use property pages. Patch by Andre.
GitHub #69.
* A test failure in `t/compile_c++_t.pl` on new installs was fixed.
## 1.0.3 - 2014-12-02
* A memory and file handle leak on Win32 was fixed when getting the database
size fails. Patch by Federico G. Schwindt. GitHub PR #49.
* Documentation fix. Federico G. Schwindt. GitHub PR #50.
* Added Visual Studio build files and fixed incorrect CreateFileMappingA
usage. Patch by Andre. GitHub #52.
* The includes for the Windows header files were made lowercase in order to
match the actual file names on case-sensitive file systems. GitHub PR #57.
* Removed `realloc()` calls that caused warnings on Windows and generally
cleaned up memory allocation in `MMDB_vget_value()`. See relevant discussion
in GitHub #52.
* Added an `extern "C" { ... }` wrapper to maxminddb.h when compiling with a
C++ compiler. GitHub #55.
## 1.0.2 - 2014-09-22
* Fixed a number of small issues found by Coverity.
* When freeing the MMDB struct in `MMDB_close()` we make sure to set the
pointers to NULL after freeing the memory they point to. This makes it safe
to call `MMDB_close` more than once on the same `MMDB_s` struct
pointer. Before this change, calling this function twice on the same pointer
could cause the code to free memory that belonged to something else in the
process. Patch by Shuxin Yang. GitHub PR #41.
## 1.0.1 - 2014-09-03
* Added missing LICENSE and NOTICE files to distribution. No code changes.
## 1.0.0 - 2014-09-02
* Bumped version to 1.0.0. No code changes.
## 0.5.6 - 2014-07-21
* There was a leak in the `MMDB_open()` sub when it was called against a file
which did not contain any MMDB metadata. Reported by Federico
G. Schwindt. GitHub issue #36.
* Fixed an error that occurred when passing AI_V4MAPPED to `getaddrinfo()` on
FreeBSD. Apparently this macro is defined but doesn't work the way we
expected it to on that platform.
* Made sure to call `freeaddrinfo()` when a call to `getaddrinfo()` fails but
still allocated memory.
* Fixed a segfault in the tests that occurred on FreeBSD if we passed a NULL
value to `freeaddrinfo()`.
* Added a missing step to the README.md file for installing from our GitHub
repository. Patch by Yasith Fernando.
* Added instructions for installing via Homebrew. Patch by Yasith Fernando.
## 0.5.5 - 2014-03-11
* The previous tarball failed to compile because it was missing the
src/maxminddb-compat-util.h file. Reported by Günter Grodotzki. GitHub issue
#18.
## 0.5.4 - 2014-03-03
* Added support for compiling in the MinGW environment. Patch by Michael
Eisendle.
* Added const declarations to many spots in the public API. None of these
should require changes to existing code.
* Various documentation improvements.
* Changed the license to the Apache 2.0 license.
## 0.5.3 - 2013-12-23
* The internal value_for_key_as_uint16 method was returning a uint32_t instead
of a uint16_t. Reported by Robert Wells. GitHub issue #11.
* The ip_version member of the MMDB_metadata_s struct was a uint8_t, even
though the docs and spec said it should be a uint16_t. Reported by Robert
Wells. GitHub issue #11.
* The mmdblookup_t.pl test now reports that it needs IPC::Run3 to run (which
it always did, but it didn't tell you this). Patch by Elan Ruusamäe. GitHub
issue #10.
## 0.5.2 - 2013-11-20
* Running `make` from the tarball failed. This is now fixed.
## 0.5.1 - 2013-11-20
* Renamed MMDB_LOOKUP_PATH_DOES_NOT_MATCH_DATA define to
MMDB_LOOKUP_PATH_DOES_NOT_MATCH_DATA_ERROR for consistency. Fixes github
issue #5. Reported by Albert Strasheim.
* Updated README.md to show git clone with --recursive flag so you get the
needed submodules. Fixes github issue #4. Reported by Ryan Peck.
* Fixed some bugs with the MMDB_get_*value functions when navigating a data
structure that included pointers. Fixes github issue #3. Reported by
bagadon.
* Fixed compilation problems on OSX and OpenBSD. We have tested this on OSX
and OpenBSD 5.4. Fixes github issue #6.
* Removed some unneeded memory allocations and added const to many variable
declarations. Based on patches by Timo Teräs. Github issue #8.
* Added a test that uses threads to check for thread safety issue in the
library.
* Distro tarball now includes man pages, tests, and test data

View File

@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -0,0 +1,48 @@
include_HEADERS = include/maxminddb.h
nodist_include_HEADERS = include/maxminddb_config.h
SUBDIRS = \
src
if BINARIES
SUBDIRS += \
bin
endif
if TESTS
SUBDIRS += \
t
endif
EXTRA_DIST = doc Changes.md LICENSE NOTICE README.md projects/VS12 projects/VS12-tests \
CMakeLists.txt t/CMakeLists.txt bin/CMakeLists.txt \
include/maxminddb_config.h.cmake.in
dist-hook:
dev-bin/make-man-pages.pl $(distdir)
find $(distdir) -name '.git*' | xargs rm -fr
safedist: clean dist
tmpdir="$${TMPDIR-/tmp}/safedist-$$$$" \
&& mkdir "$$tmpdir" \
&& tar -xvf $(distdir).tar.gz --directory "$$tmpdir" \
&& $(am__cd) "$$tmpdir/$(distdir)" \
&& ./configure \
&& make -j 4 check
man1_MANS = man/man1/*.1
man3_MANS = man/man3/*.3
man/man1/*.1:
if [ ! -f man/man1/mmdblookup.1 ]; then mkdir -p man/man1 && touch man/man1/mmdblookup.1; fi
man/man3/*.3:
if [ ! -f man/man3/libmaxminddb.3 ]; then mkdir -p man/man3 && touch man/man3/libmaxminddb.3; fi
release:
dev-bin/make-release.sh
.PHONY: man/man1/*.1 man/man3/*.3 release

View File

@ -0,0 +1,13 @@
Copyright 2013-2022 MaxMind, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -0,0 +1,77 @@
# Releasing this library
We release by uploading the tarball to GitHub and uploading Ubuntu PPAs.
## Creating the release tarball
You may want to refer to the section about prerequisites.
* Check whether there are any open issues to fix while you're doing this.
* Update `Changes.md` to include specify the new version, today's date, and
list relevant changes. Commit this.
* Create a new branch off of the latest `main` for the release.
* Run `./dev-bin/release.sh` to update various files in the distro, our
GitHub pages, and creates a GitHub release with the tarball.
* Check the release looks good on both GitHub and launchpad.net.
* Make a pull request against `main` with the changes from the release
script.
## PPA
In order to upload a PPA, you have to create a launchpad.net account and
register a GPG key with that account. You also need to be added to the MaxMind
team. Ask in the dev channel for someone to add you. See
https://help.launchpad.net/Packaging/PPA for more details.
The PPA release script is at `dev-bin/ppa-release.sh`. Running it should
guide you though the release, although it may require some changes to run on
configurations different than Greg's machine.
Check whether any new Ubuntu versions need to be listed in this script
before running it.
You should run it from `main`.
## Homebrew (optional)
Releasing to Homebrew is no longer required as the formulas are easily
updated by the end-user using a built-in feature in the tool. These
directions remain in case there is a more significant change to the
build process that may require a non-trivial update to the formula or
in the case where we want the Homebrew version updated promptly for
some reason.
* Go to https://github.com/Homebrew/homebrew-core/edit/master/Formula/libmaxminddb.rb
* Edit the file to update the url and sha256. You can get the sha256 for the
tarball with the `sha256sum` command line utility.
* Make a commit with the summary `libmaxminddb <VERSION>`
* Submit a PR with the changes you just made.
# Prerequisites for releasing
* Required packages (Ubuntu Artful): vim git-core dput build-essential
autoconf automake libtool git-buildpackage libfile-slurp-perl pandoc
dirmngr libfile-slurp-tiny-perl libdatetime-perl debhelper dh-autoreconf
libipc-run3-perl libtest-output-perl devscripts
* Install [gh](https://github.com/cli/cli/releases).
* GitHub ssh key (e.g. in `~/.ssh/id_rsa`)
* Git config (e.g. `~/.gitconfig`)
* Import your GPG secret key (or create one if you don't have a suitable
one)
* `gpg --import /path/to/key`
* `gpg --edit-key KEYID` and trust it ultimately
* Ensure it shows with `gpg --list-secret-keys`
* You need to be invited to the launchpad.net MaxMind organization on your
launchpad.net account.
* You need your GPG key listed on your launchpad.net account
* You can add it in the web interface. It wants the output of
`gpg --fingerprint`.
* Part of the instructions involve having your key published on the
Ubuntu keyserver:
`gpg --keyserver keyserver.ubuntu.com --send-keys KEYID`
* You'll get an email with an encrypted payload that you need to decrypt
and follow the link to confirm it.
* Ensure `dch` knows your name and email. Refer to its man page for how to
tell it this. One way is to set the `DEBFULLNAME` and `DEBEMAIL`
environment variables. These should match your GPG key's name and email
exactly. This is what gets used in the Debian changelog as well as
defines what GPG key to use.

View File

@ -0,0 +1,136 @@
# About
The libmaxminddb library provides a C library for reading MaxMind DB files,
including the GeoIP2 databases from MaxMind. This is a custom binary format
designed to facilitate fast lookups of IP addresses while allowing for great
flexibility in the type of data associated with an address.
The MaxMind DB format is an open format. The spec is available at
https://maxmind.github.io/MaxMind-DB/. This spec is licensed under the
Creative Commons Attribution-ShareAlike 3.0 Unported License.
See https://dev.maxmind.com/ for more details about MaxMind's GeoIP2 products.
# License
This library is licensed under the Apache License, Version 2.
# Installation
## From a Named Release Tarball
**NOTE:** These instructions are for installation from the _named_ `.tar.gz`
tarballs on the [Releases](https://github.com/maxmind/libmaxminddb/releases)
page (e.g. `libmaxminddb-*.tar.gz`).
This code is known to work with GCC 4.4+ and clang 3.2+. It should also work
on other compilers that supports C99, POSIX.1-2001, and the `-fms-extensions
flag` (or equivalent). The latter is needed to allow an anonymous union in a
structure.
To install this code, run the following commands:
$ ./configure
$ make
$ make check
$ sudo make install
$ sudo ldconfig
You can skip the `make check` step but it's always good to know that tests are
passing on your platform.
The `configure` script takes the standard options to set where files are
installed such as `--prefix`, etc. See `./configure --help` for details.
If after installing, you receive an error that `libmaxminddb.so.0` is missing
you may need to add the `lib` directory in your `prefix` to your library path.
On most Linux distributions when using the default prefix (`/usr/local`), you
can do this by running the following commands:
$ sudo sh -c "echo /usr/local/lib >> /etc/ld.so.conf.d/local.conf"
$ ldconfig
## From a GitHub "Source Code" Archive / Git Repo Clone (Achtung!)
**NOTE:** These instructions are for installation from the GitHub "Source
Code" archives also available on the
[Releases](https://github.com/maxmind/libmaxminddb/releases) page (e.g.
`X.Y.Z.zip` or `X.Y.Z.tar.gz`), as well as installation directly from a clone
of the [Git repo](https://github.com/maxmind/libmaxminddb). Installation from
these sources are possible but will present challenges to users not
comfortable with manual dependency resolution.
You will need `automake`, `autoconf`, and `libtool` installed
in addition to `make` and a compiler.
You can clone this repository and build it by running:
$ git clone --recursive https://github.com/maxmind/libmaxminddb
After cloning, run `./bootstrap` from the `libmaxminddb` directory and then
follow the instructions for installing from a named release tarball as
described above.
## Using CMake
We provide a CMake build script. This is primarily targeted at Windows users,
but it can be used in other circumstances where the Autotools script does not
work.
$ mkdir build && cd build
$ cmake ..
$ cmake --build .
$ ctest -V .
$ cmake --build . --target install
When building with Visual Studio, you may build a multithreaded (MT/MTd)
runtime library, using the `MSVC_STATIC_RUNTIME` setting:
$ cmake -DMSVC_STATIC_RUNTIME=ON -DBUILD_SHARED_LIBS=OFF ..
## On Ubuntu via PPA
MaxMind provides a PPA for recent version of Ubuntu. To add the PPA to your
APT sources, run:
$ sudo add-apt-repository ppa:maxmind/ppa
Then install the packages by running:
$ sudo apt update
$ sudo apt install libmaxminddb0 libmaxminddb-dev mmdb-bin
## On macOS via Homebrew or MacPorts
You can install libmaxminddb on macOS using [Homebrew](https://brew.sh):
$ brew install libmaxminddb
Or with [MacPorts](https://ports.macports.org/port/libmaxminddb):
$ sudo port install libmaxminddb
# Bug Reports
Please report bugs by filing an issue with our GitHub issue tracker at
https://github.com/maxmind/libmaxminddb/issues
# Creating a Release Tarball
Use `make safedist` to check the resulting tarball.
# Copyright and License
Copyright 2013-2022 MaxMind, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -0,0 +1,20 @@
# getopt is required by mmdblookup which is not available by default on Windows
# but available in mingw-64 toolchain by-default.
if(NOT MSVC)
add_executable(mmdblookup
mmdblookup.c
)
# Otherwise 'undefined reference to WinMain' linker error happen due to wmain()
if(MINGW)
target_link_options(mmdblookup PRIVATE "-municode")
endif()
target_link_libraries(mmdblookup maxminddb pthread)
install(
TARGETS mmdblookup
DESTINATION bin
)
endif()

View File

@ -0,0 +1,14 @@
include $(top_srcdir)/common.mk
AM_LDFLAGS = $(top_builddir)/src/libmaxminddb.la
bin_PROGRAMS = mmdblookup
if WINDOWS
AM_LDFLAGS += -municode
endif
if !WINDOWS
AM_CPPFLAGS += -pthread
AM_LDFLAGS += -pthread
endif

View File

@ -0,0 +1,780 @@
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "maxminddb.h"
#include <errno.h>
#include <getopt.h>
#ifndef _WIN32
#include <pthread.h>
#endif
#include <limits.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#ifdef _WIN32
#ifndef UNICODE
#define UNICODE
#endif
#include <malloc.h>
#else
#include <libgen.h>
#include <unistd.h>
#endif
static void usage(char *program, int exit_code, const char *error);
static const char **get_options(int argc,
char **argv,
char **mmdb_file,
char **ip_address,
int *verbose,
int *iterations,
int *lookup_path_length,
int *const thread_count,
char **const ip_file);
static MMDB_s open_or_die(const char *fname);
static void dump_meta(MMDB_s *mmdb);
static bool lookup_from_file(MMDB_s *const mmdb,
char const *const ip_file,
bool const dump);
static int lookup_and_print(MMDB_s *mmdb,
const char *ip_address,
const char **lookup_path,
int lookup_path_length,
bool verbose);
static int benchmark(MMDB_s *mmdb, int iterations);
static MMDB_lookup_result_s lookup_or_die(MMDB_s *mmdb, const char *ipstr);
static void random_ipv4(char *ip);
#ifndef _WIN32
// These aren't with the automatically generated prototypes as we'd lose the
// enclosing macros.
static bool start_threaded_benchmark(MMDB_s *const mmdb,
int const thread_count,
int const iterations);
static long double get_time(void);
static void *thread(void *arg);
#endif
#ifdef _WIN32
int wmain(int argc, wchar_t **wargv) {
// Convert our argument list from UTF-16 to UTF-8.
char **argv = (char **)calloc(argc, sizeof(char *));
if (!argv) {
fprintf(stderr, "calloc(): %s\n", strerror(errno));
exit(1);
}
for (int i = 0; i < argc; i++) {
int utf8_width;
char *utf8_string;
utf8_width =
WideCharToMultiByte(CP_UTF8, 0, wargv[i], -1, NULL, 0, NULL, NULL);
if (utf8_width < 1) {
fprintf(
stderr, "WideCharToMultiByte() failed: %d\n", GetLastError());
exit(1);
}
utf8_string = calloc(utf8_width, sizeof(char));
if (!utf8_string) {
fprintf(stderr, "calloc(): %s\n", strerror(errno));
exit(1);
}
if (WideCharToMultiByte(
CP_UTF8, 0, wargv[i], -1, utf8_string, utf8_width, NULL, NULL) <
1) {
fprintf(
stderr, "WideCharToMultiByte() failed: %d\n", GetLastError());
exit(1);
}
argv[i] = utf8_string;
}
#else // _WIN32
int main(int argc, char **argv) {
#endif // _WIN32
char *mmdb_file = NULL;
char *ip_address = NULL;
int verbose = 0;
int iterations = 0;
int lookup_path_length = 0;
int thread_count = 0;
char *ip_file = NULL;
const char **lookup_path = get_options(argc,
argv,
&mmdb_file,
&ip_address,
&verbose,
&iterations,
&lookup_path_length,
&thread_count,
&ip_file);
MMDB_s mmdb = open_or_die(mmdb_file);
if (verbose) {
dump_meta(&mmdb);
}
// The benchmarking and lookup from file modes are hidden features mainly
// intended for development right now. This means there are several flags
// that exist but are intentionally not mentioned in the usage or man page.
// The lookup from file mode may be useful to expose publicly in the usage,
// but we should have it respect the lookup_path functionality if we do so.
if (ip_file) {
free((void *)lookup_path);
if (!lookup_from_file(&mmdb, ip_file, verbose == 1)) {
MMDB_close(&mmdb);
return 1;
}
MMDB_close(&mmdb);
return 0;
}
if (0 == iterations) {
exit(lookup_and_print(
&mmdb, ip_address, lookup_path, lookup_path_length, verbose));
}
free((void *)lookup_path);
srand((unsigned int)time(NULL));
#ifndef _WIN32
if (thread_count > 0) {
if (!start_threaded_benchmark(&mmdb, thread_count, iterations)) {
MMDB_close(&mmdb);
exit(1);
}
MMDB_close(&mmdb);
exit(0);
}
#endif
exit(benchmark(&mmdb, iterations));
}
static void usage(char *program, int exit_code, const char *error) {
if (NULL != error) {
fprintf(stderr, "\n *ERROR: %s\n", error);
}
char *usage =
"\n"
" %s --file /path/to/file.mmdb --ip 1.2.3.4 [path to lookup]\n"
"\n"
" This application accepts the following options:\n"
"\n"
" --file (-f) The path to the MMDB file. Required.\n"
"\n"
" --ip (-i) The IP address to look up. Required.\n"
"\n"
" --verbose (-v) Turns on verbose output. Specifically, this "
"causes this\n"
" application to output the database metadata.\n"
"\n"
" --version Print the program's version number and exit.\n"
"\n"
" --help (-h -?) Show usage information.\n"
"\n"
" If an IP's data entry resolves to a map or array, you can provide\n"
" a lookup path to only show part of that data.\n"
"\n"
" For example, given a JSON structure like this:\n"
"\n"
" {\n"
" \"names\": {\n"
" \"en\": \"Germany\",\n"
" \"de\": \"Deutschland\"\n"
" },\n"
" \"cities\": [ \"Berlin\", \"Frankfurt\" ]\n"
" }\n"
"\n"
" You could look up just the English name by calling mmdblookup with "
"a lookup path of:\n"
"\n"
" mmdblookup --file ... --ip ... names en\n"
"\n"
" Or you could look up the second city in the list with:\n"
"\n"
" mmdblookup --file ... --ip ... cities 1\n"
"\n"
" Array numbering begins with zero (0).\n"
"\n"
" If you do not provide a path to lookup, all of the information for "
"a given IP\n"
" will be shown.\n"
"\n";
fprintf(stdout, usage, program);
exit(exit_code);
}
static const char **get_options(int argc,
char **argv,
char **mmdb_file,
char **ip_address,
int *verbose,
int *iterations,
int *lookup_path_length,
int *const thread_count,
char **const ip_file) {
static int help = 0;
static int version = 0;
#ifdef _WIN32
char *program = alloca(strlen(argv[0]));
_splitpath(argv[0], NULL, NULL, program, NULL);
_splitpath(argv[0], NULL, NULL, NULL, program + strlen(program));
#else
char *program = basename(argv[0]);
#endif
while (1) {
static struct option options[] = {
{"file", required_argument, 0, 'f'},
{"ip", required_argument, 0, 'i'},
{"verbose", no_argument, 0, 'v'},
{"version", no_argument, 0, 'n'},
{"benchmark", required_argument, 0, 'b'},
#ifndef _WIN32
{"threads", required_argument, 0, 't'},
#endif
{"ip-file", required_argument, 0, 'I'},
{"help", no_argument, 0, 'h'},
{"?", no_argument, 0, 1},
{0, 0, 0, 0}};
int opt_index;
#ifdef _WIN32
char const *const optstring = "f:i:b:I:vnh?";
#else
char const *const optstring = "f:i:b:t:I:vnh?";
#endif
int opt_char = getopt_long(argc, argv, optstring, options, &opt_index);
if (-1 == opt_char) {
break;
}
if ('f' == opt_char) {
*mmdb_file = optarg;
} else if ('i' == opt_char) {
*ip_address = optarg;
} else if ('v' == opt_char) {
*verbose = 1;
} else if ('n' == opt_char) {
version = 1;
} else if ('b' == opt_char) {
long const i = strtol(optarg, NULL, 10);
if (i > INT_MAX) {
usage(program, 1, "iterations exceeds maximum value");
}
*iterations = (int)i;
} else if ('h' == opt_char || '?' == opt_char) {
help = 1;
} else if (opt_char == 't') {
long const i = strtol(optarg, NULL, 10);
if (i > INT_MAX) {
usage(program, 1, "thread count exceeds maximum value");
}
*thread_count = (int)i;
} else if (opt_char == 'I') {
*ip_file = optarg;
}
}
if (help) {
usage(program, 0, NULL);
}
if (version) {
fprintf(stdout, "\n %s version %s\n\n", program, PACKAGE_VERSION);
exit(0);
}
if (NULL == *mmdb_file) {
usage(program, 1, "You must provide a filename with --file");
}
if (*ip_address == NULL && *iterations == 0 && !*ip_file) {
usage(program, 1, "You must provide an IP address with --ip");
}
const char **lookup_path =
calloc((size_t)(argc - optind) + 1, sizeof(const char *));
if (!lookup_path) {
fprintf(stderr, "calloc(): %s\n", strerror(errno));
exit(1);
}
int i;
for (i = 0; i < argc - optind; i++) {
lookup_path[i] = argv[i + optind];
(*lookup_path_length)++;
}
lookup_path[i] = NULL;
return lookup_path;
}
static MMDB_s open_or_die(const char *fname) {
MMDB_s mmdb;
int status = MMDB_open(fname, MMDB_MODE_MMAP, &mmdb);
if (MMDB_SUCCESS != status) {
fprintf(
stderr, "\n Can't open %s - %s\n", fname, MMDB_strerror(status));
if (MMDB_IO_ERROR == status) {
fprintf(stderr, " IO error: %s\n", strerror(errno));
}
fprintf(stderr, "\n");
exit(2);
}
return mmdb;
}
static void dump_meta(MMDB_s *mmdb) {
const char *meta_dump = "\n"
" Database metadata\n"
" Node count: %i\n"
" Record size: %i bits\n"
" IP version: IPv%i\n"
" Binary format: %i.%i\n"
" Build epoch: %llu (%s)\n"
" Type: %s\n"
" Languages: ";
char date[40];
const time_t epoch = (const time_t)mmdb->metadata.build_epoch;
strftime(date, 40, "%F %T UTC", gmtime(&epoch));
fprintf(stdout,
meta_dump,
mmdb->metadata.node_count,
mmdb->metadata.record_size,
mmdb->metadata.ip_version,
mmdb->metadata.binary_format_major_version,
mmdb->metadata.binary_format_minor_version,
mmdb->metadata.build_epoch,
date,
mmdb->metadata.database_type);
for (size_t i = 0; i < mmdb->metadata.languages.count; i++) {
fprintf(stdout, "%s", mmdb->metadata.languages.names[i]);
if (i < mmdb->metadata.languages.count - 1) {
fprintf(stdout, " ");
}
}
fprintf(stdout, "\n");
fprintf(stdout, " Description:\n");
for (size_t i = 0; i < mmdb->metadata.description.count; i++) {
fprintf(stdout,
" %s: %s\n",
mmdb->metadata.description.descriptions[i]->language,
mmdb->metadata.description.descriptions[i]->description);
}
fprintf(stdout, "\n");
}
// The input file should have one IP per line.
//
// We look up each IP.
//
// If dump is true, we dump the data for each IP to stderr. This is useful for
// comparison in that you can dump out the data for the IPs before and after
// making changes. It goes to stderr rather than stdout so that the report does
// not get included in what you will compare (since it will almost always be
// different).
//
// In addition to being useful for comparisons, this function provides a way to
// have a more deterministic set of lookups for benchmarking.
static bool lookup_from_file(MMDB_s *const mmdb,
char const *const ip_file,
bool const dump) {
FILE *const fh = fopen(ip_file, "r");
if (!fh) {
fprintf(stderr, "fopen(): %s: %s\n", ip_file, strerror(errno));
return false;
}
clock_t const clock_start = clock();
char buf[1024] = {0};
// I'd normally use uint64_t, but support for it is optional in C99.
unsigned long long i = 0;
while (1) {
if (fgets(buf, sizeof(buf), fh) == NULL) {
if (!feof(fh)) {
fprintf(stderr, "fgets(): %s\n", strerror(errno));
fclose(fh);
return false;
}
if (fclose(fh) != 0) {
fprintf(stderr, "fclose(): %s\n", strerror(errno));
return false;
}
break;
}
char *ptr = buf;
while (*ptr != '\0') {
if (*ptr == '\n') {
*ptr = '\0';
break;
}
ptr++;
}
if (strlen(buf) == 0) {
continue;
}
i++;
MMDB_lookup_result_s result = lookup_or_die(mmdb, buf);
if (!result.found_entry) {
continue;
}
MMDB_entry_data_list_s *entry_data_list = NULL;
int const status =
MMDB_get_entry_data_list(&result.entry, &entry_data_list);
if (status != MMDB_SUCCESS) {
fprintf(stderr,
"MMDB_get_entry_data_list(): %s\n",
MMDB_strerror(status));
fclose(fh);
MMDB_free_entry_data_list(entry_data_list);
return false;
}
if (!entry_data_list) {
fprintf(stderr, "entry_data_list is NULL\n");
fclose(fh);
return false;
}
if (dump) {
fprintf(stdout, "%s:\n", buf);
int const status2 =
MMDB_dump_entry_data_list(stderr, entry_data_list, 0);
if (status2 != MMDB_SUCCESS) {
fprintf(stderr,
"MMDB_dump_entry_data_list(): %s\n",
MMDB_strerror(status2));
fclose(fh);
MMDB_free_entry_data_list(entry_data_list);
return false;
}
}
MMDB_free_entry_data_list(entry_data_list);
}
clock_t const clock_diff = clock() - clock_start;
double const seconds = (double)clock_diff / CLOCKS_PER_SEC;
fprintf(
stdout,
"Looked up %llu addresses in %.2f seconds. %.2Lf lookups per second.\n",
i,
seconds,
(long double)i / seconds);
return true;
}
static int lookup_and_print(MMDB_s *mmdb,
const char *ip_address,
const char **lookup_path,
int lookup_path_length,
bool verbose) {
MMDB_lookup_result_s result = lookup_or_die(mmdb, ip_address);
MMDB_entry_data_list_s *entry_data_list = NULL;
int exit_code = 0;
if (verbose) {
fprintf(stdout, "\n Record prefix length: %d\n", result.netmask);
}
if (result.found_entry) {
int status;
if (lookup_path_length) {
MMDB_entry_data_s entry_data;
status = MMDB_aget_value(&result.entry, &entry_data, lookup_path);
if (MMDB_SUCCESS == status) {
if (entry_data.offset) {
MMDB_entry_s entry = {.mmdb = mmdb,
.offset = entry_data.offset};
status = MMDB_get_entry_data_list(&entry, &entry_data_list);
} else {
fprintf(stdout,
"\n No data was found at the lookup path you "
"provided\n\n");
}
}
} else {
status = MMDB_get_entry_data_list(&result.entry, &entry_data_list);
}
if (MMDB_SUCCESS != status) {
fprintf(stderr,
"Got an error looking up the entry data - %s\n",
MMDB_strerror(status));
exit_code = 5;
goto end;
}
if (NULL != entry_data_list) {
fprintf(stdout, "\n");
MMDB_dump_entry_data_list(stdout, entry_data_list, 2);
fprintf(stdout, "\n");
}
} else {
fprintf(stderr,
"\n Could not find an entry for this IP address (%s)\n\n",
ip_address);
exit_code = 6;
}
end:
MMDB_free_entry_data_list(entry_data_list);
MMDB_close(mmdb);
free((void *)lookup_path);
return exit_code;
}
static int benchmark(MMDB_s *mmdb, int iterations) {
char ip_address[16];
int exit_code = 0;
clock_t time = clock();
for (int i = 0; i < iterations; i++) {
random_ipv4(ip_address);
MMDB_lookup_result_s result = lookup_or_die(mmdb, ip_address);
MMDB_entry_data_list_s *entry_data_list = NULL;
if (result.found_entry) {
int status =
MMDB_get_entry_data_list(&result.entry, &entry_data_list);
if (MMDB_SUCCESS != status) {
fprintf(stderr,
"Got an error looking up the entry data - %s\n",
MMDB_strerror(status));
exit_code = 5;
MMDB_free_entry_data_list(entry_data_list);
goto end;
}
}
MMDB_free_entry_data_list(entry_data_list);
}
time = clock() - time;
double seconds = ((double)time / CLOCKS_PER_SEC);
fprintf(stdout,
"\n Looked up %i addresses in %.2f seconds. %.2f lookups per "
"second.\n\n",
iterations,
seconds,
iterations / seconds);
end:
MMDB_close(mmdb);
return exit_code;
}
static MMDB_lookup_result_s lookup_or_die(MMDB_s *mmdb, const char *ipstr) {
int gai_error, mmdb_error;
MMDB_lookup_result_s result =
MMDB_lookup_string(mmdb, ipstr, &gai_error, &mmdb_error);
if (0 != gai_error) {
#ifdef _WIN32
char const *const strerr = gai_strerrorA(gai_error);
#else
char const *const strerr = gai_strerror(gai_error);
#endif
fprintf(stderr,
"\n Error from call to getaddrinfo for %s - %s\n\n",
ipstr,
strerr);
exit(3);
}
if (MMDB_SUCCESS != mmdb_error) {
fprintf(stderr,
"\n Got an error from the maxminddb library: %s\n\n",
MMDB_strerror(mmdb_error));
exit(4);
}
return result;
}
static void random_ipv4(char *ip) {
// rand() is perfectly fine for this use case
// coverity[dont_call]
int ip_int = rand();
uint8_t *bytes = (uint8_t *)&ip_int;
snprintf(ip,
16,
"%u.%u.%u.%u",
*bytes,
*(bytes + 1),
*(bytes + 2),
*(bytes + 3));
}
#ifndef _WIN32
struct thread_info {
pthread_t id;
int num;
MMDB_s *mmdb;
int iterations;
};
static bool start_threaded_benchmark(MMDB_s *const mmdb,
int const thread_count,
int const iterations) {
struct thread_info *const tinfo =
calloc((size_t)thread_count, sizeof(struct thread_info));
if (!tinfo) {
fprintf(stderr, "calloc(): %s\n", strerror(errno));
return false;
}
// Using clock() isn't appropriate for multiple threads. It's CPU time, not
// wall time.
long double const start_time = get_time();
if (start_time == -1) {
free(tinfo);
return false;
}
for (int i = 0; i < thread_count; i++) {
tinfo[i].num = i;
tinfo[i].mmdb = mmdb;
tinfo[i].iterations = iterations;
if (pthread_create(&tinfo[i].id, NULL, &thread, &tinfo[i]) != 0) {
fprintf(stderr, "pthread_create() failed\n");
free(tinfo);
return false;
}
}
for (int i = 0; i < thread_count; i++) {
if (pthread_join(tinfo[i].id, NULL) != 0) {
fprintf(stderr, "pthread_join() failed\n");
free(tinfo);
return false;
}
}
free(tinfo);
long double const end_time = get_time();
if (end_time == -1) {
return false;
}
long double const elapsed = end_time - start_time;
unsigned long long const total_ips =
(unsigned long long)(iterations * thread_count);
long double rate = total_ips;
if (elapsed != 0) {
rate = total_ips / elapsed;
}
fprintf(stdout,
"Looked up %llu addresses using %d threads in %.2Lf seconds. %.2Lf "
"lookups per second.\n",
total_ips,
thread_count,
elapsed,
rate);
return true;
}
static long double get_time(void) {
// clock_gettime() is not present on OSX until 10.12.
#ifdef HAVE_CLOCK_GETTIME
struct timespec tp = {
.tv_sec = 0,
.tv_nsec = 0,
};
clockid_t clk_id = CLOCK_REALTIME;
#ifdef _POSIX_MONOTONIC_CLOCK
clk_id = CLOCK_MONOTONIC;
#endif
if (clock_gettime(clk_id, &tp) != 0) {
fprintf(stderr, "clock_gettime(): %s\n", strerror(errno));
return -1;
}
return (long double)tp.tv_sec + ((float)tp.tv_nsec / 1e9);
#else
time_t t = time(NULL);
if (t == (time_t)-1) {
fprintf(stderr, "time(): %s\n", strerror(errno));
return -1;
}
return (long double)t;
#endif
}
static void *thread(void *arg) {
const struct thread_info *const tinfo = arg;
if (!tinfo) {
fprintf(stderr, "thread(): %s\n", strerror(EINVAL));
return NULL;
}
char ip_address[16] = {0};
for (int i = 0; i < tinfo->iterations; i++) {
memset(ip_address, 0, 16);
random_ipv4(ip_address);
MMDB_lookup_result_s result = lookup_or_die(tinfo->mmdb, ip_address);
if (!result.found_entry) {
continue;
}
MMDB_entry_data_list_s *entry_data_list = NULL;
int const status =
MMDB_get_entry_data_list(&result.entry, &entry_data_list);
if (status != MMDB_SUCCESS) {
fprintf(stderr,
"MMDB_get_entry_data_list(): %s\n",
MMDB_strerror(status));
MMDB_free_entry_data_list(entry_data_list);
return NULL;
}
if (!entry_data_list) {
fprintf(stderr, "entry_data_list is NULL\n");
return NULL;
}
MMDB_free_entry_data_list(entry_data_list);
}
return NULL;
}
#endif

View File

@ -0,0 +1,21 @@
#! /bin/sh
# make sure to use the installed libtool
if [ -f ltmain.sh ]; then
rm ltmain.sh
fi
autoreconf -fiv
###################################################
# the steps below may help with outdated toolsets
# disable dependency trackeing for OS X with multiply arch option's
# automake -i --gnu --add-missing
#aclocal \
#&& automake -i --gnu --add-missing \
#&& autoconf
#LIBTOOLIZE=$( which libtoolize glibtoolize | head -1 )
#$LIBTOOLIZE -f

View File

@ -0,0 +1,7 @@
if(MSVC)
set(CMAKE_C_FLAGS_DEBUG_INIT "/D_DEBUG /MTd /Zi /Ob0 /Od /RTC1")
set(CMAKE_C_FLAGS_MINSIZEREL_INIT "/MT /O1 /Ob1 /D NDEBUG")
set(CMAKE_C_FLAGS_RELEASE_INIT "/MT /O2 /Ob2 /D NDEBUG")
set(CMAKE_C_FLAGS_RELWITHDEBINFO_INIT "/MT /Zi /O2 /Ob1 /D NDEBUG")
endif()

View File

@ -0,0 +1,7 @@
if DEBUG
AM_CFLAGS=-O0 -g -Wall -Wextra
else
AM_CFLAGS=-O2 -g
endif
AM_CPPFLAGS = -I$(top_srcdir)/include

View File

@ -0,0 +1,138 @@
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_PREREQ([2.63])
AC_INIT([libmaxminddb], [1.7.1], [support@maxmind.com])
AC_CONFIG_SRCDIR([include/maxminddb.h])
AC_CONFIG_HEADERS([config.h include/maxminddb_config.h])
PKG_PROG_PKG_CONFIG
m4_ifdef([PKG_INSTALLDIR], [PKG_INSTALLDIR], [AC_SUBST([pkgconfigdir], [${libdir}/pkgconfig])])
AC_CONFIG_FILES([src/libmaxminddb.pc])
LT_INIT
AM_INIT_AUTOMAKE(foreign m4_esyscmd([case `automake --version | head -n 1` in
*1.14*) echo subdir-objects;;
*1.11*);;
*) echo serial-tests;;
esac]))
AC_PROG_LIBTOOL
# Checks for programs.
AC_PROG_CC_C99
# Copied from http://stackoverflow.com/a/10682813/9832 and tweaked for C (as
# opposed to C++)
#
# AX_CHECK_CFLAGS(ADDITIONAL-CFLAGS, ACTION-IF-FOUND, ACTION-IF-NOT-FOUND)
#
# checks whether the $(CC) compiler accepts the ADDITIONAL-CFLAGS
# if so, they are added to the CXXFLAGS
AC_DEFUN([AX_CHECK_CFLAGS],
[
AC_MSG_CHECKING([whether compiler accepts "$1"])
cat > conftest.c << EOF
int main(){
return 0;
}
EOF
if $CC $CFLAGS -o conftest.o conftest.c [$1] > /dev/null 2>&1
then
AC_MSG_RESULT([yes])
CFLAGS="${CFLAGS} [$1]"
[$2]
else
AC_MSG_RESULT([no])
[$3]
fi
])dnl AX_CHECK_CFLAGS
AX_CHECK_CFLAGS([-fms-extensions])
# We will add this back for non-debug builds in the common.mk file
CFLAGS=`echo ${CFLAGS} | sed 's/-O2//'`
CXXFLAGS=`echo ${CXXFLAGS} | sed 's/-O2//'`
# autoconf insists on giving us gnu99 if it's available
CC=`echo ${CC} | sed 's/-std=gnu99/-std=c99/'`
AC_C_RESTRICT
AC_CHECK_HEADERS([arpa/inet.h assert.h fcntl.h inttypes.h libgen.h math.h netdb.h netinet/in.h stdarg.h stdbool.h stdint.h stdio.h stdlib.h string.h sys/mman.h sys/socket.h sys/stat.h sys/time.h sys/types.h unistd.h])
# configure generates an invalid config for MinGW because of the type checks
# so we only run them on non MinGW-Systems. For MinGW we also need to link
# against ws2_32.
AC_CANONICAL_HOST
is_windows=false
case $host_os in
mingw*)
LDFLAGS="-lws2_32"
is_windows=true
;;
*)
AC_TYPE_OFF_T
AC_TYPE_SIZE_T
AC_TYPE_SSIZE_T
AC_TYPE_UINT8_T
AC_TYPE_UINT32_T
AC_TYPE_UINT64_T
;;
esac
AM_CONDITIONAL([WINDOWS], [test x$is_windows = xtrue])
# This check is backwards in order to make life easier for people writing
# extensions in other languages that link to this library. If they want to
# simply assume that they are using a newish compiler, they don't need to
# check for this type nor do they need to define anything on the CLI. They'll
# just get code that assumes this type exists.
AC_CHECK_TYPE(
[unsigned __int128],
[AC_DEFINE([MMDB_UINT128_IS_BYTE_ARRAY], [0], [Missing the unsigned __int128 type])],
[AC_CHECK_TYPE(
[unsigned int __attribute__((mode(TI)))],
[AC_DEFINE([MMDB_UINT128_IS_BYTE_ARRAY], [0], [Missing the unsigned __int128 type])
AC_DEFINE([MMDB_UINT128_USING_MODE], [1], [int128 types are available with __attribute__((mode(TI)))])],
[AC_DEFINE([MMDB_UINT128_IS_BYTE_ARRAY], [1], [Missing the unsigned __int128 type])])])
AC_CHECK_TYPES([boolean])
AC_CHECK_FUNCS([clock_gettime open_memstream])
AC_C_BIGENDIAN(
[AC_DEFINE([MMDB_LITTLE_ENDIAN], [0], [System is big-endian])],
[AC_DEFINE([MMDB_LITTLE_ENDIAN], [1], [System is little-endian])])
AC_FUNC_MMAP
AC_SEARCH_LIBS([fabs], [m])
AC_SEARCH_LIBS([fabsf], [m])
AC_SEARCH_LIBS([getaddrinfo], [socket])
AC_ARG_ENABLE(
[debug],
[ --enable-debug Turn on debugging],
[case "${enableval}" in
yes) debug=true ;;
no) debug=false ;;
*) AC_MSG_ERROR([bad value ${enableval} for --enable-debug]) ;;
esac],[debug=false])
AM_CONDITIONAL([DEBUG], [test x$debug = xtrue])
AC_ARG_ENABLE([binaries],
AS_HELP_STRING([--enable-binaries], [Compilation of binaries code]),
[enable_binaries=${enableval}],
[enable_binaries=yes])
AM_CONDITIONAL([BINARIES], [test "${enable_binaries}" = "yes"])
AC_ARG_ENABLE([tests],
AS_HELP_STRING([--enable-tests], [Compilation of tests code]),
[enable_tests=${enableval}],
[enable_tests=yes])
AM_CONDITIONAL([TESTS], [test "${enable_tests}" = "yes"])
AC_CONFIG_FILES([Makefile
src/Makefile
bin/Makefile
t/Makefile])
AC_OUTPUT

View File

@ -0,0 +1,6 @@
if(MSVC)
set(CMAKE_CXX_FLAGS_DEBUG_INIT "/D_DEBUG /MTd /Zi /Ob0 /Od /RTC1")
set(CMAKE_CXX_FLAGS_MINSIZEREL_INIT "/MT /O1 /Ob1 /D NDEBUG")
set(CMAKE_CXX_FLAGS_RELEASE_INIT "/MT /O2 /Ob2 /D NDEBUG")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO_INIT "/MT /Zi /O2 /Ob1 /D NDEBUG")
endif()

View File

@ -0,0 +1,15 @@
#!/bin/sh
format="clang-format -i -style=file"
for dir in bin include src t; do
c_files=`find $dir -maxdepth 1 -name '*.c'`
if [ "$c_files" != "" ]; then
$format $dir/*.c;
fi
h_files=`find $dir -maxdepth 1 -name '*.h'`
if [ "$h_files" != "" ]; then
$format $dir/*.h;
fi
done

View File

@ -0,0 +1,99 @@
#!/usr/bin/env perl
use strict;
use warnings;
use autodie qw( :all );
use FindBin qw( $Bin );
use File::Path qw( mkpath );
use File::Slurp qw( edit_file read_file );
use File::Which qw( which );
sub main {
my $target = shift || "$Bin/..";
my @translators = qw ( lowdown pandoc );
my $translator;
foreach my $p (@translators) {
if ( defined which($p) ) {
$translator = $p;
last;
}
}
unless ( defined $translator ) {
die "\n You must install one of "
. join( ', ', @translators )
. " in order to generate the man pages.\n\n";
}
_make_man( $translator, $target, 'libmaxminddb', 3 );
_make_lib_man_links($target);
_make_man( $translator, $target, 'mmdblookup', 1 );
}
sub _make_man {
my $translator = shift;
my $target = shift;
my $name = shift;
my $section = shift;
my $input = "$Bin/../doc/$name.md";
my $man_dir = "$target/man/man$section";
mkpath($man_dir);
my $output = "$man_dir/$name.$section";
if ( $translator eq 'pandoc' ) {
system(
'pandoc',
'-s',
'-f', 'markdown_mmd+backtick_code_blocks',
'-t', 'man',
'-M', "title:$name",
'-M', "section:$section",
$input,
'-o', $output,
);
_pandoc_postprocess($output);
}
elsif ( $translator eq 'lowdown' ) {
system(
'lowdown',
'-s',
'--out-no-smarty',
'-Tman',
'-M', "title:$name",
'-M', "section:$section",
$input,
'-o', $output,
);
}
}
sub _make_lib_man_links {
my $target = shift;
my $header = read_file("$Bin/../include/maxminddb.h");
for my $proto ( $header =~ /^ *extern.+?(MMDB_\w+)\(/gsm ) {
open my $fh, '>', "$target/man/man3/$proto.3";
print {$fh} ".so man3/libmaxminddb.3\n";
close $fh;
}
}
# AFAICT there's no way to control the indentation depth for code blocks with
# Pandoc.
sub _pandoc_postprocess {
my $file = shift;
edit_file(
sub {
s/^\.IP\n\.nf/.IP "" 4\n.nf/gm;
s/(Automatically generated by Pandoc)(.+)$/$1/m;
},
$file
);
}
main(shift);

View File

@ -0,0 +1,53 @@
#!/bin/bash
set -e
set -x
set -u
DISTS=( groovy focal bionic xenial trusty )
VERSION=$(perl -MFile::Slurp::Tiny=read_file -MDateTime <<EOF
use v5.16;
my \$log = read_file(q{Changes.md});
\$log =~ /^## (\d+\.\d+\.\d+) - (\d{4}-\d{2}-\d{2})/;
die 'Release time is not today!' unless DateTime->now->ymd eq \$2;
say \$1;
EOF
)
RESULTS=/tmp/build-libmaxminddb-results/
SRCDIR="$RESULTS/libmaxminddb"
mkdir -p "$SRCDIR"
# gbp does weird things without a pristine checkout
git clone git@github.com:maxmind/libmaxminddb.git -b ubuntu-ppa $SRCDIR
pushd "$SRCDIR"
git merge "$VERSION"
for dist in "${DISTS[@]}"; do
dch -v "$VERSION-0+maxmind1~$dist" -D "$dist" -u low "New upstream release."
gbp buildpackage -S --git-ignore-new
git clean -xfd
git reset HEAD --hard
done
read -e -p "Release to PPA? (y/n)" SHOULD_RELEASE
if [ "$SHOULD_RELEASE" != "y" ]; then
echo "Aborting"
exit 1
fi
# Upload to launchpad
dput ppa:maxmind/ppa ../*source.changes
# Make the changelog up to date in git
dch -v "$VERSION-0+maxmind1" -D "${DISTS[0]}" -u low "New upstream release."
git add debian/changelog
git commit -m "Update debian/changelog for $VERSION"
git push

View File

@ -0,0 +1,54 @@
#!/usr/bin/env perl
use strict;
use warnings;
use FindBin qw( $Bin );
use Data::UUID;
use File::Slurp qw( read_file write_file );
use Path::Iterator::Rule;
sub main {
my $rule = Path::Iterator::Rule->new;
$rule->file->name(qr/_t.c$/);
my $ug = Data::UUID->new;
my $template = read_file("$Bin/../projects/test.vcxproj.template");
my @names;
for my $file ( $rule->all("$Bin/../t/") ) {
my ($name) = $file =~ /(\w*)_t.c$/;
next unless $name;
next if $name eq 'threads';
push @names, $name;
my $project = $template;
$project =~ s/%TESTNAME%/$name/g;
my $uuid = $ug->to_string( $ug->create );
$project =~ s/%UUID%/$uuid/g;
write_file( "$Bin/../projects/VS12-tests/$name.vcxproj", $project );
}
_modify_yml(@names);
}
sub _modify_yml {
my @names = @_;
my $exe_block = join "\n",
map { " - .\\projects\\VS12\\Debug\\test_${_}.exe" } @names;
my $file = "$Bin/../appveyor.yml";
my $config = read_file($file);
$config =~ s/(#EXES).*?(#ENDEXES)/$1\n$exe_block\n $2/s;
write_file( $file, $config );
}
main();

View File

@ -0,0 +1,118 @@
#!/bin/bash
set -eu -o pipefail
changelog=$(cat Changes.md)
regex='## ([0-9]+\.[0-9]+\.[0-9]+) - ([0-9]{4}-[0-9]{2}-[0-9]{2})
((.|
)*)
'
if [[ ! $changelog =~ $regex ]]; then
echo "Could not find date line in change log!"
exit 1
fi
version="${BASH_REMATCH[1]}"
date="${BASH_REMATCH[2]}"
notes="$(echo "${BASH_REMATCH[3]}" | sed -n -e '/^## [0-9]\+\.[0-9]\+\.[0-9]\+/,$!p')"
dist="libmaxminddb-$version.tar.gz"
if [[ "$date" != $(date +"%Y-%m-%d") ]]; then
echo "$date is not today!"
exit 1
fi
if [ -n "$(git status --porcelain)" ]; then
echo ". is not clean." >&2
exit 1
fi
old_version=$(perl -MFile::Slurp=read_file <<EOF
use v5.16;
my \$conf = read_file(q{configure.ac});
\$conf =~ /AC_INIT.+\[(\d+\.\d+\.\d+)\]/;
say \$1;
EOF
)
perl -MFile::Slurp=edit_file -e \
"edit_file { s/\Q$old_version/$version/g } \$_ for qw( configure.ac include/maxminddb.h CMakeLists.txt )"
if [ -n "$(git status --porcelain)" ]; then
git diff
read -e -p "Commit changes? " should_commit
if [ "$should_commit" != "y" ]; then
echo "Aborting"
exit 1
fi
git add configure.ac include/maxminddb.h CMakeLists.txt
git commit -m "Bumped version to $version"
fi
./bootstrap
./configure
make
make check
make clean
make safedist
if [ ! -d .gh-pages ]; then
echo "Checking out gh-pages in .gh-pages"
git clone -b gh-pages git@github.com:maxmind/libmaxminddb.git .gh-pages
pushd .gh-pages
else
echo "Updating .gh-pages"
pushd .gh-pages
git pull
fi
if [ -n "$(git status --porcelain)" ]; then
echo ".gh-pages is not clean" >&2
exit 1
fi
index=index.md
cat <<EOF > $index
---
layout: default
title: libmaxminddb - a library for working with MaxMind DB files
version: $version
---
EOF
cat ../doc/libmaxminddb.md >> $index
mmdblookup=mmdblookup.md
cat <<EOF > $mmdblookup
---
layout: default
title: mmdblookup - a utility to look up an IP address in a MaxMind DB file
version: $version
---
EOF
cat ../doc/mmdblookup.md >> $mmdblookup
git commit -m "Updated for $version" -a
read -p "Push to origin? (y/n) " should_push
if [ "$should_push" != "y" ]; then
echo "Aborting"
exit 1
fi
git push
popd
git push
gh release create --target "$(git branch --show-current)" -t "$version" -n "$notes" "$version" "$dist"

View File

@ -0,0 +1,53 @@
#!/usr/bin/env perl
# Note to run this you will probably want to build with ./configure
# --disable-shared. You don't want to valgrind the libtool script.
#
# Also make sure you compile the tests first (`make check').
use strict;
use warnings;
use File::Basename qw( basename );
use FindBin qw( $Bin );
use IPC::Run3;
my $top_dir = "$Bin/..";
my $output;
my @tests;
push @tests, glob "$top_dir/t/*_t";
push @tests, glob "$top_dir/t/*-t";
my @mmdblookup = (
"$top_dir/bin/mmdblookup",
'--file', "$top_dir/t/maxmind-db/test-data/MaxMind-DB-test-decoder.mmdb",
'--ip',
);
# We want IPv4 and IPv6 addresses - one of each that exists in the db and one
# that doesn't
my @ips = ( '1.1.1.1', '10.0.0.0', 'abcd::', '0900::' );
my @cmds = (
( map { [ @mmdblookup, $_ ] } @ips ),
( map { [$_] } @tests ),
);
for my $cmd (@cmds) {
my $output;
run3(
[ qw( valgrind -v --leak-check=full --show-leak-kinds=all -- ), @{$cmd} ],
\undef,
\$output,
\$output,
);
$output =~ s/^(?!=).*\n//mg;
my $marker = '-' x 60;
print $marker, "\n", ( join q{ }, basename( shift @{$cmd} ), @{$cmd} ),
"\n", $marker, "\n", $output,
"\n\n";
}

View File

@ -0,0 +1,897 @@
# NAME
libmaxminddb - a library for working with MaxMind DB files
# SYNOPSIS
```c
#include <maxminddb.h>
int MMDB_open(
const char *const filename,
uint32_t flags,
MMDB_s *const mmdb);
void MMDB_close(MMDB_s *const mmdb);
MMDB_lookup_result_s MMDB_lookup_string(
MMDB_s *const mmdb,
const char *const ipstr,
int *const gai_error,
int *const mmdb_error);
MMDB_lookup_result_s MMDB_lookup_sockaddr(
MMDB_s *const mmdb,
const struct sockaddr *const
sockaddr,
int *const mmdb_error);
int MMDB_get_value(
MMDB_entry_s *const start,
MMDB_entry_data_s *const entry_data,
...);
int MMDB_vget_value(
MMDB_entry_s *const start,
MMDB_entry_data_s *const entry_data,
va_list va_path);
int MMDB_aget_value(
MMDB_entry_s *const start,
MMDB_entry_data_s *const entry_data,
const char *const *const path);
int MMDB_get_entry_data_list(
MMDB_entry_s *start,
MMDB_entry_data_list_s **const entry_data_list);
void MMDB_free_entry_data_list(
MMDB_entry_data_list_s *const entry_data_list);
int MMDB_get_metadata_as_entry_data_list(
MMDB_s *const mmdb,
MMDB_entry_data_list_s **const entry_data_list);
int MMDB_dump_entry_data_list(
FILE *const stream,
MMDB_entry_data_list_s *const entry_data_list,
int indent);
int MMDB_read_node(
MMDB_s *const mmdb,
uint32_t node_number,
MMDB_search_node_s *const node);
const char *MMDB_lib_version(void);
const char *MMDB_strerror(int error_code);
typedef struct MMDB_lookup_result_s {
bool found_entry;
MMDB_entry_s entry;
uint16_t netmask;
} MMDB_lookup_result_s;
typedef struct MMDB_entry_data_s {
bool has_data;
union {
uint32_t pointer;
const char *utf8_string;
double double_value;
const uint8_t *bytes;
uint16_t uint16;
uint32_t uint32;
int32_t int32;
uint64_t uint64;
{mmdb_uint128_t or uint8_t[16]} uint128;
bool boolean;
float float_value;
};
...
uint32_t data_size;
uint32_t type;
} MMDB_entry_data_s;
typedef struct MMDB_entry_data_list_s {
MMDB_entry_data_s entry_data;
struct MMDB_entry_data_list_s *next;
} MMDB_entry_data_list_s;
```
# DESCRIPTION
The libmaxminddb library provides functions for working MaxMind DB files. See
https://maxmind.github.io/MaxMind-DB/ for the MaxMind DB format
specification. The database and results are all represented by different
data structures. Databases are opened by calling `MMDB_open()`. You can
look up IP addresses as a string with `MMDB_lookup_string()` or as a
pointer to a `sockaddr` structure with `MMDB_lookup_sockaddr()`.
If the lookup finds the IP address in the database, it returns a
`MMDB_lookup_result_s` structure. If that structure indicates that the database
has data for the IP, there are a number of functions that can be used to fetch
that data. These include `MMDB_get_value()` and `MMDB_get_entry_data_list()`.
See the function documentation below for more details.
When you are done with the database handle you should call `MMDB_close()`.
All publicly visible functions, structures, and macros begin with "MMDB_".
# DATA STRUCTURES
All data structures exported by this library's `maxminddb.h` header are
typedef'd in the form `typedef struct foo_s { ... } foo_s` so you can refer to
them without the `struct` prefix.
This library provides the following data structures:
## `MMDB_s`
This is the handle for a MaxMind DB file. We only document some of this
structure's fields intended for public use. All other fields are subject to
change and are intended only for internal use.
```c
typedef struct MMDB_s {
uint32_t flags;
const char *filename;
...
MMDB_metadata_s metadata;
} MMDB_s;
```
* `uint32_t flags` - the flags this database was opened with. See the
`MMDB_open()` documentation for more details.
* `const char *filename` - the name of the file which was opened, as passed to
`MMDB_open()`.
* `MMDB_metadata_s metadata` - the metadata for the database.
## `MMDB_metadata_s` and `MMDB_description_s`
This structure can be retrieved from the `MMDB_s` structure. It contains the
metadata read from the database file. Note that you may find it more convenient
to access this metadata by calling `MMDB_get_metadata_as_entry_data_list()`
instead.
```c
typedef struct MMDB_metadata_s {
uint32_t node_count;
uint16_t record_size;
uint16_t ip_version;
const char *database_type;
struct {
size_t count;
const char **names;
} languages;
uint16_t binary_format_major_version;
uint16_t binary_format_minor_version;
uint64_t build_epoch;
struct {
size_t count;
MMDB_description_s **descriptions;
} description;
} MMDB_metadata_s;
typedef struct MMDB_description_s {
const char *language;
const char *description;
} MMDB_description_s;
```
These structures should be mostly self-explanatory.
The `ip_version` member should always be `4` or `6`. The
`binary_format_major_version` should always be `2`.
There is no requirement that the database metadata include languages or
descriptions, so the `count` for these parts of the metadata can be zero. All
of the other `MMDB_metadata_s` fields should be populated.
## `MMDB_lookup_result_s`
This structure is returned as the result of looking up an IP address.
```c
typedef struct MMDB_lookup_result_s {
bool found_entry;
MMDB_entry_s entry;
uint16_t netmask;
} MMDB_lookup_result_s;
```
If the `found_entry` member is false then the other members of this structure
do not contain meaningful values. Always check that `found_entry` is true
first.
The `entry` member is used to look up the data associated with the IP address.
The `netmask` member tells you what subnet the IP address belongs to in this
database. For example, if you look up the address `1.1.1.1` in an IPv4 database
and the returned `netmask` is 16, then the address is part of the `1.1.0.0/16`
subnet.
If the database is an IPv6 database, the returned netmask is always an IPv6
prefix length (from 0-128), even if that database *also* contains IPv4
networks. If you look up an IPv4 address and would like to turn the netmask
into an IPv4 netmask value, you can simply subtract `96` from the value.
## `MMDB_result_s`
You don't really need to dig around in this structure. You'll get this from a
`MMDB_lookup_result_s` structure and pass it to various functions.
## `MMDB_entry_data_s`
This structure is used to return a single data section entry for an IP. These
entries can in turn point to other entries, as is the case for things like maps
and arrays. Some members of this structure are not documented as they are only
for internal use.
```c
typedef struct MMDB_entry_data_s {
bool has_data;
union {
uint32_t pointer;
const char *utf8_string;
double double_value;
const uint8_t *bytes;
uint16_t uint16;
uint32_t uint32;
int32_t int32;
uint64_t uint64;
{mmdb_uint128_t or uint8_t[16]} uint128;
bool boolean;
float float_value;
};
...
uint32_t data_size;
uint32_t type;
} MMDB_entry_data_s;
```
The `has_data` member is true if data was found for a given lookup. See
`MMDB_get_value()` for more details. If this member is false then none of the
other values in the structure are meaningful.
The union at the beginning of the structure defines the actual data. To
determine which union member is populated you should look at the `type` member.
The `pointer` member of the union should never be populated in any data
returned by the API. Pointers should always be resolved internally.
The `data_size` member is only relevant for `utf8_string` and `bytes` data.
`utf8_string` is not null terminated and `data_size` _must_ be used to
determine its length.
The `type` member can be compared to one of the `MMDB_DATA_TYPE_*` macros.
### 128-bit Integers
The handling of `uint128` data depends on how your platform supports 128-bit
integers, if it does so at all. With GCC 4.4 and 4.5 we can write `unsigned
int __attribute__ ((__mode__ (TI)))`. With newer versions of GCC (4.6+) and
clang (3.2+) we can simply write "unsigned __int128".
In order to work around these differences, this library defines an
`mmdb_uint128_t` type. This type is defined in the `maxminddb.h` header so you
can use it in your own code.
With older compilers, we can't use an integer so we instead use a 16 byte
array of `uint8_t` values. This is the raw data from the database.
This library provides a public macro `MMDB_UINT128_IS_BYTE_ARRAY` macro. If
this is true (1), then `uint128` values are returned as a byte array, if it is
false then they are returned as a `mmdb_uint128_t` integer.
### Data Type Macros
This library provides a macro for every data type defined by the MaxMind DB
spec.
* `MMDB_DATA_TYPE_UTF8_STRING`
* `MMDB_DATA_TYPE_DOUBLE`
* `MMDB_DATA_TYPE_BYTES`
* `MMDB_DATA_TYPE_UINT16`
* `MMDB_DATA_TYPE_UINT32`
* `MMDB_DATA_TYPE_MAP`
* `MMDB_DATA_TYPE_INT32`
* `MMDB_DATA_TYPE_UINT64`
* `MMDB_DATA_TYPE_UINT128`
* `MMDB_DATA_TYPE_ARRAY`
* `MMDB_DATA_TYPE_BOOLEAN`
* `MMDB_DATA_TYPE_FLOAT`
There are also a few types that are for internal use only:
* `MMDB_DATA_TYPE_EXTENDED`
* `MMDB_DATA_TYPE_POINTER`
* `MMDB_DATA_TYPE_CONTAINER`
* `MMDB_DATA_TYPE_END_MARKER`
If you see one of these in returned data then something has gone very wrong.
The database is damaged or was generated incorrectly or there is a bug in the
libmaxminddb code.
### Pointer Values and `MMDB_close()`
The `utf8_string`, `bytes`, and (maybe) the `uint128` members of this structure
are all pointers directly into the database's data section. This can either be
a `calloc`'d or `mmap`'d block of memory. In either case, these pointers will
become invalid after `MMDB_close()` is called.
If you need to refer to this data after that time you should copy the data
with an appropriate function (`strdup`, `memcpy`, etc.).
## `MMDB_entry_data_list_s`
This structure encapsulates a linked list of `MMDB_entry_data_s` structures.
```c
typedef struct MMDB_entry_data_list_s {
MMDB_entry_data_s entry_data;
struct MMDB_entry_data_list_s *next;
} MMDB_entry_data_list_s;
```
This structure lets you look at entire map or array data entry by iterating
over the linked list.
## `MMDB_search_node_s`
This structure encapsulates the two records in a search node. This is really
only useful if you want to write code that iterates over the entire search
tree as opposed to looking up a specific IP address.
```c
typedef struct MMDB_search_node_s {
uint64_t left_record;
uint64_t right_record;
uint8_t left_record_type;
uint8_t right_record_type;
MMDB_entry_s left_record_entry;
MMDB_entry_s right_record_entry;
} MMDB_search_node_s;
```
The two record types will take one of the following values:
* `MMDB_RECORD_TYPE_SEARCH_NODE` - The record points to the next search node.
* `MMDB_RECORD_TYPE_EMPTY` - The record is a placeholder that indicates there
is no data for the IP address. The search should end here.
* `MMDB_RECORD_TYPE_DATA` - The record is for data in the data section of the
database. Use the entry for the record when looking up the data for the
record.
* `MMDB_RECORD_TYPE_INVALID` - The record is invalid. Either an invalid node
was looked up or the database is corrupt.
The `MMDB_entry_s` for the record is only valid if the type is
`MMDB_RECORD_TYPE_DATA`. Attempts to use an entry for other record types will
result in an error or invalid data.
# STATUS CODES
This library returns (or populates) status codes for many functions. These
status codes are:
* `MMDB_SUCCESS` - everything worked
* `MMDB_FILE_OPEN_ERROR` - there was an error trying to open the MaxMind DB
file.
* `MMDB_IO_ERROR` - an IO operation failed. Check `errno` for more details.
* `MMDB_CORRUPT_SEARCH_TREE_ERROR` - looking up an IP address in the search
tree gave us an impossible result. The database is damaged or was generated
incorrectly or there is a bug in the libmaxminddb code.
* `MMDB_INVALID_METADATA_ERROR` - something in the database is wrong. This
includes missing metadata keys as well as impossible values (like an
`ip_version` of 7).
* `MMDB_UNKNOWN_DATABASE_FORMAT_ERROR` - The database metadata indicates that
it's major version is not 2. This library can only handle major version 2.
* `MMDB_OUT_OF_MEMORY_ERROR` - a memory allocation call (`malloc`, etc.)
failed.
* `MMDB_INVALID_DATA_ERROR` - an entry in the data section contains invalid
data. For example, a `uint16` field is claiming to be more than 2 bytes long.
The database is probably damaged or was generated incorrectly.
* `MMDB_INVALID_LOOKUP_PATH_ERROR` - The lookup path passed to
`MMDB_get_value`, `MMDB_vget_value`, or `MMDB_aget_value` contains an array
offset that is larger than LONG_MAX or smaller than LONG_MIN.
* `MMDB_LOOKUP_PATH_DOES_NOT_MATCH_DATA_ERROR` - The lookup path passed to
`MMDB_get_value`,`MMDB_vget_value`, or `MMDB_aget_value` does not match the
data structure for the entry. There are number of reasons this can
happen. The lookup path could include a key not in a map. The lookup path
could include an array index larger than an array or smaller than the
minimum offset from the end of an array. It can also happen when the path
expects to find a map or array where none exist.
All status codes should be treated as `int` values.
## `MMDB_strerror()`
```c
const char *MMDB_strerror(int error_code)
```
This function takes a status code and returns an English string explaining the
status.
# FUNCTIONS
This library provides the following exported functions:
## `MMDB_open()`
```c
int MMDB_open(
const char *const filename,
uint32_t flags,
MMDB_s *const mmdb);
```
This function opens a handle to a MaxMind DB file. Its return value is a
status code as defined above. Always check this call's return value.
```c
MMDB_s mmdb;
int status =
MMDB_open("/path/to/file.mmdb", MMDB_MODE_MMAP, &mmdb);
if (MMDB_SUCCESS != status) { ... }
...
MMDB_close(&mmdb);
```
`filename` must be encoded as UTF-8 on Windows.
The `MMDB_s` structure you pass in can be on the stack or allocated from the
heap. However, if the open is successful it will contain heap-allocated data,
so you need to close it with `MMDB_close()`. If the status returned is not
`MMDB_SUCCESS` then this library makes sure that all allocated memory is freed
before returning.
The flags currently provided are:
* `MMDB_MODE_MMAP` - open the database with `mmap()`.
Passing in other values for `flags` may yield unpredictable results. In the
future we may add additional flags that you can bitwise-or together with the
mode, as well as additional modes.
You can also pass `0` as the `flags` value in which case the database will be
opened with the default flags. However, these defaults may change in future
releases. The current default is `MMDB_MODE_MMAP`.
## `MMDB_close()`
```c
void MMDB_close(MMDB_s *const mmdb);
```
This frees any allocated or mmap'd memory that is held from the `MMDB_s`
structure. *It does not free the memory allocated for the structure itself!*
If you allocated the structure from the heap then you are responsible for
freeing it.
## `MMDB_lookup_string()`
```c
MMDB_lookup_result_s MMDB_lookup_string(
MMDB_s *const mmdb,
const char *const ipstr,
int *const gai_error,
int *const mmdb_error);
```
This function looks up an IP address that is passed in as a null-terminated
string. Internally it calls `getaddrinfo()` to resolve the address into a
binary form. It then calls `MMDB_lookup_sockaddr()` to look the address up in
the database. If you have already resolved an address you can call
`MMDB_lookup_sockaddr()` directly, rather than resolving the address twice.
```c
int gai_error, mmdb_error;
MMDB_lookup_result_s result =
MMDB_lookup_string(&mmdb, "1.2.3.4", &gai_error, &mmdb_error);
if (0 != gai_error) { ... }
if (MMDB_SUCCESS != mmdb_error) { ... }
if (result.found_entry) { ... }
```
This function always returns an `MMDB_lookup_result_s` structure, but you
should also check the `gai_error` and `mmdb_error` parameters. If either of
these indicates an error then the returned structure is meaningless.
If no error occurred you still need to make sure that the `found_entry` member
in the returned result is true. If it's not, this means that the IP address
does not have an entry in the database.
This function will work with IPv4 addresses even when the database contains
data for both IPv4 and IPv6 addresses. The IPv4 address will be looked up as
'::xxx.xxx.xxx.xxx' rather than being remapped to the `::ffff:xxx.xxx.xxx.xxx`
block allocated for IPv4-mapped IPv6 addresses.
If you pass an IPv6 address to a database with only IPv4 data then the
`found_entry` member will be false, but the `mmdb_error` status will still be
`MMDB_SUCCESS`.
## `MMDB_lookup_sockaddr()`
```c
MMDB_lookup_result_s MMDB_lookup_sockaddr(
MMDB_s *const mmdb,
const struct sockaddr *const sockaddr,
int *const mmdb_error);
```
This function looks up an IP address that has already been resolved by
`getaddrinfo()`.
Other than not calling `getaddrinfo()` itself, this function is identical to
the `MMDB_lookup_string()` function.
```c
int mmdb_error;
MMDB_lookup_result_s result =
MMDB_lookup_sockaddr(&mmdb, address->ai_addr, &mmdb_error);
if (MMDB_SUCCESS != mmdb_error) { ... }
if (result.found_entry) { ... }
```
## Data Lookup Functions
There are three functions for looking up data associated with an IP address.
```c
int MMDB_get_value(
MMDB_entry_s *const start,
MMDB_entry_data_s *const entry_data,
...);
int MMDB_vget_value(
MMDB_entry_s *const start,
MMDB_entry_data_s *const entry_data,
va_list va_path);
int MMDB_aget_value(
MMDB_entry_s *const start,
MMDB_entry_data_s *const entry_data,
const char *const *const path);
```
The three functions allow three slightly different calling styles, but they
all do the same thing.
The first parameter is an `MMDB_entry_s` value. In most cases this will come
from the `MMDB_lookup_result_s` value returned by `MMDB_lookup_string()` or
`MMDB_lookup_sockaddr()`.
The second parameter is a reference to an `MMDB_entry_data_s` structure. This
will be populated with the data that is being looked up, if any is found. If
nothing is found, then the `has_data` member of this structure will be false.
If `has_data` is true then you can look at the `data_type` member.
The final parameter is a lookup path. The path consists of a set of strings
representing either map keys (e.g, "city") or array indexes (e.g., "0", "1",
"-1") to use in the lookup.
Negative array indexes will be treated as an offset from the end of the array.
For instance, "-1" refers to the last element of the array.
The lookup path allows you to navigate a complex data structure. For example,
given this data:
```js
{
"names": {
"en": "Germany",
"de": "Deutschland"
},
"cities": [ "Berlin", "Frankfurt" ]
}
```
We could look up the English name with this code:
```c
MMDB_lookup_result_s result =
MMDB_lookup_sockaddr(&mmdb, address->ai_addr, &mmdb_error);
MMDB_entry_data_s entry_data;
int status =
MMDB_get_value(&result.entry, &entry_data,
"names", "en", NULL);
if (MMDB_SUCCESS != status) { ... }
if (entry_data.has_data) { ... }
```
If we wanted to find the first city the lookup path would be `"cities",
"0"`. If you don't provide a lookup path at all, you'll get the entry which
corresponds to the top level map. The lookup path must always end with `NULL`,
regardless of which function you call.
The `MMDB_get_value` function takes a variable number of arguments. All of the
arguments after the `MMDB_entry_data_s *` structure pointer are the lookup
path. The last argument must be `NULL`.
The `MMDB_vget_value` function accepts a `va_list` as the lookup path. The
last element retrieved by `va_arg()` must be `NULL`.
Finally, the `MMDB_aget_value` accepts an array of strings as the lookup
path. The last member of this array must be `NULL`.
If you want to get all of the entry data at once you can call
`MMDB_get_entry_data_list()` instead.
For each of the three functions, the return value is a status code as
defined above.
## `MMDB_get_entry_data_list()`
```c
int MMDB_get_entry_data_list(
MMDB_entry_s *start,
MMDB_entry_data_list_s **const entry_data_list);
```
This function allows you to get all of the data for a complex data structure
at once, rather than looking up each piece using repeated calls to
`MMDB_get_value()`.
```c
MMDB_lookup_result_s result =
MMDB_lookup_sockaddr(&mmdb, address->ai_addr, &mmdb_error);
MMDB_entry_data_list_s *entry_data_list, *first;
int status =
MMDB_get_entry_data_list(&result.entry, &entry_data_list);
if (MMDB_SUCCESS != status) { ... }
// save this so we can free this data later
first = entry_data_list;
while (1) {
MMDB_entry_data_list_s *next = entry_data_list = entry_data_list->next;
if (NULL == next) {
break;
}
switch (next->entry_data.type) {
case MMDB_DATA_TYPE_MAP: { ... }
case MMDB_DATA_TYPE_UTF8_STRING: { ... }
...
}
}
MMDB_free_entry_data_list(first);
```
It's up to you to interpret the `entry_data_list` data structure. The list is
linked in a depth-first traversal. Let's use this structure as an example:
```js
{
"names": {
"en": "Germany",
"de": "Deutschland"
},
"cities": [ "Berlin", "Frankfurt" ]
}
```
The list will consist of the following items:
1. MAP - top level map
2. UTF8_STRING - "names" key
3. MAP - map for "names" key
4. UTF8_STRING - "en" key
5. UTF8_STRING - value for "en" key
6. UTF8_STRING - "de" key
7. UTF8_STRING - value for "de" key
8. UTF8_STRING - "cities" key
9. ARRAY - value for "cities" key
10. UTF8_STRING - array[0]
11. UTF8_STRING - array[1]
The return value of the function is a status code as defined above.
## `MMDB_free_entry_data_list()`
```c
void MMDB_free_entry_data_list(
MMDB_entry_data_list_s *const entry_data_list);
```
The `MMDB_get_entry_data_list()` and `MMDB_get_metadata_as_entry_data_list()`
functions will allocate the linked list structure from the heap. Call this
function to free the `MMDB_entry_data_list_s` structure.
## `MMDB_get_metadata_as_entry_data_list()`
```c
int MMDB_get_metadata_as_entry_data_list(
MMDB_s *const mmdb,
MMDB_entry_data_list_s **const entry_data_list);
```
This function allows you to retrieve the database metadata as a linked list of
`MMDB_entry_data_list_s` structures. This can be a more convenient way to deal
with the metadata than using the metadata structure directly.
```c
MMDB_entry_data_list_s *entry_data_list, *first;
int status =
MMDB_get_metadata_as_entry_data_list(&mmdb, &entry_data_list);
if (MMDB_SUCCESS != status) { ... }
first = entry_data_list;
... // do something with the data
MMDB_free_entry_data_list(first);
```
The return value of the function is a status code as defined above.
## `MMDB_dump_entry_data_list()`
```c
int MMDB_dump_entry_data_list(
FILE *const stream,
MMDB_entry_data_list_s *const entry_data_list,
int indent);
```
This function takes a linked list of `MMDB_entry_data_list_s` structures and
stringifies it to the given `stream`. The `indent` parameter is the starting
indent level for the generated output. It is incremented for nested data
structures (maps, array, etc.).
The `stream` must be a file handle (`stdout`, etc). If your platform provides
something like the GNU `open_memstream()` you can use that to capture the
output as a string.
The output is formatted in a JSON-ish fashion, but values are marked with their
data type (except for maps and arrays which are shown with "{}" and "[]"
respectively).
The specific output format may change in future releases, so you should not
rely on the specific formatting produced by this function. It is intended to be
used to show data to users in a readable way and for debugging purposes.
The return value of the function is a status code as defined above.
## `MMDB_read_node()`
```c
int MMDB_read_node(
MMDB_s *const mmdb,
uint32_t node_number,
MMDB_search_node_s *const node);
```
This reads a specific node in the search tree. The third argument is a
reference to an `MMDB_search_node_s` structure that will be populated by this
function.
The return value is a status code. If you pass a `node_number` that is greater
than the number of nodes in the database, this function will return
`MMDB_INVALID_NODE_NUMBER_ERROR`, otherwise it will return `MMDB_SUCCESS`.
The first node in the search tree is always node 0. If you wanted to iterate
over the whole search tree, you would start by reading node 0 and then
following the the records that make up this node, based on the type of each
record. If the type is `MMDB_RECORD_TYPE_SEARCH_NODE` then the record contains
an integer for the next node to look up.
## `MMDB_lib_version()`
```c
const char *MMDB_lib_version(void)
```
This function returns the library version as a string, something like "2.0.0".
# EXAMPLE
```c
#include <errno.h>
#include <maxminddb.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char **argv)
{
char *filename = argv[1];
char *ip_address = argv[2];
MMDB_s mmdb;
int status = MMDB_open(filename, MMDB_MODE_MMAP, &mmdb);
if (MMDB_SUCCESS != status) {
fprintf(stderr, "\n Can't open %s - %s\n",
filename, MMDB_strerror(status));
if (MMDB_IO_ERROR == status) {
fprintf(stderr, " IO error: %s\n", strerror(errno));
}
exit(1);
}
int gai_error, mmdb_error;
MMDB_lookup_result_s result =
MMDB_lookup_string(&mmdb, ip_address, &gai_error, &mmdb_error);
if (0 != gai_error) {
fprintf(stderr,
"\n Error from getaddrinfo for %s - %s\n\n",
ip_address, gai_strerror(gai_error));
exit(2);
}
if (MMDB_SUCCESS != mmdb_error) {
fprintf(stderr,
"\n Got an error from libmaxminddb: %s\n\n",
MMDB_strerror(mmdb_error));
exit(3);
}
MMDB_entry_data_list_s *entry_data_list = NULL;
int exit_code = 0;
if (result.found_entry) {
int status = MMDB_get_entry_data_list(&result.entry,
&entry_data_list);
if (MMDB_SUCCESS != status) {
fprintf(
stderr,
"Got an error looking up the entry data - %s\n",
MMDB_strerror(status));
exit_code = 4;
goto end;
}
if (NULL != entry_data_list) {
MMDB_dump_entry_data_list(stdout, entry_data_list, 2);
}
} else {
fprintf(
stderr,
"\n No entry for this IP address (%s) was found\n\n",
ip_address);
exit_code = 5;
}
end:
MMDB_free_entry_data_list(entry_data_list);
MMDB_close(&mmdb);
exit(exit_code);
}
```
# THREAD SAFETY
This library is thread safe when compiled and linked with a thread-safe
`malloc` and `free` implementation.
# INSTALLATION AND SOURCE
You can download the latest release of libmaxminddb
[from GitHub](https://github.com/maxmind/libmaxminddb/releases).
[Our GitHub repo](https://github.com/maxmind/libmaxminddb) is publicly
available. Please fork it!
# BUG REPORTS AND PULL REQUESTS
Please report all issues to
[our GitHub issue tracker](https://github.com/maxmind/libmaxminddb/issues). We
welcome bug reports and pull requests. Please note that pull requests are
greatly preferred over patches.
# AUTHORS
This library was written by Boris Zentner (bzentner@maxmind.com) and Dave
Rolsky (drolsky@maxmind.com).
# COPYRIGHT AND LICENSE
Copyright 2013-2022 MaxMind, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
# SEE ALSO
mmdblookup(1)

View File

@ -0,0 +1,103 @@
# NAME
mmdblookup - a utility to look up an IP address in a MaxMind DB file
# SYNOPSIS
mmdblookup --file [FILE PATH] --ip [IP ADDRESS] [DATA PATH]
# DESCRIPTION
`mmdblookup` looks up an IP address in the specified MaxMind DB file. The
record for the IP address is displayed in a JSON-like structure with type
annotations.
If an IP's data entry resolves to a map or array, you can provide a lookup
path to only show part of that data.
For example, given a JSON structure like this:
```js
{
"names": {
"en": "Germany",
"de": "Deutschland"
},
"cities": [ "Berlin", "Frankfurt" ]
}
```
You could look up just the English name by calling mmdblookup with a lookup
path of:
```bash
mmdblookup --file ... --ip ... names en
```
Or you could look up the second city in the list with:
```bash
mmdblookup --file ... --ip ... cities 1
```
Array numbering begins with zero (0).
If you do not provide a path to lookup, all of the information for a given IP
will be shown.
# OPTIONS
This application accepts the following options:
-f, --file
: The path to the MMDB file. Required.
-i, --ip
: The IP address to look up. Required.
-v, --verbose
: Turns on verbose output. Specifically, this causes this
application to output the database metadata.
--version
: Print the program's version number and exit.
-h, -?, --help
: Show usage information.
# BUG REPORTS AND PULL REQUESTS
Please report all issues to
[our GitHub issue tracker](https://github.com/maxmind/libmaxminddb/issues). We
welcome bug reports and pull requests. Please note that pull requests are
greatly preferred over patches.
# AUTHORS
This utility was written by Boris Zentner (bzentner@maxmind.com) and Dave
Rolsky (drolsky@maxmind.com).
# COPYRIGHT AND LICENSE
Copyright 2013-2022 MaxMind, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
# SEE ALSO
libmaxminddb(3)

View File

@ -0,0 +1,258 @@
#ifdef __cplusplus
extern "C" {
#endif
#ifndef MAXMINDDB_H
#define MAXMINDDB_H
/* Request POSIX.1-2008. However, we want to remain compatible with
* POSIX.1-2001 (since we have been historically and see no reason to drop
* compatibility). By requesting POSIX.1-2008, we can conditionally use
* features provided by that standard if the implementation provides it. We can
* check for what the implementation provides by checking the _POSIX_VERSION
* macro after including unistd.h. If a feature is in POSIX.1-2008 but not
* POSIX.1-2001, check that macro before using the feature (or check for the
* feature directly if possible). */
#ifndef _POSIX_C_SOURCE
#define _POSIX_C_SOURCE 200809L
#endif
#include "maxminddb_config.h"
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <sys/types.h>
#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
/* libmaxminddb package version from configure */
#define PACKAGE_VERSION "1.7.1"
typedef ADDRESS_FAMILY sa_family_t;
#if defined(_MSC_VER)
/* MSVC doesn't define signed size_t, copy it from configure */
#define ssize_t SSIZE_T
/* MSVC doesn't support restricted pointers */
#define restrict
#endif
#else
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>
#endif
#define MMDB_DATA_TYPE_EXTENDED (0)
#define MMDB_DATA_TYPE_POINTER (1)
#define MMDB_DATA_TYPE_UTF8_STRING (2)
#define MMDB_DATA_TYPE_DOUBLE (3)
#define MMDB_DATA_TYPE_BYTES (4)
#define MMDB_DATA_TYPE_UINT16 (5)
#define MMDB_DATA_TYPE_UINT32 (6)
#define MMDB_DATA_TYPE_MAP (7)
#define MMDB_DATA_TYPE_INT32 (8)
#define MMDB_DATA_TYPE_UINT64 (9)
#define MMDB_DATA_TYPE_UINT128 (10)
#define MMDB_DATA_TYPE_ARRAY (11)
#define MMDB_DATA_TYPE_CONTAINER (12)
#define MMDB_DATA_TYPE_END_MARKER (13)
#define MMDB_DATA_TYPE_BOOLEAN (14)
#define MMDB_DATA_TYPE_FLOAT (15)
#define MMDB_RECORD_TYPE_SEARCH_NODE (0)
#define MMDB_RECORD_TYPE_EMPTY (1)
#define MMDB_RECORD_TYPE_DATA (2)
#define MMDB_RECORD_TYPE_INVALID (3)
/* flags for open */
#define MMDB_MODE_MMAP (1)
#define MMDB_MODE_MASK (7)
/* error codes */
#define MMDB_SUCCESS (0)
#define MMDB_FILE_OPEN_ERROR (1)
#define MMDB_CORRUPT_SEARCH_TREE_ERROR (2)
#define MMDB_INVALID_METADATA_ERROR (3)
#define MMDB_IO_ERROR (4)
#define MMDB_OUT_OF_MEMORY_ERROR (5)
#define MMDB_UNKNOWN_DATABASE_FORMAT_ERROR (6)
#define MMDB_INVALID_DATA_ERROR (7)
#define MMDB_INVALID_LOOKUP_PATH_ERROR (8)
#define MMDB_LOOKUP_PATH_DOES_NOT_MATCH_DATA_ERROR (9)
#define MMDB_INVALID_NODE_NUMBER_ERROR (10)
#define MMDB_IPV6_LOOKUP_IN_IPV4_DATABASE_ERROR (11)
#if !(MMDB_UINT128_IS_BYTE_ARRAY)
#if MMDB_UINT128_USING_MODE
typedef unsigned int mmdb_uint128_t __attribute__((__mode__(TI)));
#else
typedef unsigned __int128 mmdb_uint128_t;
#endif
#endif
/* This is a pointer into the data section for a given IP address lookup */
typedef struct MMDB_entry_s {
const struct MMDB_s *mmdb;
uint32_t offset;
} MMDB_entry_s;
typedef struct MMDB_lookup_result_s {
bool found_entry;
MMDB_entry_s entry;
uint16_t netmask;
} MMDB_lookup_result_s;
typedef struct MMDB_entry_data_s {
bool has_data;
union {
uint32_t pointer;
const char *utf8_string;
double double_value;
const uint8_t *bytes;
uint16_t uint16;
uint32_t uint32;
int32_t int32;
uint64_t uint64;
#if MMDB_UINT128_IS_BYTE_ARRAY
uint8_t uint128[16];
#else
mmdb_uint128_t uint128;
#endif
bool boolean;
float float_value;
};
/* This is a 0 if a given entry cannot be found. This can only happen
* when a call to MMDB_(v)get_value() asks for hash keys or array
* indices that don't exist. */
uint32_t offset;
/* This is the next entry in the data section, but it's really only
* relevant for entries that part of a larger map or array
* struct. There's no good reason for an end user to look at this
* directly. */
uint32_t offset_to_next;
/* This is only valid for strings, utf8_strings or binary data */
uint32_t data_size;
/* This is an MMDB_DATA_TYPE_* constant */
uint32_t type;
} MMDB_entry_data_s;
/* This is the return type when someone asks for all the entry data in a map or
* array */
typedef struct MMDB_entry_data_list_s {
MMDB_entry_data_s entry_data;
struct MMDB_entry_data_list_s *next;
void *pool;
} MMDB_entry_data_list_s;
typedef struct MMDB_description_s {
const char *language;
const char *description;
} MMDB_description_s;
/* WARNING: do not add new fields to this struct without bumping the SONAME.
* The struct is allocated by the users of this library and increasing the
* size will cause existing users to allocate too little space when the shared
* library is upgraded */
typedef struct MMDB_metadata_s {
uint32_t node_count;
uint16_t record_size;
uint16_t ip_version;
const char *database_type;
struct {
size_t count;
const char **names;
} languages;
uint16_t binary_format_major_version;
uint16_t binary_format_minor_version;
uint64_t build_epoch;
struct {
size_t count;
MMDB_description_s **descriptions;
} description;
/* See above warning before adding fields */
} MMDB_metadata_s;
/* WARNING: do not add new fields to this struct without bumping the SONAME.
* The struct is allocated by the users of this library and increasing the
* size will cause existing users to allocate too little space when the shared
* library is upgraded */
typedef struct MMDB_ipv4_start_node_s {
uint16_t netmask;
uint32_t node_value;
/* See above warning before adding fields */
} MMDB_ipv4_start_node_s;
/* WARNING: do not add new fields to this struct without bumping the SONAME.
* The struct is allocated by the users of this library and increasing the
* size will cause existing users to allocate too little space when the shared
* library is upgraded */
typedef struct MMDB_s {
uint32_t flags;
const char *filename;
ssize_t file_size;
const uint8_t *file_content;
const uint8_t *data_section;
uint32_t data_section_size;
const uint8_t *metadata_section;
uint32_t metadata_section_size;
uint16_t full_record_byte_size;
uint16_t depth;
MMDB_ipv4_start_node_s ipv4_start_node;
MMDB_metadata_s metadata;
/* See above warning before adding fields */
} MMDB_s;
typedef struct MMDB_search_node_s {
uint64_t left_record;
uint64_t right_record;
uint8_t left_record_type;
uint8_t right_record_type;
MMDB_entry_s left_record_entry;
MMDB_entry_s right_record_entry;
} MMDB_search_node_s;
extern int
MMDB_open(const char *const filename, uint32_t flags, MMDB_s *const mmdb);
extern MMDB_lookup_result_s MMDB_lookup_string(const MMDB_s *const mmdb,
const char *const ipstr,
int *const gai_error,
int *const mmdb_error);
extern MMDB_lookup_result_s
MMDB_lookup_sockaddr(const MMDB_s *const mmdb,
const struct sockaddr *const sockaddr,
int *const mmdb_error);
extern int MMDB_read_node(const MMDB_s *const mmdb,
uint32_t node_number,
MMDB_search_node_s *const node);
extern int MMDB_get_value(MMDB_entry_s *const start,
MMDB_entry_data_s *const entry_data,
...);
extern int MMDB_vget_value(MMDB_entry_s *const start,
MMDB_entry_data_s *const entry_data,
va_list va_path);
extern int MMDB_aget_value(MMDB_entry_s *const start,
MMDB_entry_data_s *const entry_data,
const char *const *const path);
extern int MMDB_get_metadata_as_entry_data_list(
const MMDB_s *const mmdb, MMDB_entry_data_list_s **const entry_data_list);
extern int
MMDB_get_entry_data_list(MMDB_entry_s *start,
MMDB_entry_data_list_s **const entry_data_list);
extern void
MMDB_free_entry_data_list(MMDB_entry_data_list_s *const entry_data_list);
extern void MMDB_close(MMDB_s *const mmdb);
extern const char *MMDB_lib_version(void);
extern int
MMDB_dump_entry_data_list(FILE *const stream,
MMDB_entry_data_list_s *const entry_data_list,
int indent);
extern const char *MMDB_strerror(int error_code);
#endif /* MAXMINDDB_H */
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,14 @@
#ifndef MAXMINDDB_CONFIG_H
#define MAXMINDDB_CONFIG_H
#ifndef MMDB_UINT128_USING_MODE
/* Define as 1 if we use unsigned int __atribute__ ((__mode__(TI))) for uint128 values */
#cmakedefine MMDB_UINT128_USING_MODE @MMDB_UINT128_USING_MODE@
#endif
#ifndef MMDB_UINT128_IS_BYTE_ARRAY
/* Define as 1 if we don't have an unsigned __int128 type */
#cmakedefine MMDB_UINT128_IS_BYTE_ARRAY @MMDB_UINT128_IS_BYTE_ARRAY@
#endif
#endif /* MAXMINDDB_CONFIG_H */

View File

@ -0,0 +1,14 @@
#ifndef MAXMINDDB_CONFIG_H
#define MAXMINDDB_CONFIG_H
#ifndef MMDB_UINT128_USING_MODE
/* Define as 1 if we use unsigned int __atribute__ ((__mode__(TI))) for uint128 values */
#define MMDB_UINT128_USING_MODE 0
#endif
#ifndef MMDB_UINT128_IS_BYTE_ARRAY
/* Define as 1 if we don't have an unsigned __int128 type */
#undef MMDB_UINT128_IS_BYTE_ARRAY
#endif
#endif /* MAXMINDDB_CONFIG_H */

View File

@ -0,0 +1,105 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{B19839F4-376C-11E7-A95B-48C58C130AD6}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>bad_pointers</RootNamespace>
<ProjectName>test_bad_pointers</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<IntDir>$(Configuration)\$(ProjectName)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<IntDir>$(Configuration)\$(ProjectName)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(SolutionDir)\..\..\include;$(SolutionDir)\..\..\t\libtap;$(SolutionDir)\..\..\src</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\t\bad_pointers_t.c" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="libtap.vcxproj">
<Project>{4dfc985a-83d7-4e61-85fe-c6ea6e43e3aa}</Project>
</ProjectReference>
<ProjectReference Include="..\VS12\libmaxminddb.vcxproj">
<Project>{82953bda-2960-4ada-a6d5-92e65ccb4a3d}</Project>
</ProjectReference>
<ProjectReference Include="maxminddb_test_helper.vcxproj">
<Project>{a8f568f6-5507-4ec2-a834-f2c0a3c635a5}</Project>
<Private>true</Private>
<ReferenceOutputAssembly>true</ReferenceOutputAssembly>
<CopyLocalSatelliteAssemblies>true</CopyLocalSatelliteAssemblies>
<LinkLibraryDependencies>true</LinkLibraryDependencies>
<UseLibraryDependencyInputs>false</UseLibraryDependencyInputs>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,105 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{B1983C10-376C-11E7-A95B-48C58C130AD6}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>basic_lookup</RootNamespace>
<ProjectName>test_basic_lookup</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<IntDir>$(Configuration)\$(ProjectName)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<IntDir>$(Configuration)\$(ProjectName)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(SolutionDir)\..\..\include;$(SolutionDir)\..\..\t\libtap;$(SolutionDir)\..\..\src</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\t\basic_lookup_t.c" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="libtap.vcxproj">
<Project>{4dfc985a-83d7-4e61-85fe-c6ea6e43e3aa}</Project>
</ProjectReference>
<ProjectReference Include="..\VS12\libmaxminddb.vcxproj">
<Project>{82953bda-2960-4ada-a6d5-92e65ccb4a3d}</Project>
</ProjectReference>
<ProjectReference Include="maxminddb_test_helper.vcxproj">
<Project>{a8f568f6-5507-4ec2-a834-f2c0a3c635a5}</Project>
<Private>true</Private>
<ReferenceOutputAssembly>true</ReferenceOutputAssembly>
<CopyLocalSatelliteAssemblies>true</CopyLocalSatelliteAssemblies>
<LinkLibraryDependencies>true</LinkLibraryDependencies>
<UseLibraryDependencyInputs>false</UseLibraryDependencyInputs>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,105 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{B1983E90-376C-11E7-A95B-48C58C130AD6}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>data_entry_list</RootNamespace>
<ProjectName>test_data_entry_list</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<IntDir>$(Configuration)\$(ProjectName)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<IntDir>$(Configuration)\$(ProjectName)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(SolutionDir)\..\..\include;$(SolutionDir)\..\..\t\libtap;$(SolutionDir)\..\..\src</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\t\data_entry_list_t.c" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="libtap.vcxproj">
<Project>{4dfc985a-83d7-4e61-85fe-c6ea6e43e3aa}</Project>
</ProjectReference>
<ProjectReference Include="..\VS12\libmaxminddb.vcxproj">
<Project>{82953bda-2960-4ada-a6d5-92e65ccb4a3d}</Project>
</ProjectReference>
<ProjectReference Include="maxminddb_test_helper.vcxproj">
<Project>{a8f568f6-5507-4ec2-a834-f2c0a3c635a5}</Project>
<Private>true</Private>
<ReferenceOutputAssembly>true</ReferenceOutputAssembly>
<CopyLocalSatelliteAssemblies>true</CopyLocalSatelliteAssemblies>
<LinkLibraryDependencies>true</LinkLibraryDependencies>
<UseLibraryDependencyInputs>false</UseLibraryDependencyInputs>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,105 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{B198400C-376C-11E7-A95B-48C58C130AD6}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>data_types</RootNamespace>
<ProjectName>test_data_types</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<IntDir>$(Configuration)\$(ProjectName)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<IntDir>$(Configuration)\$(ProjectName)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(SolutionDir)\..\..\include;$(SolutionDir)\..\..\t\libtap;$(SolutionDir)\..\..\src</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\t\data_types_t.c" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="libtap.vcxproj">
<Project>{4dfc985a-83d7-4e61-85fe-c6ea6e43e3aa}</Project>
</ProjectReference>
<ProjectReference Include="..\VS12\libmaxminddb.vcxproj">
<Project>{82953bda-2960-4ada-a6d5-92e65ccb4a3d}</Project>
</ProjectReference>
<ProjectReference Include="maxminddb_test_helper.vcxproj">
<Project>{a8f568f6-5507-4ec2-a834-f2c0a3c635a5}</Project>
<Private>true</Private>
<ReferenceOutputAssembly>true</ReferenceOutputAssembly>
<CopyLocalSatelliteAssemblies>true</CopyLocalSatelliteAssemblies>
<LinkLibraryDependencies>true</LinkLibraryDependencies>
<UseLibraryDependencyInputs>false</UseLibraryDependencyInputs>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,105 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{B1984188-376C-11E7-A95B-48C58C130AD6}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>dump</RootNamespace>
<ProjectName>test_dump</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<IntDir>$(Configuration)\$(ProjectName)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<IntDir>$(Configuration)\$(ProjectName)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(SolutionDir)\..\..\include;$(SolutionDir)\..\..\t\libtap;$(SolutionDir)\..\..\src</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\t\dump_t.c" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="libtap.vcxproj">
<Project>{4dfc985a-83d7-4e61-85fe-c6ea6e43e3aa}</Project>
</ProjectReference>
<ProjectReference Include="..\VS12\libmaxminddb.vcxproj">
<Project>{82953bda-2960-4ada-a6d5-92e65ccb4a3d}</Project>
</ProjectReference>
<ProjectReference Include="maxminddb_test_helper.vcxproj">
<Project>{a8f568f6-5507-4ec2-a834-f2c0a3c635a5}</Project>
<Private>true</Private>
<ReferenceOutputAssembly>true</ReferenceOutputAssembly>
<CopyLocalSatelliteAssemblies>true</CopyLocalSatelliteAssemblies>
<LinkLibraryDependencies>true</LinkLibraryDependencies>
<UseLibraryDependencyInputs>false</UseLibraryDependencyInputs>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,105 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{B1984480-376C-11E7-A95B-48C58C130AD6}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>get_value</RootNamespace>
<ProjectName>test_get_value</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<IntDir>$(Configuration)\$(ProjectName)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<IntDir>$(Configuration)\$(ProjectName)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(SolutionDir)\..\..\include;$(SolutionDir)\..\..\t\libtap;$(SolutionDir)\..\..\src</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\t\get_value_t.c" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="libtap.vcxproj">
<Project>{4dfc985a-83d7-4e61-85fe-c6ea6e43e3aa}</Project>
</ProjectReference>
<ProjectReference Include="..\VS12\libmaxminddb.vcxproj">
<Project>{82953bda-2960-4ada-a6d5-92e65ccb4a3d}</Project>
</ProjectReference>
<ProjectReference Include="maxminddb_test_helper.vcxproj">
<Project>{a8f568f6-5507-4ec2-a834-f2c0a3c635a5}</Project>
<Private>true</Private>
<ReferenceOutputAssembly>true</ReferenceOutputAssembly>
<CopyLocalSatelliteAssemblies>true</CopyLocalSatelliteAssemblies>
<LinkLibraryDependencies>true</LinkLibraryDependencies>
<UseLibraryDependencyInputs>false</UseLibraryDependencyInputs>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,105 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{B1984304-376C-11E7-A95B-48C58C130AD6}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>get_value_pointer_bug</RootNamespace>
<ProjectName>test_get_value_pointer_bug</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<IntDir>$(Configuration)\$(ProjectName)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<IntDir>$(Configuration)\$(ProjectName)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(SolutionDir)\..\..\include;$(SolutionDir)\..\..\t\libtap;$(SolutionDir)\..\..\src</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\t\get_value_pointer_bug_t.c" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="libtap.vcxproj">
<Project>{4dfc985a-83d7-4e61-85fe-c6ea6e43e3aa}</Project>
</ProjectReference>
<ProjectReference Include="..\VS12\libmaxminddb.vcxproj">
<Project>{82953bda-2960-4ada-a6d5-92e65ccb4a3d}</Project>
</ProjectReference>
<ProjectReference Include="maxminddb_test_helper.vcxproj">
<Project>{a8f568f6-5507-4ec2-a834-f2c0a3c635a5}</Project>
<Private>true</Private>
<ReferenceOutputAssembly>true</ReferenceOutputAssembly>
<CopyLocalSatelliteAssemblies>true</CopyLocalSatelliteAssemblies>
<LinkLibraryDependencies>true</LinkLibraryDependencies>
<UseLibraryDependencyInputs>false</UseLibraryDependencyInputs>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,105 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{B198466A-376C-11E7-A95B-48C58C130AD6}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>ipv4_start_cache</RootNamespace>
<ProjectName>test_ipv4_start_cache</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<IntDir>$(Configuration)\$(ProjectName)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<IntDir>$(Configuration)\$(ProjectName)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(SolutionDir)\..\..\include;$(SolutionDir)\..\..\t\libtap;$(SolutionDir)\..\..\src</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\t\ipv4_start_cache_t.c" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="libtap.vcxproj">
<Project>{4dfc985a-83d7-4e61-85fe-c6ea6e43e3aa}</Project>
</ProjectReference>
<ProjectReference Include="..\VS12\libmaxminddb.vcxproj">
<Project>{82953bda-2960-4ada-a6d5-92e65ccb4a3d}</Project>
</ProjectReference>
<ProjectReference Include="maxminddb_test_helper.vcxproj">
<Project>{a8f568f6-5507-4ec2-a834-f2c0a3c635a5}</Project>
<Private>true</Private>
<ReferenceOutputAssembly>true</ReferenceOutputAssembly>
<CopyLocalSatelliteAssemblies>true</CopyLocalSatelliteAssemblies>
<LinkLibraryDependencies>true</LinkLibraryDependencies>
<UseLibraryDependencyInputs>false</UseLibraryDependencyInputs>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,105 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{B1984872-376C-11E7-A95B-48C58C130AD6}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>ipv6_lookup_in_ipv4</RootNamespace>
<ProjectName>test_ipv6_lookup_in_ipv4</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<IntDir>$(Configuration)\$(ProjectName)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<IntDir>$(Configuration)\$(ProjectName)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(SolutionDir)\..\..\include;$(SolutionDir)\..\..\t\libtap;$(SolutionDir)\..\..\src</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\t\ipv6_lookup_in_ipv4_t.c" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="libtap.vcxproj">
<Project>{4dfc985a-83d7-4e61-85fe-c6ea6e43e3aa}</Project>
</ProjectReference>
<ProjectReference Include="..\VS12\libmaxminddb.vcxproj">
<Project>{82953bda-2960-4ada-a6d5-92e65ccb4a3d}</Project>
</ProjectReference>
<ProjectReference Include="maxminddb_test_helper.vcxproj">
<Project>{a8f568f6-5507-4ec2-a834-f2c0a3c635a5}</Project>
<Private>true</Private>
<ReferenceOutputAssembly>true</ReferenceOutputAssembly>
<CopyLocalSatelliteAssemblies>true</CopyLocalSatelliteAssemblies>
<LinkLibraryDependencies>true</LinkLibraryDependencies>
<UseLibraryDependencyInputs>false</UseLibraryDependencyInputs>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,85 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{4DFC985A-83D7-4E61-85FE-C6EA6E43E3AA}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>libtap</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v120</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v120</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<IntDir>$(Configuration)\$(ProjectName)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalOptions>/Z7 %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="..\..\t\libtap\tap.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\t\libtap\tap.c" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,107 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{A8F568F6-5507-4EC2-A834-F2C0A3C635A5}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>ConsoleApplication1</RootNamespace>
<ProjectName>test_maxminddb_test_helper</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(SolutionDir)\..\..\include;$(SolutionDir)\..\..\t\libtap;$(SolutionDir)\..\..\src</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ProjectReference Include="..\..\t\libtap\libtap.vcxproj">
<Project>{4dfc985a-83d7-4e61-85fe-c6ea6e43e3aa}</Project>
<Private>true</Private>
<ReferenceOutputAssembly>true</ReferenceOutputAssembly>
<CopyLocalSatelliteAssemblies>true</CopyLocalSatelliteAssemblies>
<LinkLibraryDependencies>true</LinkLibraryDependencies>
<UseLibraryDependencyInputs>false</UseLibraryDependencyInputs>
</ProjectReference>
<ProjectReference Include="..\VS12\libmaxminddb.vcxproj">
<Project>{82953bda-2960-4ada-a6d5-92e65ccb4a3d}</Project>
<Private>true</Private>
<ReferenceOutputAssembly>true</ReferenceOutputAssembly>
<CopyLocalSatelliteAssemblies>true</CopyLocalSatelliteAssemblies>
<LinkLibraryDependencies>true</LinkLibraryDependencies>
<UseLibraryDependencyInputs>false</UseLibraryDependencyInputs>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\t\maxminddb_test_helper.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\t\maxminddb_test_helper.c" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,105 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{B1984C6E-376C-11E7-A95B-48C58C130AD6}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>metadata</RootNamespace>
<ProjectName>test_metadata</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<IntDir>$(Configuration)\$(ProjectName)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<IntDir>$(Configuration)\$(ProjectName)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(SolutionDir)\..\..\include;$(SolutionDir)\..\..\t\libtap;$(SolutionDir)\..\..\src</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\t\metadata_t.c" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="libtap.vcxproj">
<Project>{4dfc985a-83d7-4e61-85fe-c6ea6e43e3aa}</Project>
</ProjectReference>
<ProjectReference Include="..\VS12\libmaxminddb.vcxproj">
<Project>{82953bda-2960-4ada-a6d5-92e65ccb4a3d}</Project>
</ProjectReference>
<ProjectReference Include="maxminddb_test_helper.vcxproj">
<Project>{a8f568f6-5507-4ec2-a834-f2c0a3c635a5}</Project>
<Private>true</Private>
<ReferenceOutputAssembly>true</ReferenceOutputAssembly>
<CopyLocalSatelliteAssemblies>true</CopyLocalSatelliteAssemblies>
<LinkLibraryDependencies>true</LinkLibraryDependencies>
<UseLibraryDependencyInputs>false</UseLibraryDependencyInputs>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,105 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{B19849D0-376C-11E7-A95B-48C58C130AD6}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>metadata_pointers</RootNamespace>
<ProjectName>test_metadata_pointers</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<IntDir>$(Configuration)\$(ProjectName)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<IntDir>$(Configuration)\$(ProjectName)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(SolutionDir)\..\..\include;$(SolutionDir)\..\..\t\libtap;$(SolutionDir)\..\..\src</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\t\metadata_pointers_t.c" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="libtap.vcxproj">
<Project>{4dfc985a-83d7-4e61-85fe-c6ea6e43e3aa}</Project>
</ProjectReference>
<ProjectReference Include="..\VS12\libmaxminddb.vcxproj">
<Project>{82953bda-2960-4ada-a6d5-92e65ccb4a3d}</Project>
</ProjectReference>
<ProjectReference Include="maxminddb_test_helper.vcxproj">
<Project>{a8f568f6-5507-4ec2-a834-f2c0a3c635a5}</Project>
<Private>true</Private>
<ReferenceOutputAssembly>true</ReferenceOutputAssembly>
<CopyLocalSatelliteAssemblies>true</CopyLocalSatelliteAssemblies>
<LinkLibraryDependencies>true</LinkLibraryDependencies>
<UseLibraryDependencyInputs>false</UseLibraryDependencyInputs>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,105 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{B1984EC6-376C-11E7-A95B-48C58C130AD6}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>no_map_get_value</RootNamespace>
<ProjectName>test_no_map_get_value</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<IntDir>$(Configuration)\$(ProjectName)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<IntDir>$(Configuration)\$(ProjectName)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(SolutionDir)\..\..\include;$(SolutionDir)\..\..\t\libtap;$(SolutionDir)\..\..\src</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\t\no_map_get_value_t.c" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="libtap.vcxproj">
<Project>{4dfc985a-83d7-4e61-85fe-c6ea6e43e3aa}</Project>
</ProjectReference>
<ProjectReference Include="..\VS12\libmaxminddb.vcxproj">
<Project>{82953bda-2960-4ada-a6d5-92e65ccb4a3d}</Project>
</ProjectReference>
<ProjectReference Include="maxminddb_test_helper.vcxproj">
<Project>{a8f568f6-5507-4ec2-a834-f2c0a3c635a5}</Project>
<Private>true</Private>
<ReferenceOutputAssembly>true</ReferenceOutputAssembly>
<CopyLocalSatelliteAssemblies>true</CopyLocalSatelliteAssemblies>
<LinkLibraryDependencies>true</LinkLibraryDependencies>
<UseLibraryDependencyInputs>false</UseLibraryDependencyInputs>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,105 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{B198504C-376C-11E7-A95B-48C58C130AD6}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>read_node</RootNamespace>
<ProjectName>test_read_node</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<IntDir>$(Configuration)\$(ProjectName)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<IntDir>$(Configuration)\$(ProjectName)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(SolutionDir)\..\..\include;$(SolutionDir)\..\..\t\libtap;$(SolutionDir)\..\..\src</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\t\read_node_t.c" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="libtap.vcxproj">
<Project>{4dfc985a-83d7-4e61-85fe-c6ea6e43e3aa}</Project>
</ProjectReference>
<ProjectReference Include="..\VS12\libmaxminddb.vcxproj">
<Project>{82953bda-2960-4ada-a6d5-92e65ccb4a3d}</Project>
</ProjectReference>
<ProjectReference Include="maxminddb_test_helper.vcxproj">
<Project>{a8f568f6-5507-4ec2-a834-f2c0a3c635a5}</Project>
<Private>true</Private>
<ReferenceOutputAssembly>true</ReferenceOutputAssembly>
<CopyLocalSatelliteAssemblies>true</CopyLocalSatelliteAssemblies>
<LinkLibraryDependencies>true</LinkLibraryDependencies>
<UseLibraryDependencyInputs>false</UseLibraryDependencyInputs>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,104 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{A8F568F6-5507-4EC2-A834-F2C0A3C635A5}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>ConsoleApplication1</RootNamespace>
<ProjectName>test_maxminddb_test_helper</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<IntDir>$(Configuration)\$(ProjectName)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(SolutionDir)\..\..\include;$(SolutionDir)\..\..\t\libtap;$(SolutionDir)\..\..\src</AdditionalIncludeDirectories>
<AdditionalOptions>/FS %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ProjectReference Include="..\VS12\libmaxminddb.vcxproj">
<Project>{82953bda-2960-4ada-a6d5-92e65ccb4a3d}</Project>
<Private>true</Private>
<ReferenceOutputAssembly>true</ReferenceOutputAssembly>
<CopyLocalSatelliteAssemblies>true</CopyLocalSatelliteAssemblies>
<LinkLibraryDependencies>true</LinkLibraryDependencies>
<UseLibraryDependencyInputs>false</UseLibraryDependencyInputs>
</ProjectReference>
<ProjectReference Include="libtap.vcxproj">
<Project>{4dfc985a-83d7-4e61-85fe-c6ea6e43e3aa}</Project>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\t\maxminddb_test_helper.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\t\maxminddb_test_helper.c" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,103 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{8E11E9FC-7B63-11E4-AE98-6B41E8A9DDB2}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>threads</RootNamespace>
<ProjectName>test_threads</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(SolutionDir)\..\..\include;$(SolutionDir)\..\..\t\libtap;$(SolutionDir)\..\..\src</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\t\threads_t.c" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="libtap.vcxproj">
<Project>{4dfc985a-83d7-4e61-85fe-c6ea6e43e3aa}</Project>
</ProjectReference>
<ProjectReference Include="..\VS12\libmaxminddb.vcxproj">
<Project>{82953bda-2960-4ada-a6d5-92e65ccb4a3d}</Project>
</ProjectReference>
<ProjectReference Include="maxminddb_test_helper.vcxproj">
<Project>{a8f568f6-5507-4ec2-a834-f2c0a3c635a5}</Project>
<Private>true</Private>
<ReferenceOutputAssembly>true</ReferenceOutputAssembly>
<CopyLocalSatelliteAssemblies>true</CopyLocalSatelliteAssemblies>
<LinkLibraryDependencies>true</LinkLibraryDependencies>
<UseLibraryDependencyInputs>false</UseLibraryDependencyInputs>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,105 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{B19851FA-376C-11E7-A95B-48C58C130AD6}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>version</RootNamespace>
<ProjectName>test_version</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<IntDir>$(Configuration)\$(ProjectName)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<IntDir>$(Configuration)\$(ProjectName)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(SolutionDir)\..\..\include;$(SolutionDir)\..\..\t\libtap;$(SolutionDir)\..\..\src</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\t\version_t.c" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="libtap.vcxproj">
<Project>{4dfc985a-83d7-4e61-85fe-c6ea6e43e3aa}</Project>
</ProjectReference>
<ProjectReference Include="..\VS12\libmaxminddb.vcxproj">
<Project>{82953bda-2960-4ada-a6d5-92e65ccb4a3d}</Project>
</ProjectReference>
<ProjectReference Include="maxminddb_test_helper.vcxproj">
<Project>{a8f568f6-5507-4ec2-a834-f2c0a3c635a5}</Project>
<Private>true</Private>
<ReferenceOutputAssembly>true</ReferenceOutputAssembly>
<CopyLocalSatelliteAssemblies>true</CopyLocalSatelliteAssemblies>
<LinkLibraryDependencies>true</LinkLibraryDependencies>
<UseLibraryDependencyInputs>false</UseLibraryDependencyInputs>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,64 @@
# Deprecated
*These files are deprecated and will be removed in a future release.
Please use CMake instead.*
# Project Notes
DO NOT modify project settings for each configuration and/or platform
on a per-project basis. Use property sheets to set shared configuration
properties. The rule of thumb - if you set same value for the same
property in more than one configuration or platform, you did it wrong.
## libmaxminddb.props
This is the base property sheet for libMaxMindDB project. It contains
settings that are shared between all configurations, such as compiler
warning level, not using link-time code generation, etc.
In order to minimize the number of property sheet files, this propery
sheet also contains settings for Win32 and Debug configurations, which
are overridden by the x64 and Release property sheets described below.
## libmaxminddb-release.props
This property sheet contains all Release settings and is shared between
Win32 and x64 release builds. It must be located higher than the base
property sheet in the property Manager window for each configuration
where it's used (i.e. Release|Win32 and Release|x64).
## libmaxminddb-x64.props
This property sheet contains all x64 settings and is shared between all
Debug and Release x64 configurations. It must be located higher than the
base property sheet in the property Manager window for each configuration
where it's used (i.e. Debug|x64 and Release|x64).
## Adding More Projects
If you want to add more projects into this solution, follow the same logic
and create their own property sheets. Do not use libmaxminddb property
sheets in those projects because it will interfere with their intermediate
directories. Instead, copy and rename libmaxminddb property sheets as a
starting point.
DO NOT add libmaxminddb.lib to the Additional Dependencies box of command
line tools or any other libraries you built, for that matter. This box is
only for standard Windows libraries. Instead, add libmaxminddb as a reference
to all command line tool projects. Do the same for any other library projects
you added to this solutionn.
For external 3rd-party .lib files, create a solution folder called Libraries
and add Debug, Debug64, Release, Release64 subfolders, then drag and drop all
versinos of .lib to their respective folders and use Exclude From Build in
each library file's property to assign them to the proper build confguration.
Unused libraries will be shown with a traffic stop sign in each configuration.
If you have a lot of projects, it might be easier to do this by editing .vcxproj
and .vcxproj.filters in a text editor.
# Tests
To use the tests, you must download the `libtap` and `maxmind-db` submodules.
This can be done by running `git submodule update --init --recursive` from
the Git checkout. Each test source file has a separate project. Once compiled,
the tests must be run from the base directory of the checkout.

View File

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ImportGroup Label="PropertySheets" />
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<ItemDefinitionGroup>
<ClCompile>
<Optimization>MaxSpeed</Optimization>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup>
<ClCompile>
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup>
<ClCompile>
<IntrinsicFunctions>true</IntrinsicFunctions>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup>
<ClCompile>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup>
<ClCompile>
<OmitFramePointers>true</OmitFramePointers>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup />
</Project>

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ImportGroup Label="PropertySheets" />
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<IntDir>$(SolutionDir)$(Platform)\$(Configuration)\obj\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup>
<Lib>
<TargetMachine>MachineX64</TargetMachine>
</Lib>
</ItemDefinitionGroup>
<ItemGroup />
</Project>

View File

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ImportGroup Label="PropertySheets" />
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<IntDir>$(SolutionDir)$(Configuration)\obj\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>..\..\include</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<WarningLevel>Level3</WarningLevel>
<ExceptionHandling>false</ExceptionHandling>
<ProgramDataBaseFileName>$(OutDir)vc$(PlatformToolsetVersion).pdb</ProgramDataBaseFileName>
<Optimization>Disabled</Optimization>
<InlineFunctionExpansion>Disabled</InlineFunctionExpansion>
<OmitFramePointers>false</OmitFramePointers>
<WholeProgramOptimization>false</WholeProgramOptimization>
</ClCompile>
<PreBuildEvent>
<Command>if NOT EXIST (..\..\include\maxminddb_config.h) (
copy maxminddb_config.h ..\..\include\maxminddb_config.h
)</Command>
</PreBuildEvent>
<Lib>
<TargetMachine>MachineX86</TargetMachine>
<LinkTimeCodeGeneration>false</LinkTimeCodeGeneration>
</Lib>
</ItemDefinitionGroup>
<ItemGroup />
</Project>

View File

@ -0,0 +1,150 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.31101.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libmaxminddb", "libmaxminddb.vcxproj", "{82953BDA-2960-4ADA-A6D5-92E65CCB4A3D}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_basic_lookup", "..\VS12-tests\basic_lookup.vcxproj", "{8E11C512-7B63-11E4-AE98-6B41E8A9DDB2}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_data_entry_list", "..\VS12-tests\data_entry_list.vcxproj", "{8E11C882-7B63-11E4-AE98-6B41E8A9DDB2}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_data_types", "..\VS12-tests\data_types.vcxproj", "{8E11CBD4-7B63-11E4-AE98-6B41E8A9DDB2}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_dump", "..\VS12-tests\dump.vcxproj", "{8E11CEEA-7B63-11E4-AE98-6B41E8A9DDB2}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_get_value", "..\VS12-tests\get_value.vcxproj", "{8E11D5E8-7B63-11E4-AE98-6B41E8A9DDB2}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_get_value_pointer_bug", "..\VS12-tests\get_value_pointer_bug.vcxproj", "{8E11D2AA-7B63-11E4-AE98-6B41E8A9DDB2}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_ipv4_start_cache", "..\VS12-tests\ipv4_start_cache.vcxproj", "{8E11D930-7B63-11E4-AE98-6B41E8A9DDB2}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_ipv6_lookup_in_ipv4", "..\VS12-tests\ipv6_lookup_in_ipv4.vcxproj", "{8E11DC64-7B63-11E4-AE98-6B41E8A9DDB2}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libtap", "..\VS12-tests\libtap.vcxproj", "{4DFC985A-83D7-4E61-85FE-C6EA6E43E3AA}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_metadata", "..\VS12-tests\metadata.vcxproj", "{8E11DFC0-7B63-11E4-AE98-6B41E8A9DDB2}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_no_map_get_value", "..\VS12-tests\no_map_get_value.vcxproj", "{8E11E33A-7B63-11E4-AE98-6B41E8A9DDB2}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_read_node", "..\VS12-tests\read_node.vcxproj", "{8E11E68C-7B63-11E4-AE98-6B41E8A9DDB2}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_maxminddb_test_helper", "..\VS12-tests\shared.vcxproj", "{A8F568F6-5507-4EC2-A834-F2C0A3C635A5}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_version", "..\VS12-tests\version.vcxproj", "{8E11ED26-7B63-11E4-AE98-6B41E8A9DDB2}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_bad_pointers", "..\VS12-tests\bad_pointers.vcxproj", "{8E11BAF4-7B63-11E4-AE98-6B41E8A9DDB2}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_metadata_pointers", "..\VS12-tests\metadata_pointers.vcxproj", "{8E11CBD4-7B63-11E4-AE98-6B41E8A9DDB2}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Debug|x64 = Debug|x64
Release|Win32 = Release|Win32
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{82953BDA-2960-4ADA-A6D5-92E65CCB4A3D}.Debug|Win32.ActiveCfg = Debug|Win32
{82953BDA-2960-4ADA-A6D5-92E65CCB4A3D}.Debug|Win32.Build.0 = Debug|Win32
{82953BDA-2960-4ADA-A6D5-92E65CCB4A3D}.Debug|x64.ActiveCfg = Debug|x64
{82953BDA-2960-4ADA-A6D5-92E65CCB4A3D}.Debug|x64.Build.0 = Debug|x64
{82953BDA-2960-4ADA-A6D5-92E65CCB4A3D}.Release|Win32.ActiveCfg = Release|Win32
{82953BDA-2960-4ADA-A6D5-92E65CCB4A3D}.Release|Win32.Build.0 = Release|Win32
{82953BDA-2960-4ADA-A6D5-92E65CCB4A3D}.Release|x64.ActiveCfg = Release|x64
{82953BDA-2960-4ADA-A6D5-92E65CCB4A3D}.Release|x64.Build.0 = Release|x64
{8E11C512-7B63-11E4-AE98-6B41E8A9DDB2}.Debug|Win32.ActiveCfg = Debug|Win32
{8E11C512-7B63-11E4-AE98-6B41E8A9DDB2}.Debug|Win32.Build.0 = Debug|Win32
{8E11C512-7B63-11E4-AE98-6B41E8A9DDB2}.Debug|x64.ActiveCfg = Debug|Win32
{8E11C512-7B63-11E4-AE98-6B41E8A9DDB2}.Release|Win32.ActiveCfg = Release|Win32
{8E11C512-7B63-11E4-AE98-6B41E8A9DDB2}.Release|Win32.Build.0 = Release|Win32
{8E11C512-7B63-11E4-AE98-6B41E8A9DDB2}.Release|x64.ActiveCfg = Release|Win32
{8E11C882-7B63-11E4-AE98-6B41E8A9DDB2}.Debug|Win32.ActiveCfg = Debug|Win32
{8E11C882-7B63-11E4-AE98-6B41E8A9DDB2}.Debug|Win32.Build.0 = Debug|Win32
{8E11C882-7B63-11E4-AE98-6B41E8A9DDB2}.Debug|x64.ActiveCfg = Debug|Win32
{8E11C882-7B63-11E4-AE98-6B41E8A9DDB2}.Release|Win32.ActiveCfg = Release|Win32
{8E11C882-7B63-11E4-AE98-6B41E8A9DDB2}.Release|Win32.Build.0 = Release|Win32
{8E11C882-7B63-11E4-AE98-6B41E8A9DDB2}.Release|x64.ActiveCfg = Release|Win32
{8E11CBD4-7B63-11E4-AE98-6B41E8A9DDB2}.Debug|Win32.ActiveCfg = Debug|Win32
{8E11CBD4-7B63-11E4-AE98-6B41E8A9DDB2}.Debug|Win32.Build.0 = Debug|Win32
{8E11CBD4-7B63-11E4-AE98-6B41E8A9DDB2}.Debug|x64.ActiveCfg = Debug|Win32
{8E11CBD4-7B63-11E4-AE98-6B41E8A9DDB2}.Release|Win32.ActiveCfg = Release|Win32
{8E11CBD4-7B63-11E4-AE98-6B41E8A9DDB2}.Release|Win32.Build.0 = Release|Win32
{8E11CBD4-7B63-11E4-AE98-6B41E8A9DDB2}.Release|x64.ActiveCfg = Release|Win32
{8E11CEEA-7B63-11E4-AE98-6B41E8A9DDB2}.Debug|Win32.ActiveCfg = Debug|Win32
{8E11CEEA-7B63-11E4-AE98-6B41E8A9DDB2}.Debug|Win32.Build.0 = Debug|Win32
{8E11CEEA-7B63-11E4-AE98-6B41E8A9DDB2}.Debug|x64.ActiveCfg = Debug|Win32
{8E11CEEA-7B63-11E4-AE98-6B41E8A9DDB2}.Release|Win32.ActiveCfg = Release|Win32
{8E11CEEA-7B63-11E4-AE98-6B41E8A9DDB2}.Release|Win32.Build.0 = Release|Win32
{8E11CEEA-7B63-11E4-AE98-6B41E8A9DDB2}.Release|x64.ActiveCfg = Release|Win32
{8E11D5E8-7B63-11E4-AE98-6B41E8A9DDB2}.Debug|Win32.ActiveCfg = Debug|Win32
{8E11D5E8-7B63-11E4-AE98-6B41E8A9DDB2}.Debug|Win32.Build.0 = Debug|Win32
{8E11D5E8-7B63-11E4-AE98-6B41E8A9DDB2}.Debug|x64.ActiveCfg = Debug|Win32
{8E11D5E8-7B63-11E4-AE98-6B41E8A9DDB2}.Release|Win32.ActiveCfg = Release|Win32
{8E11D5E8-7B63-11E4-AE98-6B41E8A9DDB2}.Release|Win32.Build.0 = Release|Win32
{8E11D5E8-7B63-11E4-AE98-6B41E8A9DDB2}.Release|x64.ActiveCfg = Release|Win32
{8E11D2AA-7B63-11E4-AE98-6B41E8A9DDB2}.Debug|Win32.ActiveCfg = Debug|Win32
{8E11D2AA-7B63-11E4-AE98-6B41E8A9DDB2}.Debug|Win32.Build.0 = Debug|Win32
{8E11D2AA-7B63-11E4-AE98-6B41E8A9DDB2}.Debug|x64.ActiveCfg = Debug|Win32
{8E11D2AA-7B63-11E4-AE98-6B41E8A9DDB2}.Release|Win32.ActiveCfg = Release|Win32
{8E11D2AA-7B63-11E4-AE98-6B41E8A9DDB2}.Release|Win32.Build.0 = Release|Win32
{8E11D2AA-7B63-11E4-AE98-6B41E8A9DDB2}.Release|x64.ActiveCfg = Release|Win32
{8E11D930-7B63-11E4-AE98-6B41E8A9DDB2}.Debug|Win32.ActiveCfg = Debug|Win32
{8E11D930-7B63-11E4-AE98-6B41E8A9DDB2}.Debug|Win32.Build.0 = Debug|Win32
{8E11D930-7B63-11E4-AE98-6B41E8A9DDB2}.Debug|x64.ActiveCfg = Debug|Win32
{8E11D930-7B63-11E4-AE98-6B41E8A9DDB2}.Release|Win32.ActiveCfg = Release|Win32
{8E11D930-7B63-11E4-AE98-6B41E8A9DDB2}.Release|Win32.Build.0 = Release|Win32
{8E11D930-7B63-11E4-AE98-6B41E8A9DDB2}.Release|x64.ActiveCfg = Release|Win32
{8E11DC64-7B63-11E4-AE98-6B41E8A9DDB2}.Debug|Win32.ActiveCfg = Debug|Win32
{8E11DC64-7B63-11E4-AE98-6B41E8A9DDB2}.Debug|Win32.Build.0 = Debug|Win32
{8E11DC64-7B63-11E4-AE98-6B41E8A9DDB2}.Debug|x64.ActiveCfg = Debug|Win32
{8E11DC64-7B63-11E4-AE98-6B41E8A9DDB2}.Release|Win32.ActiveCfg = Release|Win32
{8E11DC64-7B63-11E4-AE98-6B41E8A9DDB2}.Release|Win32.Build.0 = Release|Win32
{8E11DC64-7B63-11E4-AE98-6B41E8A9DDB2}.Release|x64.ActiveCfg = Release|Win32
{4DFC985A-83D7-4E61-85FE-C6EA6E43E3AA}.Debug|Win32.ActiveCfg = Debug|Win32
{4DFC985A-83D7-4E61-85FE-C6EA6E43E3AA}.Debug|Win32.Build.0 = Debug|Win32
{4DFC985A-83D7-4E61-85FE-C6EA6E43E3AA}.Debug|x64.ActiveCfg = Debug|Win32
{4DFC985A-83D7-4E61-85FE-C6EA6E43E3AA}.Release|Win32.ActiveCfg = Release|Win32
{4DFC985A-83D7-4E61-85FE-C6EA6E43E3AA}.Release|Win32.Build.0 = Release|Win32
{4DFC985A-83D7-4E61-85FE-C6EA6E43E3AA}.Release|x64.ActiveCfg = Release|Win32
{8E11DFC0-7B63-11E4-AE98-6B41E8A9DDB2}.Debug|Win32.ActiveCfg = Debug|Win32
{8E11DFC0-7B63-11E4-AE98-6B41E8A9DDB2}.Debug|Win32.Build.0 = Debug|Win32
{8E11DFC0-7B63-11E4-AE98-6B41E8A9DDB2}.Debug|x64.ActiveCfg = Debug|Win32
{8E11DFC0-7B63-11E4-AE98-6B41E8A9DDB2}.Release|Win32.ActiveCfg = Release|Win32
{8E11DFC0-7B63-11E4-AE98-6B41E8A9DDB2}.Release|Win32.Build.0 = Release|Win32
{8E11DFC0-7B63-11E4-AE98-6B41E8A9DDB2}.Release|x64.ActiveCfg = Release|Win32
{8E11E33A-7B63-11E4-AE98-6B41E8A9DDB2}.Debug|Win32.ActiveCfg = Debug|Win32
{8E11E33A-7B63-11E4-AE98-6B41E8A9DDB2}.Debug|Win32.Build.0 = Debug|Win32
{8E11E33A-7B63-11E4-AE98-6B41E8A9DDB2}.Debug|x64.ActiveCfg = Debug|Win32
{8E11E33A-7B63-11E4-AE98-6B41E8A9DDB2}.Release|Win32.ActiveCfg = Release|Win32
{8E11E33A-7B63-11E4-AE98-6B41E8A9DDB2}.Release|Win32.Build.0 = Release|Win32
{8E11E33A-7B63-11E4-AE98-6B41E8A9DDB2}.Release|x64.ActiveCfg = Release|Win32
{8E11E68C-7B63-11E4-AE98-6B41E8A9DDB2}.Debug|Win32.ActiveCfg = Debug|Win32
{8E11E68C-7B63-11E4-AE98-6B41E8A9DDB2}.Debug|Win32.Build.0 = Debug|Win32
{8E11E68C-7B63-11E4-AE98-6B41E8A9DDB2}.Debug|x64.ActiveCfg = Debug|Win32
{8E11E68C-7B63-11E4-AE98-6B41E8A9DDB2}.Release|Win32.ActiveCfg = Release|Win32
{8E11E68C-7B63-11E4-AE98-6B41E8A9DDB2}.Release|Win32.Build.0 = Release|Win32
{8E11E68C-7B63-11E4-AE98-6B41E8A9DDB2}.Release|x64.ActiveCfg = Release|Win32
{A8F568F6-5507-4EC2-A834-F2C0A3C635A5}.Debug|Win32.ActiveCfg = Debug|Win32
{A8F568F6-5507-4EC2-A834-F2C0A3C635A5}.Debug|Win32.Build.0 = Debug|Win32
{A8F568F6-5507-4EC2-A834-F2C0A3C635A5}.Debug|x64.ActiveCfg = Debug|Win32
{A8F568F6-5507-4EC2-A834-F2C0A3C635A5}.Release|Win32.ActiveCfg = Release|Win32
{A8F568F6-5507-4EC2-A834-F2C0A3C635A5}.Release|Win32.Build.0 = Release|Win32
{A8F568F6-5507-4EC2-A834-F2C0A3C635A5}.Release|x64.ActiveCfg = Release|Win32
{8E11ED26-7B63-11E4-AE98-6B41E8A9DDB2}.Debug|Win32.ActiveCfg = Debug|Win32
{8E11ED26-7B63-11E4-AE98-6B41E8A9DDB2}.Debug|Win32.Build.0 = Debug|Win32
{8E11ED26-7B63-11E4-AE98-6B41E8A9DDB2}.Debug|x64.ActiveCfg = Debug|Win32
{8E11ED26-7B63-11E4-AE98-6B41E8A9DDB2}.Release|Win32.ActiveCfg = Release|Win32
{8E11ED26-7B63-11E4-AE98-6B41E8A9DDB2}.Release|Win32.Build.0 = Release|Win32
{8E11ED26-7B63-11E4-AE98-6B41E8A9DDB2}.Release|x64.ActiveCfg = Release|Win32
{8E11BAF4-7B63-11E4-AE98-6B41E8A9DDB2}.Debug|Win32.ActiveCfg = Debug|Win32
{8E11BAF4-7B63-11E4-AE98-6B41E8A9DDB2}.Debug|Win32.Build.0 = Debug|Win32
{8E11BAF4-7B63-11E4-AE98-6B41E8A9DDB2}.Debug|x64.ActiveCfg = Debug|Win32
{8E11BAF4-7B63-11E4-AE98-6B41E8A9DDB2}.Release|Win32.ActiveCfg = Release|Win32
{8E11BAF4-7B63-11E4-AE98-6B41E8A9DDB2}.Release|Win32.Build.0 = Release|Win32
{8E11BAF4-7B63-11E4-AE98-6B41E8A9DDB2}.Release|x64.ActiveCfg = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,143 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\src\maxminddb.c" />
<ClCompile Include="..\..\src\data-pool.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\include\maxminddb.h" />
<ClInclude Include="..\..\src\data-pool.h" />
</ItemGroup>
<ItemGroup>
<None Include="README" />
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{82953BDA-2960-4ADA-A6D5-92E65CCB4A3D}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>libmaxminddb</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="libmaxminddb.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="libmaxminddb.props" />
<Import Project="libmaxminddb-x64.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="libmaxminddb.props" />
<Import Project="libmaxminddb-release.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="libmaxminddb.props" />
<Import Project="libmaxminddb-x64.props" />
<Import Project="libmaxminddb-release.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<TargetName>$(ProjectName)d</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<TargetName>$(ProjectName)d</TargetName>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
<PreBuildEvent />
<Lib />
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
<PreBuildEvent />
<Lib />
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
<PreBuildEvent />
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
<PreBuildEvent />
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\src\maxminddb.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\data-pool.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\include\maxminddb.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\src\data-pool.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="README" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,14 @@
#ifndef MAXMINDDB_CONFIG_H
#define MAXMINDDB_CONFIG_H
#ifndef MMDB_UINT128_USING_MODE
/* Define as 1 if we we use unsigned int __atribute__ ((__mode__(TI))) for uint128 values */
#define MMDB_UINT128_USING_MODE 0
#endif
#ifndef MMDB_UINT128_IS_BYTE_ARRAY
/* Define as 1 if we don't have an unsigned __int128 type */
#define MMDB_UINT128_IS_BYTE_ARRAY 1
#endif
#endif /* MAXMINDDB_CONFIG_H */

View File

@ -0,0 +1,105 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{%UUID%}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>%TESTNAME%</RootNamespace>
<ProjectName>test_%TESTNAME%</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<IntDir>$(Configuration)\$(ProjectName)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<IntDir>$(Configuration)\$(ProjectName)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(SolutionDir)\..\..\include;$(SolutionDir)\..\..\t\libtap;$(SolutionDir)\..\..\src</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\t\%TESTNAME%_t.c" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="libtap.vcxproj">
<Project>{4dfc985a-83d7-4e61-85fe-c6ea6e43e3aa}</Project>
</ProjectReference>
<ProjectReference Include="..\VS12\libmaxminddb.vcxproj">
<Project>{82953bda-2960-4ada-a6d5-92e65ccb4a3d}</Project>
</ProjectReference>
<ProjectReference Include="maxminddb_test_helper.vcxproj">
<Project>{a8f568f6-5507-4ec2-a834-f2c0a3c635a5}</Project>
<Private>true</Private>
<ReferenceOutputAssembly>true</ReferenceOutputAssembly>
<CopyLocalSatelliteAssemblies>true</CopyLocalSatelliteAssemblies>
<LinkLibraryDependencies>true</LinkLibraryDependencies>
<UseLibraryDependencyInputs>false</UseLibraryDependencyInputs>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,29 @@
include $(top_srcdir)/common.mk
lib_LTLIBRARIES = libmaxminddb.la
libmaxminddb_la_SOURCES = maxminddb.c maxminddb-compat-util.h \
data-pool.c data-pool.h
libmaxminddb_la_LDFLAGS = -version-info 0:7:0 -export-symbols-regex '^MMDB_.*'
if WINDOWS
libmaxminddb_la_LDFLAGS += -no-undefined
endif
include_HEADERS = $(top_srcdir)/include/maxminddb.h
pkgconfig_DATA = libmaxminddb.pc
TESTS = test-data-pool
check_PROGRAMS = test-data-pool
test_data_pool_SOURCES = data-pool.c data-pool.h
test_data_pool_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/t -DTEST_DATA_POOL
test_data_pool_LDADD = $(top_srcdir)/t/libmmdbtest.la \
$(top_srcdir)/t/libtap/libtap.a
$(top_srcdir)/t/libmmdbtest.la:
$(MAKE) -C $(top_srcdir)/t libmmdbtest.la
$(top_srcdir)/t/libtap/libtap.a:
$(MAKE) -C $(top_srcdir)/t/libtap libtap.a

Some files were not shown because too many files have changed in this diff Show More