Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
M
mongoose
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
mongoose
Commits
d60c99b0
Commit
d60c99b0
authored
Oct 31, 2015
by
Deomid Ryabkov
Committed by
Sergey Lyubka
Nov 18, 2015
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Make MG debug go to stderr
PUBLISHED_FROM=11618b6b2a50c62dd612d241c6b13a9aab357909
parent
b8aeba06
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
1393 additions
and
1368 deletions
+1393
-1368
mongoose.c
mongoose.c
+1373
-1358
mongoose.h
mongoose.h
+20
-10
No files found.
mongoose.c
View file @
d60c99b0
...
@@ -111,7 +111,7 @@ extern void *(*test_calloc)(size_t, size_t);
...
@@ -111,7 +111,7 @@ extern void *(*test_calloc)(size_t, size_t);
#endif
/* MG_INTERNAL_HEADER_INCLUDED */
#endif
/* MG_INTERNAL_HEADER_INCLUDED */
#ifdef NS_MODULE_LINES
#ifdef NS_MODULE_LINES
#line 1 "src/../../common/
mbuf
.c"
#line 1 "src/../../common/
base64
.c"
/**/
/**/
#endif
#endif
/*
/*
...
@@ -121,1629 +121,1644 @@ extern void *(*test_calloc)(size_t, size_t);
...
@@ -121,1629 +121,1644 @@ extern void *(*test_calloc)(size_t, size_t);
#ifndef EXCLUDE_COMMON
#ifndef EXCLUDE_COMMON
#include <assert.h>
/* Amalgamated: #include "base64.h" */
#include <string.h>
#include <string.h>
/* Amalgamated: #include "mbuf.h" */
#ifndef MBUF_REALLOC
/* ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ */
#define MBUF_REALLOC realloc
#endif
#
ifndef MBUF_FREE
#
define NUM_UPPERCASES ('Z' - 'A' + 1)
#define
MBUF_FREE free
#define
NUM_LETTERS (NUM_UPPERCASES * 2)
#
endif
#
define NUM_DIGITS ('9' - '0' + 1)
void
mbuf_init
(
struct
mbuf
*
mbuf
,
size_t
initial_size
)
{
/*
mbuf
->
len
=
mbuf
->
size
=
0
;
* Emit a base64 code char.
mbuf
->
buf
=
NULL
;
*
mbuf_resize
(
mbuf
,
initial_size
);
* Doesn't use memory, thus it's safe to use to safely dump memory in crashdumps
*/
static
void
cs_base64_emit_code
(
struct
cs_base64_ctx
*
ctx
,
int
v
)
{
if
(
v
<
NUM_UPPERCASES
)
{
ctx
->
b64_putc
(
v
+
'A'
,
ctx
->
user_data
);
}
else
if
(
v
<
(
NUM_LETTERS
))
{
ctx
->
b64_putc
(
v
-
NUM_UPPERCASES
+
'a'
,
ctx
->
user_data
);
}
else
if
(
v
<
(
NUM_LETTERS
+
NUM_DIGITS
))
{
ctx
->
b64_putc
(
v
-
NUM_LETTERS
+
'0'
,
ctx
->
user_data
);
}
else
{
ctx
->
b64_putc
(
v
-
NUM_LETTERS
-
NUM_DIGITS
==
0
?
'+'
:
'/'
,
ctx
->
user_data
);
}
}
}
void
mbuf_free
(
struct
mbuf
*
mbuf
)
{
static
void
cs_base64_emit_chunk
(
struct
cs_base64_ctx
*
ctx
)
{
if
(
mbuf
->
buf
!=
NULL
)
{
int
a
,
b
,
c
;
MBUF_FREE
(
mbuf
->
buf
);
mbuf_init
(
mbuf
,
0
);
a
=
ctx
->
chunk
[
0
];
b
=
ctx
->
chunk
[
1
];
c
=
ctx
->
chunk
[
2
];
cs_base64_emit_code
(
ctx
,
a
>>
2
);
cs_base64_emit_code
(
ctx
,
((
a
&
3
)
<<
4
)
|
(
b
>>
4
));
if
(
ctx
->
chunk_size
>
1
)
{
cs_base64_emit_code
(
ctx
,
(
b
&
15
)
<<
2
|
(
c
>>
6
));
}
if
(
ctx
->
chunk_size
>
2
)
{
cs_base64_emit_code
(
ctx
,
c
&
63
);
}
}
}
}
void
mbuf_resize
(
struct
mbuf
*
a
,
size_t
new_size
)
{
void
cs_base64_init
(
struct
cs_base64_ctx
*
ctx
,
cs_base64_putc_t
b64_putc
,
if
(
new_size
>
a
->
size
||
(
new_size
<
a
->
size
&&
new_size
>=
a
->
len
))
{
void
*
user_data
)
{
char
*
buf
=
(
char
*
)
MBUF_REALLOC
(
a
->
buf
,
new_size
);
ctx
->
chunk_size
=
0
;
/*
ctx
->
b64_putc
=
b64_putc
;
* In case realloc fails, there's not much we can do, except keep things as
ctx
->
user_data
=
user_data
;
* they are. Note that NULL is a valid return value from realloc when
}
* size == 0, but that is covered too.
*/
void
cs_base64_update
(
struct
cs_base64_ctx
*
ctx
,
const
char
*
str
,
size_t
len
)
{
if
(
buf
==
NULL
&&
new_size
!=
0
)
return
;
const
unsigned
char
*
src
=
(
const
unsigned
char
*
)
str
;
a
->
buf
=
buf
;
size_t
i
;
a
->
size
=
new_size
;
for
(
i
=
0
;
i
<
len
;
i
++
)
{
ctx
->
chunk
[
ctx
->
chunk_size
++
]
=
src
[
i
];
if
(
ctx
->
chunk_size
==
3
)
{
cs_base64_emit_chunk
(
ctx
);
ctx
->
chunk_size
=
0
;
}
}
}
}
}
void
mbuf_trim
(
struct
mbuf
*
mbuf
)
{
void
cs_base64_finish
(
struct
cs_base64_ctx
*
ctx
)
{
mbuf_resize
(
mbuf
,
mbuf
->
len
);
if
(
ctx
->
chunk_size
>
0
)
{
int
i
;
memset
(
&
ctx
->
chunk
[
ctx
->
chunk_size
],
0
,
3
-
ctx
->
chunk_size
);
cs_base64_emit_chunk
(
ctx
);
for
(
i
=
0
;
i
<
(
3
-
ctx
->
chunk_size
);
i
++
)
{
ctx
->
b64_putc
(
'='
,
ctx
->
user_data
);
}
}
}
}
size_t
mbuf_insert
(
struct
mbuf
*
a
,
size_t
off
,
const
void
*
buf
,
size_t
len
)
{
#define BASE64_ENCODE_BODY \
char
*
p
=
NULL
;
static const char *b64 = \
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; \
int i, j, a, b, c; \
\
for (i = j = 0; i < src_len; i += 3) { \
a = src[i]; \
b = i + 1 >= src_len ? 0 : src[i + 1]; \
c = i + 2 >= src_len ? 0 : src[i + 2]; \
\
BASE64_OUT(b64[a >> 2]); \
BASE64_OUT(b64[((a & 3) << 4) | (b >> 4)]); \
if (i + 1 < src_len) { \
BASE64_OUT(b64[(b & 15) << 2 | (c >> 6)]); \
} \
if (i + 2 < src_len) { \
BASE64_OUT(b64[c & 63]); \
} \
} \
\
while (j % 4 != 0) { \
BASE64_OUT('='); \
} \
BASE64_FLUSH()
assert
(
a
!=
NULL
);
#define BASE64_OUT(ch) \
assert
(
a
->
len
<=
a
->
size
);
do { \
assert
(
off
<=
a
->
len
);
dst[j++] = (ch); \
} while (0)
/* check overflow */
#define BASE64_FLUSH() \
if
(
~
(
size_t
)
0
-
(
size_t
)
a
->
buf
<
len
)
return
0
;
do { \
dst[j++] = '\0'; \
} while (0)
if
(
a
->
len
+
len
<=
a
->
size
)
{
void
cs_base64_encode
(
const
unsigned
char
*
src
,
int
src_len
,
char
*
dst
)
{
memmove
(
a
->
buf
+
off
+
len
,
a
->
buf
+
off
,
a
->
len
-
off
);
BASE64_ENCODE_BODY
;
if
(
buf
!=
NULL
)
{
}
memcpy
(
a
->
buf
+
off
,
buf
,
len
);
}
a
->
len
+=
len
;
}
else
if
((
p
=
(
char
*
)
MBUF_REALLOC
(
a
->
buf
,
(
a
->
len
+
len
)
*
MBUF_SIZE_MULTIPLIER
))
!=
NULL
)
{
a
->
buf
=
p
;
memmove
(
a
->
buf
+
off
+
len
,
a
->
buf
+
off
,
a
->
len
-
off
);
if
(
buf
!=
NULL
)
{
memcpy
(
a
->
buf
+
off
,
buf
,
len
);
}
a
->
len
+=
len
;
a
->
size
=
a
->
len
*
MBUF_SIZE_MULTIPLIER
;
}
else
{
len
=
0
;
}
return
len
;
#undef BASE64_OUT
#undef BASE64_FLUSH
#define BASE64_OUT(ch) \
do { \
fprintf(f, "%c", (ch)); \
j++; \
} while (0)
#define BASE64_FLUSH()
void
cs_fprint_base64
(
FILE
*
f
,
const
unsigned
char
*
src
,
int
src_len
)
{
BASE64_ENCODE_BODY
;
}
}
size_t
mbuf_append
(
struct
mbuf
*
a
,
const
void
*
buf
,
size_t
len
)
{
#undef BASE64_OUT
return
mbuf_insert
(
a
,
a
->
len
,
buf
,
len
);
#undef BASE64_FLUSH
/* Convert one byte of encoded base64 input stream to 6-bit chunk */
static
unsigned
char
from_b64
(
unsigned
char
ch
)
{
/* Inverse lookup map */
static
const
unsigned
char
tab
[
128
]
=
{
255
,
255
,
255
,
255
,
255
,
255
,
255
,
255
,
/* 0 */
255
,
255
,
255
,
255
,
255
,
255
,
255
,
255
,
/* 8 */
255
,
255
,
255
,
255
,
255
,
255
,
255
,
255
,
/* 16 */
255
,
255
,
255
,
255
,
255
,
255
,
255
,
255
,
/* 24 */
255
,
255
,
255
,
255
,
255
,
255
,
255
,
255
,
/* 32 */
255
,
255
,
255
,
62
,
255
,
255
,
255
,
63
,
/* 40 */
52
,
53
,
54
,
55
,
56
,
57
,
58
,
59
,
/* 48 */
60
,
61
,
255
,
255
,
255
,
200
,
255
,
255
,
/* 56 '=' is 200, on index 61 */
255
,
0
,
1
,
2
,
3
,
4
,
5
,
6
,
/* 64 */
7
,
8
,
9
,
10
,
11
,
12
,
13
,
14
,
/* 72 */
15
,
16
,
17
,
18
,
19
,
20
,
21
,
22
,
/* 80 */
23
,
24
,
25
,
255
,
255
,
255
,
255
,
255
,
/* 88 */
255
,
26
,
27
,
28
,
29
,
30
,
31
,
32
,
/* 96 */
33
,
34
,
35
,
36
,
37
,
38
,
39
,
40
,
/* 104 */
41
,
42
,
43
,
44
,
45
,
46
,
47
,
48
,
/* 112 */
49
,
50
,
51
,
255
,
255
,
255
,
255
,
255
,
/* 120 */
};
return
tab
[
ch
&
127
];
}
}
void
mbuf_remove
(
struct
mbuf
*
mb
,
size_t
n
)
{
int
cs_base64_decode
(
const
unsigned
char
*
s
,
int
len
,
char
*
dst
)
{
if
(
n
>
0
&&
n
<=
mb
->
len
)
{
unsigned
char
a
,
b
,
c
,
d
;
memmove
(
mb
->
buf
,
mb
->
buf
+
n
,
mb
->
len
-
n
);
int
orig_len
=
len
;
mb
->
len
-=
n
;
while
(
len
>=
4
&&
(
a
=
from_b64
(
s
[
0
]))
!=
255
&&
(
b
=
from_b64
(
s
[
1
]))
!=
255
&&
(
c
=
from_b64
(
s
[
2
]))
!=
255
&&
(
d
=
from_b64
(
s
[
3
]))
!=
255
)
{
s
+=
4
;
len
-=
4
;
if
(
a
==
200
||
b
==
200
)
break
;
/* '=' can't be there */
*
dst
++
=
a
<<
2
|
b
>>
4
;
if
(
c
==
200
)
break
;
*
dst
++
=
b
<<
4
|
c
>>
2
;
if
(
d
==
200
)
break
;
*
dst
++
=
c
<<
6
|
d
;
}
}
*
dst
=
0
;
return
orig_len
-
len
;
}
}
#endif
/* EXCLUDE_COMMON */
#endif
/* EXCLUDE_COMMON */
#ifdef NS_MODULE_LINES
#ifdef NS_MODULE_LINES
#line 1 "src/../../common/
sha1
.c"
#line 1 "src/../../common/
cs_dbg
.c"
/**/
/**/
#endif
#endif
/* Copyright(c) By Steve Reid <steve@edmweb.com> */
#include <stdarg.h>
/* 100% Public Domain */
#include <stdio.h>
#if !defined(DISABLE_SHA1) && !defined(EXCLUDE_COMMON)
/* Amalgamated: #include "sha1.h" */
#define SHA1HANDSOFF
void
cs_dbg_printf
(
const
char
*
fmt
,
...)
{
#if defined(__sun)
va_list
ap
;
/* Amalgamated: #include "solarisfixes.h" */
va_start
(
ap
,
fmt
);
vfprintf
(
stderr
,
fmt
,
ap
);
va_end
(
ap
);
fputc
(
'\n'
,
stderr
);
fflush
(
stderr
);
}
#ifdef NS_MODULE_LINES
#line 1 "src/../../common/dirent.c"
/**/
#endif
#endif
/*
* Copyright (c) 2015 Cesanta Software Limited
* All rights reserved
*/
union
char64long16
{
#ifndef EXCLUDE_COMMON
unsigned
char
c
[
64
];
uint32_t
l
[
16
];
};
#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
/* Amalgamated: #include "osdep.h" */
static
uint32_t
blk0
(
union
char64long16
*
block
,
int
i
)
{
/*
/* Forrest: SHA expect BIG_ENDIAN, swap if LITTLE_ENDIAN */
* This file contains POSIX opendir/closedir/readdir API implementation
#if BYTE_ORDER == LITTLE_ENDIAN
* for systems which do not natively support it (e.g. Windows).
block
->
l
[
i
]
=
*/
(
rol
(
block
->
l
[
i
],
24
)
&
0xFF00FF00
)
|
(
rol
(
block
->
l
[
i
],
8
)
&
0x00FF00FF
);
#endif
return
block
->
l
[
i
];
}
/* Avoid redefine warning (ARM /usr/include/sys/ucontext.h define R0~R4) */
#ifndef MG_FREE
#undef blk
#define MG_FREE free
#undef R0
#endif
#undef R1
#undef R2
#undef R3
#undef R4
#define blk(i) \
#ifndef MG_MALLOC
(block->l[i & 15] = rol(block->l[(i + 13) & 15] ^ block->l[(i + 8) & 15] ^ \
#define MG_MALLOC malloc
block->l[(i + 2) & 15] ^ block->l[i & 15], \
#endif
1))
#define R0(v, w, x, y, z, i) \
z += ((w & (x ^ y)) ^ y) + blk0(block, i) + 0x5A827999 + rol(v, 5); \
w = rol(w, 30);
#define R1(v, w, x, y, z, i) \
z += ((w & (x ^ y)) ^ y) + blk(i) + 0x5A827999 + rol(v, 5); \
w = rol(w, 30);
#define R2(v, w, x, y, z, i) \
z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + rol(v, 5); \
w = rol(w, 30);
#define R3(v, w, x, y, z, i) \
z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + rol(v, 5); \
w = rol(w, 30);
#define R4(v, w, x, y, z, i) \
z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + rol(v, 5); \
w = rol(w, 30);
void
cs_sha1_transform
(
uint32_t
state
[
5
],
const
unsigned
char
buffer
[
64
])
{
#ifdef _WIN32
uint32_t
a
,
b
,
c
,
d
,
e
;
DIR
*
opendir
(
const
char
*
name
)
{
union
char64long16
block
[
1
];
DIR
*
dir
=
NULL
;
wchar_t
wpath
[
MAX_PATH
];
DWORD
attrs
;
memcpy
(
block
,
buffer
,
64
);
if
(
name
==
NULL
)
{
a
=
state
[
0
];
SetLastError
(
ERROR_BAD_ARGUMENTS
);
b
=
state
[
1
];
}
else
if
((
dir
=
(
DIR
*
)
MG_MALLOC
(
sizeof
(
*
dir
)))
==
NULL
)
{
c
=
state
[
2
];
SetLastError
(
ERROR_NOT_ENOUGH_MEMORY
);
d
=
state
[
3
];
}
else
{
e
=
state
[
4
];
to_wchar
(
name
,
wpath
,
ARRAY_SIZE
(
wpath
));
R0
(
a
,
b
,
c
,
d
,
e
,
0
);
attrs
=
GetFileAttributesW
(
wpath
);
R0
(
e
,
a
,
b
,
c
,
d
,
1
);
if
(
attrs
!=
0xFFFFFFFF
&&
(
attrs
&
FILE_ATTRIBUTE_DIRECTORY
))
{
R0
(
d
,
e
,
a
,
b
,
c
,
2
);
(
void
)
wcscat
(
wpath
,
L"
\\
*"
);
R0
(
c
,
d
,
e
,
a
,
b
,
3
);
dir
->
handle
=
FindFirstFileW
(
wpath
,
&
dir
->
info
);
R0
(
b
,
c
,
d
,
e
,
a
,
4
);
dir
->
result
.
d_name
[
0
]
=
'\0'
;
R0
(
a
,
b
,
c
,
d
,
e
,
5
);
}
else
{
R0
(
e
,
a
,
b
,
c
,
d
,
6
);
MG_FREE
(
dir
);
R0
(
d
,
e
,
a
,
b
,
c
,
7
);
dir
=
NULL
;
R0
(
c
,
d
,
e
,
a
,
b
,
8
);
}
R0
(
b
,
c
,
d
,
e
,
a
,
9
);
}
R0
(
a
,
b
,
c
,
d
,
e
,
10
);
R0
(
e
,
a
,
b
,
c
,
d
,
11
);
R0
(
d
,
e
,
a
,
b
,
c
,
12
);
R0
(
c
,
d
,
e
,
a
,
b
,
13
);
R0
(
b
,
c
,
d
,
e
,
a
,
14
);
R0
(
a
,
b
,
c
,
d
,
e
,
15
);
R1
(
e
,
a
,
b
,
c
,
d
,
16
);
R1
(
d
,
e
,
a
,
b
,
c
,
17
);
R1
(
c
,
d
,
e
,
a
,
b
,
18
);
R1
(
b
,
c
,
d
,
e
,
a
,
19
);
R2
(
a
,
b
,
c
,
d
,
e
,
20
);
R2
(
e
,
a
,
b
,
c
,
d
,
21
);
R2
(
d
,
e
,
a
,
b
,
c
,
22
);
R2
(
c
,
d
,
e
,
a
,
b
,
23
);
R2
(
b
,
c
,
d
,
e
,
a
,
24
);
R2
(
a
,
b
,
c
,
d
,
e
,
25
);
R2
(
e
,
a
,
b
,
c
,
d
,
26
);
R2
(
d
,
e
,
a
,
b
,
c
,
27
);
R2
(
c
,
d
,
e
,
a
,
b
,
28
);
R2
(
b
,
c
,
d
,
e
,
a
,
29
);
R2
(
a
,
b
,
c
,
d
,
e
,
30
);
R2
(
e
,
a
,
b
,
c
,
d
,
31
);
R2
(
d
,
e
,
a
,
b
,
c
,
32
);
R2
(
c
,
d
,
e
,
a
,
b
,
33
);
R2
(
b
,
c
,
d
,
e
,
a
,
34
);
R2
(
a
,
b
,
c
,
d
,
e
,
35
);
R2
(
e
,
a
,
b
,
c
,
d
,
36
);
R2
(
d
,
e
,
a
,
b
,
c
,
37
);
R2
(
c
,
d
,
e
,
a
,
b
,
38
);
R2
(
b
,
c
,
d
,
e
,
a
,
39
);
R3
(
a
,
b
,
c
,
d
,
e
,
40
);
R3
(
e
,
a
,
b
,
c
,
d
,
41
);
R3
(
d
,
e
,
a
,
b
,
c
,
42
);
R3
(
c
,
d
,
e
,
a
,
b
,
43
);
R3
(
b
,
c
,
d
,
e
,
a
,
44
);
R3
(
a
,
b
,
c
,
d
,
e
,
45
);
R3
(
e
,
a
,
b
,
c
,
d
,
46
);
R3
(
d
,
e
,
a
,
b
,
c
,
47
);
R3
(
c
,
d
,
e
,
a
,
b
,
48
);
R3
(
b
,
c
,
d
,
e
,
a
,
49
);
R3
(
a
,
b
,
c
,
d
,
e
,
50
);
R3
(
e
,
a
,
b
,
c
,
d
,
51
);
R3
(
d
,
e
,
a
,
b
,
c
,
52
);
R3
(
c
,
d
,
e
,
a
,
b
,
53
);
R3
(
b
,
c
,
d
,
e
,
a
,
54
);
R3
(
a
,
b
,
c
,
d
,
e
,
55
);
R3
(
e
,
a
,
b
,
c
,
d
,
56
);
R3
(
d
,
e
,
a
,
b
,
c
,
57
);
R3
(
c
,
d
,
e
,
a
,
b
,
58
);
R3
(
b
,
c
,
d
,
e
,
a
,
59
);
R4
(
a
,
b
,
c
,
d
,
e
,
60
);
R4
(
e
,
a
,
b
,
c
,
d
,
61
);
R4
(
d
,
e
,
a
,
b
,
c
,
62
);
R4
(
c
,
d
,
e
,
a
,
b
,
63
);
R4
(
b
,
c
,
d
,
e
,
a
,
64
);
R4
(
a
,
b
,
c
,
d
,
e
,
65
);
R4
(
e
,
a
,
b
,
c
,
d
,
66
);
R4
(
d
,
e
,
a
,
b
,
c
,
67
);
R4
(
c
,
d
,
e
,
a
,
b
,
68
);
R4
(
b
,
c
,
d
,
e
,
a
,
69
);
R4
(
a
,
b
,
c
,
d
,
e
,
70
);
R4
(
e
,
a
,
b
,
c
,
d
,
71
);
R4
(
d
,
e
,
a
,
b
,
c
,
72
);
R4
(
c
,
d
,
e
,
a
,
b
,
73
);
R4
(
b
,
c
,
d
,
e
,
a
,
74
);
R4
(
a
,
b
,
c
,
d
,
e
,
75
);
R4
(
e
,
a
,
b
,
c
,
d
,
76
);
R4
(
d
,
e
,
a
,
b
,
c
,
77
);
R4
(
c
,
d
,
e
,
a
,
b
,
78
);
R4
(
b
,
c
,
d
,
e
,
a
,
79
);
state
[
0
]
+=
a
;
state
[
1
]
+=
b
;
state
[
2
]
+=
c
;
state
[
3
]
+=
d
;
state
[
4
]
+=
e
;
/* Erase working structures. The order of operations is important,
* used to ensure that compiler doesn't optimize those out. */
memset
(
block
,
0
,
sizeof
(
block
));
a
=
b
=
c
=
d
=
e
=
0
;
(
void
)
a
;
(
void
)
b
;
(
void
)
c
;
(
void
)
d
;
(
void
)
e
;
}
void
cs_sha1_init
(
cs_sha1_ctx
*
context
)
{
return
dir
;
context
->
state
[
0
]
=
0x67452301
;
context
->
state
[
1
]
=
0xEFCDAB89
;
context
->
state
[
2
]
=
0x98BADCFE
;
context
->
state
[
3
]
=
0x10325476
;
context
->
state
[
4
]
=
0xC3D2E1F0
;
context
->
count
[
0
]
=
context
->
count
[
1
]
=
0
;
}
}
void
cs_sha1_update
(
cs_sha1_ctx
*
context
,
const
unsigned
char
*
data
,
uint32_t
len
)
{
int
closedir
(
DIR
*
dir
)
{
uint32_t
i
,
j
;
int
result
=
0
;
j
=
context
->
count
[
0
];
if
(
dir
!=
NULL
)
{
if
((
context
->
count
[
0
]
+=
len
<<
3
)
<
j
)
context
->
count
[
1
]
++
;
if
(
dir
->
handle
!=
INVALID_HANDLE_VALUE
)
context
->
count
[
1
]
+=
(
len
>>
29
);
result
=
FindClose
(
dir
->
handle
)
?
0
:
-
1
;
j
=
(
j
>>
3
)
&
63
;
MG_FREE
(
dir
);
if
((
j
+
len
)
>
63
)
{
}
else
{
memcpy
(
&
context
->
buffer
[
j
],
data
,
(
i
=
64
-
j
));
result
=
-
1
;
cs_sha1_transform
(
context
->
state
,
context
->
buffer
);
SetLastError
(
ERROR_BAD_ARGUMENTS
);
for
(;
i
+
63
<
len
;
i
+=
64
)
{
cs_sha1_transform
(
context
->
state
,
&
data
[
i
]);
}
}
j
=
0
;
}
else
return
result
;
i
=
0
;
memcpy
(
&
context
->
buffer
[
j
],
&
data
[
i
],
len
-
i
);
}
}
void
cs_sha1_final
(
unsigned
char
digest
[
20
],
cs_sha1_ctx
*
context
)
{
struct
dirent
*
readdir
(
DIR
*
dir
)
{
unsigned
i
;
struct
dirent
*
result
=
0
;
unsigned
char
finalcount
[
8
],
c
;
for
(
i
=
0
;
i
<
8
;
i
++
)
{
if
(
dir
)
{
finalcount
[
i
]
=
(
unsigned
char
)
((
context
->
count
[(
i
>=
4
?
0
:
1
)]
>>
if
(
dir
->
handle
!=
INVALID_HANDLE_VALUE
)
{
((
3
-
(
i
&
3
))
*
8
))
&
result
=
&
dir
->
result
;
255
);
(
void
)
WideCharToMultiByte
(
CP_UTF8
,
0
,
dir
->
info
.
cFileName
,
-
1
,
result
->
d_name
,
sizeof
(
result
->
d_name
),
NULL
,
NULL
);
if
(
!
FindNextFileW
(
dir
->
handle
,
&
dir
->
info
))
{
(
void
)
FindClose
(
dir
->
handle
);
dir
->
handle
=
INVALID_HANDLE_VALUE
;
}
}
c
=
0200
;
cs_sha1_update
(
context
,
&
c
,
1
);
}
else
{
while
((
context
->
count
[
0
]
&
504
)
!=
448
)
{
SetLastError
(
ERROR_FILE_NOT_FOUND
);
c
=
0000
;
cs_sha1_update
(
context
,
&
c
,
1
);
}
}
cs_sha1_update
(
context
,
finalcount
,
8
);
}
else
{
for
(
i
=
0
;
i
<
20
;
i
++
)
{
SetLastError
(
ERROR_BAD_ARGUMENTS
);
digest
[
i
]
=
(
unsigned
char
)
((
context
->
state
[
i
>>
2
]
>>
((
3
-
(
i
&
3
))
*
8
))
&
255
);
}
}
memset
(
context
,
'\0'
,
sizeof
(
*
context
));
memset
(
&
finalcount
,
'\0'
,
sizeof
(
finalcount
));
}
void
cs_hmac_sha1
(
const
unsigned
char
*
key
,
size_t
keylen
,
return
result
;
const
unsigned
char
*
data
,
size_t
datalen
,
}
unsigned
char
out
[
20
])
{
#endif
cs_sha1_ctx
ctx
;
unsigned
char
buf1
[
64
],
buf2
[
64
],
tmp_key
[
20
],
i
;
if
(
keylen
>
sizeof
(
buf1
))
{
cs_sha1_init
(
&
ctx
);
cs_sha1_update
(
&
ctx
,
key
,
keylen
);
cs_sha1_final
(
tmp_key
,
&
ctx
);
key
=
tmp_key
;
keylen
=
sizeof
(
tmp_key
);
}
memset
(
buf1
,
0
,
sizeof
(
buf1
));
memset
(
buf2
,
0
,
sizeof
(
buf2
));
memcpy
(
buf1
,
key
,
keylen
);
memcpy
(
buf2
,
key
,
keylen
);
for
(
i
=
0
;
i
<
sizeof
(
buf1
);
i
++
)
{
buf1
[
i
]
^=
0x36
;
buf2
[
i
]
^=
0x5c
;
}
cs_sha1_init
(
&
ctx
);
cs_sha1_update
(
&
ctx
,
buf1
,
sizeof
(
buf1
));
cs_sha1_update
(
&
ctx
,
data
,
datalen
);
cs_sha1_final
(
out
,
&
ctx
);
cs_sha1_init
(
&
ctx
);
cs_sha1_update
(
&
ctx
,
buf2
,
sizeof
(
buf2
));
cs_sha1_update
(
&
ctx
,
out
,
20
);
cs_sha1_final
(
out
,
&
ctx
);
}
#endif
/* EXCLUDE_COMMON */
#endif
/* EXCLUDE_COMMON */
#ifdef NS_MODULE_LINES
#ifdef NS_MODULE_LINES
#line 1 "src/../
../common/md5
.c"
#line 1 "src/../
deps/frozen/frozen
.c"
/**/
/**/
#endif
#endif
/*
/*
* This code implements the MD5 message-digest algorithm.
* Copyright (c) 2004-2013 Sergey Lyubka <valenok@gmail.com>
* The algorithm is due to Ron Rivest. This code was
* Copyright (c) 2013 Cesanta Software Limited
* written by Colin Plumb in 1993, no copyright is claimed.
* All rights reserved
* This code is in the public domain; do with it what you wish.
*
*
*
Equivalent code is available from RSA Data Security, Inc.
*
This library is dual-licensed: you can redistribute it and/or modify
*
This code has been tested against that, and is equivalent,
*
it under the terms of the GNU General Public License version 2 as
*
except that you don't need to include two pages of legalese
*
published by the Free Software Foundation. For the terms of this
*
with every copy
.
*
license, see <http: *www.gnu.org/licenses/>
.
*
*
* To compute the message digest of a chunk of bytes, declare an
* You are free to use this library under the terms of the GNU General
* MD5Context structure, pass it to MD5Init, call MD5Update as
* Public License, but WITHOUT ANY WARRANTY; without even the implied
* needed on buffers full of bytes, and then call MD5Final, which
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* will fill a supplied 16-byte array with the digest.
* See the GNU General Public License for more details.
*
* Alternatively, you can license this library under a commercial
* license, as set out in <https://www.cesanta.com/license>.
*/
*/
#
if !defined(DISABLE_MD5) && !defined(EXCLUDE_COMMON)
#
define _CRT_SECURE_NO_WARNINGS
/* Disable deprecation warning in VS2005+ */
/* Amalgamated: #include "md5.h" */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
/* Amalgamated: #include "frozen.h" */
#ifndef CS_ENABLE_NATIVE_MD5
#ifdef _WIN32
static
void
byteReverse
(
unsigned
char
*
buf
,
unsigned
longs
)
{
#define snprintf _snprintf
/* Forrest: MD5 expect LITTLE_ENDIAN, swap if BIG_ENDIAN */
#if BYTE_ORDER == BIG_ENDIAN
do
{
uint32_t
t
=
(
uint32_t
)((
unsigned
)
buf
[
3
]
<<
8
|
buf
[
2
])
<<
16
|
((
unsigned
)
buf
[
1
]
<<
8
|
buf
[
0
]);
*
(
uint32_t
*
)
buf
=
t
;
buf
+=
4
;
}
while
(
--
longs
);
#else
(
void
)
buf
;
(
void
)
longs
;
#endif
#endif
}
#define F1(x, y, z) (z ^ (x & (y ^ z)))
#define F2(x, y, z) F1(z, x, y)
#define F3(x, y, z) (x ^ y ^ z)
#define F4(x, y, z) (y ^ (x | ~z))
#define MD5STEP(f, w, x, y, z, data, s) \
(w += f(x, y, z) + data, w = w << s | w >> (32 - s), w += x)
/*
* Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
* initialization constants.
*/
void
MD5_Init
(
MD5_CTX
*
ctx
)
{
ctx
->
buf
[
0
]
=
0x67452301
;
ctx
->
buf
[
1
]
=
0xefcdab89
;
ctx
->
buf
[
2
]
=
0x98badcfe
;
ctx
->
buf
[
3
]
=
0x10325476
;
ctx
->
bits
[
0
]
=
0
;
#ifndef FROZEN_REALLOC
ctx
->
bits
[
1
]
=
0
;
#define FROZEN_REALLOC realloc
}
#endif
static
void
MD5Transform
(
uint32_t
buf
[
4
],
uint32_t
const
in
[
16
])
{
#ifndef FROZEN_FREE
register
uint32_t
a
,
b
,
c
,
d
;
#define FROZEN_FREE free
#endif
a
=
buf
[
0
];
struct
frozen
{
b
=
buf
[
1
];
const
char
*
end
;
c
=
buf
[
2
];
const
char
*
cur
;
d
=
buf
[
3
];
struct
json_token
*
tokens
;
int
max_tokens
;
int
num_tokens
;
int
do_realloc
;
};
MD5STEP
(
F1
,
a
,
b
,
c
,
d
,
in
[
0
]
+
0xd76aa478
,
7
);
static
int
parse_object
(
struct
frozen
*
f
);
MD5STEP
(
F1
,
d
,
a
,
b
,
c
,
in
[
1
]
+
0xe8c7b756
,
12
);
static
int
parse_value
(
struct
frozen
*
f
);
MD5STEP
(
F1
,
c
,
d
,
a
,
b
,
in
[
2
]
+
0x242070db
,
17
);
MD5STEP
(
F1
,
b
,
c
,
d
,
a
,
in
[
3
]
+
0xc1bdceee
,
22
);
MD5STEP
(
F1
,
a
,
b
,
c
,
d
,
in
[
4
]
+
0xf57c0faf
,
7
);
MD5STEP
(
F1
,
d
,
a
,
b
,
c
,
in
[
5
]
+
0x4787c62a
,
12
);
MD5STEP
(
F1
,
c
,
d
,
a
,
b
,
in
[
6
]
+
0xa8304613
,
17
);
MD5STEP
(
F1
,
b
,
c
,
d
,
a
,
in
[
7
]
+
0xfd469501
,
22
);
MD5STEP
(
F1
,
a
,
b
,
c
,
d
,
in
[
8
]
+
0x698098d8
,
7
);
MD5STEP
(
F1
,
d
,
a
,
b
,
c
,
in
[
9
]
+
0x8b44f7af
,
12
);
MD5STEP
(
F1
,
c
,
d
,
a
,
b
,
in
[
10
]
+
0xffff5bb1
,
17
);
MD5STEP
(
F1
,
b
,
c
,
d
,
a
,
in
[
11
]
+
0x895cd7be
,
22
);
MD5STEP
(
F1
,
a
,
b
,
c
,
d
,
in
[
12
]
+
0x6b901122
,
7
);
MD5STEP
(
F1
,
d
,
a
,
b
,
c
,
in
[
13
]
+
0xfd987193
,
12
);
MD5STEP
(
F1
,
c
,
d
,
a
,
b
,
in
[
14
]
+
0xa679438e
,
17
);
MD5STEP
(
F1
,
b
,
c
,
d
,
a
,
in
[
15
]
+
0x49b40821
,
22
);
MD5STEP
(
F2
,
a
,
b
,
c
,
d
,
in
[
1
]
+
0xf61e2562
,
5
);
#define EXPECT(cond, err_code) do { if (!(cond)) return (err_code); } while (0)
MD5STEP
(
F2
,
d
,
a
,
b
,
c
,
in
[
6
]
+
0xc040b340
,
9
);
#define TRY(expr) do { int _n = expr; if (_n < 0) return _n; } while (0)
MD5STEP
(
F2
,
c
,
d
,
a
,
b
,
in
[
11
]
+
0x265e5a51
,
14
);
#define END_OF_STRING (-1)
MD5STEP
(
F2
,
b
,
c
,
d
,
a
,
in
[
0
]
+
0xe9b6c7aa
,
20
);
MD5STEP
(
F2
,
a
,
b
,
c
,
d
,
in
[
5
]
+
0xd62f105d
,
5
);
MD5STEP
(
F2
,
d
,
a
,
b
,
c
,
in
[
10
]
+
0x02441453
,
9
);
MD5STEP
(
F2
,
c
,
d
,
a
,
b
,
in
[
15
]
+
0xd8a1e681
,
14
);
MD5STEP
(
F2
,
b
,
c
,
d
,
a
,
in
[
4
]
+
0xe7d3fbc8
,
20
);
MD5STEP
(
F2
,
a
,
b
,
c
,
d
,
in
[
9
]
+
0x21e1cde6
,
5
);
MD5STEP
(
F2
,
d
,
a
,
b
,
c
,
in
[
14
]
+
0xc33707d6
,
9
);
MD5STEP
(
F2
,
c
,
d
,
a
,
b
,
in
[
3
]
+
0xf4d50d87
,
14
);
MD5STEP
(
F2
,
b
,
c
,
d
,
a
,
in
[
8
]
+
0x455a14ed
,
20
);
MD5STEP
(
F2
,
a
,
b
,
c
,
d
,
in
[
13
]
+
0xa9e3e905
,
5
);
MD5STEP
(
F2
,
d
,
a
,
b
,
c
,
in
[
2
]
+
0xfcefa3f8
,
9
);
MD5STEP
(
F2
,
c
,
d
,
a
,
b
,
in
[
7
]
+
0x676f02d9
,
14
);
MD5STEP
(
F2
,
b
,
c
,
d
,
a
,
in
[
12
]
+
0x8d2a4c8a
,
20
);
MD5STEP
(
F3
,
a
,
b
,
c
,
d
,
in
[
5
]
+
0xfffa3942
,
4
);
static
int
left
(
const
struct
frozen
*
f
)
{
MD5STEP
(
F3
,
d
,
a
,
b
,
c
,
in
[
8
]
+
0x8771f681
,
11
);
return
f
->
end
-
f
->
cur
;
MD5STEP
(
F3
,
c
,
d
,
a
,
b
,
in
[
11
]
+
0x6d9d6122
,
16
);
}
MD5STEP
(
F3
,
b
,
c
,
d
,
a
,
in
[
14
]
+
0xfde5380c
,
23
);
MD5STEP
(
F3
,
a
,
b
,
c
,
d
,
in
[
1
]
+
0xa4beea44
,
4
);
MD5STEP
(
F3
,
d
,
a
,
b
,
c
,
in
[
4
]
+
0x4bdecfa9
,
11
);
MD5STEP
(
F3
,
c
,
d
,
a
,
b
,
in
[
7
]
+
0xf6bb4b60
,
16
);
MD5STEP
(
F3
,
b
,
c
,
d
,
a
,
in
[
10
]
+
0xbebfbc70
,
23
);
MD5STEP
(
F3
,
a
,
b
,
c
,
d
,
in
[
13
]
+
0x289b7ec6
,
4
);
MD5STEP
(
F3
,
d
,
a
,
b
,
c
,
in
[
0
]
+
0xeaa127fa
,
11
);
MD5STEP
(
F3
,
c
,
d
,
a
,
b
,
in
[
3
]
+
0xd4ef3085
,
16
);
MD5STEP
(
F3
,
b
,
c
,
d
,
a
,
in
[
6
]
+
0x04881d05
,
23
);
MD5STEP
(
F3
,
a
,
b
,
c
,
d
,
in
[
9
]
+
0xd9d4d039
,
4
);
MD5STEP
(
F3
,
d
,
a
,
b
,
c
,
in
[
12
]
+
0xe6db99e5
,
11
);
MD5STEP
(
F3
,
c
,
d
,
a
,
b
,
in
[
15
]
+
0x1fa27cf8
,
16
);
MD5STEP
(
F3
,
b
,
c
,
d
,
a
,
in
[
2
]
+
0xc4ac5665
,
23
);
MD5STEP
(
F4
,
a
,
b
,
c
,
d
,
in
[
0
]
+
0xf4292244
,
6
);
static
int
is_space
(
int
ch
)
{
MD5STEP
(
F4
,
d
,
a
,
b
,
c
,
in
[
7
]
+
0x432aff97
,
10
);
return
ch
==
' '
||
ch
==
'\t'
||
ch
==
'\r'
||
ch
==
'\n'
;
MD5STEP
(
F4
,
c
,
d
,
a
,
b
,
in
[
14
]
+
0xab9423a7
,
15
);
}
MD5STEP
(
F4
,
b
,
c
,
d
,
a
,
in
[
5
]
+
0xfc93a039
,
21
);
MD5STEP
(
F4
,
a
,
b
,
c
,
d
,
in
[
12
]
+
0x655b59c3
,
6
);
MD5STEP
(
F4
,
d
,
a
,
b
,
c
,
in
[
3
]
+
0x8f0ccc92
,
10
);
MD5STEP
(
F4
,
c
,
d
,
a
,
b
,
in
[
10
]
+
0xffeff47d
,
15
);
MD5STEP
(
F4
,
b
,
c
,
d
,
a
,
in
[
1
]
+
0x85845dd1
,
21
);
MD5STEP
(
F4
,
a
,
b
,
c
,
d
,
in
[
8
]
+
0x6fa87e4f
,
6
);
MD5STEP
(
F4
,
d
,
a
,
b
,
c
,
in
[
15
]
+
0xfe2ce6e0
,
10
);
MD5STEP
(
F4
,
c
,
d
,
a
,
b
,
in
[
6
]
+
0xa3014314
,
15
);
MD5STEP
(
F4
,
b
,
c
,
d
,
a
,
in
[
13
]
+
0x4e0811a1
,
21
);
MD5STEP
(
F4
,
a
,
b
,
c
,
d
,
in
[
4
]
+
0xf7537e82
,
6
);
MD5STEP
(
F4
,
d
,
a
,
b
,
c
,
in
[
11
]
+
0xbd3af235
,
10
);
MD5STEP
(
F4
,
c
,
d
,
a
,
b
,
in
[
2
]
+
0x2ad7d2bb
,
15
);
MD5STEP
(
F4
,
b
,
c
,
d
,
a
,
in
[
9
]
+
0xeb86d391
,
21
);
buf
[
0
]
+=
a
;
static
void
skip_whitespaces
(
struct
frozen
*
f
)
{
buf
[
1
]
+=
b
;
while
(
f
->
cur
<
f
->
end
&&
is_space
(
*
f
->
cur
))
f
->
cur
++
;
buf
[
2
]
+=
c
;
buf
[
3
]
+=
d
;
}
}
void
MD5_Update
(
MD5_CTX
*
ctx
,
const
unsigned
char
*
buf
,
size_t
len
)
{
static
int
cur
(
struct
frozen
*
f
)
{
uint32_t
t
;
skip_whitespaces
(
f
);
return
f
->
cur
>=
f
->
end
?
END_OF_STRING
:
*
(
unsigned
char
*
)
f
->
cur
;
}
t
=
ctx
->
bits
[
0
];
static
int
test_and_skip
(
struct
frozen
*
f
,
int
expected
)
{
if
((
ctx
->
bits
[
0
]
=
t
+
((
uint32_t
)
len
<<
3
))
<
t
)
ctx
->
bits
[
1
]
++
;
int
ch
=
cur
(
f
);
ctx
->
bits
[
1
]
+=
(
uint32_t
)
len
>>
29
;
if
(
ch
==
expected
)
{
f
->
cur
++
;
return
0
;
}
return
ch
==
END_OF_STRING
?
JSON_STRING_INCOMPLETE
:
JSON_STRING_INVALID
;
}
t
=
(
t
>>
3
)
&
0x3f
;
static
int
is_alpha
(
int
ch
)
{
return
(
ch
>=
'a'
&&
ch
<=
'z'
)
||
(
ch
>=
'A'
&&
ch
<=
'Z'
);
}
if
(
t
)
{
static
int
is_digit
(
int
ch
)
{
unsigned
char
*
p
=
(
unsigned
char
*
)
ctx
->
in
+
t
;
return
ch
>=
'0'
&&
ch
<=
'9'
;
}
t
=
64
-
t
;
static
int
is_hex_digit
(
int
ch
)
{
if
(
len
<
t
)
{
return
is_digit
(
ch
)
||
(
ch
>=
'a'
&&
ch
<=
'f'
)
||
(
ch
>=
'A'
&&
ch
<=
'F'
);
memcpy
(
p
,
buf
,
len
);
}
return
;
}
memcpy
(
p
,
buf
,
t
);
byteReverse
(
ctx
->
in
,
16
);
MD5Transform
(
ctx
->
buf
,
(
uint32_t
*
)
ctx
->
in
);
buf
+=
t
;
len
-=
t
;
}
while
(
len
>=
64
)
{
static
int
get_escape_len
(
const
char
*
s
,
int
len
)
{
memcpy
(
ctx
->
in
,
buf
,
64
);
switch
(
*
s
)
{
byteReverse
(
ctx
->
in
,
16
);
case
'u'
:
MD5Transform
(
ctx
->
buf
,
(
uint32_t
*
)
ctx
->
in
);
return
len
<
6
?
JSON_STRING_INCOMPLETE
:
buf
+=
64
;
is_hex_digit
(
s
[
1
])
&&
is_hex_digit
(
s
[
2
])
&&
len
-=
64
;
is_hex_digit
(
s
[
3
])
&&
is_hex_digit
(
s
[
4
])
?
5
:
JSON_STRING_INVALID
;
case
'"'
:
case
'\\'
:
case
'/'
:
case
'b'
:
case
'f'
:
case
'n'
:
case
'r'
:
case
't'
:
return
len
<
2
?
JSON_STRING_INCOMPLETE
:
1
;
default:
return
JSON_STRING_INVALID
;
}
}
memcpy
(
ctx
->
in
,
buf
,
len
);
}
}
void
MD5_Final
(
unsigned
char
digest
[
16
],
MD5_CTX
*
ctx
)
{
static
int
capture_ptr
(
struct
frozen
*
f
,
const
char
*
ptr
,
enum
json_type
type
)
{
unsigned
count
;
if
(
f
->
do_realloc
&&
f
->
num_tokens
>=
f
->
max_tokens
)
{
unsigned
char
*
p
;
int
new_size
=
f
->
max_tokens
==
0
?
100
:
f
->
max_tokens
*
2
;
uint32_t
*
a
;
void
*
p
=
FROZEN_REALLOC
(
f
->
tokens
,
new_size
*
sizeof
(
f
->
tokens
[
0
]));
if
(
p
==
NULL
)
return
JSON_TOKEN_ARRAY_TOO_SMALL
;
f
->
max_tokens
=
new_size
;
f
->
tokens
=
(
struct
json_token
*
)
p
;
}
if
(
f
->
tokens
==
NULL
||
f
->
max_tokens
==
0
)
return
0
;
if
(
f
->
num_tokens
>=
f
->
max_tokens
)
return
JSON_TOKEN_ARRAY_TOO_SMALL
;
f
->
tokens
[
f
->
num_tokens
].
ptr
=
ptr
;
f
->
tokens
[
f
->
num_tokens
].
type
=
type
;
f
->
num_tokens
++
;
return
0
;
}
count
=
(
ctx
->
bits
[
0
]
>>
3
)
&
0x3F
;
static
int
capture_len
(
struct
frozen
*
f
,
int
token_index
,
const
char
*
ptr
)
{
if
(
f
->
tokens
==
0
||
f
->
max_tokens
==
0
)
return
0
;
EXPECT
(
token_index
>=
0
&&
token_index
<
f
->
max_tokens
,
JSON_STRING_INVALID
);
f
->
tokens
[
token_index
].
len
=
ptr
-
f
->
tokens
[
token_index
].
ptr
;
f
->
tokens
[
token_index
].
num_desc
=
(
f
->
num_tokens
-
1
)
-
token_index
;
return
0
;
}
p
=
ctx
->
in
+
count
;
/* identifier = letter { letter | digit | '_' } */
*
p
++
=
0x80
;
static
int
parse_identifier
(
struct
frozen
*
f
)
{
count
=
64
-
1
-
count
;
EXPECT
(
is_alpha
(
cur
(
f
)),
JSON_STRING_INVALID
);
if
(
count
<
8
)
{
TRY
(
capture_ptr
(
f
,
f
->
cur
,
JSON_TYPE_STRING
));
memset
(
p
,
0
,
count
);
while
(
f
->
cur
<
f
->
end
&&
byteReverse
(
ctx
->
in
,
16
);
(
*
f
->
cur
==
'_'
||
is_alpha
(
*
f
->
cur
)
||
is_digit
(
*
f
->
cur
)))
{
MD5Transform
(
ctx
->
buf
,
(
uint32_t
*
)
ctx
->
in
);
f
->
cur
++
;
memset
(
ctx
->
in
,
0
,
56
);
}
else
{
memset
(
p
,
0
,
count
-
8
);
}
}
byteReverse
(
ctx
->
in
,
14
);
capture_len
(
f
,
f
->
num_tokens
-
1
,
f
->
cur
);
return
0
;
}
a
=
(
uint32_t
*
)
ctx
->
in
;
static
int
get_utf8_char_len
(
unsigned
char
ch
)
{
a
[
14
]
=
ctx
->
bits
[
0
];
if
((
ch
&
0x80
)
==
0
)
return
1
;
a
[
15
]
=
ctx
->
bits
[
1
];
switch
(
ch
&
0xf0
)
{
case
0xf0
:
return
4
;
case
0xe0
:
return
3
;
default:
return
2
;
}
}
MD5Transform
(
ctx
->
buf
,
(
uint32_t
*
)
ctx
->
in
);
/* string = '"' { quoted_printable_chars } '"' */
byteReverse
((
unsigned
char
*
)
ctx
->
buf
,
4
);
static
int
parse_string
(
struct
frozen
*
f
)
{
memcpy
(
digest
,
ctx
->
buf
,
16
);
int
n
,
ch
=
0
,
len
=
0
;
memset
((
char
*
)
ctx
,
0
,
sizeof
(
*
ctx
));
TRY
(
test_and_skip
(
f
,
'"'
));
TRY
(
capture_ptr
(
f
,
f
->
cur
,
JSON_TYPE_STRING
));
for
(;
f
->
cur
<
f
->
end
;
f
->
cur
+=
len
)
{
ch
=
*
(
unsigned
char
*
)
f
->
cur
;
len
=
get_utf8_char_len
((
unsigned
char
)
ch
);
EXPECT
(
ch
>=
32
&&
len
>
0
,
JSON_STRING_INVALID
);
/* No control chars */
EXPECT
(
len
<
left
(
f
),
JSON_STRING_INCOMPLETE
);
if
(
ch
==
'\\'
)
{
EXPECT
((
n
=
get_escape_len
(
f
->
cur
+
1
,
left
(
f
)))
>
0
,
n
);
len
+=
n
;
}
else
if
(
ch
==
'"'
)
{
capture_len
(
f
,
f
->
num_tokens
-
1
,
f
->
cur
);
f
->
cur
++
;
break
;
};
}
return
ch
==
'"'
?
0
:
JSON_STRING_INCOMPLETE
;
}
}
#endif
/* CS_ENABLE_NATIVE_MD5 */
/*
/* number = [ '-' ] digit+ [ '.' digit+ ] [ ['e'|'E'] ['+'|'-'] digit+ ] */
* Stringify binary data. Output buffer size must be 2 * size_of_input + 1
static
int
parse_number
(
struct
frozen
*
f
)
{
* because each byte of input takes 2 bytes in string representation
int
ch
=
cur
(
f
);
* plus 1 byte for the terminating \0 character.
TRY
(
capture_ptr
(
f
,
f
->
cur
,
JSON_TYPE_NUMBER
));
*/
if
(
ch
==
'-'
)
f
->
cur
++
;
void
cs_to_hex
(
char
*
to
,
const
unsigned
char
*
p
,
size_t
len
)
{
EXPECT
(
f
->
cur
<
f
->
end
,
JSON_STRING_INCOMPLETE
);
static
const
char
*
hex
=
"0123456789abcdef"
;
EXPECT
(
is_digit
(
f
->
cur
[
0
]),
JSON_STRING_INVALID
);
while
(
f
->
cur
<
f
->
end
&&
is_digit
(
f
->
cur
[
0
]))
f
->
cur
++
;
if
(
f
->
cur
<
f
->
end
&&
f
->
cur
[
0
]
==
'.'
)
{
f
->
cur
++
;
EXPECT
(
f
->
cur
<
f
->
end
,
JSON_STRING_INCOMPLETE
);
EXPECT
(
is_digit
(
f
->
cur
[
0
]),
JSON_STRING_INVALID
);
while
(
f
->
cur
<
f
->
end
&&
is_digit
(
f
->
cur
[
0
]))
f
->
cur
++
;
}
if
(
f
->
cur
<
f
->
end
&&
(
f
->
cur
[
0
]
==
'e'
||
f
->
cur
[
0
]
==
'E'
))
{
f
->
cur
++
;
EXPECT
(
f
->
cur
<
f
->
end
,
JSON_STRING_INCOMPLETE
);
if
((
f
->
cur
[
0
]
==
'+'
||
f
->
cur
[
0
]
==
'-'
))
f
->
cur
++
;
EXPECT
(
f
->
cur
<
f
->
end
,
JSON_STRING_INCOMPLETE
);
EXPECT
(
is_digit
(
f
->
cur
[
0
]),
JSON_STRING_INVALID
);
while
(
f
->
cur
<
f
->
end
&&
is_digit
(
f
->
cur
[
0
]))
f
->
cur
++
;
}
capture_len
(
f
,
f
->
num_tokens
-
1
,
f
->
cur
);
return
0
;
}
for
(;
len
--
;
p
++
)
{
/* array = '[' [ value { ',' value } ] ']' */
*
to
++
=
hex
[
p
[
0
]
>>
4
];
static
int
parse_array
(
struct
frozen
*
f
)
{
*
to
++
=
hex
[
p
[
0
]
&
0x0f
];
int
ind
;
TRY
(
test_and_skip
(
f
,
'['
));
TRY
(
capture_ptr
(
f
,
f
->
cur
-
1
,
JSON_TYPE_ARRAY
));
ind
=
f
->
num_tokens
-
1
;
while
(
cur
(
f
)
!=
']'
)
{
TRY
(
parse_value
(
f
));
if
(
cur
(
f
)
==
','
)
f
->
cur
++
;
}
}
*
to
=
'\0'
;
TRY
(
test_and_skip
(
f
,
']'
));
capture_len
(
f
,
ind
,
f
->
cur
);
return
0
;
}
}
char
*
cs_md5
(
char
buf
[
33
],
...
)
{
static
int
compare
(
const
char
*
s
,
const
char
*
str
,
int
len
)
{
unsigned
char
hash
[
16
]
;
int
i
=
0
;
const
unsigned
char
*
p
;
while
(
i
<
len
&&
s
[
i
]
==
str
[
i
])
i
++
;
va_list
ap
;
return
i
==
len
?
1
:
0
;
MD5_CTX
ctx
;
}
MD5_Init
(
&
ctx
);
static
int
expect
(
struct
frozen
*
f
,
const
char
*
s
,
int
len
,
enum
json_type
t
)
{
int
i
,
n
=
left
(
f
);
va_start
(
ap
,
buf
);
TRY
(
capture_ptr
(
f
,
f
->
cur
,
t
)
);
while
((
p
=
va_arg
(
ap
,
const
unsigned
char
*
)
)
!=
NULL
)
{
for
(
i
=
0
;
i
<
len
;
i
++
)
{
size_t
len
=
va_arg
(
ap
,
size_t
)
;
if
(
i
>=
n
)
return
JSON_STRING_INCOMPLETE
;
MD5_Update
(
&
ctx
,
p
,
len
)
;
if
(
f
->
cur
[
i
]
!=
s
[
i
])
return
JSON_STRING_INVALID
;
}
}
va_end
(
ap
);
f
->
cur
+=
len
;
TRY
(
capture_len
(
f
,
f
->
num_tokens
-
1
,
f
->
cur
));
MD5_Final
(
hash
,
&
ctx
);
cs_to_hex
(
buf
,
hash
,
sizeof
(
hash
));
return
buf
;
return
0
;
}
}
#endif
/* EXCLUDE_COMMON */
/* value = 'null' | 'true' | 'false' | number | string | array | object */
#ifdef NS_MODULE_LINES
static
int
parse_value
(
struct
frozen
*
f
)
{
#line 1 "src/../../common/base64.c"
int
ch
=
cur
(
f
);
/**/
#endif
/*
* Copyright (c) 2014 Cesanta Software Limited
* All rights reserved
*/
#ifndef EXCLUDE_COMMON
/* Amalgamated: #include "base64.h" */
#include <string.h>
/* ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ */
switch
(
ch
)
{
case
'"'
:
TRY
(
parse_string
(
f
));
break
;
case
'{'
:
TRY
(
parse_object
(
f
));
break
;
case
'['
:
TRY
(
parse_array
(
f
));
break
;
case
'n'
:
TRY
(
expect
(
f
,
"null"
,
4
,
JSON_TYPE_NULL
));
break
;
case
't'
:
TRY
(
expect
(
f
,
"true"
,
4
,
JSON_TYPE_TRUE
));
break
;
case
'f'
:
TRY
(
expect
(
f
,
"false"
,
5
,
JSON_TYPE_FALSE
));
break
;
case
'-'
:
case
'0'
:
case
'1'
:
case
'2'
:
case
'3'
:
case
'4'
:
case
'5'
:
case
'6'
:
case
'7'
:
case
'8'
:
case
'9'
:
TRY
(
parse_number
(
f
));
break
;
default:
return
ch
==
END_OF_STRING
?
JSON_STRING_INCOMPLETE
:
JSON_STRING_INVALID
;
}
#define NUM_UPPERCASES ('Z' - 'A' + 1)
return
0
;
#define NUM_LETTERS (NUM_UPPERCASES * 2)
}
#define NUM_DIGITS ('9' - '0' + 1)
/*
/* key = identifier | string */
* Emit a base64 code char.
static
int
parse_key
(
struct
frozen
*
f
)
{
*
int
ch
=
cur
(
f
);
* Doesn't use memory, thus it's safe to use to safely dump memory in crashdumps
#if 0
*/
printf("%s 1 [%.*s]\n", __func__, (int) (f->end - f->cur), f->cur);
static
void
cs_base64_emit_code
(
struct
cs_base64_ctx
*
ctx
,
int
v
)
{
#endif
if
(
v
<
NUM_UPPERCASES
)
{
if
(
is_alpha
(
ch
))
{
ctx
->
b64_putc
(
v
+
'A'
,
ctx
->
user_data
);
TRY
(
parse_identifier
(
f
));
}
else
if
(
v
<
(
NUM_LETTERS
))
{
}
else
if
(
ch
==
'"'
)
{
ctx
->
b64_putc
(
v
-
NUM_UPPERCASES
+
'a'
,
ctx
->
user_data
);
TRY
(
parse_string
(
f
));
}
else
if
(
v
<
(
NUM_LETTERS
+
NUM_DIGITS
))
{
ctx
->
b64_putc
(
v
-
NUM_LETTERS
+
'0'
,
ctx
->
user_data
);
}
else
{
}
else
{
ctx
->
b64_putc
(
v
-
NUM_LETTERS
-
NUM_DIGITS
==
0
?
'+'
:
'/'
,
return
ch
==
END_OF_STRING
?
JSON_STRING_INCOMPLETE
:
JSON_STRING_INVALID
;
ctx
->
user_data
);
}
}
return
0
;
}
}
static
void
cs_base64_emit_chunk
(
struct
cs_base64_ctx
*
ctx
)
{
/* pair = key ':' value */
int
a
,
b
,
c
;
static
int
parse_pair
(
struct
frozen
*
f
)
{
TRY
(
parse_key
(
f
));
a
=
ctx
->
chunk
[
0
];
TRY
(
test_and_skip
(
f
,
':'
));
b
=
ctx
->
chunk
[
1
];
TRY
(
parse_value
(
f
));
c
=
ctx
->
chunk
[
2
];
return
0
;
}
cs_base64_emit_code
(
ctx
,
a
>>
2
);
/* object = '{' pair { ',' pair } '}' */
cs_base64_emit_code
(
ctx
,
((
a
&
3
)
<<
4
)
|
(
b
>>
4
));
static
int
parse_object
(
struct
frozen
*
f
)
{
if
(
ctx
->
chunk_size
>
1
)
{
int
ind
;
cs_base64_emit_code
(
ctx
,
(
b
&
15
)
<<
2
|
(
c
>>
6
));
TRY
(
test_and_skip
(
f
,
'{'
));
}
TRY
(
capture_ptr
(
f
,
f
->
cur
-
1
,
JSON_TYPE_OBJECT
));
if
(
ctx
->
chunk_size
>
2
)
{
ind
=
f
->
num_tokens
-
1
;
cs_base64_emit_code
(
ctx
,
c
&
63
);
while
(
cur
(
f
)
!=
'}'
)
{
TRY
(
parse_pair
(
f
));
if
(
cur
(
f
)
==
','
)
f
->
cur
++
;
}
}
TRY
(
test_and_skip
(
f
,
'}'
));
capture_len
(
f
,
ind
,
f
->
cur
);
return
0
;
}
}
void
cs_base64_init
(
struct
cs_base64_ctx
*
ctx
,
cs_base64_putc_t
b64_putc
,
static
int
doit
(
struct
frozen
*
f
)
{
void
*
user_data
)
{
if
(
f
->
cur
==
0
||
f
->
end
<
f
->
cur
)
return
JSON_STRING_INVALID
;
ctx
->
chunk_size
=
0
;
if
(
f
->
end
==
f
->
cur
)
return
JSON_STRING_INCOMPLETE
;
ctx
->
b64_putc
=
b64_putc
;
TRY
(
parse_object
(
f
));
ctx
->
user_data
=
user_data
;
TRY
(
capture_ptr
(
f
,
f
->
cur
,
JSON_TYPE_EOF
));
}
capture_len
(
f
,
f
->
num_tokens
,
f
->
cur
);
return
0
;
void
cs_base64_update
(
struct
cs_base64_ctx
*
ctx
,
const
char
*
str
,
size_t
len
)
{
const
unsigned
char
*
src
=
(
const
unsigned
char
*
)
str
;
size_t
i
;
for
(
i
=
0
;
i
<
len
;
i
++
)
{
ctx
->
chunk
[
ctx
->
chunk_size
++
]
=
src
[
i
];
if
(
ctx
->
chunk_size
==
3
)
{
cs_base64_emit_chunk
(
ctx
);
ctx
->
chunk_size
=
0
;
}
}
}
void
cs_base64_finish
(
struct
cs_base64_ctx
*
ctx
)
{
if
(
ctx
->
chunk_size
>
0
)
{
int
i
;
memset
(
&
ctx
->
chunk
[
ctx
->
chunk_size
],
0
,
3
-
ctx
->
chunk_size
);
cs_base64_emit_chunk
(
ctx
);
for
(
i
=
0
;
i
<
(
3
-
ctx
->
chunk_size
);
i
++
)
{
ctx
->
b64_putc
(
'='
,
ctx
->
user_data
);
}
}
}
}
#define BASE64_ENCODE_BODY \
/* json = object */
static const char *b64 = \
int
parse_json
(
const
char
*
s
,
int
s_len
,
struct
json_token
*
arr
,
int
arr_len
)
{
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; \
struct
frozen
frozen
;
int i, j, a, b, c; \
\
for (i = j = 0; i < src_len; i += 3) { \
a = src[i]; \
b = i + 1 >= src_len ? 0 : src[i + 1]; \
c = i + 2 >= src_len ? 0 : src[i + 2]; \
\
BASE64_OUT(b64[a >> 2]); \
BASE64_OUT(b64[((a & 3) << 4) | (b >> 4)]); \
if (i + 1 < src_len) { \
BASE64_OUT(b64[(b & 15) << 2 | (c >> 6)]); \
} \
if (i + 2 < src_len) { \
BASE64_OUT(b64[c & 63]); \
} \
} \
\
while (j % 4 != 0) { \
BASE64_OUT('='); \
} \
BASE64_FLUSH()
#define BASE64_OUT(ch) \
memset
(
&
frozen
,
0
,
sizeof
(
frozen
));
do { \
frozen
.
end
=
s
+
s_len
;
dst[j++] = (ch); \
frozen
.
cur
=
s
;
} while (0)
frozen
.
tokens
=
arr
;
frozen
.
max_tokens
=
arr_len
;
#define BASE64_FLUSH() \
TRY
(
doit
(
&
frozen
));
do { \
dst[j++] = '\0'; \
} while (0)
void
cs_base64_encode
(
const
unsigned
char
*
src
,
int
src_len
,
char
*
dst
)
{
return
frozen
.
cur
-
s
;
BASE64_ENCODE_BODY
;
}
}
#undef BASE64_OUT
struct
json_token
*
parse_json2
(
const
char
*
s
,
int
s_len
)
{
#undef BASE64_FLUSH
struct
frozen
frozen
;
#define BASE64_OUT(ch) \
do { \
fprintf(f, "%c", (ch)); \
j++; \
} while (0)
#define BASE64_FLUSH()
memset
(
&
frozen
,
0
,
sizeof
(
frozen
));
frozen
.
end
=
s
+
s_len
;
frozen
.
cur
=
s
;
frozen
.
do_realloc
=
1
;
void
cs_fprint_base64
(
FILE
*
f
,
const
unsigned
char
*
src
,
int
src_len
)
{
if
(
doit
(
&
frozen
)
<
0
)
{
BASE64_ENCODE_BODY
;
FROZEN_FREE
((
void
*
)
frozen
.
tokens
);
frozen
.
tokens
=
NULL
;
}
return
frozen
.
tokens
;
}
}
#undef BASE64_OUT
static
int
path_part_len
(
const
char
*
p
)
{
#undef BASE64_FLUSH
int
i
=
0
;
while
(
p
[
i
]
!=
'\0'
&&
p
[
i
]
!=
'['
&&
p
[
i
]
!=
'.'
)
i
++
;
return
i
;
}
/* Convert one byte of encoded base64 input stream to 6-bit chunk */
struct
json_token
*
find_json_token
(
struct
json_token
*
toks
,
const
char
*
path
)
{
static
unsigned
char
from_b64
(
unsigned
char
ch
)
{
while
(
path
!=
0
&&
path
[
0
]
!=
'\0'
)
{
/* Inverse lookup map */
int
i
,
ind2
=
0
,
ind
=
-
1
,
skip
=
2
,
n
=
path_part_len
(
path
);
static
const
unsigned
char
tab
[
128
]
=
{
if
(
path
[
0
]
==
'['
)
{
255
,
255
,
255
,
255
,
if
(
toks
->
type
!=
JSON_TYPE_ARRAY
||
!
is_digit
(
path
[
1
]))
return
0
;
255
,
255
,
255
,
255
,
/* 0 */
for
(
ind
=
0
,
n
=
1
;
path
[
n
]
!=
']'
&&
path
[
n
]
!=
'\0'
;
n
++
)
{
255
,
255
,
255
,
255
,
if
(
!
is_digit
(
path
[
n
]))
return
0
;
255
,
255
,
255
,
255
,
/* 8 */
ind
*=
10
;
255
,
255
,
255
,
255
,
ind
+=
path
[
n
]
-
'0'
;
255
,
255
,
255
,
255
,
/* 16 */
}
255
,
255
,
255
,
255
,
if
(
path
[
n
++
]
!=
']'
)
return
0
;
255
,
255
,
255
,
255
,
/* 24 */
skip
=
1
;
/* In objects, we skip 2 elems while iterating, in arrays 1. */
255
,
255
,
255
,
255
,
}
else
if
(
toks
->
type
!=
JSON_TYPE_OBJECT
)
return
0
;
255
,
255
,
255
,
255
,
/* 32 */
toks
++
;
255
,
255
,
255
,
62
,
for
(
i
=
0
;
i
<
toks
[
-
1
].
num_desc
;
i
+=
skip
,
ind2
++
)
{
255
,
255
,
255
,
63
,
/* 40 */
/* ind == -1 indicated that we're iterating an array, not object */
52
,
53
,
54
,
55
,
if
(
ind
==
-
1
&&
toks
[
i
].
type
!=
JSON_TYPE_STRING
)
return
0
;
56
,
57
,
58
,
59
,
/* 48 */
if
(
ind2
==
ind
||
60
,
61
,
255
,
255
,
(
ind
==
-
1
&&
toks
[
i
].
len
==
n
&&
compare
(
path
,
toks
[
i
].
ptr
,
n
)))
{
255
,
200
,
255
,
255
,
/* 56 '=' is 200, on index 61 */
i
+=
skip
-
1
;
255
,
0
,
1
,
2
,
break
;
3
,
4
,
5
,
6
,
/* 64 */
7
,
8
,
9
,
10
,
11
,
12
,
13
,
14
,
/* 72 */
15
,
16
,
17
,
18
,
19
,
20
,
21
,
22
,
/* 80 */
23
,
24
,
25
,
255
,
255
,
255
,
255
,
255
,
/* 88 */
255
,
26
,
27
,
28
,
29
,
30
,
31
,
32
,
/* 96 */
33
,
34
,
35
,
36
,
37
,
38
,
39
,
40
,
/* 104 */
41
,
42
,
43
,
44
,
45
,
46
,
47
,
48
,
/* 112 */
49
,
50
,
51
,
255
,
255
,
255
,
255
,
255
,
/* 120 */
};
};
return
tab
[
ch
&
127
];
if
(
toks
[
i
-
1
+
skip
].
type
==
JSON_TYPE_ARRAY
||
toks
[
i
-
1
+
skip
].
type
==
JSON_TYPE_OBJECT
)
{
i
+=
toks
[
i
-
1
+
skip
].
num_desc
;
}
}
if
(
i
==
toks
[
-
1
].
num_desc
)
return
0
;
path
+=
n
;
if
(
path
[
0
]
==
'.'
)
path
++
;
if
(
path
[
0
]
==
'\0'
)
return
&
toks
[
i
];
toks
+=
i
;
}
return
0
;
}
}
int
cs_base64_decode
(
const
unsigned
char
*
s
,
int
len
,
char
*
dst
)
{
int
json_emit_long
(
char
*
buf
,
int
buf_len
,
long
int
value
)
{
unsigned
char
a
,
b
,
c
,
d
;
char
tmp
[
20
];
int
orig_len
=
len
;
int
n
=
snprintf
(
tmp
,
sizeof
(
tmp
),
"%ld"
,
value
);
while
(
len
>=
4
&&
(
a
=
from_b64
(
s
[
0
]))
!=
255
&&
strncpy
(
buf
,
tmp
,
buf_len
>
0
?
buf_len
:
0
);
(
b
=
from_b64
(
s
[
1
]))
!=
255
&&
(
c
=
from_b64
(
s
[
2
]))
!=
255
&&
return
n
;
(
d
=
from_b64
(
s
[
3
]))
!=
255
)
{
s
+=
4
;
len
-=
4
;
if
(
a
==
200
||
b
==
200
)
break
;
/* '=' can't be there */
*
dst
++
=
a
<<
2
|
b
>>
4
;
if
(
c
==
200
)
break
;
*
dst
++
=
b
<<
4
|
c
>>
2
;
if
(
d
==
200
)
break
;
*
dst
++
=
c
<<
6
|
d
;
}
*
dst
=
0
;
return
orig_len
-
len
;
}
}
#endif
/* EXCLUDE_COMMON */
int
json_emit_double
(
char
*
buf
,
int
buf_len
,
double
value
)
{
#ifdef NS_MODULE_LINES
char
tmp
[
20
];
#line 1 "src/../../common/str_util.c"
int
n
=
snprintf
(
tmp
,
sizeof
(
tmp
),
"%g"
,
value
);
/**/
strncpy
(
buf
,
tmp
,
buf_len
>
0
?
buf_len
:
0
);
#endif
return
n
;
/*
}
* Copyright (c) 2015 Cesanta Software Limited
* All rights reserved
*/
#ifndef EXCLUDE_COMMON
int
json_emit_quoted_str
(
char
*
s
,
int
s_len
,
const
char
*
str
,
int
len
)
{
const
char
*
begin
=
s
,
*
end
=
s
+
s_len
,
*
str_end
=
str
+
len
;
char
ch
;
/* Amalgamated: #include "osdep.h" */
#define EMIT(x) do { if (s < end) *s = x; s++; } while (0)
/* Amalgamated: #include "str_util.h" */
#if !(_XOPEN_SOURCE >= 700 || _POSIX_C_SOURCE >= 200809L) && \
EMIT
(
'"'
);
!(__DARWIN_C_LEVEL >= 200809L) && !defined(RTOS_SDK) || \
while
(
str
<
str_end
)
{
defined(_WIN32)
ch
=
*
str
++
;
size_t
strnlen
(
const
char
*
s
,
size_t
maxlen
)
{
switch
(
ch
)
{
size_t
l
=
0
;
case
'"'
:
EMIT
(
'\\'
);
EMIT
(
'"'
);
break
;
for
(;
l
<
maxlen
&&
s
[
l
]
!=
'\0'
;
l
++
)
{
case
'\\'
:
EMIT
(
'\\'
);
EMIT
(
'\\'
);
break
;
case
'\b'
:
EMIT
(
'\\'
);
EMIT
(
'b'
);
break
;
case
'\f'
:
EMIT
(
'\\'
);
EMIT
(
'f'
);
break
;
case
'\n'
:
EMIT
(
'\\'
);
EMIT
(
'n'
);
break
;
case
'\r'
:
EMIT
(
'\\'
);
EMIT
(
'r'
);
break
;
case
'\t'
:
EMIT
(
'\\'
);
EMIT
(
't'
);
break
;
default:
EMIT
(
ch
);
}
}
EMIT
(
'"'
);
if
(
s
<
end
)
{
*
s
=
'\0'
;
}
}
return
l
;
}
#endif
#define C_SNPRINTF_APPEND_CHAR(ch) \
do { \
if (i < (int) buf_size) buf[i] = ch; \
i++; \
} while (0)
#define C_SNPRINTF_FLAG_ZERO 1
#ifdef C_DISABLE_BUILTIN_SNPRINTF
return
s
-
begin
;
int
c_vsnprintf
(
char
*
buf
,
size_t
buf_size
,
const
char
*
fmt
,
va_list
ap
)
{
return
vsnprintf
(
buf
,
buf_size
,
fmt
,
ap
);
}
}
#else
static
int
c_itoa
(
char
*
buf
,
size_t
buf_size
,
int64_t
num
,
int
base
,
int
flags
,
int
field_width
)
{
char
tmp
[
40
];
int
i
=
0
,
k
=
0
,
neg
=
0
;
if
(
num
<
0
)
{
neg
++
;
num
=
-
num
;
}
/* Print into temporary buffer - in reverse order */
do
{
int
rem
=
num
%
base
;
if
(
rem
<
10
)
{
tmp
[
k
++
]
=
'0'
+
rem
;
}
else
{
tmp
[
k
++
]
=
'a'
+
(
rem
-
10
);
}
num
/=
base
;
}
while
(
num
>
0
);
/* Zero padding */
if
(
flags
&&
C_SNPRINTF_FLAG_ZERO
)
{
while
(
k
<
field_width
&&
k
<
(
int
)
sizeof
(
tmp
)
-
1
)
{
tmp
[
k
++
]
=
'0'
;
}
}
/* And sign */
int
json_emit_unquoted_str
(
char
*
buf
,
int
buf_len
,
const
char
*
str
,
int
len
)
{
if
(
neg
)
{
if
(
buf_len
>
0
&&
len
>
0
)
{
tmp
[
k
++
]
=
'-'
;
int
n
=
len
<
buf_len
?
len
:
buf_len
;
memcpy
(
buf
,
str
,
n
);
if
(
n
<
buf_len
)
{
buf
[
n
]
=
'\0'
;
}
}
/* Now output */
while
(
--
k
>=
0
)
{
C_SNPRINTF_APPEND_CHAR
(
tmp
[
k
]);
}
}
return
len
;
return
i
;
}
}
int
c_vsnprintf
(
char
*
buf
,
size_t
buf_size
,
const
char
*
fmt
,
va_list
ap
)
{
int
json_emit_va
(
char
*
s
,
int
s_len
,
const
char
*
fmt
,
va_list
ap
)
{
int
ch
,
i
=
0
,
len_mod
,
flags
,
precision
,
field_width
;
const
char
*
end
=
s
+
s_len
,
*
str
,
*
orig
=
s
;
size_t
len
;
while
((
ch
=
*
fmt
++
)
!=
'\0'
)
{
if
(
ch
!=
'%'
)
{
C_SNPRINTF_APPEND_CHAR
(
ch
);
}
else
{
/*
* Conversion specification:
* zero or more flags (one of: # 0 - <space> + ')
* an optional minimum field width (digits)
* an optional precision (. followed by digits, or *)
* an optional length modifier (one of: hh h l ll L q j z t)
* conversion specifier (one of: d i o u x X e E f F g G a A c s p n)
*/
flags
=
field_width
=
precision
=
len_mod
=
0
;
/* Flags. only zero-pad flag is supported. */
if
(
*
fmt
==
'0'
)
{
flags
|=
C_SNPRINTF_FLAG_ZERO
;
}
/* Field width */
while
(
*
fmt
>=
'0'
&&
*
fmt
<=
'9'
)
{
field_width
*=
10
;
field_width
+=
*
fmt
++
-
'0'
;
}
/* Dynamic field width */
if
(
*
fmt
==
'*'
)
{
field_width
=
va_arg
(
ap
,
int
);
fmt
++
;
}
/* Precision */
if
(
*
fmt
==
'.'
)
{
fmt
++
;
if
(
*
fmt
==
'*'
)
{
precision
=
va_arg
(
ap
,
int
);
fmt
++
;
}
else
{
while
(
*
fmt
>=
'0'
&&
*
fmt
<=
'9'
)
{
precision
*=
10
;
precision
+=
*
fmt
++
-
'0'
;
}
}
}
/* Length modifier */
while
(
*
fmt
!=
'\0'
)
{
switch
(
*
fmt
)
{
switch
(
*
fmt
)
{
case
'h'
:
case
'['
:
case
']'
:
case
'{'
:
case
'}'
:
case
','
:
case
':'
:
case
'l'
:
case
' '
:
case
'\r'
:
case
'\n'
:
case
'\t'
:
case
'L'
:
if
(
s
<
end
)
{
case
'I'
:
*
s
=
*
fmt
;
case
'q'
:
case
'j'
:
case
'z'
:
case
't'
:
len_mod
=
*
fmt
++
;
if
(
*
fmt
==
'h'
)
{
len_mod
=
'H'
;
fmt
++
;
}
if
(
*
fmt
==
'l'
)
{
len_mod
=
'q'
;
fmt
++
;
}
}
s
++
;
break
;
break
;
case
'i'
:
s
+=
json_emit_long
(
s
,
end
-
s
,
va_arg
(
ap
,
long
));
break
;
case
'f'
:
s
+=
json_emit_double
(
s
,
end
-
s
,
va_arg
(
ap
,
double
));
break
;
case
'v'
:
str
=
va_arg
(
ap
,
char
*
);
len
=
va_arg
(
ap
,
size_t
);
s
+=
json_emit_quoted_str
(
s
,
end
-
s
,
str
,
len
);
break
;
case
'V'
:
str
=
va_arg
(
ap
,
char
*
);
len
=
va_arg
(
ap
,
size_t
);
s
+=
json_emit_unquoted_str
(
s
,
end
-
s
,
str
,
len
);
break
;
case
's'
:
str
=
va_arg
(
ap
,
char
*
);
s
+=
json_emit_quoted_str
(
s
,
end
-
s
,
str
,
strlen
(
str
));
break
;
case
'S'
:
str
=
va_arg
(
ap
,
char
*
);
s
+=
json_emit_unquoted_str
(
s
,
end
-
s
,
str
,
strlen
(
str
));
break
;
case
'T'
:
s
+=
json_emit_unquoted_str
(
s
,
end
-
s
,
"true"
,
4
);
break
;
case
'F'
:
s
+=
json_emit_unquoted_str
(
s
,
end
-
s
,
"false"
,
5
);
break
;
case
'N'
:
s
+=
json_emit_unquoted_str
(
s
,
end
-
s
,
"null"
,
4
);
break
;
default:
return
0
;
}
}
fmt
++
;
ch
=
*
fmt
++
;
if
(
ch
==
's'
)
{
const
char
*
s
=
va_arg
(
ap
,
const
char
*
);
/* Always fetch parameter */
int
j
;
int
pad
=
field_width
-
(
precision
>=
0
?
strnlen
(
s
,
precision
)
:
0
);
for
(
j
=
0
;
j
<
pad
;
j
++
)
{
C_SNPRINTF_APPEND_CHAR
(
' '
);
}
/* Ignore negative and 0 precisions */
for
(
j
=
0
;
(
precision
<=
0
||
j
<
precision
)
&&
s
[
j
]
!=
'\0'
;
j
++
)
{
C_SNPRINTF_APPEND_CHAR
(
s
[
j
]);
}
}
else
if
(
ch
==
'c'
)
{
ch
=
va_arg
(
ap
,
int
);
/* Always fetch parameter */
C_SNPRINTF_APPEND_CHAR
(
ch
);
}
else
if
(
ch
==
'd'
&&
len_mod
==
0
)
{
i
+=
c_itoa
(
buf
+
i
,
buf_size
-
i
,
va_arg
(
ap
,
int
),
10
,
flags
,
field_width
);
}
else
if
(
ch
==
'd'
&&
len_mod
==
'l'
)
{
i
+=
c_itoa
(
buf
+
i
,
buf_size
-
i
,
va_arg
(
ap
,
long
),
10
,
flags
,
field_width
);
}
else
if
((
ch
==
'x'
||
ch
==
'u'
)
&&
len_mod
==
0
)
{
i
+=
c_itoa
(
buf
+
i
,
buf_size
-
i
,
va_arg
(
ap
,
unsigned
),
ch
==
'x'
?
16
:
10
,
flags
,
field_width
);
}
else
if
((
ch
==
'x'
||
ch
==
'u'
)
&&
len_mod
==
'l'
)
{
i
+=
c_itoa
(
buf
+
i
,
buf_size
-
i
,
va_arg
(
ap
,
unsigned
long
),
ch
==
'x'
?
16
:
10
,
flags
,
field_width
);
}
else
if
(
ch
==
'p'
)
{
unsigned
long
num
=
(
unsigned
long
)
va_arg
(
ap
,
void
*
);
C_SNPRINTF_APPEND_CHAR
(
'0'
);
C_SNPRINTF_APPEND_CHAR
(
'x'
);
i
+=
c_itoa
(
buf
+
i
,
buf_size
-
i
,
num
,
16
,
flags
,
0
);
}
else
{
#ifndef NO_LIBC
/*
* TODO(lsm): abort is not nice in a library, remove it
* Also, ESP8266 SDK doesn't have it
*/
abort
();
#endif
}
}
}
}
/*
Zero-terminate the result
*/
/*
Best-effort to 0-terminate generated string
*/
if
(
buf_size
>
0
)
{
if
(
s
<
end
)
{
buf
[
i
<
(
int
)
buf_size
?
i
:
(
int
)
buf_size
-
1
]
=
'\0'
;
*
s
=
'\0'
;
}
}
return
i
;
return
s
-
orig
;
}
}
#endif
int
c_snprintf
(
char
*
buf
,
size_t
buf_size
,
const
char
*
fmt
,
...)
{
int
json_emit
(
char
*
buf
,
int
buf_len
,
const
char
*
fmt
,
...)
{
int
result
;
int
len
;
va_list
ap
;
va_list
ap
;
va_start
(
ap
,
fmt
);
va_start
(
ap
,
fmt
);
result
=
c_vsnprintf
(
buf
,
buf_size
,
fmt
,
ap
);
len
=
json_emit_va
(
buf
,
buf_len
,
fmt
,
ap
);
va_end
(
ap
);
va_end
(
ap
);
return
result
;
}
#ifdef _WIN32
void
to_wchar
(
const
char
*
path
,
wchar_t
*
wbuf
,
size_t
wbuf_len
)
{
char
buf
[
MAX_PATH
*
2
],
buf2
[
MAX_PATH
*
2
],
*
p
;
strncpy
(
buf
,
path
,
sizeof
(
buf
));
buf
[
sizeof
(
buf
)
-
1
]
=
'\0'
;
/* Trim trailing slashes. Leave backslash for paths like "X:\" */
p
=
buf
+
strlen
(
buf
)
-
1
;
while
(
p
>
buf
&&
p
[
-
1
]
!=
':'
&&
(
p
[
0
]
==
'\\'
||
p
[
0
]
==
'/'
))
*
p
--
=
'\0'
;
/*
return
len
;
* Convert to Unicode and back. If doubly-converted string does not
* match the original, something is fishy, reject.
*/
memset
(
wbuf
,
0
,
wbuf_len
*
sizeof
(
wchar_t
));
MultiByteToWideChar
(
CP_UTF8
,
0
,
buf
,
-
1
,
wbuf
,
(
int
)
wbuf_len
);
WideCharToMultiByte
(
CP_UTF8
,
0
,
wbuf
,
(
int
)
wbuf_len
,
buf2
,
sizeof
(
buf2
),
NULL
,
NULL
);
if
(
strcmp
(
buf
,
buf2
)
!=
0
)
{
wbuf
[
0
]
=
L'\0'
;
}
}
}
#endif
/* _WIN32 */
#endif
/* EXCLUDE_COMMON */
#ifdef NS_MODULE_LINES
#ifdef NS_MODULE_LINES
#line 1 "src/../../common/
dirent
.c"
#line 1 "src/../../common/
md5
.c"
/**/
/**/
#endif
#endif
/*
/*
* Copyright (c) 2015 Cesanta Software Limited
* This code implements the MD5 message-digest algorithm.
* All rights reserved
* The algorithm is due to Ron Rivest. This code was
*/
* written by Colin Plumb in 1993, no copyright is claimed.
* This code is in the public domain; do with it what you wish.
#ifndef EXCLUDE_COMMON
*
* Equivalent code is available from RSA Data Security, Inc.
/* Amalgamated: #include "osdep.h" */
* This code has been tested against that, and is equivalent,
* except that you don't need to include two pages of legalese
/*
* with every copy.
* This file contains POSIX opendir/closedir/readdir API implementation
*
* for systems which do not natively support it (e.g. Windows).
* To compute the message digest of a chunk of bytes, declare an
*/
* MD5Context structure, pass it to MD5Init, call MD5Update as
* needed on buffers full of bytes, and then call MD5Final, which
#ifndef MG_FREE
* will fill a supplied 16-byte array with the digest.
#define MG_FREE free
*/
#endif
#ifndef MG_MALLOC
#define MG_MALLOC malloc
#endif
#ifdef _WIN32
DIR
*
opendir
(
const
char
*
name
)
{
DIR
*
dir
=
NULL
;
wchar_t
wpath
[
MAX_PATH
];
DWORD
attrs
;
if
(
name
==
NULL
)
{
SetLastError
(
ERROR_BAD_ARGUMENTS
);
}
else
if
((
dir
=
(
DIR
*
)
MG_MALLOC
(
sizeof
(
*
dir
)))
==
NULL
)
{
SetLastError
(
ERROR_NOT_ENOUGH_MEMORY
);
}
else
{
to_wchar
(
name
,
wpath
,
ARRAY_SIZE
(
wpath
));
attrs
=
GetFileAttributesW
(
wpath
);
if
(
attrs
!=
0xFFFFFFFF
&&
(
attrs
&
FILE_ATTRIBUTE_DIRECTORY
))
{
(
void
)
wcscat
(
wpath
,
L"
\\
*"
);
dir
->
handle
=
FindFirstFileW
(
wpath
,
&
dir
->
info
);
dir
->
result
.
d_name
[
0
]
=
'\0'
;
}
else
{
MG_FREE
(
dir
);
dir
=
NULL
;
}
}
return
dir
;
}
int
closedir
(
DIR
*
dir
)
{
#if !defined(DISABLE_MD5) && !defined(EXCLUDE_COMMON)
int
result
=
0
;
if
(
dir
!=
NULL
)
{
/* Amalgamated: #include "md5.h" */
if
(
dir
->
handle
!=
INVALID_HANDLE_VALUE
)
result
=
FindClose
(
dir
->
handle
)
?
0
:
-
1
;
MG_FREE
(
dir
);
}
else
{
result
=
-
1
;
SetLastError
(
ERROR_BAD_ARGUMENTS
);
}
return
result
;
#ifndef CS_ENABLE_NATIVE_MD5
static
void
byteReverse
(
unsigned
char
*
buf
,
unsigned
longs
)
{
/* Forrest: MD5 expect LITTLE_ENDIAN, swap if BIG_ENDIAN */
#if BYTE_ORDER == BIG_ENDIAN
do
{
uint32_t
t
=
(
uint32_t
)((
unsigned
)
buf
[
3
]
<<
8
|
buf
[
2
])
<<
16
|
((
unsigned
)
buf
[
1
]
<<
8
|
buf
[
0
]);
*
(
uint32_t
*
)
buf
=
t
;
buf
+=
4
;
}
while
(
--
longs
);
#else
(
void
)
buf
;
(
void
)
longs
;
#endif
}
}
struct
dirent
*
readdir
(
DIR
*
dir
)
{
#define F1(x, y, z) (z ^ (x & (y ^ z)))
struct
dirent
*
result
=
0
;
#define F2(x, y, z) F1(z, x, y)
#define F3(x, y, z) (x ^ y ^ z)
if
(
dir
)
{
#define F4(x, y, z) (y ^ (x | ~z))
if
(
dir
->
handle
!=
INVALID_HANDLE_VALUE
)
{
result
=
&
dir
->
result
;
(
void
)
WideCharToMultiByte
(
CP_UTF8
,
0
,
dir
->
info
.
cFileName
,
-
1
,
result
->
d_name
,
sizeof
(
result
->
d_name
),
NULL
,
NULL
);
if
(
!
FindNextFileW
(
dir
->
handle
,
&
dir
->
info
))
{
(
void
)
FindClose
(
dir
->
handle
);
dir
->
handle
=
INVALID_HANDLE_VALUE
;
}
}
else
{
SetLastError
(
ERROR_FILE_NOT_FOUND
);
}
}
else
{
SetLastError
(
ERROR_BAD_ARGUMENTS
);
}
return
result
;
#define MD5STEP(f, w, x, y, z, data, s) \
}
(w += f(x, y, z) + data, w = w << s | w >> (32 - s), w += x)
#endif
#endif
/* EXCLUDE_COMMON */
#ifdef NS_MODULE_LINES
#line 1 "src/../deps/frozen/frozen.c"
/**/
#endif
/*
/*
* Copyright (c) 2004-2013 Sergey Lyubka <valenok@gmail.com>
* Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
* Copyright (c) 2013 Cesanta Software Limited
* initialization constants.
* All rights reserved
*
* This library is dual-licensed: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation. For the terms of this
* license, see <http: *www.gnu.org/licenses/>.
*
* You are free to use this library under the terms of the GNU General
* Public License, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* Alternatively, you can license this library under a commercial
* license, as set out in <https://www.cesanta.com/license>.
*/
*/
void
MD5_Init
(
MD5_CTX
*
ctx
)
{
ctx
->
buf
[
0
]
=
0x67452301
;
ctx
->
buf
[
1
]
=
0xefcdab89
;
ctx
->
buf
[
2
]
=
0x98badcfe
;
ctx
->
buf
[
3
]
=
0x10325476
;
#define _CRT_SECURE_NO_WARNINGS
/* Disable deprecation warning in VS2005+ */
ctx
->
bits
[
0
]
=
0
;
ctx
->
bits
[
1
]
=
0
;
#include <stdio.h>
}
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
/* Amalgamated: #include "frozen.h" */
#ifdef _WIN32
static
void
MD5Transform
(
uint32_t
buf
[
4
],
uint32_t
const
in
[
16
])
{
#define snprintf _snprintf
register
uint32_t
a
,
b
,
c
,
d
;
#endif
#ifndef FROZEN_REALLOC
a
=
buf
[
0
];
#define FROZEN_REALLOC realloc
b
=
buf
[
1
];
#endif
c
=
buf
[
2
];
d
=
buf
[
3
];
#ifndef FROZEN_FREE
MD5STEP
(
F1
,
a
,
b
,
c
,
d
,
in
[
0
]
+
0xd76aa478
,
7
);
#define FROZEN_FREE free
MD5STEP
(
F1
,
d
,
a
,
b
,
c
,
in
[
1
]
+
0xe8c7b756
,
12
);
#endif
MD5STEP
(
F1
,
c
,
d
,
a
,
b
,
in
[
2
]
+
0x242070db
,
17
);
MD5STEP
(
F1
,
b
,
c
,
d
,
a
,
in
[
3
]
+
0xc1bdceee
,
22
);
MD5STEP
(
F1
,
a
,
b
,
c
,
d
,
in
[
4
]
+
0xf57c0faf
,
7
);
MD5STEP
(
F1
,
d
,
a
,
b
,
c
,
in
[
5
]
+
0x4787c62a
,
12
);
MD5STEP
(
F1
,
c
,
d
,
a
,
b
,
in
[
6
]
+
0xa8304613
,
17
);
MD5STEP
(
F1
,
b
,
c
,
d
,
a
,
in
[
7
]
+
0xfd469501
,
22
);
MD5STEP
(
F1
,
a
,
b
,
c
,
d
,
in
[
8
]
+
0x698098d8
,
7
);
MD5STEP
(
F1
,
d
,
a
,
b
,
c
,
in
[
9
]
+
0x8b44f7af
,
12
);
MD5STEP
(
F1
,
c
,
d
,
a
,
b
,
in
[
10
]
+
0xffff5bb1
,
17
);
MD5STEP
(
F1
,
b
,
c
,
d
,
a
,
in
[
11
]
+
0x895cd7be
,
22
);
MD5STEP
(
F1
,
a
,
b
,
c
,
d
,
in
[
12
]
+
0x6b901122
,
7
);
MD5STEP
(
F1
,
d
,
a
,
b
,
c
,
in
[
13
]
+
0xfd987193
,
12
);
MD5STEP
(
F1
,
c
,
d
,
a
,
b
,
in
[
14
]
+
0xa679438e
,
17
);
MD5STEP
(
F1
,
b
,
c
,
d
,
a
,
in
[
15
]
+
0x49b40821
,
22
);
struct
frozen
{
MD5STEP
(
F2
,
a
,
b
,
c
,
d
,
in
[
1
]
+
0xf61e2562
,
5
);
const
char
*
end
;
MD5STEP
(
F2
,
d
,
a
,
b
,
c
,
in
[
6
]
+
0xc040b340
,
9
);
const
char
*
cur
;
MD5STEP
(
F2
,
c
,
d
,
a
,
b
,
in
[
11
]
+
0x265e5a51
,
14
);
struct
json_token
*
tokens
;
MD5STEP
(
F2
,
b
,
c
,
d
,
a
,
in
[
0
]
+
0xe9b6c7aa
,
20
);
int
max_tokens
;
MD5STEP
(
F2
,
a
,
b
,
c
,
d
,
in
[
5
]
+
0xd62f105d
,
5
);
int
num_tokens
;
MD5STEP
(
F2
,
d
,
a
,
b
,
c
,
in
[
10
]
+
0x02441453
,
9
);
int
do_realloc
;
MD5STEP
(
F2
,
c
,
d
,
a
,
b
,
in
[
15
]
+
0xd8a1e681
,
14
);
};
MD5STEP
(
F2
,
b
,
c
,
d
,
a
,
in
[
4
]
+
0xe7d3fbc8
,
20
);
MD5STEP
(
F2
,
a
,
b
,
c
,
d
,
in
[
9
]
+
0x21e1cde6
,
5
);
MD5STEP
(
F2
,
d
,
a
,
b
,
c
,
in
[
14
]
+
0xc33707d6
,
9
);
MD5STEP
(
F2
,
c
,
d
,
a
,
b
,
in
[
3
]
+
0xf4d50d87
,
14
);
MD5STEP
(
F2
,
b
,
c
,
d
,
a
,
in
[
8
]
+
0x455a14ed
,
20
);
MD5STEP
(
F2
,
a
,
b
,
c
,
d
,
in
[
13
]
+
0xa9e3e905
,
5
);
MD5STEP
(
F2
,
d
,
a
,
b
,
c
,
in
[
2
]
+
0xfcefa3f8
,
9
);
MD5STEP
(
F2
,
c
,
d
,
a
,
b
,
in
[
7
]
+
0x676f02d9
,
14
);
MD5STEP
(
F2
,
b
,
c
,
d
,
a
,
in
[
12
]
+
0x8d2a4c8a
,
20
);
static
int
parse_object
(
struct
frozen
*
f
);
MD5STEP
(
F3
,
a
,
b
,
c
,
d
,
in
[
5
]
+
0xfffa3942
,
4
);
static
int
parse_value
(
struct
frozen
*
f
);
MD5STEP
(
F3
,
d
,
a
,
b
,
c
,
in
[
8
]
+
0x8771f681
,
11
);
MD5STEP
(
F3
,
c
,
d
,
a
,
b
,
in
[
11
]
+
0x6d9d6122
,
16
);
MD5STEP
(
F3
,
b
,
c
,
d
,
a
,
in
[
14
]
+
0xfde5380c
,
23
);
MD5STEP
(
F3
,
a
,
b
,
c
,
d
,
in
[
1
]
+
0xa4beea44
,
4
);
MD5STEP
(
F3
,
d
,
a
,
b
,
c
,
in
[
4
]
+
0x4bdecfa9
,
11
);
MD5STEP
(
F3
,
c
,
d
,
a
,
b
,
in
[
7
]
+
0xf6bb4b60
,
16
);
MD5STEP
(
F3
,
b
,
c
,
d
,
a
,
in
[
10
]
+
0xbebfbc70
,
23
);
MD5STEP
(
F3
,
a
,
b
,
c
,
d
,
in
[
13
]
+
0x289b7ec6
,
4
);
MD5STEP
(
F3
,
d
,
a
,
b
,
c
,
in
[
0
]
+
0xeaa127fa
,
11
);
MD5STEP
(
F3
,
c
,
d
,
a
,
b
,
in
[
3
]
+
0xd4ef3085
,
16
);
MD5STEP
(
F3
,
b
,
c
,
d
,
a
,
in
[
6
]
+
0x04881d05
,
23
);
MD5STEP
(
F3
,
a
,
b
,
c
,
d
,
in
[
9
]
+
0xd9d4d039
,
4
);
MD5STEP
(
F3
,
d
,
a
,
b
,
c
,
in
[
12
]
+
0xe6db99e5
,
11
);
MD5STEP
(
F3
,
c
,
d
,
a
,
b
,
in
[
15
]
+
0x1fa27cf8
,
16
);
MD5STEP
(
F3
,
b
,
c
,
d
,
a
,
in
[
2
]
+
0xc4ac5665
,
23
);
#define EXPECT(cond, err_code) do { if (!(cond)) return (err_code); } while (0)
MD5STEP
(
F4
,
a
,
b
,
c
,
d
,
in
[
0
]
+
0xf4292244
,
6
);
#define TRY(expr) do { int _n = expr; if (_n < 0) return _n; } while (0)
MD5STEP
(
F4
,
d
,
a
,
b
,
c
,
in
[
7
]
+
0x432aff97
,
10
);
#define END_OF_STRING (-1)
MD5STEP
(
F4
,
c
,
d
,
a
,
b
,
in
[
14
]
+
0xab9423a7
,
15
);
MD5STEP
(
F4
,
b
,
c
,
d
,
a
,
in
[
5
]
+
0xfc93a039
,
21
);
MD5STEP
(
F4
,
a
,
b
,
c
,
d
,
in
[
12
]
+
0x655b59c3
,
6
);
MD5STEP
(
F4
,
d
,
a
,
b
,
c
,
in
[
3
]
+
0x8f0ccc92
,
10
);
MD5STEP
(
F4
,
c
,
d
,
a
,
b
,
in
[
10
]
+
0xffeff47d
,
15
);
MD5STEP
(
F4
,
b
,
c
,
d
,
a
,
in
[
1
]
+
0x85845dd1
,
21
);
MD5STEP
(
F4
,
a
,
b
,
c
,
d
,
in
[
8
]
+
0x6fa87e4f
,
6
);
MD5STEP
(
F4
,
d
,
a
,
b
,
c
,
in
[
15
]
+
0xfe2ce6e0
,
10
);
MD5STEP
(
F4
,
c
,
d
,
a
,
b
,
in
[
6
]
+
0xa3014314
,
15
);
MD5STEP
(
F4
,
b
,
c
,
d
,
a
,
in
[
13
]
+
0x4e0811a1
,
21
);
MD5STEP
(
F4
,
a
,
b
,
c
,
d
,
in
[
4
]
+
0xf7537e82
,
6
);
MD5STEP
(
F4
,
d
,
a
,
b
,
c
,
in
[
11
]
+
0xbd3af235
,
10
);
MD5STEP
(
F4
,
c
,
d
,
a
,
b
,
in
[
2
]
+
0x2ad7d2bb
,
15
);
MD5STEP
(
F4
,
b
,
c
,
d
,
a
,
in
[
9
]
+
0xeb86d391
,
21
);
static
int
left
(
const
struct
frozen
*
f
)
{
buf
[
0
]
+=
a
;
return
f
->
end
-
f
->
cur
;
buf
[
1
]
+=
b
;
buf
[
2
]
+=
c
;
buf
[
3
]
+=
d
;
}
}
static
int
is_space
(
int
ch
)
{
void
MD5_Update
(
MD5_CTX
*
ctx
,
const
unsigned
char
*
buf
,
size_t
len
)
{
return
ch
==
' '
||
ch
==
'\t'
||
ch
==
'\r'
||
ch
==
'\n'
;
uint32_t
t
;
}
static
void
skip_whitespaces
(
struct
frozen
*
f
)
{
t
=
ctx
->
bits
[
0
];
while
(
f
->
cur
<
f
->
end
&&
is_space
(
*
f
->
cur
))
f
->
cur
++
;
if
((
ctx
->
bits
[
0
]
=
t
+
((
uint32_t
)
len
<<
3
))
<
t
)
ctx
->
bits
[
1
]
++
;
}
ctx
->
bits
[
1
]
+=
(
uint32_t
)
len
>>
29
;
static
int
cur
(
struct
frozen
*
f
)
{
t
=
(
t
>>
3
)
&
0x3f
;
skip_whitespaces
(
f
);
return
f
->
cur
>=
f
->
end
?
END_OF_STRING
:
*
(
unsigned
char
*
)
f
->
cur
;
}
static
int
test_and_skip
(
struct
frozen
*
f
,
int
expected
)
{
if
(
t
)
{
int
ch
=
cur
(
f
);
unsigned
char
*
p
=
(
unsigned
char
*
)
ctx
->
in
+
t
;
if
(
ch
==
expected
)
{
f
->
cur
++
;
return
0
;
}
return
ch
==
END_OF_STRING
?
JSON_STRING_INCOMPLETE
:
JSON_STRING_INVALID
;
}
static
int
is_alpha
(
int
ch
)
{
t
=
64
-
t
;
return
(
ch
>=
'a'
&&
ch
<=
'z'
)
||
(
ch
>=
'A'
&&
ch
<=
'Z'
);
if
(
len
<
t
)
{
}
memcpy
(
p
,
buf
,
len
);
return
;
}
memcpy
(
p
,
buf
,
t
);
byteReverse
(
ctx
->
in
,
16
);
MD5Transform
(
ctx
->
buf
,
(
uint32_t
*
)
ctx
->
in
);
buf
+=
t
;
len
-=
t
;
}
static
int
is_digit
(
int
ch
)
{
while
(
len
>=
64
)
{
return
ch
>=
'0'
&&
ch
<=
'9'
;
memcpy
(
ctx
->
in
,
buf
,
64
);
byteReverse
(
ctx
->
in
,
16
);
MD5Transform
(
ctx
->
buf
,
(
uint32_t
*
)
ctx
->
in
);
buf
+=
64
;
len
-=
64
;
}
memcpy
(
ctx
->
in
,
buf
,
len
);
}
}
static
int
is_hex_digit
(
int
ch
)
{
void
MD5_Final
(
unsigned
char
digest
[
16
],
MD5_CTX
*
ctx
)
{
return
is_digit
(
ch
)
||
(
ch
>=
'a'
&&
ch
<=
'f'
)
||
(
ch
>=
'A'
&&
ch
<=
'F'
);
unsigned
count
;
unsigned
char
*
p
;
uint32_t
*
a
;
count
=
(
ctx
->
bits
[
0
]
>>
3
)
&
0x3F
;
p
=
ctx
->
in
+
count
;
*
p
++
=
0x80
;
count
=
64
-
1
-
count
;
if
(
count
<
8
)
{
memset
(
p
,
0
,
count
);
byteReverse
(
ctx
->
in
,
16
);
MD5Transform
(
ctx
->
buf
,
(
uint32_t
*
)
ctx
->
in
);
memset
(
ctx
->
in
,
0
,
56
);
}
else
{
memset
(
p
,
0
,
count
-
8
);
}
byteReverse
(
ctx
->
in
,
14
);
a
=
(
uint32_t
*
)
ctx
->
in
;
a
[
14
]
=
ctx
->
bits
[
0
];
a
[
15
]
=
ctx
->
bits
[
1
];
MD5Transform
(
ctx
->
buf
,
(
uint32_t
*
)
ctx
->
in
);
byteReverse
((
unsigned
char
*
)
ctx
->
buf
,
4
);
memcpy
(
digest
,
ctx
->
buf
,
16
);
memset
((
char
*
)
ctx
,
0
,
sizeof
(
*
ctx
));
}
}
#endif
/* CS_ENABLE_NATIVE_MD5 */
static
int
get_escape_len
(
const
char
*
s
,
int
len
)
{
/*
switch
(
*
s
)
{
* Stringify binary data. Output buffer size must be 2 * size_of_input + 1
case
'u'
:
* because each byte of input takes 2 bytes in string representation
return
len
<
6
?
JSON_STRING_INCOMPLETE
:
* plus 1 byte for the terminating \0 character.
is_hex_digit
(
s
[
1
])
&&
is_hex_digit
(
s
[
2
])
&&
*/
is_hex_digit
(
s
[
3
])
&&
is_hex_digit
(
s
[
4
])
?
5
:
JSON_STRING_INVALID
;
void
cs_to_hex
(
char
*
to
,
const
unsigned
char
*
p
,
size_t
len
)
{
case
'"'
:
case
'\\'
:
case
'/'
:
case
'b'
:
static
const
char
*
hex
=
"0123456789abcdef"
;
case
'f'
:
case
'n'
:
case
'r'
:
case
't'
:
return
len
<
2
?
JSON_STRING_INCOMPLETE
:
1
;
for
(;
len
--
;
p
++
)
{
default:
*
to
++
=
hex
[
p
[
0
]
>>
4
];
return
JSON_STRING_INVALID
;
*
to
++
=
hex
[
p
[
0
]
&
0x0f
]
;
}
}
*
to
=
'\0'
;
}
}
static
int
capture_ptr
(
struct
frozen
*
f
,
const
char
*
ptr
,
enum
json_type
type
)
{
char
*
cs_md5
(
char
buf
[
33
],
...)
{
if
(
f
->
do_realloc
&&
f
->
num_tokens
>=
f
->
max_tokens
)
{
unsigned
char
hash
[
16
];
int
new_size
=
f
->
max_tokens
==
0
?
100
:
f
->
max_tokens
*
2
;
const
unsigned
char
*
p
;
void
*
p
=
FROZEN_REALLOC
(
f
->
tokens
,
new_size
*
sizeof
(
f
->
tokens
[
0
]));
va_list
ap
;
if
(
p
==
NULL
)
return
JSON_TOKEN_ARRAY_TOO_SMALL
;
MD5_CTX
ctx
;
f
->
max_tokens
=
new_size
;
f
->
tokens
=
(
struct
json_token
*
)
p
;
MD5_Init
(
&
ctx
);
va_start
(
ap
,
buf
);
while
((
p
=
va_arg
(
ap
,
const
unsigned
char
*
)
)
!=
NULL
)
{
size_t
len
=
va_arg
(
ap
,
size_t
);
MD5_Update
(
&
ctx
,
p
,
len
);
}
}
if
(
f
->
tokens
==
NULL
||
f
->
max_tokens
==
0
)
return
0
;
va_end
(
ap
)
;
if
(
f
->
num_tokens
>=
f
->
max_tokens
)
return
JSON_TOKEN_ARRAY_TOO_SMALL
;
f
->
tokens
[
f
->
num_tokens
].
ptr
=
ptr
;
MD5_Final
(
hash
,
&
ctx
)
;
f
->
tokens
[
f
->
num_tokens
].
type
=
type
;
cs_to_hex
(
buf
,
hash
,
sizeof
(
hash
))
;
f
->
num_tokens
++
;
return
0
;
return
buf
;
}
}
static
int
capture_len
(
struct
frozen
*
f
,
int
token_index
,
const
char
*
ptr
)
{
#endif
/* EXCLUDE_COMMON */
if
(
f
->
tokens
==
0
||
f
->
max_tokens
==
0
)
return
0
;
#ifdef NS_MODULE_LINES
EXPECT
(
token_index
>=
0
&&
token_index
<
f
->
max_tokens
,
JSON_STRING_INVALID
);
#line 1 "src/../../common/mbuf.c"
f
->
tokens
[
token_index
].
len
=
ptr
-
f
->
tokens
[
token_index
].
ptr
;
/**/
f
->
tokens
[
token_index
].
num_desc
=
(
f
->
num_tokens
-
1
)
-
token_index
;
#endif
return
0
;
/*
* Copyright (c) 2014 Cesanta Software Limited
* All rights reserved
*/
#ifndef EXCLUDE_COMMON
#include <assert.h>
#include <string.h>
/* Amalgamated: #include "mbuf.h" */
#ifndef MBUF_REALLOC
#define MBUF_REALLOC realloc
#endif
#ifndef MBUF_FREE
#define MBUF_FREE free
#endif
void
mbuf_init
(
struct
mbuf
*
mbuf
,
size_t
initial_size
)
{
mbuf
->
len
=
mbuf
->
size
=
0
;
mbuf
->
buf
=
NULL
;
mbuf_resize
(
mbuf
,
initial_size
);
}
}
/* identifier = letter { letter | digit | '_' } */
void
mbuf_free
(
struct
mbuf
*
mbuf
)
{
static
int
parse_identifier
(
struct
frozen
*
f
)
{
if
(
mbuf
->
buf
!=
NULL
)
{
EXPECT
(
is_alpha
(
cur
(
f
)),
JSON_STRING_INVALID
);
MBUF_FREE
(
mbuf
->
buf
);
TRY
(
capture_ptr
(
f
,
f
->
cur
,
JSON_TYPE_STRING
));
mbuf_init
(
mbuf
,
0
);
while
(
f
->
cur
<
f
->
end
&&
(
*
f
->
cur
==
'_'
||
is_alpha
(
*
f
->
cur
)
||
is_digit
(
*
f
->
cur
)))
{
f
->
cur
++
;
}
}
capture_len
(
f
,
f
->
num_tokens
-
1
,
f
->
cur
);
return
0
;
}
}
static
int
get_utf8_char_len
(
unsigned
char
ch
)
{
void
mbuf_resize
(
struct
mbuf
*
a
,
size_t
new_size
)
{
if
((
ch
&
0x80
)
==
0
)
return
1
;
if
(
new_size
>
a
->
size
||
(
new_size
<
a
->
size
&&
new_size
>=
a
->
len
))
{
switch
(
ch
&
0xf0
)
{
char
*
buf
=
(
char
*
)
MBUF_REALLOC
(
a
->
buf
,
new_size
);
case
0xf0
:
return
4
;
/*
case
0xe0
:
return
3
;
* In case realloc fails, there's not much we can do, except keep things as
default:
return
2
;
* they are. Note that NULL is a valid return value from realloc when
* size == 0, but that is covered too.
*/
if
(
buf
==
NULL
&&
new_size
!=
0
)
return
;
a
->
buf
=
buf
;
a
->
size
=
new_size
;
}
}
}
}
/* string = '"' { quoted_printable_chars } '"' */
void
mbuf_trim
(
struct
mbuf
*
mbuf
)
{
static
int
parse_string
(
struct
frozen
*
f
)
{
mbuf_resize
(
mbuf
,
mbuf
->
len
);
int
n
,
ch
=
0
,
len
=
0
;
TRY
(
test_and_skip
(
f
,
'"'
));
TRY
(
capture_ptr
(
f
,
f
->
cur
,
JSON_TYPE_STRING
));
for
(;
f
->
cur
<
f
->
end
;
f
->
cur
+=
len
)
{
ch
=
*
(
unsigned
char
*
)
f
->
cur
;
len
=
get_utf8_char_len
((
unsigned
char
)
ch
);
EXPECT
(
ch
>=
32
&&
len
>
0
,
JSON_STRING_INVALID
);
/* No control chars */
EXPECT
(
len
<
left
(
f
),
JSON_STRING_INCOMPLETE
);
if
(
ch
==
'\\'
)
{
EXPECT
((
n
=
get_escape_len
(
f
->
cur
+
1
,
left
(
f
)))
>
0
,
n
);
len
+=
n
;
}
else
if
(
ch
==
'"'
)
{
capture_len
(
f
,
f
->
num_tokens
-
1
,
f
->
cur
);
f
->
cur
++
;
break
;
};
}
return
ch
==
'"'
?
0
:
JSON_STRING_INCOMPLETE
;
}
}
/* number = [ '-' ] digit+ [ '.' digit+ ] [ ['e'|'E'] ['+'|'-'] digit+ ] */
size_t
mbuf_insert
(
struct
mbuf
*
a
,
size_t
off
,
const
void
*
buf
,
size_t
len
)
{
static
int
parse_number
(
struct
frozen
*
f
)
{
char
*
p
=
NULL
;
int
ch
=
cur
(
f
);
TRY
(
capture_ptr
(
f
,
f
->
cur
,
JSON_TYPE_NUMBER
));
assert
(
a
!=
NULL
);
if
(
ch
==
'-'
)
f
->
cur
++
;
assert
(
a
->
len
<=
a
->
size
);
EXPECT
(
f
->
cur
<
f
->
end
,
JSON_STRING_INCOMPLETE
);
assert
(
off
<=
a
->
len
);
EXPECT
(
is_digit
(
f
->
cur
[
0
]),
JSON_STRING_INVALID
);
while
(
f
->
cur
<
f
->
end
&&
is_digit
(
f
->
cur
[
0
]))
f
->
cur
++
;
/* check overflow */
if
(
f
->
cur
<
f
->
end
&&
f
->
cur
[
0
]
==
'.'
)
{
if
(
~
(
size_t
)
0
-
(
size_t
)
a
->
buf
<
len
)
return
0
;
f
->
cur
++
;
EXPECT
(
f
->
cur
<
f
->
end
,
JSON_STRING_INCOMPLETE
);
if
(
a
->
len
+
len
<=
a
->
size
)
{
EXPECT
(
is_digit
(
f
->
cur
[
0
]),
JSON_STRING_INVALID
);
memmove
(
a
->
buf
+
off
+
len
,
a
->
buf
+
off
,
a
->
len
-
off
);
while
(
f
->
cur
<
f
->
end
&&
is_digit
(
f
->
cur
[
0
]))
f
->
cur
++
;
if
(
buf
!=
NULL
)
{
memcpy
(
a
->
buf
+
off
,
buf
,
len
);
}
}
if
(
f
->
cur
<
f
->
end
&&
(
f
->
cur
[
0
]
==
'e'
||
f
->
cur
[
0
]
==
'E'
))
{
a
->
len
+=
len
;
f
->
cur
++
;
}
else
if
((
p
=
(
char
*
)
MBUF_REALLOC
(
EXPECT
(
f
->
cur
<
f
->
end
,
JSON_STRING_INCOMPLETE
);
a
->
buf
,
(
a
->
len
+
len
)
*
MBUF_SIZE_MULTIPLIER
))
!=
NULL
)
{
if
((
f
->
cur
[
0
]
==
'+'
||
f
->
cur
[
0
]
==
'-'
))
f
->
cur
++
;
a
->
buf
=
p
;
EXPECT
(
f
->
cur
<
f
->
end
,
JSON_STRING_INCOMPLETE
);
memmove
(
a
->
buf
+
off
+
len
,
a
->
buf
+
off
,
a
->
len
-
off
);
EXPECT
(
is_digit
(
f
->
cur
[
0
]),
JSON_STRING_INVALID
);
if
(
buf
!=
NULL
)
{
while
(
f
->
cur
<
f
->
end
&&
is_digit
(
f
->
cur
[
0
]))
f
->
cur
++
;
memcpy
(
a
->
buf
+
off
,
buf
,
len
)
;
}
}
capture_len
(
f
,
f
->
num_tokens
-
1
,
f
->
cur
);
a
->
len
+=
len
;
return
0
;
a
->
size
=
a
->
len
*
MBUF_SIZE_MULTIPLIER
;
}
else
{
len
=
0
;
}
return
len
;
}
}
/* array = '[' [ value { ',' value } ] ']' */
size_t
mbuf_append
(
struct
mbuf
*
a
,
const
void
*
buf
,
size_t
len
)
{
static
int
parse_array
(
struct
frozen
*
f
)
{
return
mbuf_insert
(
a
,
a
->
len
,
buf
,
len
);
int
ind
;
}
TRY
(
test_and_skip
(
f
,
'['
));
TRY
(
capture_ptr
(
f
,
f
->
cur
-
1
,
JSON_TYPE_ARRAY
));
void
mbuf_remove
(
struct
mbuf
*
mb
,
size_t
n
)
{
ind
=
f
->
num_tokens
-
1
;
if
(
n
>
0
&&
n
<=
mb
->
len
)
{
while
(
cur
(
f
)
!=
']'
)
{
memmove
(
mb
->
buf
,
mb
->
buf
+
n
,
mb
->
len
-
n
);
TRY
(
parse_value
(
f
));
mb
->
len
-=
n
;
if
(
cur
(
f
)
==
','
)
f
->
cur
++
;
}
}
TRY
(
test_and_skip
(
f
,
']'
));
capture_len
(
f
,
ind
,
f
->
cur
);
return
0
;
}
}
static
int
compare
(
const
char
*
s
,
const
char
*
str
,
int
len
)
{
#endif
/* EXCLUDE_COMMON */
int
i
=
0
;
#ifdef NS_MODULE_LINES
while
(
i
<
len
&&
s
[
i
]
==
str
[
i
])
i
++
;
#line 1 "src/../../common/sha1.c"
return
i
==
len
?
1
:
0
;
/**/
#endif
/* Copyright(c) By Steve Reid <steve@edmweb.com> */
/* 100% Public Domain */
#if !defined(DISABLE_SHA1) && !defined(EXCLUDE_COMMON)
/* Amalgamated: #include "sha1.h" */
#define SHA1HANDSOFF
#if defined(__sun)
/* Amalgamated: #include "solarisfixes.h" */
#endif
union
char64long16
{
unsigned
char
c
[
64
];
uint32_t
l
[
16
];
};
#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
static
uint32_t
blk0
(
union
char64long16
*
block
,
int
i
)
{
/* Forrest: SHA expect BIG_ENDIAN, swap if LITTLE_ENDIAN */
#if BYTE_ORDER == LITTLE_ENDIAN
block
->
l
[
i
]
=
(
rol
(
block
->
l
[
i
],
24
)
&
0xFF00FF00
)
|
(
rol
(
block
->
l
[
i
],
8
)
&
0x00FF00FF
);
#endif
return
block
->
l
[
i
];
}
/* Avoid redefine warning (ARM /usr/include/sys/ucontext.h define R0~R4) */
#undef blk
#undef R0
#undef R1
#undef R2
#undef R3
#undef R4
#define blk(i) \
(block->l[i & 15] = rol(block->l[(i + 13) & 15] ^ block->l[(i + 8) & 15] ^ \
block->l[(i + 2) & 15] ^ block->l[i & 15], \
1))
#define R0(v, w, x, y, z, i) \
z += ((w & (x ^ y)) ^ y) + blk0(block, i) + 0x5A827999 + rol(v, 5); \
w = rol(w, 30);
#define R1(v, w, x, y, z, i) \
z += ((w & (x ^ y)) ^ y) + blk(i) + 0x5A827999 + rol(v, 5); \
w = rol(w, 30);
#define R2(v, w, x, y, z, i) \
z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + rol(v, 5); \
w = rol(w, 30);
#define R3(v, w, x, y, z, i) \
z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + rol(v, 5); \
w = rol(w, 30);
#define R4(v, w, x, y, z, i) \
z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + rol(v, 5); \
w = rol(w, 30);
void
cs_sha1_transform
(
uint32_t
state
[
5
],
const
unsigned
char
buffer
[
64
])
{
uint32_t
a
,
b
,
c
,
d
,
e
;
union
char64long16
block
[
1
];
memcpy
(
block
,
buffer
,
64
);
a
=
state
[
0
];
b
=
state
[
1
];
c
=
state
[
2
];
d
=
state
[
3
];
e
=
state
[
4
];
R0
(
a
,
b
,
c
,
d
,
e
,
0
);
R0
(
e
,
a
,
b
,
c
,
d
,
1
);
R0
(
d
,
e
,
a
,
b
,
c
,
2
);
R0
(
c
,
d
,
e
,
a
,
b
,
3
);
R0
(
b
,
c
,
d
,
e
,
a
,
4
);
R0
(
a
,
b
,
c
,
d
,
e
,
5
);
R0
(
e
,
a
,
b
,
c
,
d
,
6
);
R0
(
d
,
e
,
a
,
b
,
c
,
7
);
R0
(
c
,
d
,
e
,
a
,
b
,
8
);
R0
(
b
,
c
,
d
,
e
,
a
,
9
);
R0
(
a
,
b
,
c
,
d
,
e
,
10
);
R0
(
e
,
a
,
b
,
c
,
d
,
11
);
R0
(
d
,
e
,
a
,
b
,
c
,
12
);
R0
(
c
,
d
,
e
,
a
,
b
,
13
);
R0
(
b
,
c
,
d
,
e
,
a
,
14
);
R0
(
a
,
b
,
c
,
d
,
e
,
15
);
R1
(
e
,
a
,
b
,
c
,
d
,
16
);
R1
(
d
,
e
,
a
,
b
,
c
,
17
);
R1
(
c
,
d
,
e
,
a
,
b
,
18
);
R1
(
b
,
c
,
d
,
e
,
a
,
19
);
R2
(
a
,
b
,
c
,
d
,
e
,
20
);
R2
(
e
,
a
,
b
,
c
,
d
,
21
);
R2
(
d
,
e
,
a
,
b
,
c
,
22
);
R2
(
c
,
d
,
e
,
a
,
b
,
23
);
R2
(
b
,
c
,
d
,
e
,
a
,
24
);
R2
(
a
,
b
,
c
,
d
,
e
,
25
);
R2
(
e
,
a
,
b
,
c
,
d
,
26
);
R2
(
d
,
e
,
a
,
b
,
c
,
27
);
R2
(
c
,
d
,
e
,
a
,
b
,
28
);
R2
(
b
,
c
,
d
,
e
,
a
,
29
);
R2
(
a
,
b
,
c
,
d
,
e
,
30
);
R2
(
e
,
a
,
b
,
c
,
d
,
31
);
R2
(
d
,
e
,
a
,
b
,
c
,
32
);
R2
(
c
,
d
,
e
,
a
,
b
,
33
);
R2
(
b
,
c
,
d
,
e
,
a
,
34
);
R2
(
a
,
b
,
c
,
d
,
e
,
35
);
R2
(
e
,
a
,
b
,
c
,
d
,
36
);
R2
(
d
,
e
,
a
,
b
,
c
,
37
);
R2
(
c
,
d
,
e
,
a
,
b
,
38
);
R2
(
b
,
c
,
d
,
e
,
a
,
39
);
R3
(
a
,
b
,
c
,
d
,
e
,
40
);
R3
(
e
,
a
,
b
,
c
,
d
,
41
);
R3
(
d
,
e
,
a
,
b
,
c
,
42
);
R3
(
c
,
d
,
e
,
a
,
b
,
43
);
R3
(
b
,
c
,
d
,
e
,
a
,
44
);
R3
(
a
,
b
,
c
,
d
,
e
,
45
);
R3
(
e
,
a
,
b
,
c
,
d
,
46
);
R3
(
d
,
e
,
a
,
b
,
c
,
47
);
R3
(
c
,
d
,
e
,
a
,
b
,
48
);
R3
(
b
,
c
,
d
,
e
,
a
,
49
);
R3
(
a
,
b
,
c
,
d
,
e
,
50
);
R3
(
e
,
a
,
b
,
c
,
d
,
51
);
R3
(
d
,
e
,
a
,
b
,
c
,
52
);
R3
(
c
,
d
,
e
,
a
,
b
,
53
);
R3
(
b
,
c
,
d
,
e
,
a
,
54
);
R3
(
a
,
b
,
c
,
d
,
e
,
55
);
R3
(
e
,
a
,
b
,
c
,
d
,
56
);
R3
(
d
,
e
,
a
,
b
,
c
,
57
);
R3
(
c
,
d
,
e
,
a
,
b
,
58
);
R3
(
b
,
c
,
d
,
e
,
a
,
59
);
R4
(
a
,
b
,
c
,
d
,
e
,
60
);
R4
(
e
,
a
,
b
,
c
,
d
,
61
);
R4
(
d
,
e
,
a
,
b
,
c
,
62
);
R4
(
c
,
d
,
e
,
a
,
b
,
63
);
R4
(
b
,
c
,
d
,
e
,
a
,
64
);
R4
(
a
,
b
,
c
,
d
,
e
,
65
);
R4
(
e
,
a
,
b
,
c
,
d
,
66
);
R4
(
d
,
e
,
a
,
b
,
c
,
67
);
R4
(
c
,
d
,
e
,
a
,
b
,
68
);
R4
(
b
,
c
,
d
,
e
,
a
,
69
);
R4
(
a
,
b
,
c
,
d
,
e
,
70
);
R4
(
e
,
a
,
b
,
c
,
d
,
71
);
R4
(
d
,
e
,
a
,
b
,
c
,
72
);
R4
(
c
,
d
,
e
,
a
,
b
,
73
);
R4
(
b
,
c
,
d
,
e
,
a
,
74
);
R4
(
a
,
b
,
c
,
d
,
e
,
75
);
R4
(
e
,
a
,
b
,
c
,
d
,
76
);
R4
(
d
,
e
,
a
,
b
,
c
,
77
);
R4
(
c
,
d
,
e
,
a
,
b
,
78
);
R4
(
b
,
c
,
d
,
e
,
a
,
79
);
state
[
0
]
+=
a
;
state
[
1
]
+=
b
;
state
[
2
]
+=
c
;
state
[
3
]
+=
d
;
state
[
4
]
+=
e
;
/* Erase working structures. The order of operations is important,
* used to ensure that compiler doesn't optimize those out. */
memset
(
block
,
0
,
sizeof
(
block
));
a
=
b
=
c
=
d
=
e
=
0
;
(
void
)
a
;
(
void
)
b
;
(
void
)
c
;
(
void
)
d
;
(
void
)
e
;
}
void
cs_sha1_init
(
cs_sha1_ctx
*
context
)
{
context
->
state
[
0
]
=
0x67452301
;
context
->
state
[
1
]
=
0xEFCDAB89
;
context
->
state
[
2
]
=
0x98BADCFE
;
context
->
state
[
3
]
=
0x10325476
;
context
->
state
[
4
]
=
0xC3D2E1F0
;
context
->
count
[
0
]
=
context
->
count
[
1
]
=
0
;
}
}
static
int
expect
(
struct
frozen
*
f
,
const
char
*
s
,
int
len
,
enum
json_type
t
)
{
void
cs_sha1_update
(
cs_sha1_ctx
*
context
,
const
unsigned
char
*
data
,
uint32_t
len
)
{
int
i
,
n
=
left
(
f
)
;
uint32_t
i
,
j
;
TRY
(
capture_ptr
(
f
,
f
->
cur
,
t
));
j
=
context
->
count
[
0
];
for
(
i
=
0
;
i
<
len
;
i
++
)
{
if
((
context
->
count
[
0
]
+=
len
<<
3
)
<
j
)
context
->
count
[
1
]
++
;
if
(
i
>=
n
)
return
JSON_STRING_INCOMPLETE
;
context
->
count
[
1
]
+=
(
len
>>
29
);
if
(
f
->
cur
[
i
]
!=
s
[
i
])
return
JSON_STRING_INVALID
;
j
=
(
j
>>
3
)
&
63
;
if
((
j
+
len
)
>
63
)
{
memcpy
(
&
context
->
buffer
[
j
],
data
,
(
i
=
64
-
j
));
cs_sha1_transform
(
context
->
state
,
context
->
buffer
);
for
(;
i
+
63
<
len
;
i
+=
64
)
{
cs_sha1_transform
(
context
->
state
,
&
data
[
i
]);
}
}
f
->
cur
+=
len
;
j
=
0
;
TRY
(
capture_len
(
f
,
f
->
num_tokens
-
1
,
f
->
cur
));
}
else
i
=
0
;
return
0
;
memcpy
(
&
context
->
buffer
[
j
],
&
data
[
i
],
len
-
i
)
;
}
}
/* value = 'null' | 'true' | 'false' | number | string | array | object */
void
cs_sha1_final
(
unsigned
char
digest
[
20
],
cs_sha1_ctx
*
context
)
{
static
int
parse_value
(
struct
frozen
*
f
)
{
unsigned
i
;
int
ch
=
cur
(
f
)
;
unsigned
char
finalcount
[
8
],
c
;
switch
(
ch
)
{
for
(
i
=
0
;
i
<
8
;
i
++
)
{
case
'"'
:
TRY
(
parse_string
(
f
));
break
;
finalcount
[
i
]
=
(
unsigned
char
)
((
context
->
count
[(
i
>=
4
?
0
:
1
)]
>>
case
'{'
:
TRY
(
parse_object
(
f
));
break
;
((
3
-
(
i
&
3
))
*
8
))
&
case
'['
:
TRY
(
parse_array
(
f
));
break
;
255
);
case
'n'
:
TRY
(
expect
(
f
,
"null"
,
4
,
JSON_TYPE_NULL
));
break
;
case
't'
:
TRY
(
expect
(
f
,
"true"
,
4
,
JSON_TYPE_TRUE
));
break
;
case
'f'
:
TRY
(
expect
(
f
,
"false"
,
5
,
JSON_TYPE_FALSE
));
break
;
case
'-'
:
case
'0'
:
case
'1'
:
case
'2'
:
case
'3'
:
case
'4'
:
case
'5'
:
case
'6'
:
case
'7'
:
case
'8'
:
case
'9'
:
TRY
(
parse_number
(
f
));
break
;
default:
return
ch
==
END_OF_STRING
?
JSON_STRING_INCOMPLETE
:
JSON_STRING_INVALID
;
}
}
c
=
0200
;
return
0
;
cs_sha1_update
(
context
,
&
c
,
1
);
}
while
((
context
->
count
[
0
]
&
504
)
!=
448
)
{
c
=
0000
;
/* key = identifier | string */
cs_sha1_update
(
context
,
&
c
,
1
);
static
int
parse_key
(
struct
frozen
*
f
)
{
int
ch
=
cur
(
f
);
#if 0
printf("%s 1 [%.*s]\n", __func__, (int) (f->end - f->cur), f->cur);
#endif
if
(
is_alpha
(
ch
))
{
TRY
(
parse_identifier
(
f
));
}
else
if
(
ch
==
'"'
)
{
TRY
(
parse_string
(
f
));
}
else
{
return
ch
==
END_OF_STRING
?
JSON_STRING_INCOMPLETE
:
JSON_STRING_INVALID
;
}
}
return
0
;
cs_sha1_update
(
context
,
finalcount
,
8
);
for
(
i
=
0
;
i
<
20
;
i
++
)
{
digest
[
i
]
=
(
unsigned
char
)
((
context
->
state
[
i
>>
2
]
>>
((
3
-
(
i
&
3
))
*
8
))
&
255
);
}
memset
(
context
,
'\0'
,
sizeof
(
*
context
));
memset
(
&
finalcount
,
'\0'
,
sizeof
(
finalcount
));
}
}
/* pair = key ':' value */
void
cs_hmac_sha1
(
const
unsigned
char
*
key
,
size_t
keylen
,
static
int
parse_pair
(
struct
frozen
*
f
)
{
const
unsigned
char
*
data
,
size_t
datalen
,
TRY
(
parse_key
(
f
));
unsigned
char
out
[
20
])
{
TRY
(
test_and_skip
(
f
,
':'
));
cs_sha1_ctx
ctx
;
TRY
(
parse_value
(
f
));
unsigned
char
buf1
[
64
],
buf2
[
64
],
tmp_key
[
20
],
i
;
return
0
;
}
/* object = '{' pair { ',' pair } '}' */
if
(
keylen
>
sizeof
(
buf1
))
{
static
int
parse_object
(
struct
frozen
*
f
)
{
cs_sha1_init
(
&
ctx
);
int
ind
;
cs_sha1_update
(
&
ctx
,
key
,
keylen
);
TRY
(
test_and_skip
(
f
,
'{'
));
cs_sha1_final
(
tmp_key
,
&
ctx
);
TRY
(
capture_ptr
(
f
,
f
->
cur
-
1
,
JSON_TYPE_OBJECT
));
key
=
tmp_key
;
ind
=
f
->
num_tokens
-
1
;
keylen
=
sizeof
(
tmp_key
);
while
(
cur
(
f
)
!=
'}'
)
{
TRY
(
parse_pair
(
f
));
if
(
cur
(
f
)
==
','
)
f
->
cur
++
;
}
}
TRY
(
test_and_skip
(
f
,
'}'
));
capture_len
(
f
,
ind
,
f
->
cur
);
return
0
;
}
static
int
doit
(
struct
frozen
*
f
)
{
if
(
f
->
cur
==
0
||
f
->
end
<
f
->
cur
)
return
JSON_STRING_INVALID
;
if
(
f
->
end
==
f
->
cur
)
return
JSON_STRING_INCOMPLETE
;
TRY
(
parse_object
(
f
));
TRY
(
capture_ptr
(
f
,
f
->
cur
,
JSON_TYPE_EOF
));
capture_len
(
f
,
f
->
num_tokens
,
f
->
cur
);
return
0
;
}
/* json = object */
memset
(
buf1
,
0
,
sizeof
(
buf1
));
int
parse_json
(
const
char
*
s
,
int
s_len
,
struct
json_token
*
arr
,
int
arr_len
)
{
memset
(
buf2
,
0
,
sizeof
(
buf2
));
struct
frozen
frozen
;
memcpy
(
buf1
,
key
,
keylen
);
memcpy
(
buf2
,
key
,
keylen
);
memset
(
&
frozen
,
0
,
sizeof
(
frozen
));
for
(
i
=
0
;
i
<
sizeof
(
buf1
);
i
++
)
{
frozen
.
end
=
s
+
s_len
;
buf1
[
i
]
^=
0x36
;
frozen
.
cur
=
s
;
buf2
[
i
]
^=
0x5c
;
frozen
.
tokens
=
arr
;
}
frozen
.
max_tokens
=
arr_len
;
TRY
(
doit
(
&
frozen
));
cs_sha1_init
(
&
ctx
);
cs_sha1_update
(
&
ctx
,
buf1
,
sizeof
(
buf1
));
cs_sha1_update
(
&
ctx
,
data
,
datalen
);
cs_sha1_final
(
out
,
&
ctx
);
return
frozen
.
cur
-
s
;
cs_sha1_init
(
&
ctx
);
cs_sha1_update
(
&
ctx
,
buf2
,
sizeof
(
buf2
));
cs_sha1_update
(
&
ctx
,
out
,
20
);
cs_sha1_final
(
out
,
&
ctx
);
}
}
struct
json_token
*
parse_json2
(
const
char
*
s
,
int
s_len
)
{
#endif
/* EXCLUDE_COMMON */
struct
frozen
frozen
;
#ifdef NS_MODULE_LINES
#line 1 "src/../../common/str_util.c"
/**/
#endif
/*
* Copyright (c) 2015 Cesanta Software Limited
* All rights reserved
*/
memset
(
&
frozen
,
0
,
sizeof
(
frozen
));
#ifndef EXCLUDE_COMMON
frozen
.
end
=
s
+
s_len
;
frozen
.
cur
=
s
;
frozen
.
do_realloc
=
1
;
if
(
doit
(
&
frozen
)
<
0
)
{
/* Amalgamated: #include "osdep.h" */
FROZEN_FREE
((
void
*
)
frozen
.
tokens
);
/* Amalgamated: #include "str_util.h" */
frozen
.
tokens
=
NULL
;
#if !(_XOPEN_SOURCE >= 700 || _POSIX_C_SOURCE >= 200809L) && \
!(__DARWIN_C_LEVEL >= 200809L) && !defined(RTOS_SDK) || \
defined(_WIN32)
size_t
strnlen
(
const
char
*
s
,
size_t
maxlen
)
{
size_t
l
=
0
;
for
(;
l
<
maxlen
&&
s
[
l
]
!=
'\0'
;
l
++
)
{
}
}
return
frozen
.
tokens
;
return
l
;
}
}
#endif
static
int
path_part_len
(
const
char
*
p
)
{
#define C_SNPRINTF_APPEND_CHAR(ch) \
int
i
=
0
;
do { \
while
(
p
[
i
]
!=
'\0'
&&
p
[
i
]
!=
'['
&&
p
[
i
]
!=
'.'
)
i
++
;
if (i < (int) buf_size) buf[i] = ch; \
return
i
;
i++; \
} while (0)
#define C_SNPRINTF_FLAG_ZERO 1
#ifdef C_DISABLE_BUILTIN_SNPRINTF
int
c_vsnprintf
(
char
*
buf
,
size_t
buf_size
,
const
char
*
fmt
,
va_list
ap
)
{
return
vsnprintf
(
buf
,
buf_size
,
fmt
,
ap
);
}
}
#else
static
int
c_itoa
(
char
*
buf
,
size_t
buf_size
,
int64_t
num
,
int
base
,
int
flags
,
int
field_width
)
{
char
tmp
[
40
];
int
i
=
0
,
k
=
0
,
neg
=
0
;
struct
json_token
*
find_json_token
(
struct
json_token
*
toks
,
const
char
*
path
)
{
if
(
num
<
0
)
{
while
(
path
!=
0
&&
path
[
0
]
!=
'\0'
)
{
neg
++
;
int
i
,
ind2
=
0
,
ind
=
-
1
,
skip
=
2
,
n
=
path_part_len
(
path
);
num
=
-
num
;
if
(
path
[
0
]
==
'['
)
{
if
(
toks
->
type
!=
JSON_TYPE_ARRAY
||
!
is_digit
(
path
[
1
]))
return
0
;
for
(
ind
=
0
,
n
=
1
;
path
[
n
]
!=
']'
&&
path
[
n
]
!=
'\0'
;
n
++
)
{
if
(
!
is_digit
(
path
[
n
]))
return
0
;
ind
*=
10
;
ind
+=
path
[
n
]
-
'0'
;
}
}
if
(
path
[
n
++
]
!=
']'
)
return
0
;
skip
=
1
;
/* In objects, we skip 2 elems while iterating, in arrays 1. */
/* Print into temporary buffer - in reverse order */
}
else
if
(
toks
->
type
!=
JSON_TYPE_OBJECT
)
return
0
;
do
{
toks
++
;
int
rem
=
num
%
base
;
for
(
i
=
0
;
i
<
toks
[
-
1
].
num_desc
;
i
+=
skip
,
ind2
++
)
{
if
(
rem
<
10
)
{
/* ind == -1 indicated that we're iterating an array, not object */
tmp
[
k
++
]
=
'0'
+
rem
;
if
(
ind
==
-
1
&&
toks
[
i
].
type
!=
JSON_TYPE_STRING
)
return
0
;
}
else
{
if
(
ind2
==
ind
||
tmp
[
k
++
]
=
'a'
+
(
rem
-
10
);
(
ind
==
-
1
&&
toks
[
i
].
len
==
n
&&
compare
(
path
,
toks
[
i
].
ptr
,
n
)))
{
i
+=
skip
-
1
;
break
;
};
if
(
toks
[
i
-
1
+
skip
].
type
==
JSON_TYPE_ARRAY
||
toks
[
i
-
1
+
skip
].
type
==
JSON_TYPE_OBJECT
)
{
i
+=
toks
[
i
-
1
+
skip
].
num_desc
;
}
}
num
/=
base
;
}
while
(
num
>
0
);
/* Zero padding */
if
(
flags
&&
C_SNPRINTF_FLAG_ZERO
)
{
while
(
k
<
field_width
&&
k
<
(
int
)
sizeof
(
tmp
)
-
1
)
{
tmp
[
k
++
]
=
'0'
;
}
}
if
(
i
==
toks
[
-
1
].
num_desc
)
return
0
;
path
+=
n
;
if
(
path
[
0
]
==
'.'
)
path
++
;
if
(
path
[
0
]
==
'\0'
)
return
&
toks
[
i
];
toks
+=
i
;
}
}
return
0
;
}
int
json_emit_long
(
char
*
buf
,
int
buf_len
,
long
int
value
)
{
/* And sign */
char
tmp
[
20
];
if
(
neg
)
{
int
n
=
snprintf
(
tmp
,
sizeof
(
tmp
),
"%ld"
,
value
);
tmp
[
k
++
]
=
'-'
;
strncpy
(
buf
,
tmp
,
buf_len
>
0
?
buf_len
:
0
);
}
return
n
;
}
int
json_emit_double
(
char
*
buf
,
int
buf_len
,
double
value
)
{
/* Now output */
char
tmp
[
20
];
while
(
--
k
>=
0
)
{
int
n
=
snprintf
(
tmp
,
sizeof
(
tmp
),
"%g"
,
value
);
C_SNPRINTF_APPEND_CHAR
(
tmp
[
k
]);
strncpy
(
buf
,
tmp
,
buf_len
>
0
?
buf_len
:
0
);
}
return
n
;
return
i
;
}
}
int
json_emit_quoted_str
(
char
*
s
,
int
s_len
,
const
char
*
str
,
int
len
)
{
int
c_vsnprintf
(
char
*
buf
,
size_t
buf_size
,
const
char
*
fmt
,
va_list
ap
)
{
const
char
*
begin
=
s
,
*
end
=
s
+
s_len
,
*
str_end
=
str
+
len
;
int
ch
,
i
=
0
,
len_mod
,
flags
,
precision
,
field_width
;
char
ch
;
#define EMIT(x) do { if (s < end) *s = x; s++; } while (0)
while
((
ch
=
*
fmt
++
)
!=
'\0'
)
{
if
(
ch
!=
'%'
)
{
C_SNPRINTF_APPEND_CHAR
(
ch
);
}
else
{
/*
* Conversion specification:
* zero or more flags (one of: # 0 - <space> + ')
* an optional minimum field width (digits)
* an optional precision (. followed by digits, or *)
* an optional length modifier (one of: hh h l ll L q j z t)
* conversion specifier (one of: d i o u x X e E f F g G a A c s p n)
*/
flags
=
field_width
=
precision
=
len_mod
=
0
;
EMIT
(
'"'
);
/* Flags. only zero-pad flag is supported. */
while
(
str
<
str_end
)
{
if
(
*
fmt
==
'0'
)
{
ch
=
*
str
++
;
flags
|=
C_SNPRINTF_FLAG_ZERO
;
switch
(
ch
)
{
case
'"'
:
EMIT
(
'\\'
);
EMIT
(
'"'
);
break
;
case
'\\'
:
EMIT
(
'\\'
);
EMIT
(
'\\'
);
break
;
case
'\b'
:
EMIT
(
'\\'
);
EMIT
(
'b'
);
break
;
case
'\f'
:
EMIT
(
'\\'
);
EMIT
(
'f'
);
break
;
case
'\n'
:
EMIT
(
'\\'
);
EMIT
(
'n'
);
break
;
case
'\r'
:
EMIT
(
'\\'
);
EMIT
(
'r'
);
break
;
case
'\t'
:
EMIT
(
'\\'
);
EMIT
(
't'
);
break
;
default:
EMIT
(
ch
);
}
}
/* Field width */
while
(
*
fmt
>=
'0'
&&
*
fmt
<=
'9'
)
{
field_width
*=
10
;
field_width
+=
*
fmt
++
-
'0'
;
}
}
EMIT
(
'"'
);
/* Dynamic field width */
if
(
s
<
end
)
{
if
(
*
fmt
==
'*'
)
{
*
s
=
'\0'
;
field_width
=
va_arg
(
ap
,
int
);
fmt
++
;
}
}
return
s
-
begin
;
/* Precision */
}
if
(
*
fmt
==
'.'
)
{
fmt
++
;
int
json_emit_unquoted_str
(
char
*
buf
,
int
buf_len
,
const
char
*
str
,
int
len
)
{
if
(
*
fmt
==
'*'
)
{
if
(
buf_len
>
0
&&
len
>
0
)
{
precision
=
va_arg
(
ap
,
int
);
int
n
=
len
<
buf_len
?
len
:
buf_len
;
fmt
++
;
memcpy
(
buf
,
str
,
n
);
}
else
{
if
(
n
<
buf_len
)
{
while
(
*
fmt
>=
'0'
&&
*
fmt
<=
'9'
)
{
buf
[
n
]
=
'\0'
;
precision
*=
10
;
precision
+=
*
fmt
++
-
'0'
;
}
}
}
}
}
return
len
;
}
int
json_emit_va
(
char
*
s
,
int
s_len
,
const
char
*
fmt
,
va_list
ap
)
{
const
char
*
end
=
s
+
s_len
,
*
str
,
*
orig
=
s
;
size_t
len
;
while
(
*
fmt
!=
'\0'
)
{
/* Length modifier */
switch
(
*
fmt
)
{
switch
(
*
fmt
)
{
case
'['
:
case
']'
:
case
'{'
:
case
'}'
:
case
','
:
case
':'
:
case
'h'
:
case
' '
:
case
'\r'
:
case
'\n'
:
case
'\t'
:
case
'l'
:
if
(
s
<
end
)
{
case
'L'
:
*
s
=
*
fmt
;
case
'I'
:
case
'q'
:
case
'j'
:
case
'z'
:
case
't'
:
len_mod
=
*
fmt
++
;
if
(
*
fmt
==
'h'
)
{
len_mod
=
'H'
;
fmt
++
;
}
if
(
*
fmt
==
'l'
)
{
len_mod
=
'q'
;
fmt
++
;
}
}
s
++
;
break
;
case
'i'
:
s
+=
json_emit_long
(
s
,
end
-
s
,
va_arg
(
ap
,
long
));
break
;
case
'f'
:
s
+=
json_emit_double
(
s
,
end
-
s
,
va_arg
(
ap
,
double
));
break
;
case
'v'
:
str
=
va_arg
(
ap
,
char
*
);
len
=
va_arg
(
ap
,
size_t
);
s
+=
json_emit_quoted_str
(
s
,
end
-
s
,
str
,
len
);
break
;
case
'V'
:
str
=
va_arg
(
ap
,
char
*
);
len
=
va_arg
(
ap
,
size_t
);
s
+=
json_emit_unquoted_str
(
s
,
end
-
s
,
str
,
len
);
break
;
case
's'
:
str
=
va_arg
(
ap
,
char
*
);
s
+=
json_emit_quoted_str
(
s
,
end
-
s
,
str
,
strlen
(
str
));
break
;
case
'S'
:
str
=
va_arg
(
ap
,
char
*
);
s
+=
json_emit_unquoted_str
(
s
,
end
-
s
,
str
,
strlen
(
str
));
break
;
case
'T'
:
s
+=
json_emit_unquoted_str
(
s
,
end
-
s
,
"true"
,
4
);
break
;
case
'F'
:
s
+=
json_emit_unquoted_str
(
s
,
end
-
s
,
"false"
,
5
);
break
;
case
'N'
:
s
+=
json_emit_unquoted_str
(
s
,
end
-
s
,
"null"
,
4
);
break
;
break
;
default:
return
0
;
}
}
fmt
++
;
ch
=
*
fmt
++
;
if
(
ch
==
's'
)
{
const
char
*
s
=
va_arg
(
ap
,
const
char
*
);
/* Always fetch parameter */
int
j
;
int
pad
=
field_width
-
(
precision
>=
0
?
strnlen
(
s
,
precision
)
:
0
);
for
(
j
=
0
;
j
<
pad
;
j
++
)
{
C_SNPRINTF_APPEND_CHAR
(
' '
);
}
}
/* Best-effort to 0-terminate generated string */
/* Ignore negative and 0 precisions */
if
(
s
<
end
)
{
for
(
j
=
0
;
(
precision
<=
0
||
j
<
precision
)
&&
s
[
j
]
!=
'\0'
;
j
++
)
{
*
s
=
'\0'
;
C_SNPRINTF_APPEND_CHAR
(
s
[
j
]);
}
}
else
if
(
ch
==
'c'
)
{
ch
=
va_arg
(
ap
,
int
);
/* Always fetch parameter */
C_SNPRINTF_APPEND_CHAR
(
ch
);
}
else
if
(
ch
==
'd'
&&
len_mod
==
0
)
{
i
+=
c_itoa
(
buf
+
i
,
buf_size
-
i
,
va_arg
(
ap
,
int
),
10
,
flags
,
field_width
);
}
else
if
(
ch
==
'd'
&&
len_mod
==
'l'
)
{
i
+=
c_itoa
(
buf
+
i
,
buf_size
-
i
,
va_arg
(
ap
,
long
),
10
,
flags
,
field_width
);
}
else
if
((
ch
==
'x'
||
ch
==
'u'
)
&&
len_mod
==
0
)
{
i
+=
c_itoa
(
buf
+
i
,
buf_size
-
i
,
va_arg
(
ap
,
unsigned
),
ch
==
'x'
?
16
:
10
,
flags
,
field_width
);
}
else
if
((
ch
==
'x'
||
ch
==
'u'
)
&&
len_mod
==
'l'
)
{
i
+=
c_itoa
(
buf
+
i
,
buf_size
-
i
,
va_arg
(
ap
,
unsigned
long
),
ch
==
'x'
?
16
:
10
,
flags
,
field_width
);
}
else
if
(
ch
==
'p'
)
{
unsigned
long
num
=
(
unsigned
long
)
va_arg
(
ap
,
void
*
);
C_SNPRINTF_APPEND_CHAR
(
'0'
);
C_SNPRINTF_APPEND_CHAR
(
'x'
);
i
+=
c_itoa
(
buf
+
i
,
buf_size
-
i
,
num
,
16
,
flags
,
0
);
}
else
{
#ifndef NO_LIBC
/*
* TODO(lsm): abort is not nice in a library, remove it
* Also, ESP8266 SDK doesn't have it
*/
abort
();
#endif
}
}
}
}
return
s
-
orig
;
/* Zero-terminate the result */
if
(
buf_size
>
0
)
{
buf
[
i
<
(
int
)
buf_size
?
i
:
(
int
)
buf_size
-
1
]
=
'\0'
;
}
return
i
;
}
}
#endif
int
json_emit
(
char
*
buf
,
int
buf_len
,
const
char
*
fmt
,
...)
{
int
c_snprintf
(
char
*
buf
,
size_t
buf_size
,
const
char
*
fmt
,
...)
{
int
len
;
int
result
;
va_list
ap
;
va_list
ap
;
va_start
(
ap
,
fmt
);
va_start
(
ap
,
fmt
);
len
=
json_emit_va
(
buf
,
buf_len
,
fmt
,
ap
);
result
=
c_vsnprintf
(
buf
,
buf_size
,
fmt
,
ap
);
va_end
(
ap
);
va_end
(
ap
);
return
result
;
}
return
len
;
#ifdef _WIN32
void
to_wchar
(
const
char
*
path
,
wchar_t
*
wbuf
,
size_t
wbuf_len
)
{
char
buf
[
MAX_PATH
*
2
],
buf2
[
MAX_PATH
*
2
],
*
p
;
strncpy
(
buf
,
path
,
sizeof
(
buf
));
buf
[
sizeof
(
buf
)
-
1
]
=
'\0'
;
/* Trim trailing slashes. Leave backslash for paths like "X:\" */
p
=
buf
+
strlen
(
buf
)
-
1
;
while
(
p
>
buf
&&
p
[
-
1
]
!=
':'
&&
(
p
[
0
]
==
'\\'
||
p
[
0
]
==
'/'
))
*
p
--
=
'\0'
;
/*
* Convert to Unicode and back. If doubly-converted string does not
* match the original, something is fishy, reject.
*/
memset
(
wbuf
,
0
,
wbuf_len
*
sizeof
(
wchar_t
));
MultiByteToWideChar
(
CP_UTF8
,
0
,
buf
,
-
1
,
wbuf
,
(
int
)
wbuf_len
);
WideCharToMultiByte
(
CP_UTF8
,
0
,
wbuf
,
(
int
)
wbuf_len
,
buf2
,
sizeof
(
buf2
),
NULL
,
NULL
);
if
(
strcmp
(
buf
,
buf2
)
!=
0
)
{
wbuf
[
0
]
=
L'\0'
;
}
}
}
#endif
/* _WIN32 */
#endif
/* EXCLUDE_COMMON */
#ifdef NS_MODULE_LINES
#ifdef NS_MODULE_LINES
#line 1 "src/net.c"
#line 1 "src/net.c"
/**/
/**/
...
...
mongoose.h
View file @
d60c99b0
...
@@ -26,6 +26,10 @@
...
@@ -26,6 +26,10 @@
#ifdef MG_LOCALS
#ifdef MG_LOCALS
#include <mg_locals.h>
#include <mg_locals.h>
#endif
#endif
#if defined(MG_ENABLE_DEBUG) && !defined(CS_ENABLE_DEBUG)
#define CS_ENABLE_DEBUG
#endif
/*
/*
* Copyright (c) 2015 Cesanta Software Limited
* Copyright (c) 2015 Cesanta Software Limited
* All rights reserved
* All rights reserved
...
@@ -260,25 +264,31 @@ int64_t strtoll(const char *str, char **endptr, int base);
...
@@ -260,25 +264,31 @@ int64_t strtoll(const char *str, char **endptr, int base);
#endif
#endif
#endif
/* !_WIN32 */
#endif
/* !_WIN32 */
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
#endif
#endif
/* OSDEP_HEADER_INCLUDED */
#ifndef _CS_DBG_H_
#define _CS_DBG_H_
#ifdef CS_ENABLE_DEBUG
void
cs_dbg_printf
(
const
char
*
fmt
,
...);
#define __DBG(x) \
#define __DBG(x) \
do { \
do { \
printf("%-20s ", __func__); \
fprintf(stderr, "%-20s ", __func__); \
printf x; \
cs_dbg_printf x; \
putchar('\n'); \
fflush(stdout); \
} while (0)
} while (0)
#ifdef MG_ENABLE_DEBUG
#define DBG __DBG
#define DBG __DBG
#else
#else
#define DBG(x)
#define DBG(x)
#endif
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
#endif
#endif
#endif
/*
OSDEP_HEADER_INCLUDED
*/
#endif
/*
_CS_DBG_H_
*/
/*
/*
* Copyright (c) 2015 Cesanta Software Limited
* Copyright (c) 2015 Cesanta Software Limited
* All rights reserved
* All rights reserved
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment