/* Dispatch a GET request REQ, writing the response body to FD fd. If * RANGE is non-NULL, then it is the value of the Range request * header, e.g. "bytes=1-5". Returns an NE_* error code. */ static int dispatch_to_fd(ne_request *req, int fd, const char *range) { ne_session *const sess = ne_get_session(req); const ne_status *const st = ne_get_status(req); int ret; do { const char *value; ret = ne_begin_request(req); if (ret != NE_OK) break; value = ne_get_response_header(req, "Content-Range"); /* For a 206 response, check that a Content-Range header is * given which matches the Range request header. */ if (range && st->code == 206 && (value == NULL || strncmp(value, "bytes ", 6) != 0 || strcmp(range + 6, value + 6))) { ne_set_error(sess, _("Response did not include requested range")); return NE_ERROR; } if ((range && st->code == 206) || (!range && st->klass == 2)) { ret = ne_read_response_to_fd(req, fd); } else { ret = ne_discard_response(req); } if (ret == NE_OK) ret = ne_end_request(req); } while (ret == NE_RETRY); return ret; }
/* A slightly ugly hack: the pre_send hook is scoped per-session, so * must check that the invoking request is this one, before doing * anything, and must be unregistered when the context is * destroyed. */ ne_decompress *ne_decompress_reader(ne_request *req, ne_accept_response acpt, ne_block_reader rdr, void *userdata) { ne_decompress *ctx = ne_calloc(sizeof *ctx); ne_add_request_header(req, "Accept-Encoding", "gzip"); ne_add_response_body_reader(req, gz_acceptor, gz_reader, ctx); ctx->reader = rdr; ctx->userdata = userdata; ctx->session = ne_get_session(req); ctx->request = req; ctx->acceptor = acpt; ne_hook_pre_send(ne_get_session(req), gz_pre_send, ctx); return ctx; }
MateVFSResult ne_matevfs_last_error (ne_request *req) { ne_session *sess; sess = ne_get_session (req); if (sess && sess->socket) return sess->socket->last_error; return MATE_VFS_OK; }
int ne_xml_parse_response(ne_request *req, ne_xml_parser *parser) { char buf[8000]; ssize_t bytes; int ret = 0; while ((bytes = ne_read_response_block(req, buf, sizeof buf)) > 0) { ret = ne_xml_parse(parser, buf, bytes); if (ret) return parse_error(ne_get_session(req), parser); } if (bytes == 0) { /* Tell the parser that end of document was reached: */ if (ne_xml_parse(parser, NULL, 0) == 0) return NE_OK; else return parse_error(ne_get_session(req), parser); } else { return NE_ERROR; } }
void ne_lock_using_parent(ne_request *req, const char *path) { NE_DEBUG_WINSCP_CONTEXT(ne_get_session(req)); struct lh_req_cookie *lrc = ne_get_request_private(req, HOOK_ID); ne_uri u = {0}; struct lock_list *item; char *parent; if (lrc == NULL) return; parent = ne_path_parent(path); if (parent == NULL) return; ne_fill_server_uri(ne_get_session(req), &u); for (item = lrc->store->locks; item != NULL; item = item->next) { /* Only care about locks which are on this server. */ u.path = item->lock->uri.path; if (ne_uri_cmp(&u, &item->lock->uri)) continue; /* This lock is needed if it is an infinite depth lock which * covers the parent, or a lock on the parent itself. */ if ((item->lock->depth == NE_DEPTH_INFINITE && ne_path_childof(item->lock->uri.path, parent)) || ne_path_compare(item->lock->uri.path, parent) == 0) { NE_DEBUG(NE_DBG_LOCKS, "Locked parent, %s on %s\n", item->lock->token, item->lock->uri.path); submit_lock(lrc, item->lock); } } u.path = parent; /* handy: makes u.path valid and ne_free(parent). */ ne_uri_free(&u); }
/* Dispatch a GET request REQ, writing the response body to FD fd. If * RANGE is non-NULL, then it is the value of the Range request * header, e.g. "bytes=1-5". Returns an NE_* error code. */ static int dispatch_to_fd(ne_request *req, int fd, const char *range) { ne_session *const sess = ne_get_session(req); const ne_status *const st = ne_get_status(req); int ret; do { const char *value; ret = ne_begin_request(req); if (ret != NE_OK) break; value = ne_get_response_header(req, "Content-Range"); /* For a 206 response, check that a Content-Range header is * given which matches the Range request header. */ if (range && st->code == 206) { int err = 0; if (value == NULL || strncmp(value, "bytes ", 6) != 0) { err++; } else { /* If the response gives a range begin-end/total, limit * the comparison to the range itself. */ int len = strlen(value); char *cp = strchr(value, '/'); if (cp != NULL) len = (int)(cp - value); len -= 6; if (strncmp(range + 6, value + 6, len)) err++; } if (err) { ne_set_error(sess, _("Response did not include requested range")); return NE_ERROR; } } if ((range && st->code == 206) || (!range && st->klass == 2)) { ret = ne_read_response_to_fd(req, fd); } else { ret = ne_discard_response(req); } if (ret == NE_OK) ret = ne_end_request(req); } while (ret == NE_RETRY); return ret; }
static int lk_startelm(void *userdata, int parent, const char *nspace, const char *name, const char **atts) { struct lock_ctx *ctx = userdata; int id; NE_DEBUG_WINSCP_CONTEXT(ne_get_session(ctx->req)); id = ne_xml_mapid(element_map, NE_XML_MAPLEN(element_map), nspace, name); NE_DEBUG(NE_DBG_LOCKS, "lk_startelm: %s => %d\n", name, id); if (id == 0) return NE_XML_DECLINE; if (parent == 0 && ctx->token == NULL) { const char *token = ne_get_response_header(ctx->req, "Lock-Token"); /* at the root element; retrieve the Lock-Token header, * and bail if it wasn't given. */ if (token == NULL) { ne_xml_set_error(ctx->parser, _("LOCK response missing Lock-Token header")); return NE_XML_ABORT; } if (token[0] == '<') token++; ctx->token = ne_strdup(token); ne_shave(ctx->token, ">"); NE_DEBUG(NE_DBG_LOCKS, "lk_startelm: Finding token %s\n", ctx->token); } /* TODO: only accept 'prop' as root for LOCK response */ if (!can_accept(parent, id)) return NE_XML_DECLINE; if (id == ELM_activelock && !ctx->found) { /* a new activelock */ ne_lock_free(&ctx->active); memset(&ctx->active, 0, sizeof ctx->active); ctx->active.timeout = NE_TIMEOUT_INVALID; } ne_buffer_clear(ctx->cdata); return id; }
int ne__negotiate_ssl (ne_request *req) { MateVFSSSL *ssl; MateVFSCancellation *cancellation; ne_session *sess; ne_socket *sock; int fd; sess = ne_get_session (req); sock = sess->socket; if (!mate_vfs_ssl_enabled ()) { sock->last_error = MATE_VFS_ERROR_NOT_SUPPORTED; return NE_SOCK_ERROR; } peek_cancellation (cancellation); fd = mate_vfs_inet_connection_get_fd (sock->connection); sock->last_error = mate_vfs_ssl_create_from_fd (&ssl, fd, cancellation); if (sock->last_error != MATE_VFS_OK) { return NE_SOCK_ERROR; } mate_vfs_socket_free (sock->socket); sock->socket = mate_vfs_ssl_to_socket (ssl); mate_vfs_socket_buffer_flush (sock->socket_buffer, cancellation); sock->last_error = mate_vfs_socket_buffer_destroy (sock->socket_buffer, FALSE, cancellation); mate_vfs_inet_connection_free (sock->connection, cancellation); sock->socket_buffer = mate_vfs_socket_buffer_new (sock->socket); return 0; }
void ne_lock_using_resource(ne_request *req, const char *uri, int depth) { NE_DEBUG_WINSCP_CONTEXT(ne_get_session(req)); struct lh_req_cookie *lrc = ne_get_request_private(req, HOOK_ID); struct lock_list *item; int match; if (lrc == NULL) return; /* Iterate over the list of stored locks to see if any of them * apply to this resource */ for (item = lrc->store->locks; item != NULL; item = item->next) { match = 0; if (depth == NE_DEPTH_INFINITE && ne_path_childof(uri, item->lock->uri.path)) { /* Case 1: this is a depth-infinity request which will * modify a lock somewhere inside the collection. */ NE_DEBUG(NE_DBG_LOCKS, "Has child: %s\n", item->lock->token); match = 1; } else if (ne_path_compare(uri, item->lock->uri.path) == 0) { /* Case 2: this request is directly on a locked resource */ NE_DEBUG(NE_DBG_LOCKS, "Has direct lock: %s\n", item->lock->token); match = 1; } else if (item->lock->depth == NE_DEPTH_INFINITE && ne_path_childof(item->lock->uri.path, uri)) { /* Case 3: there is a higher-up infinite-depth lock which * covers the resource that this request will modify. */ NE_DEBUG(NE_DBG_LOCKS, "Is child of: %s\n", item->lock->token); match = 1; } if (match) { submit_lock(lrc, item->lock); } } }