mirror of
https://github.com/cesanta/mongoose.git
synced 2026-10-25 12:04:47 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c41a22195c | ||
|
|
900c05213b | ||
|
|
c5850e4b05 | ||
|
|
ff4649fe42 | ||
|
|
1a38e91042 | ||
|
|
b6196371bb | ||
|
|
d5beb7ba3f | ||
|
|
19acf23c49 | ||
|
|
5cd3291fec | ||
|
|
b3e0f780c3 | ||
|
|
2bdbfc27f6 | ||
|
|
3fc61a3edc | ||
|
|
12339bbf4c | ||
|
|
1fb9f922b0 | ||
|
|
b93bc02ab0 | ||
|
|
747e393a54 | ||
|
|
4e8660a21f | ||
|
|
3fe77fa9a6 | ||
|
|
b4fbaf7c13 | ||
|
|
9884241df8 | ||
|
|
63d7a4fa45 | ||
|
|
8f4b6c41a2 | ||
|
|
4493d65ec9 | ||
|
|
e5910da300 | ||
|
|
c277a1d878 | ||
|
|
7820ad3a59 | ||
|
|
23533b83a4 | ||
|
|
ab650ec5c9 | ||
|
|
8f36597048 | ||
|
|
d0213ee90a | ||
|
|
1e9fabe1ca | ||
|
|
148d3f0562 | ||
|
|
c3057df3f5 | ||
|
|
0b2e474d52 | ||
|
|
95a36b1759 | ||
|
|
86ffa3a3ea | ||
|
|
69e2b2985d | ||
|
|
c431904b56 | ||
|
|
c2a10601b9 | ||
|
|
e9a8e5468d | ||
|
|
22e602debb | ||
|
|
455cec67a5 | ||
|
|
e2dfac946d | ||
|
|
c198d2e5f1 | ||
|
|
9a70abef24 | ||
|
|
53e1c469a2 | ||
|
|
139c2061a8 | ||
|
|
15b361fbac | ||
|
|
3130e59244 | ||
|
|
93286836f9 | ||
|
|
91b57aa9a8 | ||
|
|
220231e647 | ||
|
|
c438bb0bc5 | ||
|
|
95afa323c0 | ||
|
|
bc56353a79 | ||
|
|
1ffccdb7b2 | ||
|
|
e79fe4b8f0 | ||
|
|
aaf1fc3a4a | ||
|
|
8b42353039 | ||
|
|
05c687e251 | ||
|
|
492b8f6950 | ||
|
|
8ccee82059 | ||
|
|
b99a94a652 | ||
|
|
41e5d7e471 | ||
|
|
1adea37c45 | ||
|
|
98f6c8aa4f | ||
|
|
341ae53e85 | ||
|
|
291fc024cd | ||
|
|
f63d833a33 | ||
|
|
ab035901f8 | ||
|
|
20f54059ad | ||
|
|
563c31303e | ||
|
|
421e099f2b | ||
|
|
955d4a3129 | ||
|
|
b84981ad03 | ||
|
|
777b8e94e2 | ||
|
|
6df642623a | ||
|
|
0a3e186f11 | ||
|
|
c2d83a9db0 | ||
|
|
f33d3a4e02 | ||
|
|
86b8a56b05 | ||
|
|
ac6ec15aed | ||
|
|
31632c6361 | ||
|
|
98c99279c3 | ||
|
|
cdb8d7b692 | ||
|
|
93ac3e19f0 | ||
|
|
6a51af9efe | ||
|
|
9d73b3470b | ||
|
|
1c8449cea6 | ||
|
|
3bbbd41196 | ||
|
|
339bbee0df | ||
|
|
9ba6eb716d | ||
|
|
d949c19c7e | ||
|
|
1299d6118f | ||
|
|
244ff92e78 | ||
|
|
53f34dea04 | ||
|
|
1f5c3fac31 | ||
|
|
7014258c8d | ||
|
|
1614e7ba8d | ||
|
|
43b5a4e735 | ||
|
|
43191db63e | ||
|
|
e89be2e944 | ||
|
|
c2fbff6d0e | ||
|
|
b8eca17c55 | ||
|
|
4650e491df | ||
|
|
3e33e57707 | ||
|
|
c80f4c5313 | ||
|
|
132ecbec2f | ||
|
|
0a90cab44a | ||
|
|
d16dbc197f | ||
|
|
127f27e375 | ||
|
|
6523cc4da0 | ||
|
|
2516da1c89 | ||
|
|
0ae2b82b60 | ||
|
|
dab526936f | ||
|
|
780077d118 | ||
|
|
ad8f1d88d4 | ||
|
|
a3c4a48ef7 | ||
|
|
84a11fe3b1 | ||
|
|
2a3cfc9858 | ||
|
|
b9b20c6494 | ||
|
|
a8a7d2cf7e | ||
|
|
50ecc30b4d | ||
|
|
cd89db5c2f | ||
|
|
1ed99999bd | ||
|
|
4afebdcb2b | ||
|
|
c3d9d17e34 | ||
|
|
7bf5144e62 | ||
|
|
3eb4eb8074 | ||
|
|
ab000c684a | ||
|
|
aba60dadec | ||
|
|
f29457e967 | ||
|
|
8742fac5d8 | ||
|
|
0ab1c7ef76 | ||
|
|
47abc641f1 | ||
|
|
7519b2ef3a | ||
|
|
ce8657f12f | ||
|
|
8e366916d5 | ||
|
|
33f53ab000 | ||
|
|
bd15ad4301 | ||
|
|
e5b3b8ad32 | ||
|
|
e116c48bef | ||
|
|
7d7bb3b388 | ||
|
|
0b4bf13335 | ||
|
|
228984a3fc | ||
|
|
f084ad8008 | ||
|
|
255da78bed | ||
|
|
5d5badfcee | ||
|
|
4cf9f99ae9 | ||
|
|
673f25f75a | ||
|
|
961fb96bb7 | ||
|
|
d6475fcd19 | ||
|
|
ac538f755f | ||
|
|
5b2eb4f0e1 | ||
|
|
10c274c774 | ||
|
|
eb3b81297d | ||
|
|
80f4133bbf | ||
|
|
d10fb9451c | ||
|
|
88ae2ecadb | ||
|
|
85d19dad47 | ||
|
|
c5cc414181 | ||
|
|
17703fe3e8 | ||
|
|
04aeeba2fa | ||
|
|
4e11d5cdbf | ||
|
|
be63c0dc89 | ||
|
|
987bc1d580 | ||
|
|
ddd35c0cba | ||
|
|
c97b615785 | ||
|
|
9ab6d084df | ||
|
|
cf8d0a25aa | ||
|
|
0a0852b576 | ||
|
|
90716417c9 | ||
|
|
101afbc9b8 | ||
|
|
a197646867 | ||
|
|
00d1d2c0e7 |
No files matched your search
@@ -1,8 +0,0 @@
|
||||
People who have agreed to the
|
||||
[Cesanta CLA](https://docs.cesanta.com/contributors_la.shtml)
|
||||
can make contributions. Note that the CLA isn't a copyright
|
||||
_assigment_ but rather a copyright _license_.
|
||||
You retain the copyright on your contributions.
|
||||
|
||||
We follow the Google C/C++ style guide: https://google.github.io/styleguide/cppguide.html
|
||||
We'd appreciate if your contribution follows the same style guide.
|
||||
@@ -1,5 +1,5 @@
|
||||
Copyright (c) 2004-2013 Sergey Lyubka <valenok@gmail.com>
|
||||
Copyright (c) 2013-2016 Cesanta Software Limited
|
||||
Copyright (c) 2013-2018 Cesanta Software Limited
|
||||
All rights reserved
|
||||
|
||||
This software is dual-licensed: you can redistribute it and/or modify
|
||||
|
||||
@@ -16,8 +16,8 @@ Check out [Mongoose OS](https://mongoose-os.com) - open source embedded operatin
|
||||
|
||||
# Support
|
||||
- [Study mongoose example code](https://github.com/cesanta/mongoose/tree/master/examples)
|
||||
- [Read User Guide and API reference](https://docs.cesanta.com/mongoose)
|
||||
- [Support Forum - ask your technical questions here](https://forum.mongoose-os.com/categories/mongoose)
|
||||
- [Read User Guide and API reference](https://cesanta.com/docs/overview/intro.html)
|
||||
- [Support Forum - ask your technical questions here](https://community.mongoose-os.com/)
|
||||
- [Commercial licensing and support available](https://www.cesanta.com/licensing.html)
|
||||
- [Check our latest releases](https://github.com/cesanta/mongoose/releases)
|
||||
|
||||
@@ -62,7 +62,7 @@ the functionality:
|
||||
# Contributions
|
||||
|
||||
To submit contributions, sign [Cesanta CLA](https://cesanta.com/cla.html)
|
||||
and send GitHub pull request. You retain the copyright on your contributions.
|
||||
and send GitHub pull request.
|
||||
|
||||
# Looking for a pre-compiled Mongoose web server Windows or Mac binary?
|
||||
- [Download pre-compiled Mongoose web server binary.](https://www.cesanta.com/binary.html)
|
||||
@@ -1,16 +0,0 @@
|
||||
---
|
||||
title: "struct mg_http_multipart_part"
|
||||
decl_name: "struct mg_http_multipart_part"
|
||||
symbol_kind: "struct"
|
||||
signature: |
|
||||
struct mg_http_multipart_part {
|
||||
const char *file_name;
|
||||
const char *var_name;
|
||||
struct mg_str data;
|
||||
int status; /* <0 on error */
|
||||
void *user_data;
|
||||
};
|
||||
---
|
||||
|
||||
HTTP multipart part
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
---
|
||||
title: "mg_http_parse_header()"
|
||||
decl_name: "mg_http_parse_header"
|
||||
symbol_kind: "func"
|
||||
signature: |
|
||||
int mg_http_parse_header(struct mg_str *hdr, const char *var_name, char *buf,
|
||||
size_t buf_size);
|
||||
---
|
||||
|
||||
Parses the HTTP header `hdr`. Finds variable `var_name` and stores its value
|
||||
in the buffer `buf`, `buf_size`. Returns 0 if variable not found, non-zero
|
||||
otherwise.
|
||||
|
||||
This function is supposed to parse cookies, authentication headers, etc.
|
||||
Example (error handling omitted):
|
||||
|
||||
char user[20];
|
||||
struct mg_str *hdr = mg_get_http_header(hm, "Authorization");
|
||||
mg_http_parse_header(hdr, "username", user, sizeof(user));
|
||||
|
||||
Returns the length of the variable's value. If buffer is not large enough,
|
||||
or variable not found, 0 is returned.
|
||||
|
||||
+12
-12
@@ -1,16 +1,16 @@
|
||||
---
|
||||
items:
|
||||
- { name: mbuf.h }
|
||||
- { name: net.h }
|
||||
- { name: http.h }
|
||||
- { name: http_server.h }
|
||||
- { name: http_client.h }
|
||||
- { name: dns.h }
|
||||
- { name: dns_server.h }
|
||||
- { name: resolv.h }
|
||||
- { name: mqtt.h }
|
||||
- { name: mqtt_server.h }
|
||||
- { name: coap.h }
|
||||
- { name: util.h }
|
||||
- { name: uri.h }
|
||||
- { name: mg_net.h }
|
||||
- { name: mg_http.h }
|
||||
- { name: mg_http_server.h }
|
||||
- { name: mg_http_client.h }
|
||||
- { name: mg_dns.h }
|
||||
- { name: mg_dns_server.h }
|
||||
- { name: mg_resolv.h }
|
||||
- { name: mg_mqtt.h }
|
||||
- { name: mg_mqtt_server.h }
|
||||
- { name: mg_coap.h }
|
||||
- { name: mg_util.h }
|
||||
- { name: mg_uri.h }
|
||||
---
|
||||
@@ -1,12 +1,15 @@
|
||||
---
|
||||
title: "Memory Buffers"
|
||||
title: "mbuf.h"
|
||||
symbol_kind: "intro"
|
||||
decl_name: "mbuf.h"
|
||||
items:
|
||||
- { name: mbuf_append.md }
|
||||
- { name: mbuf_append_and_free.md }
|
||||
- { name: mbuf_clear.md }
|
||||
- { name: mbuf_free.md }
|
||||
- { name: mbuf_init.md }
|
||||
- { name: mbuf_insert.md }
|
||||
- { name: mbuf_move.md }
|
||||
- { name: mbuf_remove.md }
|
||||
- { name: mbuf_resize.md }
|
||||
- { name: mbuf_trim.md }
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
---
|
||||
title: "mbuf_append_and_free()"
|
||||
decl_name: "mbuf_append_and_free"
|
||||
symbol_kind: "func"
|
||||
signature: |
|
||||
size_t mbuf_append_and_free(struct mbuf *, void *data, size_t data_size);
|
||||
---
|
||||
|
||||
Appends data to the Mbuf and frees it (data must be heap-allocated).
|
||||
|
||||
Returns the number of bytes appended or 0 if out of memory.
|
||||
data is freed irrespective of return value.
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
---
|
||||
title: "mbuf_clear()"
|
||||
decl_name: "mbuf_clear"
|
||||
symbol_kind: "func"
|
||||
signature: |
|
||||
void mbuf_clear(struct mbuf *);
|
||||
---
|
||||
|
||||
Removes all the data from mbuf (if any).
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
---
|
||||
title: "mbuf_move()"
|
||||
decl_name: "mbuf_move"
|
||||
symbol_kind: "func"
|
||||
signature: |
|
||||
void mbuf_move(struct mbuf *from, struct mbuf *to);
|
||||
---
|
||||
|
||||
Moves the state from one mbuf to the other.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
title: "CoAP API reference"
|
||||
symbol_kind: "intro"
|
||||
decl_name: "coap.h"
|
||||
decl_name: "mg_coap.h"
|
||||
items:
|
||||
- { name: mg_coap_add_option.md }
|
||||
- { name: mg_coap_compose.md }
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -1,7 +1,7 @@
|
||||
---
|
||||
title: "DNS API reference"
|
||||
symbol_kind: "intro"
|
||||
decl_name: "dns.h"
|
||||
decl_name: "mg_dns.h"
|
||||
items:
|
||||
- { name: mg_dns_copy_questions.md }
|
||||
- { name: mg_dns_encode_name.md }
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -1,7 +1,7 @@
|
||||
---
|
||||
title: "DNS server API reference"
|
||||
symbol_kind: "intro"
|
||||
decl_name: "dns_server.h"
|
||||
decl_name: "mg_dns_server.h"
|
||||
items:
|
||||
- { name: mg_dns_create_reply.md }
|
||||
- { name: mg_dns_reply_record.md }
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -1,10 +1,12 @@
|
||||
---
|
||||
title: "Common API reference"
|
||||
symbol_kind: "intro"
|
||||
decl_name: "http.h"
|
||||
decl_name: "mg_http.h"
|
||||
items:
|
||||
- { name: mg_connect_ws.md }
|
||||
- { name: mg_connect_ws_opt.md }
|
||||
- { name: mg_http_is_authorized.md }
|
||||
- { name: mg_http_send_digest_auth_request.md }
|
||||
- { name: mg_printf_websocket_frame.md }
|
||||
- { name: mg_send_websocket_frame.md }
|
||||
- { name: mg_send_websocket_framev.md }
|
||||
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,16 @@
|
||||
---
|
||||
title: "mg_http_is_authorized()"
|
||||
decl_name: "mg_http_is_authorized"
|
||||
symbol_kind: "func"
|
||||
signature: |
|
||||
int mg_http_is_authorized(struct http_message *hm, struct mg_str path,
|
||||
const char *domain, const char *passwords_file,
|
||||
int flags);
|
||||
---
|
||||
|
||||
Checks whether an http request is authorized. `domain` is the authentication
|
||||
realm, `passwords_file` is a htdigest file (can be created e.g. with
|
||||
`htdigest` utility). If either `domain` or `passwords_file` is NULL, this
|
||||
function always returns 1; otherwise checks the authentication in the
|
||||
http request and returns 1 only if there is a match; 0 otherwise.
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
---
|
||||
title: "mg_http_send_digest_auth_request()"
|
||||
decl_name: "mg_http_send_digest_auth_request"
|
||||
symbol_kind: "func"
|
||||
signature: |
|
||||
void mg_http_send_digest_auth_request(struct mg_connection *c,
|
||||
const char *domain);
|
||||
---
|
||||
|
||||
Sends 401 Unauthorized response.
|
||||
|
||||
File renamed without changes.
File renamed without changes.
+2
-4
@@ -7,8 +7,6 @@ signature: |
|
||||
const struct mg_str *strings, int num_strings);
|
||||
---
|
||||
|
||||
Sends multiple websocket frames.
|
||||
|
||||
Like `mg_send_websocket_frame()`, but composes a frame from multiple
|
||||
*buffers.
|
||||
Like `mg_send_websocket_frame()`, but composes a single frame from multiple
|
||||
buffers.
|
||||
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+3
-1
@@ -30,7 +30,9 @@ The user-defined event handler will receive following extra events:
|
||||
- MG_EV_WEBSOCKET_HANDSHAKE_REQUEST: server has received the WebSocket
|
||||
handshake request. `ev_data` contains parsed HTTP request.
|
||||
- MG_EV_WEBSOCKET_HANDSHAKE_DONE: server has completed the WebSocket
|
||||
handshake. `ev_data` is `NULL`.
|
||||
handshake. `ev_data` is a `struct http_message` containing the
|
||||
client's request (server mode) or server's response (client).
|
||||
In client mode handler can examine `resp_code`, which should be 101.
|
||||
- MG_EV_WEBSOCKET_FRAME: new WebSocket frame has arrived. `ev_data` is
|
||||
`struct websocket_message *`
|
||||
|
||||
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "struct mg_http_multipart_part"
|
||||
decl_name: "struct mg_http_multipart_part"
|
||||
symbol_kind: "struct"
|
||||
signature: |
|
||||
struct mg_http_multipart_part {
|
||||
const char *file_name;
|
||||
const char *var_name;
|
||||
struct mg_str data;
|
||||
int status; /* <0 on error */
|
||||
void *user_data;
|
||||
/*
|
||||
* User handler can indicate how much of the data was consumed
|
||||
* by setting this variable. By default, it is assumed that all
|
||||
* data has been consumed by the handler.
|
||||
* If not all data was consumed, user's handler will be invoked again later
|
||||
* with the remainder.
|
||||
*/
|
||||
size_t num_data_consumed;
|
||||
};
|
||||
---
|
||||
|
||||
HTTP multipart part
|
||||
|
||||
File renamed without changes.
File renamed without changes.
@@ -1,7 +1,7 @@
|
||||
---
|
||||
title: "Client API reference"
|
||||
symbol_kind: "intro"
|
||||
decl_name: "http_client.h"
|
||||
decl_name: "mg_http_client.h"
|
||||
items:
|
||||
- { name: mg_connect_http.md }
|
||||
- { name: mg_connect_http_opt.md }
|
||||
File renamed without changes.
File renamed without changes.
+1
-1
@@ -6,7 +6,7 @@ signature: |
|
||||
int mg_http_create_digest_auth_header(char *buf, size_t buf_len,
|
||||
const char *method, const char *uri,
|
||||
const char *auth_domain, const char *user,
|
||||
const char *passwd);
|
||||
const char *passwd, const char *nonce);
|
||||
---
|
||||
|
||||
Creates digest authentication header for a client request.
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
title: "Server API reference"
|
||||
symbol_kind: "intro"
|
||||
decl_name: "http_server.h"
|
||||
decl_name: "mg_http_server.h"
|
||||
items:
|
||||
- { name: mg_check_digest_auth.md }
|
||||
- { name: mg_file_upload_handler.md }
|
||||
@@ -10,6 +10,7 @@ items:
|
||||
- { name: mg_get_http_var.md }
|
||||
- { name: mg_http_check_digest_auth.md }
|
||||
- { name: mg_http_parse_header.md }
|
||||
- { name: mg_http_parse_header2.md }
|
||||
- { name: mg_http_reverse_proxy.md }
|
||||
- { name: mg_http_send_error.md }
|
||||
- { name: mg_http_send_redirect.md }
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,15 @@
|
||||
---
|
||||
title: "mg_http_parse_header()"
|
||||
decl_name: "mg_http_parse_header"
|
||||
symbol_kind: "func"
|
||||
signature: |
|
||||
int mg_http_parse_header(struct mg_str *hdr, const char *var_name, char *buf,
|
||||
size_t buf_size);
|
||||
---
|
||||
|
||||
DEPRECATED: use mg_http_parse_header2() instead.
|
||||
|
||||
Same as mg_http_parse_header2(), but takes buffer as a `char *` (instead of
|
||||
`char **`), and thus it cannot allocate a new buffer if the provided one
|
||||
is not enough, and just returns 0 in that case.
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
---
|
||||
title: "mg_http_parse_header2()"
|
||||
decl_name: "mg_http_parse_header2"
|
||||
symbol_kind: "func"
|
||||
signature: |
|
||||
int mg_http_parse_header2(struct mg_str *hdr, const char *var_name, char **buf,
|
||||
size_t buf_size);
|
||||
---
|
||||
|
||||
Parses the HTTP header `hdr`. Finds variable `var_name` and stores its value
|
||||
in the buffer `*buf`, `buf_size`. If the buffer size is not enough,
|
||||
allocates a buffer of required size and writes it to `*buf`, similar to
|
||||
asprintf(). The caller should always check whether the buffer was updated,
|
||||
and free it if so.
|
||||
|
||||
This function is supposed to parse cookies, authentication headers, etc.
|
||||
Example (error handling omitted):
|
||||
|
||||
char user_buf[20];
|
||||
char *user = user_buf;
|
||||
struct mg_str *hdr = mg_get_http_header(hm, "Authorization");
|
||||
mg_http_parse_header2(hdr, "username", &user, sizeof(user_buf));
|
||||
// ... do something useful with user
|
||||
if (user != user_buf) {
|
||||
free(user);
|
||||
}
|
||||
|
||||
Returns the length of the variable's value. If variable is not found, 0 is
|
||||
returned.
|
||||
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -1,7 +1,7 @@
|
||||
---
|
||||
title: "MQTT API reference"
|
||||
symbol_kind: "intro"
|
||||
decl_name: "mqtt.h"
|
||||
decl_name: "mg_mqtt.h"
|
||||
items:
|
||||
- { name: mg_mqtt_connack.md }
|
||||
- { name: mg_mqtt_disconnect.md }
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Loaded 100 of 412 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user