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
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
1398 additions
and
1373 deletions
+1398
-1373
mongoose.c
mongoose.c
+1377
-1362
mongoose.h
mongoose.h
+21
-11
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
);
#ifndef MG_FREE
#define MG_FREE free
#endif
#endif
return
block
->
l
[
i
];
}
/* Avoid redefine warning (ARM /usr/include/sys/ucontext.h define R0~R4) */
#ifndef MG_MALLOC
#undef blk
#define MG_MALLOC malloc
#undef R0
#endif
#undef R1
#undef R2
#undef R3
#undef R4
#define blk(i) \
#ifdef _WIN32
(block->l[i & 15] = rol(block->l[(i + 13) & 15] ^ block->l[(i + 8) & 15] ^ \
DIR
*
opendir
(
const
char
*
name
)
{
block->l[(i + 2) & 15] ^ block->l[i & 15], \
DIR
*
dir
=
NULL
;
1))
wchar_t
wpath
[
MAX_PATH
];
#define R0(v, w, x, y, z, i) \
DWORD
attrs
;
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
])
{
if
(
name
==
NULL
)
{
uint32_t
a
,
b
,
c
,
d
,
e
;
SetLastError
(
ERROR_BAD_ARGUMENTS
);
union
char64long16
block
[
1
];
}
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
;
}
}
memcpy
(
block
,
buffer
,
64
);
return
dir
;
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
)
{
int
closedir
(
DIR
*
dir
)
{
context
->
state
[
0
]
=
0x67452301
;
int
result
=
0
;
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
)
{
if
(
dir
!=
NULL
)
{
uint32_t
i
,
j
;
if
(
dir
->
handle
!=
INVALID_HANDLE_VALUE
)
result
=
FindClose
(
dir
->
handle
)
?
0
:
-
1
;
MG_FREE
(
dir
);
}
else
{
result
=
-
1
;
SetLastError
(
ERROR_BAD_ARGUMENTS
);
}
j
=
context
->
count
[
0
];
return
result
;
if
((
context
->
count
[
0
]
+=
len
<<
3
)
<
j
)
context
->
count
[
1
]
++
;
context
->
count
[
1
]
+=
(
len
>>
29
);
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
]);
}
j
=
0
;
}
else
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
,
c
=
0200
;
NULL
);
cs_sha1_update
(
context
,
&
c
,
1
);
while
((
context
->
count
[
0
]
&
504
)
!=
448
)
{
c
=
0000
;
cs_sha1_update
(
context
,
&
c
,
1
);
}
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
));
}
void
cs_hmac_sha1
(
const
unsigned
char
*
key
,
size_t
keylen
,
if
(
!
FindNextFileW
(
dir
->
handle
,
&
dir
->
info
))
{
const
unsigned
char
*
data
,
size_t
datalen
,
(
void
)
FindClose
(
dir
->
handle
);
unsigned
char
out
[
20
])
{
dir
->
handle
=
INVALID_HANDLE_VALUE
;
cs_sha1_ctx
ctx
;
}
unsigned
char
buf1
[
64
],
buf2
[
64
],
tmp_key
[
20
],
i
;
if
(
keylen
>
sizeof
(
buf1
))
{
}
else
{
cs_sha1_init
(
&
ctx
);
SetLastError
(
ERROR_FILE_NOT_FOUND
);
cs_sha1_update
(
&
ctx
,
key
,
keylen
);
}
cs_sha1_final
(
tmp_key
,
&
ctx
);
}
else
{
key
=
tmp_key
;
SetLastError
(
ERROR_BAD_ARGUMENTS
);
keylen
=
sizeof
(
tmp_key
);
}
}
memset
(
buf1
,
0
,
sizeof
(
buf1
));
return
result
;
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
#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)
/*
#ifndef FROZEN_REALLOC
* Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
#define FROZEN_REALLOC realloc
* initialization constants.
#endif
*/
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
;
ctx
->
bits
[
1
]
=
0
;
}
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
;
count
=
(
ctx
->
bits
[
0
]
>>
3
)
&
0x3F
;
f
->
max_tokens
=
new_size
;
f
->
tokens
=
(
struct
json_token
*
)
p
;
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
);
if
(
f
->
tokens
==
NULL
||
f
->
max_tokens
==
0
)
return
0
;
if
(
f
->
num_tokens
>=
f
->
max_tokens
)
return
JSON_TOKEN_ARRAY_TOO_SMALL
;
a
=
(
uint32_t
*
)
ctx
->
in
;
f
->
tokens
[
f
->
num_tokens
].
ptr
=
ptr
;
a
[
14
]
=
ctx
->
bits
[
0
];
f
->
tokens
[
f
->
num_tokens
].
type
=
type
;
a
[
15
]
=
ctx
->
bits
[
1
];
f
->
num_tokens
++
;
return
0
;
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
capture_len
(
struct
frozen
*
f
,
int
token_index
,
const
char
*
ptr
)
{
* Stringify binary data. Output buffer size must be 2 * size_of_input + 1
if
(
f
->
tokens
==
0
||
f
->
max_tokens
==
0
)
return
0
;
* because each byte of input takes 2 bytes in string representation
EXPECT
(
token_index
>=
0
&&
token_index
<
f
->
max_tokens
,
JSON_STRING_INVALID
);
* plus 1 byte for the terminating \0 character.
f
->
tokens
[
token_index
].
len
=
ptr
-
f
->
tokens
[
token_index
].
ptr
;
*/
f
->
tokens
[
token_index
].
num_desc
=
(
f
->
num_tokens
-
1
)
-
token_index
;
void
cs_to_hex
(
char
*
to
,
const
unsigned
char
*
p
,
size_t
len
)
{
return
0
;
static
const
char
*
hex
=
"0123456789abcdef"
;
}
for
(;
len
--
;
p
++
)
{
/* identifier = letter { letter | digit | '_' } */
*
to
++
=
hex
[
p
[
0
]
>>
4
];
static
int
parse_identifier
(
struct
frozen
*
f
)
{
*
to
++
=
hex
[
p
[
0
]
&
0x0f
];
EXPECT
(
is_alpha
(
cur
(
f
)),
JSON_STRING_INVALID
);
TRY
(
capture_ptr
(
f
,
f
->
cur
,
JSON_TYPE_STRING
));
while
(
f
->
cur
<
f
->
end
&&
(
*
f
->
cur
==
'_'
||
is_alpha
(
*
f
->
cur
)
||
is_digit
(
*
f
->
cur
)))
{
f
->
cur
++
;
}
}
*
to
=
'\0'
;
capture_len
(
f
,
f
->
num_tokens
-
1
,
f
->
cur
);
return
0
;
}
}
char
*
cs_md5
(
char
buf
[
33
],
...)
{
static
int
get_utf8_char_len
(
unsigned
char
ch
)
{
unsigned
char
hash
[
16
];
if
((
ch
&
0x80
)
==
0
)
return
1
;
const
unsigned
char
*
p
;
switch
(
ch
&
0xf0
)
{
va_list
ap
;
case
0xf0
:
return
4
;
MD5_CTX
ctx
;
case
0xe0
:
return
3
;
default:
return
2
;
}
}
MD5_Init
(
&
ctx
);
/* string = '"' { quoted_printable_chars } '"' */
static
int
parse_string
(
struct
frozen
*
f
)
{
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
;
}
va_start
(
ap
,
buf
);
/* number = [ '-' ] digit+ [ '.' digit+ ] [ ['e'|'E'] ['+'|'-'] digit+ ] */
while
((
p
=
va_arg
(
ap
,
const
unsigned
char
*
)
)
!=
NULL
)
{
static
int
parse_number
(
struct
frozen
*
f
)
{
size_t
len
=
va_arg
(
ap
,
size_t
);
int
ch
=
cur
(
f
);
MD5_Update
(
&
ctx
,
p
,
len
);
TRY
(
capture_ptr
(
f
,
f
->
cur
,
JSON_TYPE_NUMBER
));
if
(
ch
==
'-'
)
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
]
==
'.'
)
{
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
++
;
}
}
va_end
(
ap
);
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
;
}
MD5_Final
(
hash
,
&
ctx
);
/* array = '[' [ value { ',' value } ] ']' */
cs_to_hex
(
buf
,
hash
,
sizeof
(
hash
));
static
int
parse_array
(
struct
frozen
*
f
)
{
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
++
;
}
TRY
(
test_and_skip
(
f
,
']'
));
capture_len
(
f
,
ind
,
f
->
cur
);
return
0
;
}
return
buf
;
static
int
compare
(
const
char
*
s
,
const
char
*
str
,
int
len
)
{
int
i
=
0
;
while
(
i
<
len
&&
s
[
i
]
==
str
[
i
])
i
++
;
return
i
==
len
?
1
:
0
;
}
}
#endif
/* EXCLUDE_COMMON */
static
int
expect
(
struct
frozen
*
f
,
const
char
*
s
,
int
len
,
enum
json_type
t
)
{
#ifdef NS_MODULE_LINES
int
i
,
n
=
left
(
f
);
#line 1 "src/../../common/base64.c"
/**/
#endif
/*
* Copyright (c) 2014 Cesanta Software Limited
* All rights reserved
*/
#ifndef EXCLUDE_COMMON
TRY
(
capture_ptr
(
f
,
f
->
cur
,
t
));
for
(
i
=
0
;
i
<
len
;
i
++
)
{
if
(
i
>=
n
)
return
JSON_STRING_INCOMPLETE
;
if
(
f
->
cur
[
i
]
!=
s
[
i
])
return
JSON_STRING_INVALID
;
}
f
->
cur
+=
len
;
TRY
(
capture_len
(
f
,
f
->
num_tokens
-
1
,
f
->
cur
));
/* Amalgamated: #include "base64.h" */
return
0
;
#include <string.h>
}
/* ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ */
/* value = 'null' | 'true' | 'false' | number | string | array | object */
static
int
parse_value
(
struct
frozen
*
f
)
{
int
ch
=
cur
(
f
);
#define NUM_UPPERCASES ('Z' - 'A' + 1)
switch
(
ch
)
{
#define NUM_LETTERS (NUM_UPPERCASES * 2)
case
'"'
:
TRY
(
parse_string
(
f
));
break
;
#define NUM_DIGITS ('9' - '0' + 1)
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
;
}
/*
return
0
;
* Emit a base64 code char.
}
*
* Doesn't use memory, thus it's safe to use to safely dump memory in crashdumps
/* key = identifier | string */
*/
static
int
parse_key
(
struct
frozen
*
f
)
{
static
void
cs_base64_emit_code
(
struct
cs_base64_ctx
*
ctx
,
int
v
)
{
int
ch
=
cur
(
f
);
if
(
v
<
NUM_UPPERCASES
)
{
#if 0
ctx
->
b64_putc
(
v
+
'A'
,
ctx
->
user_data
);
printf("%s 1 [%.*s]\n", __func__, (int) (f->end - f->cur), f->cur);
}
else
if
(
v
<
(
NUM_LETTERS
))
{
#endif
ctx
->
b64_putc
(
v
-
NUM_UPPERCASES
+
'a'
,
ctx
->
user_data
);
if
(
is_alpha
(
ch
))
{
}
else
if
(
v
<
(
NUM_LETTERS
+
NUM_DIGITS
))
{
TRY
(
parse_identifier
(
f
));
ctx
->
b64_putc
(
v
-
NUM_LETTERS
+
'0'
,
ctx
->
user_data
);
}
else
if
(
ch
==
'"'
)
{
TRY
(
parse_string
(
f
));
}
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) \
memset
(
&
frozen
,
0
,
sizeof
(
frozen
));
do { \
frozen
.
end
=
s
+
s_len
;
fprintf(f, "%c", (ch)); \
frozen
.
cur
=
s
;
j++; \
frozen
.
do_realloc
=
1
;
} while (0)
#define BASE64_FLUSH()
if
(
doit
(
&
frozen
)
<
0
)
{
FROZEN_FREE
((
void
*
)
frozen
.
tokens
);
frozen
.
tokens
=
NULL
;
}
return
frozen
.
tokens
;
}
void
cs_fprint_base64
(
FILE
*
f
,
const
unsigned
char
*
src
,
int
src_len
)
{
static
int
path_part_len
(
const
char
*
p
)
{
BASE64_ENCODE_BODY
;
int
i
=
0
;
while
(
p
[
i
]
!=
'\0'
&&
p
[
i
]
!=
'['
&&
p
[
i
]
!=
'.'
)
i
++
;
return
i
;
}
}
#undef BASE64_OUT
struct
json_token
*
find_json_token
(
struct
json_token
*
toks
,
const
char
*
path
)
{
#undef BASE64_FLUSH
while
(
path
!=
0
&&
path
[
0
]
!=
'\0'
)
{
int
i
,
ind2
=
0
,
ind
=
-
1
,
skip
=
2
,
n
=
path_part_len
(
path
);
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. */
}
else
if
(
toks
->
type
!=
JSON_TYPE_OBJECT
)
return
0
;
toks
++
;
for
(
i
=
0
;
i
<
toks
[
-
1
].
num_desc
;
i
+=
skip
,
ind2
++
)
{
/* ind == -1 indicated that we're iterating an array, not object */
if
(
ind
==
-
1
&&
toks
[
i
].
type
!=
JSON_TYPE_STRING
)
return
0
;
if
(
ind2
==
ind
||
(
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
;
}
}
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
;
}
/* Convert one byte of encoded base64 input stream to 6-bit chunk */
int
json_emit_long
(
char
*
buf
,
int
buf_len
,
long
int
value
)
{
static
unsigned
char
from_b64
(
unsigned
char
ch
)
{
char
tmp
[
20
];
/* Inverse lookup map */
int
n
=
snprintf
(
tmp
,
sizeof
(
tmp
),
"%ld"
,
value
);
static
const
unsigned
char
tab
[
128
]
=
{
strncpy
(
buf
,
tmp
,
buf_len
>
0
?
buf_len
:
0
);
255
,
255
,
255
,
255
,
return
n
;
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
];
}
}
int
cs_base64_decode
(
const
unsigned
char
*
s
,
int
len
,
char
*
dst
)
{
int
json_emit_double
(
char
*
buf
,
int
buf_len
,
double
value
)
{
unsigned
char
a
,
b
,
c
,
d
;
char
tmp
[
20
];
int
orig_len
=
len
;
int
n
=
snprintf
(
tmp
,
sizeof
(
tmp
),
"%g"
,
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_quoted_str
(
char
*
s
,
int
s_len
,
const
char
*
str
,
int
len
)
{
#ifdef NS_MODULE_LINES
const
char
*
begin
=
s
,
*
end
=
s
+
s_len
,
*
str_end
=
str
+
len
;
#line 1 "src/../../common/str_util.c"
char
ch
;
/**/
#endif
/*
* Copyright (c) 2015 Cesanta Software Limited
* All rights reserved
*/
#
ifndef EXCLUDE_COMMON
#
define EMIT(x) do { if (s < end) *s = x; s++; } while (0)
/* Amalgamated: #include "osdep.h" */
EMIT
(
'"'
);
/* Amalgamated: #include "str_util.h" */
while
(
str
<
str_end
)
{
ch
=
*
str
++
;
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
);
}
}
EMIT
(
'"'
);
if
(
s
<
end
)
{
*
s
=
'\0'
;
}
#if !(_XOPEN_SOURCE >= 700 || _POSIX_C_SOURCE >= 200809L) && \
return
s
-
begin
;
!(__DARWIN_C_LEVEL >= 200809L) && !defined(RTOS_SDK) || \
}
defined(_WIN32)
size_t
strnlen
(
const
char
*
s
,
size_t
maxlen
)
{
int
json_emit_unquoted_str
(
char
*
buf
,
int
buf_len
,
const
char
*
str
,
int
len
)
{
size_t
l
=
0
;
if
(
buf_len
>
0
&&
len
>
0
)
{
for
(;
l
<
maxlen
&&
s
[
l
]
!=
'\0'
;
l
++
)
{
int
n
=
len
<
buf_len
?
len
:
buf_len
;
memcpy
(
buf
,
str
,
n
);
if
(
n
<
buf_len
)
{
buf
[
n
]
=
'\0'
;
}
}
}
return
l
;
return
l
en
;
}
}
#endif
#define C_SNPRINTF_APPEND_CHAR(ch) \
int
json_emit_va
(
char
*
s
,
int
s_len
,
const
char
*
fmt
,
va_list
ap
)
{
do { \
const
char
*
end
=
s
+
s_len
,
*
str
,
*
orig
=
s
;
if (i < (int) buf_size) buf[i] = ch; \
size_t
len
;
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
;
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 */
if
(
neg
)
{
tmp
[
k
++
]
=
'-'
;
}
/* Now output */
while
(
--
k
>=
0
)
{
C_SNPRINTF_APPEND_CHAR
(
tmp
[
k
]);
}
return
i
;
}
int
c_vsnprintf
(
char
*
buf
,
size_t
buf_size
,
const
char
*
fmt
,
va_list
ap
)
{
int
ch
,
i
=
0
,
len_mod
,
flags
,
precision
,
field_width
;
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 */
switch
(
*
fmt
)
{
case
'h'
:
case
'l'
:
case
'L'
:
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
++
;
}
break
;
}
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 */
while
(
*
fmt
!=
'\0'
)
{
for
(
j
=
0
;
(
precision
<=
0
||
j
<
precision
)
&&
s
[
j
]
!=
'\0'
;
j
++
)
{
switch
(
*
fmt
)
{
C_SNPRINTF_APPEND_CHAR
(
s
[
j
]);
case
'['
:
case
']'
:
case
'{'
:
case
'}'
:
case
','
:
case
':'
:
case
' '
:
case
'\r'
:
case
'\n'
:
case
'\t'
:
if
(
s
<
end
)
{
*
s
=
*
fmt
;
}
}
}
else
if
(
ch
==
'c'
)
{
s
++
;
ch
=
va_arg
(
ap
,
int
);
/* Always fetch parameter */
break
;
C_SNPRINTF_APPEND_CHAR
(
ch
);
case
'i'
:
}
else
if
(
ch
==
'd'
&&
len_mod
==
0
)
{
s
+=
json_emit_long
(
s
,
end
-
s
,
va_arg
(
ap
,
long
));
i
+=
c_itoa
(
buf
+
i
,
buf_size
-
i
,
va_arg
(
ap
,
int
),
10
,
flags
,
break
;
field_width
);
case
'f'
:
}
else
if
(
ch
==
'd'
&&
len_mod
==
'l'
)
{
s
+=
json_emit_double
(
s
,
end
-
s
,
va_arg
(
ap
,
double
));
i
+=
c_itoa
(
buf
+
i
,
buf_size
-
i
,
va_arg
(
ap
,
long
),
10
,
flags
,
break
;
field_width
);
case
'v'
:
}
else
if
((
ch
==
'x'
||
ch
==
'u'
)
&&
len_mod
==
0
)
{
str
=
va_arg
(
ap
,
char
*
);
i
+=
c_itoa
(
buf
+
i
,
buf_size
-
i
,
va_arg
(
ap
,
unsigned
),
len
=
va_arg
(
ap
,
size_t
);
ch
==
'x'
?
16
:
10
,
flags
,
field_width
);
s
+=
json_emit_quoted_str
(
s
,
end
-
s
,
str
,
len
);
}
else
if
((
ch
==
'x'
||
ch
==
'u'
)
&&
len_mod
==
'l'
)
{
break
;
i
+=
c_itoa
(
buf
+
i
,
buf_size
-
i
,
va_arg
(
ap
,
unsigned
long
),
case
'V'
:
ch
==
'x'
?
16
:
10
,
flags
,
field_width
);
str
=
va_arg
(
ap
,
char
*
);
}
else
if
(
ch
==
'p'
)
{
len
=
va_arg
(
ap
,
size_t
);
unsigned
long
num
=
(
unsigned
long
)
va_arg
(
ap
,
void
*
);
s
+=
json_emit_unquoted_str
(
s
,
end
-
s
,
str
,
len
);
C_SNPRINTF_APPEND_CHAR
(
'0'
);
break
;
C_SNPRINTF_APPEND_CHAR
(
'x'
);
case
's'
:
i
+=
c_itoa
(
buf
+
i
,
buf_size
-
i
,
num
,
16
,
flags
,
0
);
str
=
va_arg
(
ap
,
char
*
);
}
else
{
s
+=
json_emit_quoted_str
(
s
,
end
-
s
,
str
,
strlen
(
str
));
#ifndef NO_LIBC
break
;
/*
case
'S'
:
* TODO(lsm): abort is not nice in a library, remove it
str
=
va_arg
(
ap
,
char
*
);
* Also, ESP8266 SDK doesn't have it
s
+=
json_emit_unquoted_str
(
s
,
end
-
s
,
str
,
strlen
(
str
));
*/
break
;
abort
();
case
'T'
:
#endif
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
++
;
}
}
/*
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
));
return
len
;
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/../../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.
*
* Equivalent code is available from RSA Data Security, Inc.
* 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.
*
* 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
* will fill a supplied 16-byte array with the digest.
*/
*/
#if
ndef EXCLUDE_COMMON
#if
!defined(DISABLE_MD5) && !defined(EXCLUDE_COMMON)
/* Amalgamated: #include "osdep.h" */
/* Amalgamated: #include "md5.h" */
#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
}
#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)
/*
/*
*
This file contains POSIX opendir/closedir/readdir API implementation
*
Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
*
for systems which do not natively support it (e.g. Windows)
.
*
initialization constants
.
*/
*/
void
MD5_Init
(
MD5_CTX
*
ctx
)
{
ctx
->
buf
[
0
]
=
0x67452301
;
ctx
->
buf
[
1
]
=
0xefcdab89
;
ctx
->
buf
[
2
]
=
0x98badcfe
;
ctx
->
buf
[
3
]
=
0x10325476
;
#ifndef MG_FREE
ctx
->
bits
[
0
]
=
0
;
#define MG_FREE free
ctx
->
bits
[
1
]
=
0
;
#endif
}
#ifndef MG_MALLOC
static
void
MD5Transform
(
uint32_t
buf
[
4
],
uint32_t
const
in
[
16
])
{
#define MG_MALLOC malloc
register
uint32_t
a
,
b
,
c
,
d
;
#endif
#ifdef _WIN32
a
=
buf
[
0
];
DIR
*
opendir
(
const
char
*
name
)
{
b
=
buf
[
1
];
DIR
*
dir
=
NULL
;
c
=
buf
[
2
];
wchar_t
wpath
[
MAX_PATH
];
d
=
buf
[
3
];
DWORD
attrs
;
if
(
name
==
NULL
)
{
MD5STEP
(
F1
,
a
,
b
,
c
,
d
,
in
[
0
]
+
0xd76aa478
,
7
);
SetLastError
(
ERROR_BAD_ARGUMENTS
);
MD5STEP
(
F1
,
d
,
a
,
b
,
c
,
in
[
1
]
+
0xe8c7b756
,
12
);
}
else
if
((
dir
=
(
DIR
*
)
MG_MALLOC
(
sizeof
(
*
dir
)))
==
NULL
)
{
MD5STEP
(
F1
,
c
,
d
,
a
,
b
,
in
[
2
]
+
0x242070db
,
17
);
SetLastError
(
ERROR_NOT_ENOUGH_MEMORY
);
MD5STEP
(
F1
,
b
,
c
,
d
,
a
,
in
[
3
]
+
0xc1bdceee
,
22
);
}
else
{
MD5STEP
(
F1
,
a
,
b
,
c
,
d
,
in
[
4
]
+
0xf57c0faf
,
7
);
to_wchar
(
name
,
wpath
,
ARRAY_SIZE
(
wpath
)
);
MD5STEP
(
F1
,
d
,
a
,
b
,
c
,
in
[
5
]
+
0x4787c62a
,
12
);
attrs
=
GetFileAttributesW
(
wpath
);
MD5STEP
(
F1
,
c
,
d
,
a
,
b
,
in
[
6
]
+
0xa8304613
,
17
);
if
(
attrs
!=
0xFFFFFFFF
&&
(
attrs
&
FILE_ATTRIBUTE_DIRECTORY
))
{
MD5STEP
(
F1
,
b
,
c
,
d
,
a
,
in
[
7
]
+
0xfd469501
,
22
);
(
void
)
wcscat
(
wpath
,
L"
\\
*"
);
MD5STEP
(
F1
,
a
,
b
,
c
,
d
,
in
[
8
]
+
0x698098d8
,
7
);
dir
->
handle
=
FindFirstFileW
(
wpath
,
&
dir
->
info
);
MD5STEP
(
F1
,
d
,
a
,
b
,
c
,
in
[
9
]
+
0x8b44f7af
,
12
);
dir
->
result
.
d_name
[
0
]
=
'\0'
;
MD5STEP
(
F1
,
c
,
d
,
a
,
b
,
in
[
10
]
+
0xffff5bb1
,
17
)
;
}
else
{
MD5STEP
(
F1
,
b
,
c
,
d
,
a
,
in
[
11
]
+
0x895cd7be
,
22
);
MG_FREE
(
dir
);
MD5STEP
(
F1
,
a
,
b
,
c
,
d
,
in
[
12
]
+
0x6b901122
,
7
);
dir
=
NULL
;
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
);
return
dir
;
MD5STEP
(
F2
,
a
,
b
,
c
,
d
,
in
[
1
]
+
0xf61e2562
,
5
);
}
MD5STEP
(
F2
,
d
,
a
,
b
,
c
,
in
[
6
]
+
0xc040b340
,
9
);
MD5STEP
(
F2
,
c
,
d
,
a
,
b
,
in
[
11
]
+
0x265e5a51
,
14
);
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
);
int
closedir
(
DIR
*
dir
)
{
MD5STEP
(
F3
,
a
,
b
,
c
,
d
,
in
[
5
]
+
0xfffa3942
,
4
);
int
result
=
0
;
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
);
if
(
dir
!=
NULL
)
{
MD5STEP
(
F4
,
a
,
b
,
c
,
d
,
in
[
0
]
+
0xf4292244
,
6
);
if
(
dir
->
handle
!=
INVALID_HANDLE_VALUE
)
MD5STEP
(
F4
,
d
,
a
,
b
,
c
,
in
[
7
]
+
0x432aff97
,
10
);
result
=
FindClose
(
dir
->
handle
)
?
0
:
-
1
;
MD5STEP
(
F4
,
c
,
d
,
a
,
b
,
in
[
14
]
+
0xab9423a7
,
15
);
MG_FREE
(
dir
);
MD5STEP
(
F4
,
b
,
c
,
d
,
a
,
in
[
5
]
+
0xfc93a039
,
21
);
}
else
{
MD5STEP
(
F4
,
a
,
b
,
c
,
d
,
in
[
12
]
+
0x655b59c3
,
6
);
result
=
-
1
;
MD5STEP
(
F4
,
d
,
a
,
b
,
c
,
in
[
3
]
+
0x8f0ccc92
,
10
);
SetLastError
(
ERROR_BAD_ARGUMENTS
);
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
);
return
result
;
buf
[
0
]
+=
a
;
buf
[
1
]
+=
b
;
buf
[
2
]
+=
c
;
buf
[
3
]
+=
d
;
}
}
struct
dirent
*
readdir
(
DIR
*
dir
)
{
void
MD5_Update
(
MD5_CTX
*
ctx
,
const
unsigned
char
*
buf
,
size_t
len
)
{
struct
dirent
*
result
=
0
;
uint32_t
t
;
if
(
dir
)
{
t
=
ctx
->
bits
[
0
];
if
(
dir
->
handle
!=
INVALID_HANDLE_VALUE
)
{
if
((
ctx
->
bits
[
0
]
=
t
+
((
uint32_t
)
len
<<
3
))
<
t
)
ctx
->
bits
[
1
]
++
;
result
=
&
dir
->
result
;
ctx
->
bits
[
1
]
+=
(
uint32_t
)
len
>>
29
;
(
void
)
WideCharToMultiByte
(
CP_UTF8
,
0
,
dir
->
info
.
cFileName
,
-
1
,
result
->
d_name
,
sizeof
(
result
->
d_name
),
NULL
,
NULL
);
if
(
!
FindNextFileW
(
dir
->
handle
,
&
dir
->
info
))
{
t
=
(
t
>>
3
)
&
0x3f
;
(
void
)
FindClose
(
dir
->
handle
);
dir
->
handle
=
INVALID_HANDLE_VALUE
;
}
}
else
{
if
(
t
)
{
SetLastError
(
ERROR_FILE_NOT_FOUND
);
unsigned
char
*
p
=
(
unsigned
char
*
)
ctx
->
in
+
t
;
t
=
64
-
t
;
if
(
len
<
t
)
{
memcpy
(
p
,
buf
,
len
);
return
;
}
}
}
else
{
memcpy
(
p
,
buf
,
t
);
SetLastError
(
ERROR_BAD_ARGUMENTS
);
byteReverse
(
ctx
->
in
,
16
);
MD5Transform
(
ctx
->
buf
,
(
uint32_t
*
)
ctx
->
in
);
buf
+=
t
;
len
-=
t
;
}
}
return
result
;
while
(
len
>=
64
)
{
}
memcpy
(
ctx
->
in
,
buf
,
64
);
#endif
byteReverse
(
ctx
->
in
,
16
);
MD5Transform
(
ctx
->
buf
,
(
uint32_t
*
)
ctx
->
in
);
#endif
/* EXCLUDE_COMMON */
buf
+=
64
;
#ifdef NS_MODULE_LINES
len
-=
64
;
#line 1 "src/../deps/frozen/frozen.c"
}
/**/
#endif
/*
* Copyright (c) 2004-2013 Sergey Lyubka <valenok@gmail.com>
* Copyright (c) 2013 Cesanta Software Limited
* 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>.
*/
#define _CRT_SECURE_NO_WARNINGS
/* Disable deprecation warning in VS2005+ */
memcpy
(
ctx
->
in
,
buf
,
len
);
}
#include <stdio.h>
void
MD5_Final
(
unsigned
char
digest
[
16
],
MD5_CTX
*
ctx
)
{
#include <stdlib.h>
unsigned
count
;
#include <string.h>
unsigned
char
*
p
;
#include <stdarg.h>
uint32_t
*
a
;
/* Amalgamated: #include "frozen.h" */
#ifdef _WIN32
count
=
(
ctx
->
bits
[
0
]
>>
3
)
&
0x3F
;
#define snprintf _snprintf
#endif
#ifndef FROZEN_REALLOC
p
=
ctx
->
in
+
count
;
#define FROZEN_REALLOC realloc
*
p
++
=
0x80
;
#endif
count
=
64
-
1
-
count
;
if
(
count
<
8
)
{
#ifndef FROZEN_FREE
memset
(
p
,
0
,
count
);
#define FROZEN_FREE free
byteReverse
(
ctx
->
in
,
16
);
#endif
MD5Transform
(
ctx
->
buf
,
(
uint32_t
*
)
ctx
->
in
);
memset
(
ctx
->
in
,
0
,
56
);
}
else
{
memset
(
p
,
0
,
count
-
8
);
}
byteReverse
(
ctx
->
in
,
14
);
struct
frozen
{
a
=
(
uint32_t
*
)
ctx
->
in
;
const
char
*
end
;
a
[
14
]
=
ctx
->
bits
[
0
];
const
char
*
cur
;
a
[
15
]
=
ctx
->
bits
[
1
];
struct
json_token
*
tokens
;
int
max_tokens
;
int
num_tokens
;
int
do_realloc
;
};
static
int
parse_object
(
struct
frozen
*
f
);
MD5Transform
(
ctx
->
buf
,
(
uint32_t
*
)
ctx
->
in
);
static
int
parse_value
(
struct
frozen
*
f
);
byteReverse
((
unsigned
char
*
)
ctx
->
buf
,
4
);
memcpy
(
digest
,
ctx
->
buf
,
16
);
memset
((
char
*
)
ctx
,
0
,
sizeof
(
*
ctx
));
}
#endif
/* CS_ENABLE_NATIVE_MD5 */
#define EXPECT(cond, err_code) do { if (!(cond)) return (err_code); } while (0)
/*
#define TRY(expr) do { int _n = expr; if (_n < 0) return _n; } while (0)
* Stringify binary data. Output buffer size must be 2 * size_of_input + 1
#define END_OF_STRING (-1)
* because each byte of input takes 2 bytes in string representation
* plus 1 byte for the terminating \0 character.
*/
void
cs_to_hex
(
char
*
to
,
const
unsigned
char
*
p
,
size_t
len
)
{
static
const
char
*
hex
=
"0123456789abcdef"
;
static
int
left
(
const
struct
frozen
*
f
)
{
for
(;
len
--
;
p
++
)
{
return
f
->
end
-
f
->
cur
;
*
to
++
=
hex
[
p
[
0
]
>>
4
];
*
to
++
=
hex
[
p
[
0
]
&
0x0f
];
}
*
to
=
'\0'
;
}
}
static
int
is_space
(
int
ch
)
{
char
*
cs_md5
(
char
buf
[
33
],
...)
{
return
ch
==
' '
||
ch
==
'\t'
||
ch
==
'\r'
||
ch
==
'\n'
;
unsigned
char
hash
[
16
];
}
const
unsigned
char
*
p
;
va_list
ap
;
MD5_CTX
ctx
;
static
void
skip_whitespaces
(
struct
frozen
*
f
)
{
MD5_Init
(
&
ctx
);
while
(
f
->
cur
<
f
->
end
&&
is_space
(
*
f
->
cur
))
f
->
cur
++
;
}
static
int
cur
(
struct
frozen
*
f
)
{
va_start
(
ap
,
buf
);
skip_whitespaces
(
f
);
while
((
p
=
va_arg
(
ap
,
const
unsigned
char
*
)
)
!=
NULL
)
{
return
f
->
cur
>=
f
->
end
?
END_OF_STRING
:
*
(
unsigned
char
*
)
f
->
cur
;
size_t
len
=
va_arg
(
ap
,
size_t
);
}
MD5_Update
(
&
ctx
,
p
,
len
);
}
va_end
(
ap
);
static
int
test_and_skip
(
struct
frozen
*
f
,
int
expected
)
{
MD5_Final
(
hash
,
&
ctx
);
int
ch
=
cur
(
f
);
cs_to_hex
(
buf
,
hash
,
sizeof
(
hash
));
if
(
ch
==
expected
)
{
f
->
cur
++
;
return
0
;
}
return
ch
==
END_OF_STRING
?
JSON_STRING_INCOMPLETE
:
JSON_STRING_INVALID
;
}
static
int
is_alpha
(
int
ch
)
{
return
buf
;
return
(
ch
>=
'a'
&&
ch
<=
'z'
)
||
(
ch
>=
'A'
&&
ch
<=
'Z'
);
}
}
static
int
is_digit
(
int
ch
)
{
#endif
/* EXCLUDE_COMMON */
return
ch
>=
'0'
&&
ch
<=
'9'
;
#ifdef NS_MODULE_LINES
}
#line 1 "src/../../common/mbuf.c"
/**/
#endif
/*
* Copyright (c) 2014 Cesanta Software Limited
* All rights reserved
*/
static
int
is_hex_digit
(
int
ch
)
{
#ifndef EXCLUDE_COMMON
return
is_digit
(
ch
)
||
(
ch
>=
'a'
&&
ch
<=
'f'
)
||
(
ch
>=
'A'
&&
ch
<=
'F'
);
#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
);
}
}
static
int
get_escape_len
(
const
char
*
s
,
int
len
)
{
void
mbuf_free
(
struct
mbuf
*
mbuf
)
{
switch
(
*
s
)
{
if
(
mbuf
->
buf
!=
NULL
)
{
case
'u'
:
MBUF_FREE
(
mbuf
->
buf
);
return
len
<
6
?
JSON_STRING_INCOMPLETE
:
mbuf_init
(
mbuf
,
0
);
is_hex_digit
(
s
[
1
])
&&
is_hex_digit
(
s
[
2
])
&&
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
;
}
}
}
}
static
int
capture_ptr
(
struct
frozen
*
f
,
const
char
*
ptr
,
enum
json_type
type
)
{
void
mbuf_resize
(
struct
mbuf
*
a
,
size_t
new_size
)
{
if
(
f
->
do_realloc
&&
f
->
num_tokens
>=
f
->
max_tokens
)
{
if
(
new_size
>
a
->
size
||
(
new_size
<
a
->
size
&&
new_size
>=
a
->
len
))
{
int
new_size
=
f
->
max_tokens
==
0
?
100
:
f
->
max_tokens
*
2
;
char
*
buf
=
(
char
*
)
MBUF_REALLOC
(
a
->
buf
,
new_size
);
void
*
p
=
FROZEN_REALLOC
(
f
->
tokens
,
new_size
*
sizeof
(
f
->
tokens
[
0
]));
/*
if
(
p
==
NULL
)
return
JSON_TOKEN_ARRAY_TOO_SMALL
;
* In case realloc fails, there's not much we can do, except keep things as
f
->
max_tokens
=
new_size
;
* they are. Note that NULL is a valid return value from realloc when
f
->
tokens
=
(
struct
json_token
*
)
p
;
* size == 0, but that is covered too.
*/
if
(
buf
==
NULL
&&
new_size
!=
0
)
return
;
a
->
buf
=
buf
;
a
->
size
=
new_size
;
}
}
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
;
}
}
static
int
capture_len
(
struct
frozen
*
f
,
int
token_index
,
const
char
*
ptr
)
{
void
mbuf_trim
(
struct
mbuf
*
mbuf
)
{
if
(
f
->
tokens
==
0
||
f
->
max_tokens
==
0
)
return
0
;
mbuf_resize
(
mbuf
,
mbuf
->
len
);
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
;
}
}
/* identifier = letter { letter | digit | '_' } */
size_t
mbuf_insert
(
struct
mbuf
*
a
,
size_t
off
,
const
void
*
buf
,
size_t
len
)
{
static
int
parse_identifier
(
struct
frozen
*
f
)
{
char
*
p
=
NULL
;
EXPECT
(
is_alpha
(
cur
(
f
)),
JSON_STRING_INVALID
);
TRY
(
capture_ptr
(
f
,
f
->
cur
,
JSON_TYPE_STRING
));
assert
(
a
!=
NULL
);
while
(
f
->
cur
<
f
->
end
&&
assert
(
a
->
len
<=
a
->
size
);
(
*
f
->
cur
==
'_'
||
is_alpha
(
*
f
->
cur
)
||
is_digit
(
*
f
->
cur
)))
{
assert
(
off
<=
a
->
len
);
f
->
cur
++
;
/* check overflow */
if
(
~
(
size_t
)
0
-
(
size_t
)
a
->
buf
<
len
)
return
0
;
if
(
a
->
len
+
len
<=
a
->
size
)
{
memmove
(
a
->
buf
+
off
+
len
,
a
->
buf
+
off
,
a
->
len
-
off
);
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
;
}
}
capture_len
(
f
,
f
->
num_tokens
-
1
,
f
->
cur
);
return
0
;
return
len
;
}
}
static
int
get_utf8_char_len
(
unsigned
char
ch
)
{
size_t
mbuf_append
(
struct
mbuf
*
a
,
const
void
*
buf
,
size_t
len
)
{
if
((
ch
&
0x80
)
==
0
)
return
1
;
return
mbuf_insert
(
a
,
a
->
len
,
buf
,
len
);
switch
(
ch
&
0xf0
)
{
case
0xf0
:
return
4
;
case
0xe0
:
return
3
;
default:
return
2
;
}
}
}
/* string = '"' { quoted_printable_chars } '"' */
void
mbuf_remove
(
struct
mbuf
*
mb
,
size_t
n
)
{
static
int
parse_string
(
struct
frozen
*
f
)
{
if
(
n
>
0
&&
n
<=
mb
->
len
)
{
int
n
,
ch
=
0
,
len
=
0
;
memmove
(
mb
->
buf
,
mb
->
buf
+
n
,
mb
->
len
-
n
);
TRY
(
test_and_skip
(
f
,
'"'
));
mb
->
len
-=
n
;
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+ ] */
#endif
/* EXCLUDE_COMMON */
static
int
parse_number
(
struct
frozen
*
f
)
{
#ifdef NS_MODULE_LINES
int
ch
=
cur
(
f
);
#line 1 "src/../../common/sha1.c"
TRY
(
capture_ptr
(
f
,
f
->
cur
,
JSON_TYPE_NUMBER
));
/**/
if
(
ch
==
'-'
)
f
->
cur
++
;
#endif
EXPECT
(
f
->
cur
<
f
->
end
,
JSON_STRING_INCOMPLETE
);
/* Copyright(c) By Steve Reid <steve@edmweb.com> */
EXPECT
(
is_digit
(
f
->
cur
[
0
]),
JSON_STRING_INVALID
);
/* 100% Public Domain */
while
(
f
->
cur
<
f
->
end
&&
is_digit
(
f
->
cur
[
0
]))
f
->
cur
++
;
if
(
f
->
cur
<
f
->
end
&&
f
->
cur
[
0
]
==
'.'
)
{
#if !defined(DISABLE_SHA1) && !defined(EXCLUDE_COMMON)
f
->
cur
++
;
EXPECT
(
f
->
cur
<
f
->
end
,
JSON_STRING_INCOMPLETE
);
/* Amalgamated: #include "sha1.h" */
EXPECT
(
is_digit
(
f
->
cur
[
0
]),
JSON_STRING_INVALID
);
while
(
f
->
cur
<
f
->
end
&&
is_digit
(
f
->
cur
[
0
]))
f
->
cur
++
;
#define SHA1HANDSOFF
}
#if defined(__sun)
if
(
f
->
cur
<
f
->
end
&&
(
f
->
cur
[
0
]
==
'e'
||
f
->
cur
[
0
]
==
'E'
))
{
/* Amalgamated: #include "solarisfixes.h" */
f
->
cur
++
;
#endif
EXPECT
(
f
->
cur
<
f
->
end
,
JSON_STRING_INCOMPLETE
);
if
((
f
->
cur
[
0
]
==
'+'
||
f
->
cur
[
0
]
==
'-'
))
f
->
cur
++
;
union
char64long16
{
EXPECT
(
f
->
cur
<
f
->
end
,
JSON_STRING_INCOMPLETE
);
unsigned
char
c
[
64
];
EXPECT
(
is_digit
(
f
->
cur
[
0
]),
JSON_STRING_INVALID
);
uint32_t
l
[
16
];
while
(
f
->
cur
<
f
->
end
&&
is_digit
(
f
->
cur
[
0
]))
f
->
cur
++
;
};
}
capture_len
(
f
,
f
->
num_tokens
-
1
,
f
->
cur
);
#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
return
0
;
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
];
}
}
/* array = '[' [ value { ',' value } ] ']' */
/* Avoid redefine warning (ARM /usr/include/sys/ucontext.h define R0~R4) */
static
int
parse_array
(
struct
frozen
*
f
)
{
#undef blk
int
ind
;
#undef R0
TRY
(
test_and_skip
(
f
,
'['
));
#undef R1
TRY
(
capture_ptr
(
f
,
f
->
cur
-
1
,
JSON_TYPE_ARRAY
));
#undef R2
ind
=
f
->
num_tokens
-
1
;
#undef R3
while
(
cur
(
f
)
!=
']'
)
{
#undef R4
TRY
(
parse_value
(
f
));
if
(
cur
(
f
)
==
','
)
f
->
cur
++
;
#define blk(i) \
}
(block->l[i & 15] = rol(block->l[(i + 13) & 15] ^ block->l[(i + 8) & 15] ^ \
TRY
(
test_and_skip
(
f
,
']'
));
block->l[(i + 2) & 15] ^ block->l[i & 15], \
capture_len
(
f
,
ind
,
f
->
cur
);
1))
return
0
;
#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
;
}
}
static
int
compare
(
const
char
*
s
,
const
char
*
str
,
int
len
)
{
void
cs_sha1_init
(
cs_sha1_ctx
*
context
)
{
int
i
=
0
;
context
->
state
[
0
]
=
0x67452301
;
while
(
i
<
len
&&
s
[
i
]
==
str
[
i
])
i
++
;
context
->
state
[
1
]
=
0xEFCDAB89
;
return
i
==
len
?
1
:
0
;
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
));
for
(
i
=
0
;
i
<
len
;
i
++
)
{
if
(
i
>=
n
)
return
JSON_STRING_INCOMPLETE
;
if
(
f
->
cur
[
i
]
!=
s
[
i
])
return
JSON_STRING_INVALID
;
}
f
->
cur
+=
len
;
TRY
(
capture_len
(
f
,
f
->
num_tokens
-
1
,
f
->
cur
));
return
0
;
j
=
context
->
count
[
0
];
if
((
context
->
count
[
0
]
+=
len
<<
3
)
<
j
)
context
->
count
[
1
]
++
;
context
->
count
[
1
]
+=
(
len
>>
29
);
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
]);
}
j
=
0
;
}
else
i
=
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
;
cs_sha1_update
(
context
,
&
c
,
1
);
}
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
));
}
}
/* key = identifier | string */
void
cs_hmac_sha1
(
const
unsigned
char
*
key
,
size_t
keylen
,
static
int
parse_key
(
struct
frozen
*
f
)
{
const
unsigned
char
*
data
,
size_t
datalen
,
int
ch
=
cur
(
f
);
unsigned
char
out
[
20
])
{
#if 0
cs_sha1_ctx
ctx
;
printf("%s 1 [%.*s]\n", __func__, (int) (f->end - f->cur), f->cur)
;
unsigned
char
buf1
[
64
],
buf2
[
64
],
tmp_key
[
20
],
i
;
#endif
if
(
is_alpha
(
ch
))
{
if
(
keylen
>
sizeof
(
buf1
))
{
TRY
(
parse_identifier
(
f
)
);
cs_sha1_init
(
&
ctx
);
}
else
if
(
ch
==
'"'
)
{
cs_sha1_update
(
&
ctx
,
key
,
keylen
);
TRY
(
parse_string
(
f
)
);
cs_sha1_final
(
tmp_key
,
&
ctx
);
}
else
{
key
=
tmp_key
;
return
ch
==
END_OF_STRING
?
JSON_STRING_INCOMPLETE
:
JSON_STRING_INVALID
;
keylen
=
sizeof
(
tmp_key
)
;
}
}
return
0
;
}
/* pair = key ':' value */
memset
(
buf1
,
0
,
sizeof
(
buf1
));
static
int
parse_pair
(
struct
frozen
*
f
)
{
memset
(
buf2
,
0
,
sizeof
(
buf2
));
TRY
(
parse_key
(
f
));
memcpy
(
buf1
,
key
,
keylen
);
TRY
(
test_and_skip
(
f
,
':'
));
memcpy
(
buf2
,
key
,
keylen
);
TRY
(
parse_value
(
f
));
return
0
;
}
/* object = '{' pair { ',' pair } '}' */
for
(
i
=
0
;
i
<
sizeof
(
buf1
);
i
++
)
{
static
int
parse_object
(
struct
frozen
*
f
)
{
buf1
[
i
]
^=
0x36
;
int
ind
;
buf2
[
i
]
^=
0x5c
;
TRY
(
test_and_skip
(
f
,
'{'
));
TRY
(
capture_ptr
(
f
,
f
->
cur
-
1
,
JSON_TYPE_OBJECT
));
ind
=
f
->
num_tokens
-
1
;
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
)
{
cs_sha1_init
(
&
ctx
);
if
(
f
->
cur
==
0
||
f
->
end
<
f
->
cur
)
return
JSON_STRING_INVALID
;
cs_sha1_update
(
&
ctx
,
buf1
,
sizeof
(
buf1
));
if
(
f
->
end
==
f
->
cur
)
return
JSON_STRING_INCOMPLETE
;
cs_sha1_update
(
&
ctx
,
data
,
datalen
);
TRY
(
parse_object
(
f
));
cs_sha1_final
(
out
,
&
ctx
);
TRY
(
capture_ptr
(
f
,
f
->
cur
,
JSON_TYPE_EOF
));
capture_len
(
f
,
f
->
num_tokens
,
f
->
cur
);
cs_sha1_init
(
&
ctx
);
return
0
;
cs_sha1_update
(
&
ctx
,
buf2
,
sizeof
(
buf2
));
cs_sha1_update
(
&
ctx
,
out
,
20
);
cs_sha1_final
(
out
,
&
ctx
);
}
}
/* json = object */
#endif
/* EXCLUDE_COMMON */
int
parse_json
(
const
char
*
s
,
int
s_len
,
struct
json_token
*
arr
,
int
arr_len
)
{
#ifdef NS_MODULE_LINES
struct
frozen
frozen
;
#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
.
tokens
=
arr
;
frozen
.
max_tokens
=
arr_len
;
TRY
(
doit
(
&
frozen
));
/* Amalgamated: #include "osdep.h" */
/* Amalgamated: #include "str_util.h" */
return
frozen
.
cur
-
s
;
#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
l
;
}
}
#endif
struct
json_token
*
parse_json2
(
const
char
*
s
,
int
s_len
)
{
#define C_SNPRINTF_APPEND_CHAR(ch) \
struct
frozen
frozen
;
do { \
if (i < (int) buf_size) buf[i] = ch; \
i++; \
} while (0)
memset
(
&
frozen
,
0
,
sizeof
(
frozen
));
#define C_SNPRINTF_FLAG_ZERO 1
frozen
.
end
=
s
+
s_len
;
frozen
.
cur
=
s
;
frozen
.
do_realloc
=
1
;
if
(
doit
(
&
frozen
)
<
0
)
{
#ifdef C_DISABLE_BUILTIN_SNPRINTF
FROZEN_FREE
((
void
*
)
frozen
.
tokens
);
int
c_vsnprintf
(
char
*
buf
,
size_t
buf_size
,
const
char
*
fmt
,
va_list
ap
)
{
frozen
.
tokens
=
NULL
;
return
vsnprintf
(
buf
,
buf_size
,
fmt
,
ap
);
}
return
frozen
.
tokens
;
}
}
#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
;
static
int
path_part_len
(
const
char
*
p
)
{
if
(
num
<
0
)
{
int
i
=
0
;
neg
++
;
while
(
p
[
i
]
!=
'\0'
&&
p
[
i
]
!=
'['
&&
p
[
i
]
!=
'.'
)
i
++
;
num
=
-
num
;
return
i
;
}
}
struct
json_token
*
find_json_token
(
struct
json_token
*
toks
,
const
char
*
path
)
{
/* Print into temporary buffer - in reverse order */
while
(
path
!=
0
&&
path
[
0
]
!=
'\0'
)
{
do
{
int
i
,
ind2
=
0
,
ind
=
-
1
,
skip
=
2
,
n
=
path_part_len
(
path
);
int
rem
=
num
%
base
;
if
(
path
[
0
]
==
'['
)
{
if
(
rem
<
10
)
{
if
(
toks
->
type
!=
JSON_TYPE_ARRAY
||
!
is_digit
(
path
[
1
]))
return
0
;
tmp
[
k
++
]
=
'0'
+
rem
;
for
(
ind
=
0
,
n
=
1
;
path
[
n
]
!=
']'
&&
path
[
n
]
!=
'\0'
;
n
++
)
{
}
else
{
if
(
!
is_digit
(
path
[
n
]))
return
0
;
tmp
[
k
++
]
=
'a'
+
(
rem
-
10
);
ind
*=
10
;
}
ind
+=
path
[
n
]
-
'0'
;
num
/=
base
;
}
}
while
(
num
>
0
);
if
(
path
[
n
++
]
!=
']'
)
return
0
;
skip
=
1
;
/* In objects, we skip 2 elems while iterating, in arrays 1. */
/* Zero padding */
}
else
if
(
toks
->
type
!=
JSON_TYPE_OBJECT
)
return
0
;
if
(
flags
&&
C_SNPRINTF_FLAG_ZERO
)
{
toks
++
;
while
(
k
<
field_width
&&
k
<
(
int
)
sizeof
(
tmp
)
-
1
)
{
for
(
i
=
0
;
i
<
toks
[
-
1
].
num_desc
;
i
+=
skip
,
ind2
++
)
{
tmp
[
k
++
]
=
'0'
;
/* ind == -1 indicated that we're iterating an array, not object */
if
(
ind
==
-
1
&&
toks
[
i
].
type
!=
JSON_TYPE_STRING
)
return
0
;
if
(
ind2
==
ind
||
(
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
;
}
}
}
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
);
}
}
EMIT
(
'"'
);
if
(
s
<
end
)
{
*
s
=
'\0'
;
}
return
s
-
begin
;
/* 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
++
;
}
int
json_emit_unquoted_str
(
char
*
buf
,
int
buf_len
,
const
char
*
str
,
int
len
)
{
/* Precision */
if
(
buf_len
>
0
&&
len
>
0
)
{
if
(
*
fmt
==
'.'
)
{
int
n
=
len
<
buf_len
?
len
:
buf_len
;
fmt
++
;
memcpy
(
buf
,
str
,
n
);
if
(
*
fmt
==
'*'
)
{
if
(
n
<
buf_len
)
{
precision
=
va_arg
(
ap
,
int
);
buf
[
n
]
=
'\0'
;
fmt
++
;
}
}
else
{
}
while
(
*
fmt
>=
'0'
&&
*
fmt
<=
'9'
)
{
return
len
;
precision
*=
10
;
}
precision
+=
*
fmt
++
-
'0'
;
}
}
}
int
json_emit_va
(
char
*
s
,
int
s_len
,
const
char
*
fmt
,
va_list
ap
)
{
/* Length modifier */
const
char
*
end
=
s
+
s_len
,
*
str
,
*
orig
=
s
;
switch
(
*
fmt
)
{
size_t
len
;
case
'h'
:
case
'l'
:
case
'L'
:
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
++
;
}
break
;
}
while
(
*
fmt
!=
'\0'
)
{
ch
=
*
fmt
++
;
switch
(
*
fmt
)
{
if
(
ch
==
's'
)
{
case
'['
:
case
']'
:
case
'{'
:
case
'}'
:
case
','
:
case
':'
:
const
char
*
s
=
va_arg
(
ap
,
const
char
*
);
/* Always fetch parameter */
case
' '
:
case
'\r'
:
case
'\n'
:
case
'\t'
:
int
j
;
if
(
s
<
end
)
{
int
pad
=
field_width
-
(
precision
>=
0
?
strnlen
(
s
,
precision
)
:
0
);
*
s
=
*
fmt
;
for
(
j
=
0
;
j
<
pad
;
j
++
)
{
C_SNPRINTF_APPEND_CHAR
(
' '
);
}
}
s
++
;
break
;
/* Ignore negative and 0 precisions */
case
'i'
:
for
(
j
=
0
;
(
precision
<=
0
||
j
<
precision
)
&&
s
[
j
]
!=
'\0'
;
j
++
)
{
s
+=
json_emit_long
(
s
,
end
-
s
,
va_arg
(
ap
,
long
));
C_SNPRINTF_APPEND_CHAR
(
s
[
j
]);
break
;
}
case
'f'
:
}
else
if
(
ch
==
'c'
)
{
s
+=
json_emit_double
(
s
,
end
-
s
,
va_arg
(
ap
,
double
));
ch
=
va_arg
(
ap
,
int
);
/* Always fetch parameter */
break
;
C_SNPRINTF_APPEND_CHAR
(
ch
);
case
'v'
:
}
else
if
(
ch
==
'd'
&&
len_mod
==
0
)
{
str
=
va_arg
(
ap
,
char
*
);
i
+=
c_itoa
(
buf
+
i
,
buf_size
-
i
,
va_arg
(
ap
,
int
),
10
,
flags
,
len
=
va_arg
(
ap
,
size_t
);
field_width
);
s
+=
json_emit_quoted_str
(
s
,
end
-
s
,
str
,
len
);
}
else
if
(
ch
==
'd'
&&
len_mod
==
'l'
)
{
break
;
i
+=
c_itoa
(
buf
+
i
,
buf_size
-
i
,
va_arg
(
ap
,
long
),
10
,
flags
,
case
'V'
:
field_width
);
str
=
va_arg
(
ap
,
char
*
);
}
else
if
((
ch
==
'x'
||
ch
==
'u'
)
&&
len_mod
==
0
)
{
len
=
va_arg
(
ap
,
size_t
);
i
+=
c_itoa
(
buf
+
i
,
buf_size
-
i
,
va_arg
(
ap
,
unsigned
),
s
+=
json_emit_unquoted_str
(
s
,
end
-
s
,
str
,
len
);
ch
==
'x'
?
16
:
10
,
flags
,
field_width
);
break
;
}
else
if
((
ch
==
'x'
||
ch
==
'u'
)
&&
len_mod
==
'l'
)
{
case
's'
:
i
+=
c_itoa
(
buf
+
i
,
buf_size
-
i
,
va_arg
(
ap
,
unsigned
long
),
str
=
va_arg
(
ap
,
char
*
);
ch
==
'x'
?
16
:
10
,
flags
,
field_width
);
s
+=
json_emit_quoted_str
(
s
,
end
-
s
,
str
,
strlen
(
str
));
}
else
if
(
ch
==
'p'
)
{
break
;
unsigned
long
num
=
(
unsigned
long
)
va_arg
(
ap
,
void
*
);
case
'S'
:
C_SNPRINTF_APPEND_CHAR
(
'0'
);
str
=
va_arg
(
ap
,
char
*
);
C_SNPRINTF_APPEND_CHAR
(
'x'
);
s
+=
json_emit_unquoted_str
(
s
,
end
-
s
,
str
,
strlen
(
str
));
i
+=
c_itoa
(
buf
+
i
,
buf_size
-
i
,
num
,
16
,
flags
,
0
);
break
;
}
else
{
case
'T'
:
#ifndef NO_LIBC
s
+=
json_emit_unquoted_str
(
s
,
end
-
s
,
"true"
,
4
);
/*
break
;
* TODO(lsm): abort is not nice in a library, remove it
case
'F'
:
* Also, ESP8266 SDK doesn't have it
s
+=
json_emit_unquoted_str
(
s
,
end
-
s
,
"false"
,
5
);
*/
break
;
abort
();
case
'N'
:
#endif
s
+=
json_emit_unquoted_str
(
s
,
end
-
s
,
"null"
,
4
);
}
break
;
default:
return
0
;
}
}
fmt
++
;
}
}
/*
Best-effort to 0-terminate generated string
*/
/*
Zero-terminate the result
*/
if
(
s
<
end
)
{
if
(
buf_size
>
0
)
{
*
s
=
'\0'
;
buf
[
i
<
(
int
)
buf_size
?
i
:
(
int
)
buf_size
-
1
]
=
'\0'
;
}
}
return
s
-
orig
;
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 */
#define __DBG(x) \
#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) \
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