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);
#endif
/* MG_INTERNAL_HEADER_INCLUDED */
#ifdef NS_MODULE_LINES
#line 1 "src/../../common/
mbuf
.c"
#line 1 "src/../../common/
base64
.c"
/**/
#endif
/*
...
...
@@ -121,1629 +121,1644 @@ extern void *(*test_calloc)(size_t, size_t);
#ifndef EXCLUDE_COMMON
#include <assert.h>
/* Amalgamated: #include "base64.h" */
#include <string.h>
/* Amalgamated: #include "mbuf.h" */
#ifndef MBUF_REALLOC
#define MBUF_REALLOC realloc
#endif
/* ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ */
#
ifndef MBUF_FREE
#define
MBUF_FREE free
#
endif
#
define NUM_UPPERCASES ('Z' - 'A' + 1)
#define
NUM_LETTERS (NUM_UPPERCASES * 2)
#
define NUM_DIGITS ('9' - '0' + 1)
void
mbuf_init
(
struct
mbuf
*
mbuf
,
size_t
initial_size
)
{
mbuf
->
len
=
mbuf
->
size
=
0
;
mbuf
->
buf
=
NULL
;
mbuf_resize
(
mbuf
,
initial_size
);
/*
* Emit a base64 code char.
*
* 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
)
{
if
(
mbuf
->
buf
!=
NULL
)
{
MBUF_FREE
(
mbuf
->
buf
);
mbuf_init
(
mbuf
,
0
);
static
void
cs_base64_emit_chunk
(
struct
cs_base64_ctx
*
ctx
)
{
int
a
,
b
,
c
;
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
)
{
if
(
new_size
>
a
->
size
||
(
new_size
<
a
->
size
&&
new_size
>=
a
->
len
))
{
char
*
buf
=
(
char
*
)
MBUF_REALLOC
(
a
->
buf
,
new_size
);
/*
* In case realloc fails, there's not much we can do, except keep things as
* they are. Note that NULL is a valid return value from realloc when
* size == 0, but that is covered too.
*/
if
(
buf
==
NULL
&&
new_size
!=
0
)
return
;
a
->
buf
=
buf
;
a
->
size
=
new_size
;
void
cs_base64_init
(
struct
cs_base64_ctx
*
ctx
,
cs_base64_putc_t
b64_putc
,
void
*
user_data
)
{
ctx
->
chunk_size
=
0
;
ctx
->
b64_putc
=
b64_putc
;
ctx
->
user_data
=
user_data
;
}
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
mbuf_trim
(
struct
mbuf
*
mbuf
)
{
mbuf_resize
(
mbuf
,
mbuf
->
len
);
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
);
}
}
}
size_t
mbuf_insert
(
struct
mbuf
*
a
,
size_t
off
,
const
void
*
buf
,
size_t
len
)
{
char
*
p
=
NULL
;
#define BASE64_ENCODE_BODY \
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
);
assert
(
a
->
len
<=
a
->
size
);
assert
(
off
<=
a
->
len
);
#define BASE64_OUT(ch) \
do { \
dst[j++] = (ch); \
} while (0)
/* check overflow */
if
(
~
(
size_t
)
0
-
(
size_t
)
a
->
buf
<
len
)
return
0
;
#define BASE64_FLUSH() \
do { \
dst[j++] = '\0'; \
} while (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
;
}
void
cs_base64_encode
(
const
unsigned
char
*
src
,
int
src_len
,
char
*
dst
)
{
BASE64_ENCODE_BODY
;
}
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
)
{
return
mbuf_insert
(
a
,
a
->
len
,
buf
,
len
);
#undef BASE64_OUT
#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
)
{
if
(
n
>
0
&&
n
<=
mb
->
len
)
{
memmove
(
mb
->
buf
,
mb
->
buf
+
n
,
mb
->
len
-
n
);
mb
->
len
-=
n
;
int
cs_base64_decode
(
const
unsigned
char
*
s
,
int
len
,
char
*
dst
)
{
unsigned
char
a
,
b
,
c
,
d
;
int
orig_len
=
len
;
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 */
#ifdef NS_MODULE_LINES
#line 1 "src/../../common/
sha1
.c"
#line 1 "src/../../common/
cs_dbg
.c"
/**/
#endif
/* Copyright(c) By Steve Reid <steve@edmweb.com> */
/* 100% Public Domain */
#if !defined(DISABLE_SHA1) && !defined(EXCLUDE_COMMON)
/* Amalgamated: #include "sha1.h" */
#include <stdarg.h>
#include <stdio.h>
#define SHA1HANDSOFF
#if defined(__sun)
/* Amalgamated: #include "solarisfixes.h" */
void
cs_dbg_printf
(
const
char
*
fmt
,
...)
{
va_list
ap
;
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
/*
* Copyright (c) 2015 Cesanta Software Limited
* All rights reserved
*/
union
char64long16
{
unsigned
char
c
[
64
];
uint32_t
l
[
16
];
};
#ifndef EXCLUDE_COMMON
#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 */
#if BYTE_ORDER == LITTLE_ENDIAN
block
->
l
[
i
]
=
(
rol
(
block
->
l
[
i
],
24
)
&
0xFF00FF00
)
|
(
rol
(
block
->
l
[
i
],
8
)
&
0x00FF00FF
);
/*
* This file contains POSIX opendir/closedir/readdir API implementation
* for systems which do not natively support it (e.g. Windows).
*/
#ifndef MG_FREE
#define MG_FREE free
#endif
return
block
->
l
[
i
];
}
/* Avoid redefine warning (ARM /usr/include/sys/ucontext.h define R0~R4) */
#undef blk
#undef R0
#undef R1
#undef R2
#undef R3
#undef R4
#ifndef MG_MALLOC
#define MG_MALLOC malloc
#endif
#define blk(i) \
(block->l[i & 15] = rol(block->l[(i + 13) & 15] ^ block->l[(i + 8) & 15] ^ \
block->l[(i + 2) & 15] ^ block->l[i & 15], \
1))
#define R0(v, w, x, y, z, i) \
z += ((w & (x ^ y)) ^ y) + blk0(block, i) + 0x5A827999 + rol(v, 5); \
w = rol(w, 30);
#define R1(v, w, x, y, z, i) \
z += ((w & (x ^ y)) ^ y) + blk(i) + 0x5A827999 + rol(v, 5); \
w = rol(w, 30);
#define R2(v, w, x, y, z, i) \
z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + rol(v, 5); \
w = rol(w, 30);
#define R3(v, w, x, y, z, i) \
z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + rol(v, 5); \
w = rol(w, 30);
#define R4(v, w, x, y, z, i) \
z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + rol(v, 5); \
w = rol(w, 30);
#ifdef _WIN32
DIR
*
opendir
(
const
char
*
name
)
{
DIR
*
dir
=
NULL
;
wchar_t
wpath
[
MAX_PATH
];
DWORD
attrs
;
void
cs_sha1_transform
(
uint32_t
state
[
5
],
const
unsigned
char
buffer
[
64
])
{
uint32_t
a
,
b
,
c
,
d
,
e
;
union
char64long16
block
[
1
];
if
(
name
==
NULL
)
{
SetLastError
(
ERROR_BAD_ARGUMENTS
);
}
else
if
((
dir
=
(
DIR
*
)
MG_MALLOC
(
sizeof
(
*
dir
)))
==
NULL
)
{
SetLastError
(
ERROR_NOT_ENOUGH_MEMORY
);
}
else
{
to_wchar
(
name
,
wpath
,
ARRAY_SIZE
(
wpath
));
attrs
=
GetFileAttributesW
(
wpath
);
if
(
attrs
!=
0xFFFFFFFF
&&
(
attrs
&
FILE_ATTRIBUTE_DIRECTORY
))
{
(
void
)
wcscat
(
wpath
,
L"
\\
*"
);
dir
->
handle
=
FindFirstFileW
(
wpath
,
&
dir
->
info
);
dir
->
result
.
d_name
[
0
]
=
'\0'
;
}
else
{
MG_FREE
(
dir
);
dir
=
NULL
;
}
}
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
;
return
dir
;
}
void
cs_sha1_init
(
cs_sha1_ctx
*
context
)
{
context
->
state
[
0
]
=
0x67452301
;
context
->
state
[
1
]
=
0xEFCDAB89
;
context
->
state
[
2
]
=
0x98BADCFE
;
context
->
state
[
3
]
=
0x10325476
;
context
->
state
[
4
]
=
0xC3D2E1F0
;
context
->
count
[
0
]
=
context
->
count
[
1
]
=
0
;
}
int
closedir
(
DIR
*
dir
)
{
int
result
=
0
;
void
cs_sha1_update
(
cs_sha1_ctx
*
context
,
const
unsigned
char
*
data
,
uint32_t
len
)
{
uint32_t
i
,
j
;
if
(
dir
!=
NULL
)
{
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
];
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
);
return
result
;
}
void
cs_sha1_final
(
unsigned
char
digest
[
20
],
cs_sha1_ctx
*
context
)
{
unsigned
i
;
unsigned
char
finalcount
[
8
],
c
;
struct
dirent
*
readdir
(
DIR
*
dir
)
{
struct
dirent
*
result
=
0
;
for
(
i
=
0
;
i
<
8
;
i
++
)
{
finalcount
[
i
]
=
(
unsigned
char
)
((
context
->
count
[(
i
>=
4
?
0
:
1
)]
>>
((
3
-
(
i
&
3
))
*
8
))
&
255
);
}
c
=
0200
;
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
));
}
if
(
dir
)
{
if
(
dir
->
handle
!=
INVALID_HANDLE_VALUE
)
{
result
=
&
dir
->
result
;
(
void
)
WideCharToMultiByte
(
CP_UTF8
,
0
,
dir
->
info
.
cFileName
,
-
1
,
result
->
d_name
,
sizeof
(
result
->
d_name
),
NULL
,
NULL
);
void
cs_hmac_sha1
(
const
unsigned
char
*
key
,
size_t
keylen
,
const
unsigned
char
*
data
,
size_t
datalen
,
unsigned
char
out
[
20
])
{
cs_sha1_ctx
ctx
;
unsigned
char
buf1
[
64
],
buf2
[
64
],
tmp_key
[
20
],
i
;
if
(
!
FindNextFileW
(
dir
->
handle
,
&
dir
->
info
))
{
(
void
)
FindClose
(
dir
->
handle
);
dir
->
handle
=
INVALID_HANDLE_VALUE
;
}
if
(
keylen
>
sizeof
(
buf1
))
{
cs_sha1_init
(
&
ctx
);
cs_sha1_update
(
&
ctx
,
key
,
keylen
);
cs_sha1_final
(
tmp_key
,
&
ctx
);
key
=
tmp_key
;
keylen
=
sizeof
(
tmp_key
);
}
else
{
SetLastError
(
ERROR_FILE_NOT_FOUND
);
}
}
else
{
SetLastError
(
ERROR_BAD_ARGUMENTS
);
}
memset
(
buf1
,
0
,
sizeof
(
buf1
));
memset
(
buf2
,
0
,
sizeof
(
buf2
));
memcpy
(
buf1
,
key
,
keylen
);
memcpy
(
buf2
,
key
,
keylen
);
for
(
i
=
0
;
i
<
sizeof
(
buf1
);
i
++
)
{
buf1
[
i
]
^=
0x36
;
buf2
[
i
]
^=
0x5c
;
}
cs_sha1_init
(
&
ctx
);
cs_sha1_update
(
&
ctx
,
buf1
,
sizeof
(
buf1
));
cs_sha1_update
(
&
ctx
,
data
,
datalen
);
cs_sha1_final
(
out
,
&
ctx
);
cs_sha1_init
(
&
ctx
);
cs_sha1_update
(
&
ctx
,
buf2
,
sizeof
(
buf2
));
cs_sha1_update
(
&
ctx
,
out
,
20
);
cs_sha1_final
(
out
,
&
ctx
);
return
result
;
}
#endif
#endif
/* EXCLUDE_COMMON */
#ifdef NS_MODULE_LINES
#line 1 "src/../
../common/md5
.c"
#line 1 "src/../
deps/frozen/frozen
.c"
/**/
#endif
/*
* This code implements the MD5 message-digest algorithm.
* 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.
* Copyright (c) 2004-2013 Sergey Lyubka <valenok@gmail.com>
* Copyright (c) 2013 Cesanta Software Limited
* All rights reserved
*
*
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
.
*
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/>
.
*
* 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.
* 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>.
*/
#
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
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
;
#ifdef _WIN32
#define snprintf _snprintf
#endif
}
#define F1(x, y, z) (z ^ (x & (y ^ z)))
#define F2(x, y, z) F1(z, x, y)
#define F3(x, y, z) (x ^ y ^ z)
#define F4(x, y, z) (y ^ (x | ~z))
#define MD5STEP(f, w, x, y, z, data, s) \
(w += f(x, y, z) + data, w = w << s | w >> (32 - s), w += x)
/*
* Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
* initialization constants.
*/
void
MD5_Init
(
MD5_CTX
*
ctx
)
{
ctx
->
buf
[
0
]
=
0x67452301
;
ctx
->
buf
[
1
]
=
0xefcdab89
;
ctx
->
buf
[
2
]
=
0x98badcfe
;
ctx
->
buf
[
3
]
=
0x10325476
;
ctx
->
bits
[
0
]
=
0
;
ctx
->
bits
[
1
]
=
0
;
}
#ifndef FROZEN_REALLOC
#define FROZEN_REALLOC realloc
#endif
static
void
MD5Transform
(
uint32_t
buf
[
4
],
uint32_t
const
in
[
16
])
{
register
uint32_t
a
,
b
,
c
,
d
;
#ifndef FROZEN_FREE
#define FROZEN_FREE free
#endif
a
=
buf
[
0
];
b
=
buf
[
1
];
c
=
buf
[
2
];
d
=
buf
[
3
];
struct
frozen
{
const
char
*
end
;
const
char
*
cur
;
struct
json_token
*
tokens
;
int
max_tokens
;
int
num_tokens
;
int
do_realloc
;
};
MD5STEP
(
F1
,
a
,
b
,
c
,
d
,
in
[
0
]
+
0xd76aa478
,
7
);
MD5STEP
(
F1
,
d
,
a
,
b
,
c
,
in
[
1
]
+
0xe8c7b756
,
12
);
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
);
static
int
parse_object
(
struct
frozen
*
f
);
static
int
parse_value
(
struct
frozen
*
f
);
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
);
#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)
#define END_OF_STRING (-1)
MD5STEP
(
F3
,
a
,
b
,
c
,
d
,
in
[
5
]
+
0xfffa3942
,
4
);
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
);
static
int
left
(
const
struct
frozen
*
f
)
{
return
f
->
end
-
f
->
cur
;
}
MD5STEP
(
F4
,
a
,
b
,
c
,
d
,
in
[
0
]
+
0xf4292244
,
6
);
MD5STEP
(
F4
,
d
,
a
,
b
,
c
,
in
[
7
]
+
0x432aff97
,
10
);
MD5STEP
(
F4
,
c
,
d
,
a
,
b
,
in
[
14
]
+
0xab9423a7
,
15
);
MD5STEP
(
F4
,
b
,
c
,
d
,
a
,
in
[
5
]
+
0xfc93a039
,
21
);
MD5STEP
(
F4
,
a
,
b
,
c
,
d
,
in
[
12
]
+
0x655b59c3
,
6
);
MD5STEP
(
F4
,
d
,
a
,
b
,
c
,
in
[
3
]
+
0x8f0ccc92
,
10
);
MD5STEP
(
F4
,
c
,
d
,
a
,
b
,
in
[
10
]
+
0xffeff47d
,
15
);
MD5STEP
(
F4
,
b
,
c
,
d
,
a
,
in
[
1
]
+
0x85845dd1
,
21
);
MD5STEP
(
F4
,
a
,
b
,
c
,
d
,
in
[
8
]
+
0x6fa87e4f
,
6
);
MD5STEP
(
F4
,
d
,
a
,
b
,
c
,
in
[
15
]
+
0xfe2ce6e0
,
10
);
MD5STEP
(
F4
,
c
,
d
,
a
,
b
,
in
[
6
]
+
0xa3014314
,
15
);
MD5STEP
(
F4
,
b
,
c
,
d
,
a
,
in
[
13
]
+
0x4e0811a1
,
21
);
MD5STEP
(
F4
,
a
,
b
,
c
,
d
,
in
[
4
]
+
0xf7537e82
,
6
);
MD5STEP
(
F4
,
d
,
a
,
b
,
c
,
in
[
11
]
+
0xbd3af235
,
10
);
MD5STEP
(
F4
,
c
,
d
,
a
,
b
,
in
[
2
]
+
0x2ad7d2bb
,
15
);
MD5STEP
(
F4
,
b
,
c
,
d
,
a
,
in
[
9
]
+
0xeb86d391
,
21
);
static
int
is_space
(
int
ch
)
{
return
ch
==
' '
||
ch
==
'\t'
||
ch
==
'\r'
||
ch
==
'\n'
;
}
buf
[
0
]
+=
a
;
buf
[
1
]
+=
b
;
buf
[
2
]
+=
c
;
buf
[
3
]
+=
d
;
static
void
skip_whitespaces
(
struct
frozen
*
f
)
{
while
(
f
->
cur
<
f
->
end
&&
is_space
(
*
f
->
cur
))
f
->
cur
++
;
}
void
MD5_Update
(
MD5_CTX
*
ctx
,
const
unsigned
char
*
buf
,
size_t
len
)
{
uint32_t
t
;
static
int
cur
(
struct
frozen
*
f
)
{
skip_whitespaces
(
f
);
return
f
->
cur
>=
f
->
end
?
END_OF_STRING
:
*
(
unsigned
char
*
)
f
->
cur
;
}
t
=
ctx
->
bits
[
0
];
if
((
ctx
->
bits
[
0
]
=
t
+
((
uint32_t
)
len
<<
3
))
<
t
)
ctx
->
bits
[
1
]
++
;
ctx
->
bits
[
1
]
+=
(
uint32_t
)
len
>>
29
;
static
int
test_and_skip
(
struct
frozen
*
f
,
int
expected
)
{
int
ch
=
cur
(
f
);
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
)
{
unsigned
char
*
p
=
(
unsigned
char
*
)
ctx
->
in
+
t
;
static
int
is_digit
(
int
ch
)
{
return
ch
>=
'0'
&&
ch
<=
'9'
;
}
t
=
64
-
t
;
if
(
len
<
t
)
{
memcpy
(
p
,
buf
,
len
);
return
;
}
memcpy
(
p
,
buf
,
t
);
byteReverse
(
ctx
->
in
,
16
);
MD5Transform
(
ctx
->
buf
,
(
uint32_t
*
)
ctx
->
in
);
buf
+=
t
;
len
-=
t
;
}
static
int
is_hex_digit
(
int
ch
)
{
return
is_digit
(
ch
)
||
(
ch
>=
'a'
&&
ch
<=
'f'
)
||
(
ch
>=
'A'
&&
ch
<=
'F'
);
}
while
(
len
>=
64
)
{
memcpy
(
ctx
->
in
,
buf
,
64
);
byteReverse
(
ctx
->
in
,
16
);
MD5Transform
(
ctx
->
buf
,
(
uint32_t
*
)
ctx
->
in
);
buf
+=
64
;
len
-=
64
;
static
int
get_escape_len
(
const
char
*
s
,
int
len
)
{
switch
(
*
s
)
{
case
'u'
:
return
len
<
6
?
JSON_STRING_INCOMPLETE
:
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
;
}
memcpy
(
ctx
->
in
,
buf
,
len
);
}
void
MD5_Final
(
unsigned
char
digest
[
16
],
MD5_CTX
*
ctx
)
{
unsigned
count
;
unsigned
char
*
p
;
uint32_t
*
a
;
count
=
(
ctx
->
bits
[
0
]
>>
3
)
&
0x3F
;
p
=
ctx
->
in
+
count
;
*
p
++
=
0x80
;
count
=
64
-
1
-
count
;
if
(
count
<
8
)
{
memset
(
p
,
0
,
count
);
byteReverse
(
ctx
->
in
,
16
);
MD5Transform
(
ctx
->
buf
,
(
uint32_t
*
)
ctx
->
in
);
memset
(
ctx
->
in
,
0
,
56
);
}
else
{
memset
(
p
,
0
,
count
-
8
);
static
int
capture_ptr
(
struct
frozen
*
f
,
const
char
*
ptr
,
enum
json_type
type
)
{
if
(
f
->
do_realloc
&&
f
->
num_tokens
>=
f
->
max_tokens
)
{
int
new_size
=
f
->
max_tokens
==
0
?
100
:
f
->
max_tokens
*
2
;
void
*
p
=
FROZEN_REALLOC
(
f
->
tokens
,
new_size
*
sizeof
(
f
->
tokens
[
0
]));
if
(
p
==
NULL
)
return
JSON_TOKEN_ARRAY_TOO_SMALL
;
f
->
max_tokens
=
new_size
;
f
->
tokens
=
(
struct
json_token
*
)
p
;
}
byteReverse
(
ctx
->
in
,
14
);
a
=
(
uint32_t
*
)
ctx
->
in
;
a
[
14
]
=
ctx
->
bits
[
0
];
a
[
15
]
=
ctx
->
bits
[
1
];
MD5Transform
(
ctx
->
buf
,
(
uint32_t
*
)
ctx
->
in
);
byteReverse
((
unsigned
char
*
)
ctx
->
buf
,
4
);
memcpy
(
digest
,
ctx
->
buf
,
16
);
memset
((
char
*
)
ctx
,
0
,
sizeof
(
*
ctx
));
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
;
}
#endif
/* CS_ENABLE_NATIVE_MD5 */
/*
* Stringify binary data. Output buffer size must be 2 * size_of_input + 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
capture_len
(
struct
frozen
*
f
,
int
token_index
,
const
char
*
ptr
)
{
if
(
f
->
tokens
==
0
||
f
->
max_tokens
==
0
)
return
0
;
EXPECT
(
token_index
>=
0
&&
token_index
<
f
->
max_tokens
,
JSON_STRING_INVALID
);
f
->
tokens
[
token_index
].
len
=
ptr
-
f
->
tokens
[
token_index
].
ptr
;
f
->
tokens
[
token_index
].
num_desc
=
(
f
->
num_tokens
-
1
)
-
token_index
;
return
0
;
}
for
(;
len
--
;
p
++
)
{
*
to
++
=
hex
[
p
[
0
]
>>
4
];
*
to
++
=
hex
[
p
[
0
]
&
0x0f
];
/* identifier = letter { letter | digit | '_' } */
static
int
parse_identifier
(
struct
frozen
*
f
)
{
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
],
...)
{
unsigned
char
hash
[
16
];
const
unsigned
char
*
p
;
va_list
ap
;
MD5_CTX
ctx
;
static
int
get_utf8_char_len
(
unsigned
char
ch
)
{
if
((
ch
&
0x80
)
==
0
)
return
1
;
switch
(
ch
&
0xf0
)
{
case
0xf0
:
return
4
;
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
);
while
((
p
=
va_arg
(
ap
,
const
unsigned
char
*
)
)
!=
NULL
)
{
size_t
len
=
va_arg
(
ap
,
size_t
);
MD5_Update
(
&
ctx
,
p
,
len
);
/* number = [ '-' ] digit+ [ '.' digit+ ] [ ['e'|'E'] ['+'|'-'] digit+ ] */
static
int
parse_number
(
struct
frozen
*
f
)
{
int
ch
=
cur
(
f
);
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
);
cs_to_hex
(
buf
,
hash
,
sizeof
(
hash
));
/* array = '[' [ value { ',' value } ] ']' */
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 */
#ifdef NS_MODULE_LINES
#line 1 "src/../../common/base64.c"
/**/
#endif
/*
* Copyright (c) 2014 Cesanta Software Limited
* All rights reserved
*/
static
int
expect
(
struct
frozen
*
f
,
const
char
*
s
,
int
len
,
enum
json_type
t
)
{
int
i
,
n
=
left
(
f
);
#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" */
#include <string.h>
return
0
;
}
/* 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)
#define NUM_LETTERS (NUM_UPPERCASES * 2)
#define NUM_DIGITS ('9' - '0' + 1)
switch
(
ch
)
{
case
'"'
:
TRY
(
parse_string
(
f
));
break
;
case
'{'
:
TRY
(
parse_object
(
f
));
break
;
case
'['
:
TRY
(
parse_array
(
f
));
break
;
case
'n'
:
TRY
(
expect
(
f
,
"null"
,
4
,
JSON_TYPE_NULL
));
break
;
case
't'
:
TRY
(
expect
(
f
,
"true"
,
4
,
JSON_TYPE_TRUE
));
break
;
case
'f'
:
TRY
(
expect
(
f
,
"false"
,
5
,
JSON_TYPE_FALSE
));
break
;
case
'-'
:
case
'0'
:
case
'1'
:
case
'2'
:
case
'3'
:
case
'4'
:
case
'5'
:
case
'6'
:
case
'7'
:
case
'8'
:
case
'9'
:
TRY
(
parse_number
(
f
));
break
;
default:
return
ch
==
END_OF_STRING
?
JSON_STRING_INCOMPLETE
:
JSON_STRING_INVALID
;
}
/*
* Emit a base64 code char.
*
* 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
);
return
0
;
}
/* key = identifier | string */
static
int
parse_key
(
struct
frozen
*
f
)
{
int
ch
=
cur
(
f
);
#if 0
printf("%s 1 [%.*s]\n", __func__, (int) (f->end - f->cur), f->cur);
#endif
if
(
is_alpha
(
ch
))
{
TRY
(
parse_identifier
(
f
));
}
else
if
(
ch
==
'"'
)
{
TRY
(
parse_string
(
f
));
}
else
{
ctx
->
b64_putc
(
v
-
NUM_LETTERS
-
NUM_DIGITS
==
0
?
'+'
:
'/'
,
ctx
->
user_data
);
return
ch
==
END_OF_STRING
?
JSON_STRING_INCOMPLETE
:
JSON_STRING_INVALID
;
}
return
0
;
}
static
void
cs_base64_emit_chunk
(
struct
cs_base64_ctx
*
ctx
)
{
int
a
,
b
,
c
;
a
=
ctx
->
chunk
[
0
];
b
=
ctx
->
chunk
[
1
];
c
=
ctx
->
chunk
[
2
];
/* pair = key ':' value */
static
int
parse_pair
(
struct
frozen
*
f
)
{
TRY
(
parse_key
(
f
));
TRY
(
test_and_skip
(
f
,
':'
));
TRY
(
parse_value
(
f
));
return
0
;
}
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
);
/* object = '{' pair { ',' pair } '}' */
static
int
parse_object
(
struct
frozen
*
f
)
{
int
ind
;
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
;
}
void
cs_base64_init
(
struct
cs_base64_ctx
*
ctx
,
cs_base64_putc_t
b64_putc
,
void
*
user_data
)
{
ctx
->
chunk_size
=
0
;
ctx
->
b64_putc
=
b64_putc
;
ctx
->
user_data
=
user_data
;
}
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
);
}
}
static
int
doit
(
struct
frozen
*
f
)
{
if
(
f
->
cur
==
0
||
f
->
end
<
f
->
cur
)
return
JSON_STRING_INVALID
;
if
(
f
->
end
==
f
->
cur
)
return
JSON_STRING_INCOMPLETE
;
TRY
(
parse_object
(
f
));
TRY
(
capture_ptr
(
f
,
f
->
cur
,
JSON_TYPE_EOF
));
capture_len
(
f
,
f
->
num_tokens
,
f
->
cur
);
return
0
;
}
#define BASE64_ENCODE_BODY \
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()
/* json = object */
int
parse_json
(
const
char
*
s
,
int
s_len
,
struct
json_token
*
arr
,
int
arr_len
)
{
struct
frozen
frozen
;
#define BASE64_OUT(ch) \
do { \
dst[j++] = (ch); \
} while (0)
memset
(
&
frozen
,
0
,
sizeof
(
frozen
));
frozen
.
end
=
s
+
s_len
;
frozen
.
cur
=
s
;
frozen
.
tokens
=
arr
;
frozen
.
max_tokens
=
arr_len
;
#define BASE64_FLUSH() \
do { \
dst[j++] = '\0'; \
} while (0)
TRY
(
doit
(
&
frozen
));
void
cs_base64_encode
(
const
unsigned
char
*
src
,
int
src_len
,
char
*
dst
)
{
BASE64_ENCODE_BODY
;
return
frozen
.
cur
-
s
;
}
#undef BASE64_OUT
#undef BASE64_FLUSH
struct
json_token
*
parse_json2
(
const
char
*
s
,
int
s_len
)
{
struct
frozen
frozen
;
#define BASE64_OUT(ch) \
do { \
fprintf(f, "%c", (ch)); \
j++; \
} while (0)
memset
(
&
frozen
,
0
,
sizeof
(
frozen
));
frozen
.
end
=
s
+
s_len
;
frozen
.
cur
=
s
;
frozen
.
do_realloc
=
1
;
#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
)
{
BASE64_ENCODE_BODY
;
static
int
path_part_len
(
const
char
*
p
)
{
int
i
=
0
;
while
(
p
[
i
]
!=
'\0'
&&
p
[
i
]
!=
'['
&&
p
[
i
]
!=
'.'
)
i
++
;
return
i
;
}
#undef BASE64_OUT
#undef BASE64_FLUSH
struct
json_token
*
find_json_token
(
struct
json_token
*
toks
,
const
char
*
path
)
{
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 */
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
];
int
json_emit_long
(
char
*
buf
,
int
buf_len
,
long
int
value
)
{
char
tmp
[
20
];
int
n
=
snprintf
(
tmp
,
sizeof
(
tmp
),
"%ld"
,
value
);
strncpy
(
buf
,
tmp
,
buf_len
>
0
?
buf_len
:
0
);
return
n
;
}
int
cs_base64_decode
(
const
unsigned
char
*
s
,
int
len
,
char
*
dst
)
{
unsigned
char
a
,
b
,
c
,
d
;
int
orig_len
=
len
;
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
;
int
json_emit_double
(
char
*
buf
,
int
buf_len
,
double
value
)
{
char
tmp
[
20
];
int
n
=
snprintf
(
tmp
,
sizeof
(
tmp
),
"%g"
,
value
);
strncpy
(
buf
,
tmp
,
buf_len
>
0
?
buf_len
:
0
);
return
n
;
}
#endif
/* EXCLUDE_COMMON */
#ifdef NS_MODULE_LINES
#line 1 "src/../../common/str_util.c"
/**/
#endif
/*
* Copyright (c) 2015 Cesanta Software Limited
* All rights reserved
*/
int
json_emit_quoted_str
(
char
*
s
,
int
s_len
,
const
char
*
str
,
int
len
)
{
const
char
*
begin
=
s
,
*
end
=
s
+
s_len
,
*
str_end
=
str
+
len
;
char
ch
;
#
ifndef EXCLUDE_COMMON
#
define EMIT(x) do { if (s < end) *s = x; s++; } while (0)
/* Amalgamated: #include "osdep.h" */
/* Amalgamated: #include "str_util.h" */
EMIT
(
'"'
);
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) && \
!(__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
s
-
begin
;
}
int
json_emit_unquoted_str
(
char
*
buf
,
int
buf_len
,
const
char
*
str
,
int
len
)
{
if
(
buf_len
>
0
&&
len
>
0
)
{
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) \
do { \
if (i < (int) buf_size) buf[i] = ch; \
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
(
' '
);
}
int
json_emit_va
(
char
*
s
,
int
s_len
,
const
char
*
fmt
,
va_list
ap
)
{
const
char
*
end
=
s
+
s_len
,
*
str
,
*
orig
=
s
;
size_t
len
;
/* Ignore negative and 0 precisions */
for
(
j
=
0
;
(
precision
<=
0
||
j
<
precision
)
&&
s
[
j
]
!=
'\0'
;
j
++
)
{
C_SNPRINTF_APPEND_CHAR
(
s
[
j
]);
while
(
*
fmt
!=
'\0'
)
{
switch
(
*
fmt
)
{
case
'['
:
case
']'
:
case
'{'
:
case
'}'
:
case
','
:
case
':'
:
case
' '
:
case
'\r'
:
case
'\n'
:
case
'\t'
:
if
(
s
<
end
)
{
*
s
=
*
fmt
;
}
}
else
if
(
ch
==
'c'
)
{
ch
=
va_arg
(
ap
,
int
);
/* Always fetch parameter */
C_SNPRINTF_APPEND_CHAR
(
ch
);
}
else
if
(
ch
==
'd'
&&
len_mod
==
0
)
{
i
+=
c_itoa
(
buf
+
i
,
buf_size
-
i
,
va_arg
(
ap
,
int
),
10
,
flags
,
field_width
);
}
else
if
(
ch
==
'd'
&&
len_mod
==
'l'
)
{
i
+=
c_itoa
(
buf
+
i
,
buf_size
-
i
,
va_arg
(
ap
,
long
),
10
,
flags
,
field_width
);
}
else
if
((
ch
==
'x'
||
ch
==
'u'
)
&&
len_mod
==
0
)
{
i
+=
c_itoa
(
buf
+
i
,
buf_size
-
i
,
va_arg
(
ap
,
unsigned
),
ch
==
'x'
?
16
:
10
,
flags
,
field_width
);
}
else
if
((
ch
==
'x'
||
ch
==
'u'
)
&&
len_mod
==
'l'
)
{
i
+=
c_itoa
(
buf
+
i
,
buf_size
-
i
,
va_arg
(
ap
,
unsigned
long
),
ch
==
'x'
?
16
:
10
,
flags
,
field_width
);
}
else
if
(
ch
==
'p'
)
{
unsigned
long
num
=
(
unsigned
long
)
va_arg
(
ap
,
void
*
);
C_SNPRINTF_APPEND_CHAR
(
'0'
);
C_SNPRINTF_APPEND_CHAR
(
'x'
);
i
+=
c_itoa
(
buf
+
i
,
buf_size
-
i
,
num
,
16
,
flags
,
0
);
}
else
{
#ifndef NO_LIBC
/*
* TODO(lsm): abort is not nice in a library, remove it
* Also, ESP8266 SDK doesn't have it
*/
abort
();
#endif
}
s
++
;
break
;
case
'i'
:
s
+=
json_emit_long
(
s
,
end
-
s
,
va_arg
(
ap
,
long
));
break
;
case
'f'
:
s
+=
json_emit_double
(
s
,
end
-
s
,
va_arg
(
ap
,
double
));
break
;
case
'v'
:
str
=
va_arg
(
ap
,
char
*
);
len
=
va_arg
(
ap
,
size_t
);
s
+=
json_emit_quoted_str
(
s
,
end
-
s
,
str
,
len
);
break
;
case
'V'
:
str
=
va_arg
(
ap
,
char
*
);
len
=
va_arg
(
ap
,
size_t
);
s
+=
json_emit_unquoted_str
(
s
,
end
-
s
,
str
,
len
);
break
;
case
's'
:
str
=
va_arg
(
ap
,
char
*
);
s
+=
json_emit_quoted_str
(
s
,
end
-
s
,
str
,
strlen
(
str
));
break
;
case
'S'
:
str
=
va_arg
(
ap
,
char
*
);
s
+=
json_emit_unquoted_str
(
s
,
end
-
s
,
str
,
strlen
(
str
));
break
;
case
'T'
:
s
+=
json_emit_unquoted_str
(
s
,
end
-
s
,
"true"
,
4
);
break
;
case
'F'
:
s
+=
json_emit_unquoted_str
(
s
,
end
-
s
,
"false"
,
5
);
break
;
case
'N'
:
s
+=
json_emit_unquoted_str
(
s
,
end
-
s
,
"null"
,
4
);
break
;
default:
return
0
;
}
fmt
++
;
}
/*
Zero-terminate the result
*/
if
(
buf_size
>
0
)
{
buf
[
i
<
(
int
)
buf_size
?
i
:
(
int
)
buf_size
-
1
]
=
'\0'
;
/*
Best-effort to 0-terminate generated string
*/
if
(
s
<
end
)
{
*
s
=
'\0'
;
}
return
i
;
return
s
-
orig
;
}
#endif
int
c_snprintf
(
char
*
buf
,
size_t
buf_size
,
const
char
*
fmt
,
...)
{
int
result
;
int
json_emit
(
char
*
buf
,
int
buf_len
,
const
char
*
fmt
,
...)
{
int
len
;
va_list
ap
;
va_start
(
ap
,
fmt
);
result
=
c_vsnprintf
(
buf
,
buf_size
,
fmt
,
ap
);
len
=
json_emit_va
(
buf
,
buf_len
,
fmt
,
ap
);
va_end
(
ap
);
return
result
;
}
#ifdef _WIN32
void
to_wchar
(
const
char
*
path
,
wchar_t
*
wbuf
,
size_t
wbuf_len
)
{
char
buf
[
MAX_PATH
*
2
],
buf2
[
MAX_PATH
*
2
],
*
p
;
strncpy
(
buf
,
path
,
sizeof
(
buf
));
buf
[
sizeof
(
buf
)
-
1
]
=
'\0'
;
/* Trim trailing slashes. Leave backslash for paths like "X:\" */
p
=
buf
+
strlen
(
buf
)
-
1
;
while
(
p
>
buf
&&
p
[
-
1
]
!=
':'
&&
(
p
[
0
]
==
'\\'
||
p
[
0
]
==
'/'
))
*
p
--
=
'\0'
;
/*
* 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'
;
}
return
len
;
}
#endif
/* _WIN32 */
#endif
/* EXCLUDE_COMMON */
#ifdef NS_MODULE_LINES
#line 1 "src/../../common/
dirent
.c"
#line 1 "src/../../common/
md5
.c"
/**/
#endif
/*
* Copyright (c) 2015 Cesanta Software Limited
* All rights reserved
* This code implements the MD5 message-digest algorithm.
* 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
*
for systems which do not natively support it (e.g. Windows)
.
*
Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
*
initialization constants
.
*/
void
MD5_Init
(
MD5_CTX
*
ctx
)
{
ctx
->
buf
[
0
]
=
0x67452301
;
ctx
->
buf
[
1
]
=
0xefcdab89
;
ctx
->
buf
[
2
]
=
0x98badcfe
;
ctx
->
buf
[
3
]
=
0x10325476
;
#ifndef MG_FREE
#define MG_FREE free
#endif
ctx
->
bits
[
0
]
=
0
;
ctx
->
bits
[
1
]
=
0
;
}
#ifndef MG_MALLOC
#define MG_MALLOC malloc
#endif
static
void
MD5Transform
(
uint32_t
buf
[
4
],
uint32_t
const
in
[
16
])
{
register
uint32_t
a
,
b
,
c
,
d
;
#ifdef _WIN32
DIR
*
opendir
(
const
char
*
name
)
{
DIR
*
dir
=
NULL
;
wchar_t
wpath
[
MAX_PATH
];
DWORD
attrs
;
a
=
buf
[
0
];
b
=
buf
[
1
];
c
=
buf
[
2
];
d
=
buf
[
3
];
if
(
name
==
NULL
)
{
SetLastError
(
ERROR_BAD_ARGUMENTS
);
}
else
if
((
dir
=
(
DIR
*
)
MG_MALLOC
(
sizeof
(
*
dir
)))
==
NULL
)
{
SetLastError
(
ERROR_NOT_ENOUGH_MEMORY
);
}
else
{
to_wchar
(
name
,
wpath
,
ARRAY_SIZE
(
wpath
)
);
attrs
=
GetFileAttributesW
(
wpath
);
if
(
attrs
!=
0xFFFFFFFF
&&
(
attrs
&
FILE_ATTRIBUTE_DIRECTORY
))
{
(
void
)
wcscat
(
wpath
,
L"
\\
*"
);
dir
->
handle
=
FindFirstFileW
(
wpath
,
&
dir
->
info
);
dir
->
result
.
d_name
[
0
]
=
'\0'
;
}
else
{
MG_FREE
(
dir
);
dir
=
NULL
;
}
}
MD5STEP
(
F1
,
a
,
b
,
c
,
d
,
in
[
0
]
+
0xd76aa478
,
7
);
MD5STEP
(
F1
,
d
,
a
,
b
,
c
,
in
[
1
]
+
0xe8c7b756
,
12
);
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
);
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
)
{
int
result
=
0
;
MD5STEP
(
F3
,
a
,
b
,
c
,
d
,
in
[
5
]
+
0xfffa3942
,
4
);
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
)
{
if
(
dir
->
handle
!=
INVALID_HANDLE_VALUE
)
result
=
FindClose
(
dir
->
handle
)
?
0
:
-
1
;
MG_FREE
(
dir
);
}
else
{
result
=
-
1
;
SetLastError
(
ERROR_BAD_ARGUMENTS
);
}
MD5STEP
(
F4
,
a
,
b
,
c
,
d
,
in
[
0
]
+
0xf4292244
,
6
);
MD5STEP
(
F4
,
d
,
a
,
b
,
c
,
in
[
7
]
+
0x432aff97
,
10
);
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
);
return
result
;
buf
[
0
]
+=
a
;
buf
[
1
]
+=
b
;
buf
[
2
]
+=
c
;
buf
[
3
]
+=
d
;
}
struct
dirent
*
readdir
(
DIR
*
dir
)
{
struct
dirent
*
result
=
0
;
void
MD5_Update
(
MD5_CTX
*
ctx
,
const
unsigned
char
*
buf
,
size_t
len
)
{
uint32_t
t
;
if
(
dir
)
{
if
(
dir
->
handle
!=
INVALID_HANDLE_VALUE
)
{
result
=
&
dir
->
result
;
(
void
)
WideCharToMultiByte
(
CP_UTF8
,
0
,
dir
->
info
.
cFileName
,
-
1
,
result
->
d_name
,
sizeof
(
result
->
d_name
),
NULL
,
NULL
);
t
=
ctx
->
bits
[
0
];
if
((
ctx
->
bits
[
0
]
=
t
+
((
uint32_t
)
len
<<
3
))
<
t
)
ctx
->
bits
[
1
]
++
;
ctx
->
bits
[
1
]
+=
(
uint32_t
)
len
>>
29
;
if
(
!
FindNextFileW
(
dir
->
handle
,
&
dir
->
info
))
{
(
void
)
FindClose
(
dir
->
handle
);
dir
->
handle
=
INVALID_HANDLE_VALUE
;
}
t
=
(
t
>>
3
)
&
0x3f
;
}
else
{
SetLastError
(
ERROR_FILE_NOT_FOUND
);
if
(
t
)
{
unsigned
char
*
p
=
(
unsigned
char
*
)
ctx
->
in
+
t
;
t
=
64
-
t
;
if
(
len
<
t
)
{
memcpy
(
p
,
buf
,
len
);
return
;
}
}
else
{
SetLastError
(
ERROR_BAD_ARGUMENTS
);
memcpy
(
p
,
buf
,
t
);
byteReverse
(
ctx
->
in
,
16
);
MD5Transform
(
ctx
->
buf
,
(
uint32_t
*
)
ctx
->
in
);
buf
+=
t
;
len
-=
t
;
}
return
result
;
}
#endif
#endif
/* EXCLUDE_COMMON */
#ifdef NS_MODULE_LINES
#line 1 "src/../deps/frozen/frozen.c"
/**/
#endif
/*
* Copyright (c) 2004-2013 Sergey Lyubka <valenok@gmail.com>
* 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>.
*/
while
(
len
>=
64
)
{
memcpy
(
ctx
->
in
,
buf
,
64
);
byteReverse
(
ctx
->
in
,
16
);
MD5Transform
(
ctx
->
buf
,
(
uint32_t
*
)
ctx
->
in
);
buf
+=
64
;
len
-=
64
;
}
#define _CRT_SECURE_NO_WARNINGS
/* Disable deprecation warning in VS2005+ */
memcpy
(
ctx
->
in
,
buf
,
len
);
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
/* Amalgamated: #include "frozen.h" */
void
MD5_Final
(
unsigned
char
digest
[
16
],
MD5_CTX
*
ctx
)
{
unsigned
count
;
unsigned
char
*
p
;
uint32_t
*
a
;
#ifdef _WIN32
#define snprintf _snprintf
#endif
count
=
(
ctx
->
bits
[
0
]
>>
3
)
&
0x3F
;
#ifndef FROZEN_REALLOC
#define FROZEN_REALLOC realloc
#endif
#ifndef FROZEN_FREE
#define FROZEN_FREE free
#endif
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
);
struct
frozen
{
const
char
*
end
;
const
char
*
cur
;
struct
json_token
*
tokens
;
int
max_tokens
;
int
num_tokens
;
int
do_realloc
;
};
a
=
(
uint32_t
*
)
ctx
->
in
;
a
[
14
]
=
ctx
->
bits
[
0
];
a
[
15
]
=
ctx
->
bits
[
1
];
static
int
parse_object
(
struct
frozen
*
f
);
static
int
parse_value
(
struct
frozen
*
f
);
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 */
#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)
#define END_OF_STRING (-1)
/*
* Stringify binary data. Output buffer size must be 2 * size_of_input + 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
)
{
return
f
->
end
-
f
->
cur
;
for
(;
len
--
;
p
++
)
{
*
to
++
=
hex
[
p
[
0
]
>>
4
];
*
to
++
=
hex
[
p
[
0
]
&
0x0f
];
}
*
to
=
'\0'
;
}
static
int
is_space
(
int
ch
)
{
return
ch
==
' '
||
ch
==
'\t'
||
ch
==
'\r'
||
ch
==
'\n'
;
}
char
*
cs_md5
(
char
buf
[
33
],
...)
{
unsigned
char
hash
[
16
];
const
unsigned
char
*
p
;
va_list
ap
;
MD5_CTX
ctx
;
static
void
skip_whitespaces
(
struct
frozen
*
f
)
{
while
(
f
->
cur
<
f
->
end
&&
is_space
(
*
f
->
cur
))
f
->
cur
++
;
}
MD5_Init
(
&
ctx
);
static
int
cur
(
struct
frozen
*
f
)
{
skip_whitespaces
(
f
);
return
f
->
cur
>=
f
->
end
?
END_OF_STRING
:
*
(
unsigned
char
*
)
f
->
cur
;
}
va_start
(
ap
,
buf
);
while
((
p
=
va_arg
(
ap
,
const
unsigned
char
*
)
)
!=
NULL
)
{
size_t
len
=
va_arg
(
ap
,
size_t
);
MD5_Update
(
&
ctx
,
p
,
len
);
}
va_end
(
ap
);
static
int
test_and_skip
(
struct
frozen
*
f
,
int
expected
)
{
int
ch
=
cur
(
f
);
if
(
ch
==
expected
)
{
f
->
cur
++
;
return
0
;
}
return
ch
==
END_OF_STRING
?
JSON_STRING_INCOMPLETE
:
JSON_STRING_INVALID
;
}
MD5_Final
(
hash
,
&
ctx
);
cs_to_hex
(
buf
,
hash
,
sizeof
(
hash
));
static
int
is_alpha
(
int
ch
)
{
return
(
ch
>=
'a'
&&
ch
<=
'z'
)
||
(
ch
>=
'A'
&&
ch
<=
'Z'
);
return
buf
;
}
static
int
is_digit
(
int
ch
)
{
return
ch
>=
'0'
&&
ch
<=
'9'
;
}
#endif
/* EXCLUDE_COMMON */
#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
)
{
return
is_digit
(
ch
)
||
(
ch
>=
'a'
&&
ch
<=
'f'
)
||
(
ch
>=
'A'
&&
ch
<=
'F'
);
#ifndef EXCLUDE_COMMON
#include <assert.h>
#include <string.h>
/* Amalgamated: #include "mbuf.h" */
#ifndef MBUF_REALLOC
#define MBUF_REALLOC realloc
#endif
#ifndef MBUF_FREE
#define MBUF_FREE free
#endif
void
mbuf_init
(
struct
mbuf
*
mbuf
,
size_t
initial_size
)
{
mbuf
->
len
=
mbuf
->
size
=
0
;
mbuf
->
buf
=
NULL
;
mbuf_resize
(
mbuf
,
initial_size
);
}
static
int
get_escape_len
(
const
char
*
s
,
int
len
)
{
switch
(
*
s
)
{
case
'u'
:
return
len
<
6
?
JSON_STRING_INCOMPLETE
:
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
;
void
mbuf_free
(
struct
mbuf
*
mbuf
)
{
if
(
mbuf
->
buf
!=
NULL
)
{
MBUF_FREE
(
mbuf
->
buf
);
mbuf_init
(
mbuf
,
0
);
}
}
static
int
capture_ptr
(
struct
frozen
*
f
,
const
char
*
ptr
,
enum
json_type
type
)
{
if
(
f
->
do_realloc
&&
f
->
num_tokens
>=
f
->
max_tokens
)
{
int
new_size
=
f
->
max_tokens
==
0
?
100
:
f
->
max_tokens
*
2
;
void
*
p
=
FROZEN_REALLOC
(
f
->
tokens
,
new_size
*
sizeof
(
f
->
tokens
[
0
]));
if
(
p
==
NULL
)
return
JSON_TOKEN_ARRAY_TOO_SMALL
;
f
->
max_tokens
=
new_size
;
f
->
tokens
=
(
struct
json_token
*
)
p
;
void
mbuf_resize
(
struct
mbuf
*
a
,
size_t
new_size
)
{
if
(
new_size
>
a
->
size
||
(
new_size
<
a
->
size
&&
new_size
>=
a
->
len
))
{
char
*
buf
=
(
char
*
)
MBUF_REALLOC
(
a
->
buf
,
new_size
);
/*
* In case realloc fails, there's not much we can do, except keep things as
* they are. Note that NULL is a valid return value from realloc when
* size == 0, but that is covered too.
*/
if
(
buf
==
NULL
&&
new_size
!=
0
)
return
;
a
->
buf
=
buf
;
a
->
size
=
new_size
;
}
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
)
{
if
(
f
->
tokens
==
0
||
f
->
max_tokens
==
0
)
return
0
;
EXPECT
(
token_index
>=
0
&&
token_index
<
f
->
max_tokens
,
JSON_STRING_INVALID
);
f
->
tokens
[
token_index
].
len
=
ptr
-
f
->
tokens
[
token_index
].
ptr
;
f
->
tokens
[
token_index
].
num_desc
=
(
f
->
num_tokens
-
1
)
-
token_index
;
return
0
;
void
mbuf_trim
(
struct
mbuf
*
mbuf
)
{
mbuf_resize
(
mbuf
,
mbuf
->
len
);
}
/* identifier = letter { letter | digit | '_' } */
static
int
parse_identifier
(
struct
frozen
*
f
)
{
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
++
;
size_t
mbuf_insert
(
struct
mbuf
*
a
,
size_t
off
,
const
void
*
buf
,
size_t
len
)
{
char
*
p
=
NULL
;
assert
(
a
!=
NULL
);
assert
(
a
->
len
<=
a
->
size
);
assert
(
off
<=
a
->
len
);
/* 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
)
{
if
((
ch
&
0x80
)
==
0
)
return
1
;
switch
(
ch
&
0xf0
)
{
case
0xf0
:
return
4
;
case
0xe0
:
return
3
;
default:
return
2
;
}
size_t
mbuf_append
(
struct
mbuf
*
a
,
const
void
*
buf
,
size_t
len
)
{
return
mbuf_insert
(
a
,
a
->
len
,
buf
,
len
);
}
/* 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
;
};
void
mbuf_remove
(
struct
mbuf
*
mb
,
size_t
n
)
{
if
(
n
>
0
&&
n
<=
mb
->
len
)
{
memmove
(
mb
->
buf
,
mb
->
buf
+
n
,
mb
->
len
-
n
);
mb
->
len
-=
n
;
}
return
ch
==
'"'
?
0
:
JSON_STRING_INCOMPLETE
;
}
/* number = [ '-' ] digit+ [ '.' digit+ ] [ ['e'|'E'] ['+'|'-'] digit+ ] */
static
int
parse_number
(
struct
frozen
*
f
)
{
int
ch
=
cur
(
f
);
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
++
;
}
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
;
#endif
/* EXCLUDE_COMMON */
#ifdef NS_MODULE_LINES
#line 1 "src/../../common/sha1.c"
/**/
#endif
/* Copyright(c) By Steve Reid <steve@edmweb.com> */
/* 100% Public Domain */
#if !defined(DISABLE_SHA1) && !defined(EXCLUDE_COMMON)
/* Amalgamated: #include "sha1.h" */
#define SHA1HANDSOFF
#if defined(__sun)
/* Amalgamated: #include "solarisfixes.h" */
#endif
union
char64long16
{
unsigned
char
c
[
64
];
uint32_t
l
[
16
];
};
#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
static
uint32_t
blk0
(
union
char64long16
*
block
,
int
i
)
{
/* Forrest: SHA expect BIG_ENDIAN, swap if LITTLE_ENDIAN */
#if BYTE_ORDER == LITTLE_ENDIAN
block
->
l
[
i
]
=
(
rol
(
block
->
l
[
i
],
24
)
&
0xFF00FF00
)
|
(
rol
(
block
->
l
[
i
],
8
)
&
0x00FF00FF
);
#endif
return
block
->
l
[
i
];
}
/* array = '[' [ value { ',' value } ] ']' */
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
;
/* Avoid redefine warning (ARM /usr/include/sys/ucontext.h define R0~R4) */
#undef blk
#undef R0
#undef R1
#undef R2
#undef R3
#undef R4
#define blk(i) \
(block->l[i & 15] = rol(block->l[(i + 13) & 15] ^ block->l[(i + 8) & 15] ^ \
block->l[(i + 2) & 15] ^ block->l[i & 15], \
1))
#define R0(v, w, x, y, z, i) \
z += ((w & (x ^ y)) ^ y) + blk0(block, i) + 0x5A827999 + rol(v, 5); \
w = rol(w, 30);
#define R1(v, w, x, y, z, i) \
z += ((w & (x ^ y)) ^ y) + blk(i) + 0x5A827999 + rol(v, 5); \
w = rol(w, 30);
#define R2(v, w, x, y, z, i) \
z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + rol(v, 5); \
w = rol(w, 30);
#define R3(v, w, x, y, z, i) \
z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + rol(v, 5); \
w = rol(w, 30);
#define R4(v, w, x, y, z, i) \
z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + rol(v, 5); \
w = rol(w, 30);
void
cs_sha1_transform
(
uint32_t
state
[
5
],
const
unsigned
char
buffer
[
64
])
{
uint32_t
a
,
b
,
c
,
d
,
e
;
union
char64long16
block
[
1
];
memcpy
(
block
,
buffer
,
64
);
a
=
state
[
0
];
b
=
state
[
1
];
c
=
state
[
2
];
d
=
state
[
3
];
e
=
state
[
4
];
R0
(
a
,
b
,
c
,
d
,
e
,
0
);
R0
(
e
,
a
,
b
,
c
,
d
,
1
);
R0
(
d
,
e
,
a
,
b
,
c
,
2
);
R0
(
c
,
d
,
e
,
a
,
b
,
3
);
R0
(
b
,
c
,
d
,
e
,
a
,
4
);
R0
(
a
,
b
,
c
,
d
,
e
,
5
);
R0
(
e
,
a
,
b
,
c
,
d
,
6
);
R0
(
d
,
e
,
a
,
b
,
c
,
7
);
R0
(
c
,
d
,
e
,
a
,
b
,
8
);
R0
(
b
,
c
,
d
,
e
,
a
,
9
);
R0
(
a
,
b
,
c
,
d
,
e
,
10
);
R0
(
e
,
a
,
b
,
c
,
d
,
11
);
R0
(
d
,
e
,
a
,
b
,
c
,
12
);
R0
(
c
,
d
,
e
,
a
,
b
,
13
);
R0
(
b
,
c
,
d
,
e
,
a
,
14
);
R0
(
a
,
b
,
c
,
d
,
e
,
15
);
R1
(
e
,
a
,
b
,
c
,
d
,
16
);
R1
(
d
,
e
,
a
,
b
,
c
,
17
);
R1
(
c
,
d
,
e
,
a
,
b
,
18
);
R1
(
b
,
c
,
d
,
e
,
a
,
19
);
R2
(
a
,
b
,
c
,
d
,
e
,
20
);
R2
(
e
,
a
,
b
,
c
,
d
,
21
);
R2
(
d
,
e
,
a
,
b
,
c
,
22
);
R2
(
c
,
d
,
e
,
a
,
b
,
23
);
R2
(
b
,
c
,
d
,
e
,
a
,
24
);
R2
(
a
,
b
,
c
,
d
,
e
,
25
);
R2
(
e
,
a
,
b
,
c
,
d
,
26
);
R2
(
d
,
e
,
a
,
b
,
c
,
27
);
R2
(
c
,
d
,
e
,
a
,
b
,
28
);
R2
(
b
,
c
,
d
,
e
,
a
,
29
);
R2
(
a
,
b
,
c
,
d
,
e
,
30
);
R2
(
e
,
a
,
b
,
c
,
d
,
31
);
R2
(
d
,
e
,
a
,
b
,
c
,
32
);
R2
(
c
,
d
,
e
,
a
,
b
,
33
);
R2
(
b
,
c
,
d
,
e
,
a
,
34
);
R2
(
a
,
b
,
c
,
d
,
e
,
35
);
R2
(
e
,
a
,
b
,
c
,
d
,
36
);
R2
(
d
,
e
,
a
,
b
,
c
,
37
);
R2
(
c
,
d
,
e
,
a
,
b
,
38
);
R2
(
b
,
c
,
d
,
e
,
a
,
39
);
R3
(
a
,
b
,
c
,
d
,
e
,
40
);
R3
(
e
,
a
,
b
,
c
,
d
,
41
);
R3
(
d
,
e
,
a
,
b
,
c
,
42
);
R3
(
c
,
d
,
e
,
a
,
b
,
43
);
R3
(
b
,
c
,
d
,
e
,
a
,
44
);
R3
(
a
,
b
,
c
,
d
,
e
,
45
);
R3
(
e
,
a
,
b
,
c
,
d
,
46
);
R3
(
d
,
e
,
a
,
b
,
c
,
47
);
R3
(
c
,
d
,
e
,
a
,
b
,
48
);
R3
(
b
,
c
,
d
,
e
,
a
,
49
);
R3
(
a
,
b
,
c
,
d
,
e
,
50
);
R3
(
e
,
a
,
b
,
c
,
d
,
51
);
R3
(
d
,
e
,
a
,
b
,
c
,
52
);
R3
(
c
,
d
,
e
,
a
,
b
,
53
);
R3
(
b
,
c
,
d
,
e
,
a
,
54
);
R3
(
a
,
b
,
c
,
d
,
e
,
55
);
R3
(
e
,
a
,
b
,
c
,
d
,
56
);
R3
(
d
,
e
,
a
,
b
,
c
,
57
);
R3
(
c
,
d
,
e
,
a
,
b
,
58
);
R3
(
b
,
c
,
d
,
e
,
a
,
59
);
R4
(
a
,
b
,
c
,
d
,
e
,
60
);
R4
(
e
,
a
,
b
,
c
,
d
,
61
);
R4
(
d
,
e
,
a
,
b
,
c
,
62
);
R4
(
c
,
d
,
e
,
a
,
b
,
63
);
R4
(
b
,
c
,
d
,
e
,
a
,
64
);
R4
(
a
,
b
,
c
,
d
,
e
,
65
);
R4
(
e
,
a
,
b
,
c
,
d
,
66
);
R4
(
d
,
e
,
a
,
b
,
c
,
67
);
R4
(
c
,
d
,
e
,
a
,
b
,
68
);
R4
(
b
,
c
,
d
,
e
,
a
,
69
);
R4
(
a
,
b
,
c
,
d
,
e
,
70
);
R4
(
e
,
a
,
b
,
c
,
d
,
71
);
R4
(
d
,
e
,
a
,
b
,
c
,
72
);
R4
(
c
,
d
,
e
,
a
,
b
,
73
);
R4
(
b
,
c
,
d
,
e
,
a
,
74
);
R4
(
a
,
b
,
c
,
d
,
e
,
75
);
R4
(
e
,
a
,
b
,
c
,
d
,
76
);
R4
(
d
,
e
,
a
,
b
,
c
,
77
);
R4
(
c
,
d
,
e
,
a
,
b
,
78
);
R4
(
b
,
c
,
d
,
e
,
a
,
79
);
state
[
0
]
+=
a
;
state
[
1
]
+=
b
;
state
[
2
]
+=
c
;
state
[
3
]
+=
d
;
state
[
4
]
+=
e
;
/* Erase working structures. The order of operations is important,
* used to ensure that compiler doesn't optimize those out. */
memset
(
block
,
0
,
sizeof
(
block
));
a
=
b
=
c
=
d
=
e
=
0
;
(
void
)
a
;
(
void
)
b
;
(
void
)
c
;
(
void
)
d
;
(
void
)
e
;
}
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
;
void
cs_sha1_init
(
cs_sha1_ctx
*
context
)
{
context
->
state
[
0
]
=
0x67452301
;
context
->
state
[
1
]
=
0xEFCDAB89
;
context
->
state
[
2
]
=
0x98BADCFE
;
context
->
state
[
3
]
=
0x10325476
;
context
->
state
[
4
]
=
0xC3D2E1F0
;
context
->
count
[
0
]
=
context
->
count
[
1
]
=
0
;
}
static
int
expect
(
struct
frozen
*
f
,
const
char
*
s
,
int
len
,
enum
json_type
t
)
{
int
i
,
n
=
left
(
f
);
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
));
void
cs_sha1_update
(
cs_sha1_ctx
*
context
,
const
unsigned
char
*
data
,
uint32_t
len
)
{
uint32_t
i
,
j
;
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 */
static
int
parse_value
(
struct
frozen
*
f
)
{
int
ch
=
cur
(
f
)
;
void
cs_sha1_final
(
unsigned
char
digest
[
20
],
cs_sha1_ctx
*
context
)
{
unsigned
i
;
unsigned
char
finalcount
[
8
],
c
;
switch
(
ch
)
{
case
'"'
:
TRY
(
parse_string
(
f
));
break
;
case
'{'
:
TRY
(
parse_object
(
f
));
break
;
case
'['
:
TRY
(
parse_array
(
f
));
break
;
case
'n'
:
TRY
(
expect
(
f
,
"null"
,
4
,
JSON_TYPE_NULL
));
break
;
case
't'
:
TRY
(
expect
(
f
,
"true"
,
4
,
JSON_TYPE_TRUE
));
break
;
case
'f'
:
TRY
(
expect
(
f
,
"false"
,
5
,
JSON_TYPE_FALSE
));
break
;
case
'-'
:
case
'0'
:
case
'1'
:
case
'2'
:
case
'3'
:
case
'4'
:
case
'5'
:
case
'6'
:
case
'7'
:
case
'8'
:
case
'9'
:
TRY
(
parse_number
(
f
));
break
;
default:
return
ch
==
END_OF_STRING
?
JSON_STRING_INCOMPLETE
:
JSON_STRING_INVALID
;
for
(
i
=
0
;
i
<
8
;
i
++
)
{
finalcount
[
i
]
=
(
unsigned
char
)
((
context
->
count
[(
i
>=
4
?
0
:
1
)]
>>
((
3
-
(
i
&
3
))
*
8
))
&
255
);
}
return
0
;
c
=
0200
;
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 */
static
int
parse_key
(
struct
frozen
*
f
)
{
int
ch
=
cur
(
f
);
#if 0
printf("%s 1 [%.*s]\n", __func__, (int) (f->end - f->cur), f->cur)
;
#endif
if
(
is_alpha
(
ch
))
{
TRY
(
parse_identifier
(
f
)
);
}
else
if
(
ch
==
'"'
)
{
TRY
(
parse_string
(
f
)
);
}
else
{
return
ch
==
END_OF_STRING
?
JSON_STRING_INCOMPLETE
:
JSON_STRING_INVALID
;
void
cs_hmac_sha1
(
const
unsigned
char
*
key
,
size_t
keylen
,
const
unsigned
char
*
data
,
size_t
datalen
,
unsigned
char
out
[
20
])
{
cs_sha1_ctx
ctx
;
unsigned
char
buf1
[
64
],
buf2
[
64
],
tmp_key
[
20
],
i
;
if
(
keylen
>
sizeof
(
buf1
))
{
cs_sha1_init
(
&
ctx
);
cs_sha1_update
(
&
ctx
,
key
,
keylen
);
cs_sha1_final
(
tmp_key
,
&
ctx
);
key
=
tmp_key
;
keylen
=
sizeof
(
tmp_key
)
;
}
return
0
;
}
/* pair = key ':' value */
static
int
parse_pair
(
struct
frozen
*
f
)
{
TRY
(
parse_key
(
f
));
TRY
(
test_and_skip
(
f
,
':'
));
TRY
(
parse_value
(
f
));
return
0
;
}
memset
(
buf1
,
0
,
sizeof
(
buf1
));
memset
(
buf2
,
0
,
sizeof
(
buf2
));
memcpy
(
buf1
,
key
,
keylen
);
memcpy
(
buf2
,
key
,
keylen
);
/* object = '{' pair { ',' pair } '}' */
static
int
parse_object
(
struct
frozen
*
f
)
{
int
ind
;
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
++
;
for
(
i
=
0
;
i
<
sizeof
(
buf1
);
i
++
)
{
buf1
[
i
]
^=
0x36
;
buf2
[
i
]
^=
0x5c
;
}
TRY
(
test_and_skip
(
f
,
'}'
));
capture_len
(
f
,
ind
,
f
->
cur
);
return
0
;
}
static
int
doit
(
struct
frozen
*
f
)
{
if
(
f
->
cur
==
0
||
f
->
end
<
f
->
cur
)
return
JSON_STRING_INVALID
;
if
(
f
->
end
==
f
->
cur
)
return
JSON_STRING_INCOMPLETE
;
TRY
(
parse_object
(
f
));
TRY
(
capture_ptr
(
f
,
f
->
cur
,
JSON_TYPE_EOF
));
capture_len
(
f
,
f
->
num_tokens
,
f
->
cur
);
return
0
;
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
);
}
/* json = object */
int
parse_json
(
const
char
*
s
,
int
s_len
,
struct
json_token
*
arr
,
int
arr_len
)
{
struct
frozen
frozen
;
#endif
/* EXCLUDE_COMMON */
#ifdef NS_MODULE_LINES
#line 1 "src/../../common/str_util.c"
/**/
#endif
/*
* Copyright (c) 2015 Cesanta Software Limited
* All rights reserved
*/
memset
(
&
frozen
,
0
,
sizeof
(
frozen
));
frozen
.
end
=
s
+
s_len
;
frozen
.
cur
=
s
;
frozen
.
tokens
=
arr
;
frozen
.
max_tokens
=
arr_len
;
#ifndef EXCLUDE_COMMON
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
)
{
struct
frozen
frozen
;
#define C_SNPRINTF_APPEND_CHAR(ch) \
do { \
if (i < (int) buf_size) buf[i] = ch; \
i++; \
} while (0)
memset
(
&
frozen
,
0
,
sizeof
(
frozen
));
frozen
.
end
=
s
+
s_len
;
frozen
.
cur
=
s
;
frozen
.
do_realloc
=
1
;
#define C_SNPRINTF_FLAG_ZERO 1
if
(
doit
(
&
frozen
)
<
0
)
{
FROZEN_FREE
((
void
*
)
frozen
.
tokens
);
frozen
.
tokens
=
NULL
;
}
return
frozen
.
tokens
;
#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
;
static
int
path_part_len
(
const
char
*
p
)
{
int
i
=
0
;
while
(
p
[
i
]
!=
'\0'
&&
p
[
i
]
!=
'['
&&
p
[
i
]
!=
'.'
)
i
++
;
return
i
;
}
if
(
num
<
0
)
{
neg
++
;
num
=
-
num
;
}
struct
json_token
*
find_json_token
(
struct
json_token
*
toks
,
const
char
*
path
)
{
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
;
}
/* 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'
;
}
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
)
{
char
tmp
[
20
];
int
n
=
snprintf
(
tmp
,
sizeof
(
tmp
),
"%ld"
,
value
);
strncpy
(
buf
,
tmp
,
buf_len
>
0
?
buf_len
:
0
);
return
n
;
}
/* And sign */
if
(
neg
)
{
tmp
[
k
++
]
=
'-'
;
}
int
json_emit_double
(
char
*
buf
,
int
buf_len
,
double
value
)
{
char
tmp
[
20
];
int
n
=
snprintf
(
tmp
,
sizeof
(
tmp
),
"%g"
,
value
);
strncpy
(
buf
,
tmp
,
buf_len
>
0
?
buf_len
:
0
);
return
n
;
/* Now output */
while
(
--
k
>=
0
)
{
C_SNPRINTF_APPEND_CHAR
(
tmp
[
k
]);
}
return
i
;
}
int
json_emit_quoted_str
(
char
*
s
,
int
s_len
,
const
char
*
str
,
int
len
)
{
const
char
*
begin
=
s
,
*
end
=
s
+
s_len
,
*
str_end
=
str
+
len
;
char
ch
;
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
;
#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
(
'"'
);
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'
;
}
/* Flags. only zero-pad flag is supported. */
if
(
*
fmt
==
'0'
)
{
flags
|=
C_SNPRINTF_FLAG_ZERO
;
}
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
)
{
if
(
buf_len
>
0
&&
len
>
0
)
{
int
n
=
len
<
buf_len
?
len
:
buf_len
;
memcpy
(
buf
,
str
,
n
);
if
(
n
<
buf_len
)
{
buf
[
n
]
=
'\0'
;
}
}
return
len
;
}
/* Precision */
if
(
*
fmt
==
'.'
)
{
fmt
++
;
if
(
*
fmt
==
'*'
)
{
precision
=
va_arg
(
ap
,
int
);
fmt
++
;
}
else
{
while
(
*
fmt
>=
'0'
&&
*
fmt
<=
'9'
)
{
precision
*=
10
;
precision
+=
*
fmt
++
-
'0'
;
}
}
}
int
json_emit_va
(
char
*
s
,
int
s_len
,
const
char
*
fmt
,
va_list
ap
)
{
const
char
*
end
=
s
+
s_len
,
*
str
,
*
orig
=
s
;
size_t
len
;
/* 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
;
}
while
(
*
fmt
!=
'\0'
)
{
switch
(
*
fmt
)
{
case
'['
:
case
']'
:
case
'{'
:
case
'}'
:
case
','
:
case
':'
:
case
' '
:
case
'\r'
:
case
'\n'
:
case
'\t'
:
if
(
s
<
end
)
{
*
s
=
*
fmt
;
ch
=
*
fmt
++
;
if
(
ch
==
's'
)
{
const
char
*
s
=
va_arg
(
ap
,
const
char
*
);
/* Always fetch parameter */
int
j
;
int
pad
=
field_width
-
(
precision
>=
0
?
strnlen
(
s
,
precision
)
:
0
);
for
(
j
=
0
;
j
<
pad
;
j
++
)
{
C_SNPRINTF_APPEND_CHAR
(
' '
);
}
s
++
;
break
;
case
'i'
:
s
+=
json_emit_long
(
s
,
end
-
s
,
va_arg
(
ap
,
long
));
break
;
case
'f'
:
s
+=
json_emit_double
(
s
,
end
-
s
,
va_arg
(
ap
,
double
));
break
;
case
'v'
:
str
=
va_arg
(
ap
,
char
*
);
len
=
va_arg
(
ap
,
size_t
);
s
+=
json_emit_quoted_str
(
s
,
end
-
s
,
str
,
len
);
break
;
case
'V'
:
str
=
va_arg
(
ap
,
char
*
);
len
=
va_arg
(
ap
,
size_t
);
s
+=
json_emit_unquoted_str
(
s
,
end
-
s
,
str
,
len
);
break
;
case
's'
:
str
=
va_arg
(
ap
,
char
*
);
s
+=
json_emit_quoted_str
(
s
,
end
-
s
,
str
,
strlen
(
str
));
break
;
case
'S'
:
str
=
va_arg
(
ap
,
char
*
);
s
+=
json_emit_unquoted_str
(
s
,
end
-
s
,
str
,
strlen
(
str
));
break
;
case
'T'
:
s
+=
json_emit_unquoted_str
(
s
,
end
-
s
,
"true"
,
4
);
break
;
case
'F'
:
s
+=
json_emit_unquoted_str
(
s
,
end
-
s
,
"false"
,
5
);
break
;
case
'N'
:
s
+=
json_emit_unquoted_str
(
s
,
end
-
s
,
"null"
,
4
);
break
;
default:
return
0
;
/* Ignore negative and 0 precisions */
for
(
j
=
0
;
(
precision
<=
0
||
j
<
precision
)
&&
s
[
j
]
!=
'\0'
;
j
++
)
{
C_SNPRINTF_APPEND_CHAR
(
s
[
j
]);
}
}
else
if
(
ch
==
'c'
)
{
ch
=
va_arg
(
ap
,
int
);
/* Always fetch parameter */
C_SNPRINTF_APPEND_CHAR
(
ch
);
}
else
if
(
ch
==
'd'
&&
len_mod
==
0
)
{
i
+=
c_itoa
(
buf
+
i
,
buf_size
-
i
,
va_arg
(
ap
,
int
),
10
,
flags
,
field_width
);
}
else
if
(
ch
==
'd'
&&
len_mod
==
'l'
)
{
i
+=
c_itoa
(
buf
+
i
,
buf_size
-
i
,
va_arg
(
ap
,
long
),
10
,
flags
,
field_width
);
}
else
if
((
ch
==
'x'
||
ch
==
'u'
)
&&
len_mod
==
0
)
{
i
+=
c_itoa
(
buf
+
i
,
buf_size
-
i
,
va_arg
(
ap
,
unsigned
),
ch
==
'x'
?
16
:
10
,
flags
,
field_width
);
}
else
if
((
ch
==
'x'
||
ch
==
'u'
)
&&
len_mod
==
'l'
)
{
i
+=
c_itoa
(
buf
+
i
,
buf_size
-
i
,
va_arg
(
ap
,
unsigned
long
),
ch
==
'x'
?
16
:
10
,
flags
,
field_width
);
}
else
if
(
ch
==
'p'
)
{
unsigned
long
num
=
(
unsigned
long
)
va_arg
(
ap
,
void
*
);
C_SNPRINTF_APPEND_CHAR
(
'0'
);
C_SNPRINTF_APPEND_CHAR
(
'x'
);
i
+=
c_itoa
(
buf
+
i
,
buf_size
-
i
,
num
,
16
,
flags
,
0
);
}
else
{
#ifndef NO_LIBC
/*
* TODO(lsm): abort is not nice in a library, remove it
* Also, ESP8266 SDK doesn't have it
*/
abort
();
#endif
}
}
fmt
++
;
}
/*
Best-effort to 0-terminate generated string
*/
if
(
s
<
end
)
{
*
s
=
'\0'
;
/*
Zero-terminate the result
*/
if
(
buf_size
>
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
len
;
int
c_snprintf
(
char
*
buf
,
size_t
buf_size
,
const
char
*
fmt
,
...)
{
int
result
;
va_list
ap
;
va_start
(
ap
,
fmt
);
len
=
json_emit_va
(
buf
,
buf_len
,
fmt
,
ap
);
result
=
c_vsnprintf
(
buf
,
buf_size
,
fmt
,
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
#line 1 "src/net.c"
/**/
...
...
mongoose.h
View file @
d60c99b0
...
...
@@ -26,6 +26,10 @@
#ifdef MG_LOCALS
#include <mg_locals.h>
#endif
#if defined(MG_ENABLE_DEBUG) && !defined(CS_ENABLE_DEBUG)
#define CS_ENABLE_DEBUG
#endif
/*
* Copyright (c) 2015 Cesanta Software Limited
* All rights reserved
...
...
@@ -260,25 +264,31 @@ int64_t strtoll(const char *str, char **endptr, int base);
#endif
#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 { \
printf("%-20s ", __func__); \
printf x; \
putchar('\n'); \
fflush(stdout); \
fprintf(stderr, "%-20s ", __func__); \
cs_dbg_printf x; \
} while (0)
#ifdef MG_ENABLE_DEBUG
#define DBG __DBG
#else
#define DBG(x)
#endif
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
#endif
#endif
/*
OSDEP_HEADER_INCLUDED
*/
#endif
/*
_CS_DBG_H_
*/
/*
* Copyright (c) 2015 Cesanta Software Limited
* 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