16 #define NEONBLOWSCHUNKS
17 #ifndef NEONBLOWSCHUNKS
19 #include "../neon/src/ne_private.h"
23 #include "ne_request.h"
24 #include "ne_socket.h"
25 #include "ne_string.h"
28 #if !defined(HEADER_ERR_H)
31 extern void ERR_remove_state(
int foo);
32 extern void ENGINE_cleanup(
void);
33 extern void CONF_modules_unload(
int foo);
34 extern void ERR_free_strings(
void);
35 extern void EVP_cleanup(
void);
36 extern void CRYPTO_cleanup_all_ex_data(
void);
37 extern void CRYPTO_mem_leaks(
void * ptr);
45 #define WITH_NEON_MIN_VERSION 0x002700
46 #elif defined(NE_FEATURE_I18N)
47 #define WITH_NEON_MIN_VERSION 0x002600
49 #define WITH_NEON_MIN_VERSION 0x002500
53 #if WITH_NEON_MIN_VERSION >= 0x002600
54 #define ne_propfind_set_private(_pfh, _create_item, NULL) \
55 ne_propfind_set_private(_pfh, _create_item, NULL, NULL)
66 #define _RPMAV_INTERNAL
67 #define _RPMDAV_INTERNAL
80 #define TIMEOUT_SECS 60
82 #define TIMEOUT_SECS 5
95 int rpmioHttpRetries = 20;
96 int rpmioHttpRecurseMax = 5;
97 int rpmioHttpMaxRedirect = 20;
112 ctx->modes =
_free(ctx->modes);
113 ctx->sizes =
_free(ctx->sizes);
114 ctx->mtimes =
_free(ctx->mtimes);
115 ctx->u =
urlFree(ctx->u,
"avContextDestroy");
116 ctx->uri =
_free(ctx->uri);
117 memset(ctx, 0,
sizeof(*ctx));
132 ctx =
xcalloc(1,
sizeof(*ctx));
134 ctx->u =
urlLink(u,
"avContextCreate");
136 if ((ctx->st = st) != NULL)
137 memset(ctx->st, 0,
sizeof(*ctx->st));
143 mode_t mode,
size_t size, time_t mtime)
148 fprintf(stderr,
"*** avContextAdd(%p,\"%s\", %06o, 0x%x, 0x%x)\n", ctx, path, (
unsigned)mode, (
unsigned)size, (
unsigned)mtime);
152 while (ctx->ac >= ctx->nalloced) {
153 if (ctx->nalloced <= 0)
157 (
sizeof(*ctx->modes) * ctx->nalloced));
159 (
sizeof(*ctx->sizes) * ctx->nalloced));
161 (
sizeof(*ctx->mtimes) * ctx->nalloced));
165 ctx->sizes[ctx->ac] = size;
166 ctx->mtimes[ctx->ac] = mtime;
176 fprintf(stderr,
"*** avClosedir(%p)\n", avdir);
178 #if defined(WITH_PTHREADS)
180 (void) pthread_mutex_destroy(&avdir->lock);
184 avdir =
_free(avdir);
197 if (avdir == NULL || !ISAVMAGIC(avdir) || avdir->data == NULL) {
202 dp = (
struct dirent *) avdir->data;
203 av = (
const char **) (dp + 1);
204 ac = (int)avdir->size;
205 dt = (
unsigned char *) (av + (ac + 1));
206 i = avdir->offset + 1;
208 if (i < 0 || i >= ac || av[i] == NULL)
218 #if !defined(__DragonFly__) && !defined(__CYGWIN__)
222 #if !(defined(hpux) || defined(__hpux) || defined(sun) || defined(RPM_OS_AIX) || defined(__CYGWIN__) || defined(__QNXNTO__))
223 #if !defined(__APPLE__) && !defined(__FreeBSD_kernel__) && !defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(__DragonFly__) && !defined(__OpenBSD__)
230 strncpy(dp->d_name, av[i],
sizeof(dp->d_name));
232 fprintf(stderr,
"*** avReaddir(%p) %p %s\n", (
void *)avdir, dp, dp->d_name);
248 fprintf(stderr,
"*** avOpendir(%s, %p, %p)\n", path, av, modes);
253 while (av[ac] != NULL)
254 nb += strlen(av[ac++]) + 1;
256 nb +=
sizeof(
".") +
sizeof(
"..");
258 nb +=
sizeof(*avdir) +
sizeof(*dp) + ((ac + 1) *
sizeof(*av)) + (ac + 1);
261 dp = (
struct dirent *) (avdir + 1);
262 nav = (
const char **) (dp + 1);
263 dt = (
unsigned char *) (nav + (ac + 1));
264 t = (
char *) (dt + ac + 1);
269 avdir->data = (
char *) dp;
271 avdir->allocation = nb;
277 #if defined(WITH_PTHREADS)
279 (void) pthread_mutex_init(&avdir->lock, NULL);
285 dt[nac] = (
unsigned char)
DT_DIR; nav[nac++] = t; t =
stpcpy(t,
"."); t++;
286 dt[nac] = (
unsigned char)
DT_DIR; nav[nac++] = t; t =
stpcpy(t,
".."); t++;
292 while (av[ac] != NULL) {
294 switch (modes[ac] & S_IFMT) {
295 case S_IFIFO: dt[nac]=(
unsigned char)
DT_FIFO;
break;
296 case S_IFCHR: dt[nac]=(
unsigned char)
DT_CHR;
break;
297 case S_IFDIR: dt[nac]=(
unsigned char)
DT_DIR;
break;
298 case S_IFBLK: dt[nac]=(
unsigned char)
DT_BLK;
break;
299 case S_IFREG: dt[nac]=(
unsigned char)
DT_REG;
break;
300 case S_IFLNK: dt[nac]=(
unsigned char)
DT_LNK;
break;
304 default: dt[nac]=(
unsigned char)
DT_UNKNOWN;
break;
317 return (DIR *) avdir;
330 #if WITH_NEON_MIN_VERSION >= 0x002700
335 if (u != NULL && rc != 0) {
338 ne_request_destroy(u->
ctrl->
req);
342 ne_request_destroy(u->
data->
req);
348 fprintf(stderr,
"*** davDisconnect(%p) active %d\n", u, rc);
358 if (u->
sess != NULL) {
359 ne_session_destroy(u->
sess);
378 fprintf(stderr,
"*** davFree(%p)\n", u);
384 #ifdef NE_FEATURE_SSL
385 if (ne_has_support(NE_FEATURE_SSL)) {
388 CRYPTO_cleanup_all_ex_data();
392 CRYPTO_mem_leaks(NULL);
393 CONF_modules_unload(1);
397 fprintf(stderr,
"*** davDestroy()\n");
400 static void davProgress(
void * userdata, off_t progress, off_t total)
408 assert(sess != NULL);
410 assert(u == ne_get_session_private(sess,
"urlinfo"));
417 fprintf(stderr,
"*** davProgress(%p,0x%x:0x%x) sess %p u %p\n", userdata, (
unsigned int)progress, (
unsigned int)total, sess, u);
420 #if WITH_NEON_MIN_VERSION >= 0x002700
421 static void davNotify(
void * userdata,
422 ne_session_status status,
const ne_session_status_info *info)
424 static void davNotify(
void * userdata,
425 ne_conn_status status,
const char * info)
435 assert(sess != NULL);
437 assert(u == ne_get_session_private(sess,
"urlinfo"));
445 #if WITH_NEON_MIN_VERSION >= 0x002700
448 ne_status_lookup = 0,
449 ne_status_connecting,
453 ne_status_disconnected
459 case ne_status_lookup:
462 case ne_status_connecting:
464 (void) ne_iaddr_print(info->ci.address, buf,
sizeof(buf));
465 buf[
sizeof(buf)-1] =
'\0';
468 case ne_status_connected:
471 case ne_status_sending:
475 case ne_status_recving:
479 case ne_status_disconnected:
485 (void) (*u->
notify) (u, status);
499 static const char * connstates[] = {
507 fprintf(stderr,
"*** davNotify(%p,%d,%p) sess %p u %p %s\n", userdata, status, info, sess, u, connstates[ (status < 4 ? status : 4)]);
518 static void davCreateRequest(ne_request * req,
void * userdata,
519 const char * method,
const char * uri)
524 void *
private = NULL;
525 const char *
id =
"urlinfo";
528 assert(u->
sess != NULL);
530 sess = ne_get_session(req);
531 assert(sess == u->
sess);
533 assert(u == ne_get_session_private(sess,
"urlinfo"));
536 assert(sess != NULL);
537 private = ne_get_session_private(sess,
id);
538 assert(u ==
private);
541 fprintf(stderr,
"*** davCreateRequest(%p,%p,%s,%s) %s:%p\n", req, userdata, method, uri,
id,
private);
544 static void davPreSend(ne_request * req,
void * userdata, ne_buffer * buf)
548 const char *
id =
"fd";
553 assert(u->
sess != NULL);
555 sess = ne_get_session(req);
556 assert(sess == u->
sess);
558 assert(u == ne_get_session_private(sess,
"urlinfo"));
561 fd = ne_get_request_private(req,
id);
565 fprintf(stderr,
"*** davPreSend(%p,%p,%p) sess %p %s %p\n", req, userdata, buf, sess,
id, fd);
567 fprintf(stderr,
"-> %s\n", buf->data);
571 static int davPostSend(ne_request * req,
void * userdata,
const ne_status * status)
576 const char *
id =
"fd";
580 assert(u->
sess != NULL);
582 sess = ne_get_session(req);
583 assert(sess == u->
sess);
585 assert(u == ne_get_session_private(sess,
"urlinfo"));
588 fd = ne_get_request_private(req,
id);
592 fprintf(stderr,
"*** davPostSend(%p,%p,%p) sess %p %s %p %s\n", req, userdata, status, sess,
id, fd, ne_get_error(sess));
597 static void davDestroyRequest(ne_request * req,
void * userdata)
602 const char *
id =
"fd";
606 assert(u->
sess != NULL);
608 sess = ne_get_session(req);
609 assert(sess == u->
sess);
611 assert(u == ne_get_session_private(sess,
"urlinfo"));
614 fd = ne_get_request_private(req,
id);
617 fprintf(stderr,
"*** davDestroyRequest(%p,%p) sess %p %s %p\n", req, userdata, sess,
id, fd);
620 static void davDestroySession(
void * userdata)
625 void *
private = NULL;
626 const char *
id =
"urlinfo";
629 assert(u->
sess != NULL);
632 assert(u == ne_get_session_private(sess,
"urlinfo"));
635 assert(sess != NULL);
636 private = ne_get_session_private(sess,
id);
637 assert(u ==
private);
640 fprintf(stderr,
"*** davDestroySession(%p) sess %p %s %p\n", userdata, sess,
id,
private);
644 davVerifyCert(
void *userdata,
int failures,
const ne_ssl_certificate *cert)
647 const char *hostname = userdata;
650 fprintf(stderr,
"*** davVerifyCert(%p,%d,%p) %s\n", userdata, failures, cert, hostname);
655 static int davConnect(
urlinfo u)
659 const char * path = NULL;
668 if (path == NULL || *path ==
'\0')
673 if (path != NULL && path[strlen(path)-1] ==
'/')
699 if (cap->dav_executable)
706 if (!strncmp(
"501 ", ne_get_error(u->
sess),
sizeof(
"501 ")-1)) {
712 if (!strncmp(
"301 ", ne_get_error(u->
sess),
sizeof(
"301 ")-1))
716 if (!strncmp(
"302 ", ne_get_error(u->
sess),
sizeof(
"302 ")-1)) {
718 if ((t = strchr(u->
url,
'\0')) != NULL)
733 fprintf(stderr,
"*** Connect to %s:%d failed(%d):\n\t%s\n",
745 static int davInit(
const char * url,
urlinfo * uret)
757 if (u->
url != NULL && u->
sess == NULL)
765 { ne_server_capabilities * capabilities;
770 ne_debug_init(stderr, rc);
785 {
const ne_inet_addr ** addrs;
787 ne_set_addrlist(u->
sess, addrs, n);
791 ne_set_progress(u->
sess, davProgress, u);
792 #if WITH_NEON_MIN_VERSION >= 0x002700
793 ne_set_notifier(u->
sess, davNotify, u);
795 ne_set_status(u->
sess, davNotify, u);
798 #if WITH_NEON_MIN_VERSION >= 0x002600
804 ne_set_useragent(u->
sess,
808 if (!strcasecmp(u->
scheme,
"https"))
809 ne_ssl_set_verify(u->
sess, davVerifyCert, (
char *)u->
host);
811 ne_set_session_private(u->
sess,
"urlinfo", u);
813 ne_hook_destroy_session(u->
sess, davDestroySession, u);
815 ne_hook_create_request(u->
sess, davCreateRequest, u);
816 ne_hook_pre_send(u->
sess, davPreSend, u);
817 ne_hook_post_send(u->
sess, davPostSend, u);
818 ne_hook_destroy_request(u->
sess, davDestroyRequest, u);
830 u =
urlFree(u,
"urlSplit (davInit)");
843 struct fetch_resource_s {
845 struct fetch_resource_s *next;
849 enum fetch_rtype_e type;
859 static void *fetch_destroy_item(
struct fetch_resource_s *res)
863 ne_free(res->error_reason);
870 static void *fetch_destroy_list(
struct fetch_resource_s *res)
873 struct fetch_resource_s *next;
874 for (; res != NULL; res = next) {
876 res = fetch_destroy_item(res);
882 #if WITH_NEON_MIN_VERSION >= 0x002600
883 static void *fetch_create_item(
void *userdata,
const ne_uri *uri)
885 static void *fetch_create_item(
void *userdata,
const char *uri)
889 struct fetch_resource_s * res = ne_calloc(
sizeof(*res));
897 static const ne_propname fetch_props[] = {
898 {
"DAV:",
"getcontentlength" },
899 {
"DAV:",
"getlastmodified" },
900 {
"http://apache.org/dav/props/",
"executable" },
901 {
"DAV:",
"resourcetype" },
902 {
"DAV:",
"checked-in" },
903 {
"DAV:",
"checked-out" },
908 #define ELM_resourcetype (NE_PROPS_STATE_TOP + 1)
909 #define ELM_collection (NE_PROPS_STATE_TOP + 2)
913 static const struct ne_xml_idmap fetch_idmap[] = {
914 {
"DAV:",
"resourcetype", ELM_resourcetype },
915 {
"DAV:",
"collection", ELM_collection }
919 static int fetch_startelm(
void *userdata,
int parent,
920 const char *nspace,
const char *
name,
924 ne_propfind_handler *pfh = userdata;
925 struct fetch_resource_s *r = ne_propfind_current_private(pfh);
927 int state = ne_xml_mapid(fetch_idmap, NE_XML_MAPLEN(fetch_idmap),
932 !((parent == NE_207_STATE_PROP && state == ELM_resourcetype) ||
933 (parent == ELM_resourcetype && state == ELM_collection)))
934 return NE_XML_DECLINE;
936 if (state == ELM_collection) {
937 r->type = resr_collection;
943 static int fetch_compare(
const struct fetch_resource_s *r1,
944 const struct fetch_resource_s *r2)
948 if (r1->type == resr_error) {
950 }
else if (r2->type == resr_error) {
952 }
else if (r1->type == resr_collection) {
953 if (r2->type != resr_collection) {
956 return strcmp(r1->uri, r2->uri);
959 if (r2->type != resr_collection) {
960 return strcmp(r1->uri, r2->uri);
967 #if WITH_NEON_MIN_VERSION >= 0x002600
968 static void fetch_results(
void *userdata,
const ne_uri *uarg,
969 const ne_prop_result_set *
set)
971 static void fetch_results(
void *userdata,
void *uarg,
972 const ne_prop_result_set *
set)
976 avContext ctx = userdata;
977 struct fetch_resource_s *
current, *previous, *newres;
978 const char *clength, *modtime, *isexec;
979 const char *checkin, *checkout;
980 const ne_status *status = NULL;
981 const char * path = NULL;
983 #if WITH_NEON_MIN_VERSION >= 0x002600
984 const ne_uri * uri = uarg;
985 (void)
urlPath(uri->path, &path);
987 const char * uri = uarg;
993 newres = ne_propset_private(
set);
996 fprintf(stderr,
"==> %s in uri %s\n", path, ctx->uri);
998 if (ne_path_compare(ctx->uri, path) == 0) {
1001 fprintf(stderr,
"==> %s skipping target resource.\n", path);
1009 newres->uri = ne_strdup(path);
1011 clength = ne_propset_value(
set, &fetch_props[0]);
1012 modtime = ne_propset_value(
set, &fetch_props[1]);
1013 isexec = ne_propset_value(
set, &fetch_props[2]);
1014 checkin = ne_propset_value(
set, &fetch_props[4]);
1015 checkout = ne_propset_value(
set, &fetch_props[5]);
1017 if (clength == NULL)
1018 status = ne_propset_status(
set, &fetch_props[0]);
1019 if (modtime == NULL)
1020 status = ne_propset_status(
set, &fetch_props[1]);
1022 if (newres->type == resr_normal && status != NULL) {
1024 newres->error_status = status->code;
1027 if (strcmp(status->reason_phrase,
"status text goes here") == 0) {
1029 if (status->code == 401) {
1030 desc =
_(
"Authorization Required");
1031 }
else if (status->klass == 3) {
1032 desc =
_(
"Redirect");
1033 }
else if (status->klass == 5) {
1034 desc =
_(
"Server Error");
1036 desc =
_(
"Unknown Error");
1038 newres->error_reason = ne_strdup(desc);
1040 newres->error_reason = ne_strdup(status->reason_phrase);
1042 newres->type = resr_error;
1045 if (isexec && strcasecmp(isexec,
"T") == 0) {
1046 newres->is_executable = 1;
1048 newres->is_executable = 0;
1052 newres->modtime = ne_httpdate_parse(modtime);
1055 newres->size = atoi(clength);
1060 }
else if (checkout) {
1066 current = *(
struct fetch_resource_s **)ctx->resrock;
1067 for (current = *ctx->resrock, previous = NULL; current != NULL;
1068 previous = current, current = current->next)
1070 if (fetch_compare(current, newres) >= 0) {
1075 previous->next = newres;
1078 *(
struct fetch_resource_s **)ctx->resrock = newres;
1084 static int davFetch(
const urlinfo u, avContext ctx)
1088 const char * path = NULL;
1090 struct fetch_resource_s * resitem = NULL;
1091 ne_propfind_handler *pfh;
1092 struct fetch_resource_s *
current, *next;
1098 pfh = ne_propfind_create(u->
sess, ctx->uri, depth);
1102 ctx->resrock = (
void **) &resitem;
1104 ne_xml_push_handler(ne_propfind_get_parser(pfh),
1105 fetch_startelm, NULL, NULL, pfh);
1107 ne_propfind_set_private(pfh, fetch_create_item, NULL);
1109 rc = ne_propfind_named(pfh, fetch_props, fetch_results, ctx);
1111 ne_propfind_destroy(pfh);
1113 for (current = resitem; current != NULL; current = next) {
1117 next = current->next;
1121 se = current->uri + strlen(current->uri);
1122 if (se[-1] ==
'/') {
1123 if (strlen(current->uri) <= strlen(path)) {
1124 current = fetch_destroy_item(current);
1130 while (s > current->uri && s[-1] !=
'/')
1133 val = ne_strndup(s, (se - s));
1136 val = ne_path_unescape(val);
1139 switch (current->type) {
1143 case resr_collection:
1146 case resr_reference:
1153 xx =
avContextAdd(ctx, val, st_mode, current->size, current->modtime);
1156 current = fetch_destroy_item(current);
1158 ctx->resrock = NULL;
1165 static int davHEAD(
urlinfo u,
struct stat *st)
1169 const ne_status *status = NULL;
1171 const char *value = NULL;
1176 {
size_t nb = strlen(u->
url);
1177 st->st_mode = (u->
url[nb-1] ==
'/' ? S_IFDIR : S_IFREG);
1179 st->st_blksize = 4 * 1024;
1185 req = ne_request_create(u->
sess,
"HEAD", u->
url);
1191 rc = ne_request_dispatch(req);
1192 status = ne_get_status(req);
1196 fprintf(stderr,
"HTTP request sent, awaiting response... %d %s\n", status->code, status->reason_phrase);
1204 if (status->klass != 2)
1209 #if defined(HAVE_NEON_NE_GET_RESPONSE_HEADER)
1211 value = ne_get_response_header(req, htag);
1220 value = ne_get_response_header(req, htag);
1226 htag =
"Content-Length";
1227 value = ne_get_response_header(req, htag);
1231 fprintf(stderr,
"Length: %s", value);
1234 st->st_size = strtoll(value, NULL, 10);
1236 st->st_blocks = (st->st_size + 511)/512;
1239 htag =
"Content-Type";
1240 value = ne_get_response_header(req, htag);
1243 fprintf(stderr,
" [%s]", value);
1244 if (!strcmp(value,
"text/html")
1245 || !strcmp(value,
"application/xhtml+xml"))
1246 st->st_blksize = 2 * 1024;
1249 htag =
"Last-Modified";
1250 value = ne_get_response_header(req, htag);
1253 fprintf(stderr,
" [%s]", value);
1254 st->st_mtime = ne_httpdate_parse(value);
1255 st->st_atime = st->st_ctime = st->st_mtime;
1259 fprintf(stderr,
"\n");
1263 ne_request_destroy(req);
1267 static int my_result(
const char * msg,
int ret, FILE * fp)
1276 fprintf(fp,
"*** %s: ", msg);
1280 fprintf(fp,
"%s: %s\n",
ftpStrerror(-ret), ne_get_error(sess));
1290 typedef struct rpmhtml_s * rpmhtml;
1300 const char * pattern;
1315 rpmhtml htmlFree( rpmhtml html)
1319 if (html->req != NULL) {
1320 ne_request_destroy(html->req);
1323 html->buf =
_free(html->buf);
1333 rpmhtml htmlNew(
urlinfo u, avContext ctx)
1336 rpmhtml html =
xcalloc(1,
sizeof(*html));
1338 html->nbuf = BUFSIZ;
1339 html->buf =
xmalloc(html->nbuf + 1 + 1);
1340 html->req = ne_request_create(u->
sess,
"GET", u->
url);
1346 static ssize_t htmlFill(rpmhtml html)
1349 char * b = html->buf;
1350 size_t nb = html->nbuf;
1354 fprintf(stderr,
"*** htmlFill(%p) %p[%u]\n", html, b, (
unsigned)nb);
1355 if (html->b != NULL && html->nb > 0 && html->b > html->buf) {
1356 memmove(html->buf, html->b, html->nb);
1362 rc = ne_read_response_block(html->req, b, nb) ;
1365 html->b = html->buf;
1376 unsigned char nibble(
char c)
1379 if (c >=
'0' && c <=
'9')
1380 return (
unsigned char) (c -
'0');
1381 if (c >=
'A' && c <=
'F')
1382 return (
unsigned char)((int)(c -
'A') + 10);
1383 if (c >=
'a' && c <=
'f')
1384 return (
unsigned char)((int)(c -
'a') + 10);
1385 return (
unsigned char)
'\0';
1389 static const char * hrefpat =
"(?i)<a(?:\\s+[a-z][a-z0-9_]*(?:=(?:\"[^\"]*\"|\\S+))?)*?\\s+href=(?:\"([^\"]*)\"|(\\S+))";
1393 static int htmlParse(rpmhtml html)
1400 ssize_t nr = (html->b != NULL ? (ssize_t)html->nb : htmlFill(html));
1405 fprintf(stderr,
"*** htmlParse(%p) %p[%u]\n", html, html->buf, (
unsigned)html->nbuf);
1406 html->pattern = hrefpat;
1412 while (html->nb > 0) {
1414 const char * hbn, * lpath;
1424 assert(html->b != NULL);
1425 offsets[0] = offsets[1] = -1;
1427 if (xx == 0 && offsets[0] != -1 && offsets[1] != -1) {
1430 f = html->b + offsets[0];
1431 fe = html->b + offsets[1];
1434 if (he[-1] ==
'"') he--;
1436 while (h > f && h[-1] !=
'"')
1439 nh = (size_t)(he - h);
1440 href = t =
xmalloc(nh + 1 + 1);
1447 if (isxdigit((
int)h[0]) && isxdigit((
int)h[1])) {
1458 switch ((ut =
urlPath(href, &lpath))) {
1462 if (href[nh-1] ==
'/') {
1463 st_mode = S_IFDIR | 0755;
1466 st_mode = S_IFREG | 0644;
1472 st_mode = S_IFLNK | 0755;
1481 if ((hbn = strrchr(href,
'/')) != NULL)
1485 assert(hbn != NULL);
1495 ng = (size_t)(ge - g);
1496 gbn = t =
xmalloc(ng + 1 + 1);
1497 while (g < ge && *g !=
'/')
1502 if (*hbn !=
'\0' && *gbn !=
'\0' && strcasecmp(hbn, gbn))
1503 fprintf(stderr,
"\t[%s] != [%s]\n", hbn, gbn);
1513 if (*hbn !=
'\0' && *gbn !=
'\0')
1514 if (strcmp(hbn,
".") && strcmp(hbn,
".."))
1515 if (!strcasecmp(hbn, gbn)) {
1516 size_t _st_size = (size_t)0;
1517 time_t _st_mtime = (time_t)0;
1518 xx =
avContextAdd(html->ctx, gbn, st_mode, _st_size, _st_mtime);
1524 offsets[1] += (ge - fe);
1525 html->b += offsets[1];
1526 html->nb -= offsets[1];
1528 size_t nb = html->nb;
1529 if (nr > 0) nb -= 128;
1535 nr = htmlFill(html);
1540 html->mires =
mireFreeAll(html->mires, html->nmires);
1544 fprintf(stderr,
"*** htmlParse(%p) rc %d\n", html, rc);
1550 static int htmlNLST(
urlinfo u, avContext ctx)
1554 rpmhtml html = htmlNew(u, ctx);
1558 fprintf(stderr,
"*** htmlNLST(%p, %p) html %p\n", u, ctx, html);
1561 rc = ne_begin_request(html->req);
1562 rc = my_result(
"ne_begin_req(html->req)", rc, NULL);
1563 if (rc != NE_OK)
goto exit;
1565 (void) htmlParse(html);
1567 rc = ne_end_request(html->req);
1568 rc = my_result(
"ne_end_req(html->req)", rc, NULL);
1569 }
while (rc == NE_RETRY);
1572 html = htmlFree(html);
1577 static int davNLST(avContext ctx)
1586 rc = davInit(ctx->uri, &u);
1587 if (rc || u == NULL)
1596 rc = davFetch(u, ctx);
1599 rc = davHEAD(u, ctx->st);
1602 if (rc == NE_OK && S_ISDIR(ctx->st->st_mode))
1603 rc = htmlNLST(u, ctx);
1615 if (!strncmp(
"301 ", ne_get_error(u->
sess),
sizeof(
"301 ")-1))
1619 if (!strncmp(
"302 ", ne_get_error(u->
sess),
sizeof(
"302 ")-1)) {
1620 const char * path = NULL;
1622 size_t nb = strlen(path);
1627 char * te = strchr(u->
url,
'\0');
1629 if (te != NULL && te[-1] !=
'/') {
1645 fprintf(stderr,
"*** Fetch from %s:%d failed:\n\t%s\n",
1658 static void davAcceptRanges(
void * userdata,
const char * value)
1663 if (!(u != NULL && value != NULL))
return;
1665 fprintf(stderr,
"*** u %p Accept-Ranges: %s\n", u, value);
1666 if (!strcmp(value,
"bytes"))
1668 if (!strcmp(value,
"none"))
1673 #if !defined(HAVE_NEON_NE_GET_RESPONSE_HEADER)
1674 static void davAllHeaders(
void * userdata,
const char * value)
1676 FD_t ctrl = userdata;
1678 if (!(ctrl != NULL && value != NULL))
return;
1680 fprintf(stderr,
"<- %s\n", value);
1685 static void davContentLength(
void * userdata,
const char * value)
1688 FD_t ctrl = userdata;
1690 if (!(ctrl != NULL && value != NULL))
return;
1692 fprintf(stderr,
"*** fd %p Content-Length: %s\n", ctrl, value);
1700 static void davContentType(
void * userdata,
const char * value)
1703 FD_t ctrl = userdata;
1705 if (!(ctrl != NULL && value != NULL))
return;
1707 fprintf(stderr,
"*** fd %p Content-Type: %s\n", ctrl, value);
1714 static void davContentDisposition(
void * userdata,
const char * value)
1717 FD_t ctrl = userdata;
1719 if (!(ctrl != NULL && value != NULL))
return;
1721 fprintf(stderr,
"*** fd %p Content-Disposition: %s\n", ctrl, value);
1728 static void davLastModified(
void * userdata,
const char * value)
1731 FD_t ctrl = userdata;
1733 if (!(ctrl != NULL && value != NULL))
return;
1735 fprintf(stderr,
"*** fd %p Last-Modified: %s\n", ctrl, value);
1743 static void davConnection(
void * userdata,
const char * value)
1746 FD_t ctrl = userdata;
1748 if (!(ctrl != NULL && value != NULL))
return;
1750 fprintf(stderr,
"*** fd %p Connection: %s\n", ctrl, value);
1751 if (!strcasecmp(value,
"close"))
1753 else if (!strcasecmp(value,
"Keep-Alive"))
1763 rc = ne_begin_request(ctrl->
req);
1764 rc = my_result(
"ne_begin_req(ctrl->req)", rc, NULL);
1767 fprintf(stderr,
"*** davResp(%p,%p,%p) sess %p req %p rc %d\n", u, ctrl, str, u->
sess, ctrl->
req, rc);
1779 int davReq(
FD_t ctrl,
const char * httpCmd,
const char * httpArg)
1784 assert(ctrl != NULL);
1789 fprintf(stderr,
"*** davReq(%p,%s,\"%s\") entry sess %p req %p\n", ctrl, httpCmd, (httpArg ? httpArg :
""), u->
sess, ctrl->
req);
1792 ctrl =
fdLink(ctrl,
"open ctrl (davReq)");
1793 assert(ctrl != NULL);
1795 assert(u->
sess != NULL);
1797 if (ctrl->
req == (
void *)-1)
1800 assert(ctrl->
req == NULL);
1803 ctrl->
req = ne_request_create(u->
sess, httpCmd, httpArg);
1805 assert(ctrl->
req != NULL);
1807 ne_set_request_private(ctrl->
req,
"fd", ctrl);
1809 #if !defined(HAVE_NEON_NE_GET_RESPONSE_HEADER)
1810 ne_add_response_header_catcher(ctrl->
req, davAllHeaders, ctrl);
1812 ne_add_response_header_handler(ctrl->
req,
"Content-Length",
1813 davContentLength, ctrl);
1814 ne_add_response_header_handler(ctrl->
req,
"Content-Type",
1815 davContentType, ctrl);
1816 ne_add_response_header_handler(ctrl->
req,
"Content-Disposition",
1817 davContentDisposition, ctrl);
1818 ne_add_response_header_handler(ctrl->
req,
"Last-Modified",
1819 davLastModified, ctrl);
1820 ne_add_response_header_handler(ctrl->
req,
"Connection",
1821 davConnection, ctrl);
1824 if (!strcmp(httpCmd,
"PUT")) {
1825 #if defined(HAVE_NEON_NE_SEND_REQUEST_CHUNK)
1827 ne_add_request_header(ctrl->
req,
"Transfer-Encoding",
"chunked");
1828 ne_set_request_chunked(ctrl->
req, 1);
1836 #if !defined(HAVE_NEON_NE_GET_RESPONSE_HEADER)
1837 ne_add_response_header_handler(ctrl->
req,
"Accept-Ranges",
1838 davAcceptRanges, u);
1847 }
while (rc == NE_RETRY);
1852 const ne_status *status = ne_get_status(ctrl->
req);
1853 fprintf(stderr,
"HTTP request sent, awaiting response... %d %s\n", status->code, status->reason_phrase);
1860 fprintf(stderr,
"*** davReq(%p,%s,\"%s\") exit sess %p req %p rc %d\n", ctrl, httpCmd, (httpArg ? httpArg :
""), u->
sess, ctrl->
req, rc);
1862 #if defined(HAVE_NEON_NE_GET_RESPONSE_HEADER)
1863 davContentLength(ctrl,
1864 ne_get_response_header(ctrl->
req,
"Content-Length"));
1865 davContentType(ctrl,
1866 ne_get_response_header(ctrl->
req,
"Content-Type"));
1867 davContentDisposition(ctrl,
1868 ne_get_response_header(ctrl->
req,
"Content-Disposition"));
1869 davLastModified(ctrl,
1870 ne_get_response_header(ctrl->
req,
"Last-Modified"));
1872 ne_get_response_header(ctrl->
req,
"Connection"));
1873 if (strcmp(httpCmd,
"PUT"))
1875 ne_get_response_header(ctrl->
req,
"Accept-Ranges"));
1878 ctrl =
fdLink(ctrl,
"open data (davReq)");
1887 ctrl =
fdLink(ctrl,
"error data (davReq)");
1895 const char * path = NULL;
1902 assert(!(flags & O_RDWR));
1906 fprintf(stderr,
"*** davOpen(%s,0x%x,0%o,%p)\n", url, flags, (
unsigned)mode, uret);
1907 rc = davInit(url, &u);
1908 if (rc || u == NULL || u->
sess == NULL)
1911 if (u->
ctrl == NULL)
1912 u->
ctrl =
fdNew(
"persist ctrl (davOpen)");
1916 if (yarnPeekLock(use) > 2
L && u->
data == NULL)
1917 u->
data =
fdNew(
"persist data (davOpen)");
1922 fd = u->
ctrl =
fdLink(u->
ctrl,
"grab ctrl (davOpen persist ctrl)");
1923 else if (u->
data->
url == NULL)
1924 fd = u->
data =
fdLink(u->
data,
"grab ctrl (davOpen persist data)");
1926 fd =
fdNew(
"grab ctrl (davOpen)");
1938 fd =
fdLink(fd,
"grab data (davOpen)");
1950 ssize_t
davRead(
void * cookie,
char * buf,
size_t count)
1955 #if WITH_NEON_MIN_VERSION >= 0x002700
1959 rc = ne_read_response_block(fd->
req, buf, count);
1962 if (u->
info.
status == ne_status_disconnected) {
1964 xx = ne_end_request(fd->
req);
1965 xx = my_result(
"davRead: ne_end_request(req)", xx, NULL);
1966 ne_request_destroy(fd->
req);
1967 fd->
req = (
void *)-1;
1972 u =
urlFree(u,
"url (davRead)");
1975 rc = ne_read_response_block(fd->
req, buf, count);
1979 fprintf(stderr,
"*** davRead(%p,%p,0x%x) rc 0x%x\n", cookie, buf, (
unsigned)count, (
unsigned)rc);
1986 ssize_t
davWrite(
void * cookie,
const char * buf,
size_t count)
1988 #if !defined(NEONBLOWSCHUNKS) || defined(HAVE_NEON_NE_SEND_REQUEST_CHUNK) || defined(__LCLINT__)
1994 #if !defined(NEONBLOWSCHUNKS)
1997 assert(fd->
req != NULL);
1998 sess = ne_get_session(fd->
req);
1999 assert(sess != NULL);
2002 xx = ne_sock_fullwrite(sess->socket, buf, count);
2004 #if defined(HAVE_NEON_NE_SEND_REQUEST_CHUNK) || defined(__LCLINT__)
2005 assert(fd->
req != NULL);
2007 xx = ne_send_request_chunk(fd->
req, buf, count);
2016 rc = (xx == 0 ? (ssize_t)count : -1);
2019 fprintf(stderr,
"*** davWrite(%p,%p,0x%x) rc 0x%x\n", cookie, buf, (
unsigned)count, (
unsigned)rc);
2027 fprintf(stderr,
"*** davSeek(%p,pos,%d)\n", cookie, whence);
2039 assert(fd->
req != NULL);
2040 if (fd->
req != (
void *)-1) {
2041 rc = ne_end_request(fd->
req);
2042 rc = my_result(
"ne_end_request(req)", rc, NULL);
2044 ne_request_destroy(fd->
req);
2049 fprintf(stderr,
"*** davClose(%p) rc %d\n", fd, rc);
2055 int davMkdir(
const char * path, mode_t mode)
2058 const char * src = NULL;
2061 rc = davInit(path, &u);
2068 rc = ne_mkcol(u->
sess, path);
2076 fprintf(stderr,
"*** davMkdir(%s,0%o) rc %d\n", path, (
unsigned)mode, rc);
2083 const char * src = NULL;
2086 rc = davInit(path, &u);
2095 rc = ne_delete(u->
sess, path);
2101 fprintf(stderr,
"*** davRmdir(%s) rc %d\n", path, rc);
2105 int davRename(
const char * oldpath,
const char * newpath)
2108 const char * src = NULL;
2109 const char * dst = NULL;
2113 rc = davInit(oldpath, &u);
2118 (void)
urlPath(oldpath, &src);
2119 (void)
urlPath(newpath, &dst);
2123 rc = ne_move(u->
sess, overwrite, src, dst);
2129 fprintf(stderr,
"*** davRename(%s,%s) rc %d\n", oldpath, newpath, rc);
2136 const char * src = NULL;
2139 rc = davInit(path, &u);
2148 rc = ne_delete(u->
sess, src);
2154 fprintf(stderr,
"*** davUnlink(%s) rc %d\n", path, rc);
2159 static int davChdir(
const char * path)
2163 return davCommand(
"CWD", path, NULL);
2169 static const char *
statstr(
const struct stat * st,
2174 "*** dev %x ino %x mode %0o nlink %d uid %d gid %d rdev %x size %x\n",
2175 (
unsigned)st->st_dev,
2176 (
unsigned)st->st_ino,
2177 (
unsigned)st->st_mode,
2178 (
unsigned)st->st_nlink,
2179 (
unsigned)st->st_uid,
2180 (
unsigned)st->st_gid,
2181 (
unsigned)st->st_rdev,
2182 (
unsigned)st->st_size);
2186 int davStat(
const char * path,
struct stat *st)
2190 avContext ctx = NULL;
2194 if (path == NULL || *path ==
'\0') {
2209 if (st->st_mode == 0)
2210 st->st_mode = (ctx->ac > 1 ? S_IFDIR : S_IFREG);
2211 st->st_size = (ctx->sizes ? ctx->sizes[0] : (size_t)st->st_size);
2212 st->st_mtime = (ctx->mtimes ? ctx->mtimes[0] : st->st_mtime);
2213 st->st_atime = st->st_ctime = st->st_mtime;
2214 if (S_ISDIR(st->st_mode)) {
2216 st->st_mode |= 0755;
2218 if (S_ISREG(st->st_mode)) {
2220 st->st_mode |= 0644;
2225 if (st->st_ino == 0)
2230 fprintf(stderr,
"*** davStat(%s) rc %d\n%s", path, rc,
statstr(st, buf));
2235 int davLstat(
const char * path,
struct stat *st)
2239 avContext ctx = NULL;
2243 if (path == NULL || *path ==
'\0') {
2258 if (st->st_mode == 0)
2259 st->st_mode = (ctx->ac > 1 ? S_IFDIR : S_IFREG);
2260 st->st_size = (ctx->sizes ? ctx->sizes[0] : (size_t)st->st_size);
2261 st->st_mtime = (ctx->mtimes ? ctx->mtimes[0] : st->st_mtime);
2262 st->st_atime = st->st_ctime = st->st_mtime;
2263 if (S_ISDIR(st->st_mode)) {
2265 st->st_mode |= 0755;
2267 if (S_ISREG(st->st_mode)) {
2269 st->st_mode |= 0644;
2274 if (st->st_ino == 0)
2278 fprintf(stderr,
"*** davLstat(%s) rc %d\n%s\n", path, rc,
statstr(st, buf));
2285 static int davReadlink(
const char * path,
char * buf,
size_t bufsiz)
2292 fprintf(stderr,
"*** davReadlink(%s) rc %d\n", path, rc);
2314 assert(!(flags & O_RDWR));
2319 if (u->
ctrl == NULL)
2320 u->
ctrl =
fdNew(
"persist ctrl (httpOpen)");
2321 if (u->
ctrl != NULL) {
2324 if (yarnPeekLock(use) > 2
L && u->
data == NULL)
2325 u->
data =
fdNew(
"persist data (httpOpen)");
2330 fd =
fdLink(u->
ctrl,
"grab ctrl (httpOpen persist ctrl)");
2331 else if (u->
data->
url == NULL)
2332 fd =
fdLink(u->
data,
"grab ctrl (httpOpen persist data)");
2334 fd =
fdNew(
"grab ctrl (httpOpen)");
2342 fd =
fdLink(fd,
"grab data (httpOpen)");
2372 avContext ctx = NULL;
2373 struct stat sb, *st = &sb;
2374 const char * uri = NULL;
2378 fprintf(stderr,
"*** davOpendir(%s)\n", path);
2380 if (path == NULL || *path ==
'\0') {
2387 if (path[strlen(path)-1] !=
'/')
2412 return (DIR *) avdir;
2418 char *
davRealpath(
const char * path,
char * resolved_path)
2420 assert(resolved_path == NULL);