⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cmds.c

📁 P2P NAP的C实现 P2P在网络应用中越来越流行
💻 C
📖 第 1 页 / 共 5 页
字号:
  path = getval("download");  if (*suffix && path) {    path = getval("incomplete");    /* if no incomplete path given, use CWD, not HOME */    if (path) {      path = home_file(path);    } else {      path = strdup(".");    }    r = move_to_dir(win, task, path, &lfn);    free(path);    if (r==-1) {      free(lfn);      lfn = strdup(task->lfn);    }  } else {    lfn = strdup(task->lfn);  }  wp(win, "* Download saved as \"%s\".\n", lfn);  drw(win);  free(lfn);    return;}/* add some information to an incomplete file, so that we can later do   a proper "resume" on that file (if that is ever implemented). The   idea is to append to the end of the file one or several MD5 hashes.   If a remote client's (valid) MD5 hash was reported by the server,   we add that. If the file is long enough to calculate our own MD5   hashes, then we add them too - two of them in fact, a hash of the   first 299008 bytes, and one of the first 300032 bytes, since it is   unclear which one a remote client is going to be using. (We add   these hashes so that we don't have to do it each time we are   looking for a match for a potential resume. Task is still   IN_PROGRESS. *//* some care needs to be taken because most OpenNap servers do not   send valid hashes; rather they send the string 0000...(32 times) as   the "checksum". Of course one should not base a resume on such a   hash. *//* In the future, when downloading a file, we will check if any of the   hashes in the incomplete directory match, and if so, treat it as a   resume, if not, not. In the far future, we'll also be able to   request a resume for a specific incomplete file and (gasp) maybe   even have an autoresume command. */void mark_incomplete(WINDOW *win, download_t *task) {  mhdr_t *m;  itag_t itag;  int i;  itag.n = 0;  itag.fn = task->fn;  if (task->pos >= 300032) {    /* we have a chance to calculate a valid md5 ourselves. */    m = filestats(task->lfn);    if (m) {      if (m->sz1 >= 300032) {	itag.hash[itag.n] = strdup(m->check);	itag.n++;      }      free(m);    }  }  if (task->check && strncmp(task->check, "00000000", 8)) {    /* have a valid checksum from remote client */    itag.hash[itag.n] = strdup(task->check);    itag.n++;  }  if (itag.n > 0) {    tagincompletefile(task->lfn, &itag);  }  for (i=0; i<itag.n; i++) {    free(itag.hash[i]);  }}/* attach an "incomplete tag" at the end of a file. The content of the * incomplete tag is that of the itag_s structure, minus the "lfn" and * "next" fields. The point is to attach one or several md5 checksums * to incomplete files, for convenient reference when resuming later. * * The format of the tag is: INCTAG_START size n 0 hash1 [ 0 hash2 [ 0 * hash3 ]] 0 fn 0 n size INCTAG_END, where INCTAG_START and * INCTAG_END are defined in defines.h, and size is a 4-byte unsigned * integer in big-endian byte order equal to the size of the entire * tag. n is the number of hashes represented, as a single byte.  Note * that strings are terminated by 0 on both ends, and we give the size * and n twice; this way, the tag is conveniently scannable both * forward and backward. **/void tagincompletefile(char *fn, itag_t *itag) {  int size;  char sz[4];  FILE *f;  int i;  size = 12 + strlen(INCTAG_START) + strlen(INCTAG_END) + strlen(itag->fn);  for (i=0; i<itag->n; i++) {    size += 1 + strlen(itag->hash[i]);  }  sz[0] = (size >> 24) & 0xff;  sz[1] = (size >> 16) & 0xff;  sz[2] = (size >> 8) & 0xff;  sz[3] = (size >> 0) & 0xff;    f = fopen(fn, "ab");  if (!f) {    return;  /* fail silently, since there is not much we can do */  }  fputs(INCTAG_START, f);  fwrite(sz, 4, 1, f);  fputc(itag->n, f);  for (i=0; i<itag->n; i++) {    fputc(0, f);    fputs(itag->hash[i], f);  }  fputc(0, f);  fputs(itag->fn, f);  fputc(0, f);  fputc(itag->n, f);  fwrite(sz, 4, 1, f);  fputs(INCTAG_END, f);   fclose(f);}void adduser(chans_t *c, char *nm, int scount, unsigned char conn){  user_t *cur, *cur1 = NULL;    if (!c)    return;    if (!c->users)  {    c->users = (user_t *)malloc(sizeof(user_t));    cur = c->users;  }  else  {    for (cur=c->users;cur;cur=cur->next)    {      if (!strcasecmp(cur->nm, nm))        return;      cur1 = cur;    }    cur = (user_t *)malloc(sizeof(user_t));    cur1->next = cur;  }    cur->nm = strdup(nm);  cur->addr = NULL;  cur->conn = conn;  cur->scount = scount;  cur->flag = 0;  cur->next = NULL;}/* delete a user from a channel */void deluser(chans_t *c, char *nm){  user_t *cur, *cur1 = NULL;    for (cur=c->users;;cur=cur->next)  {    if (!cur)      return;    if (!strcasecmp(cur->nm, nm))      break;    cur1 = cur;  }    if (cur1)    cur1->next = cur->next;  else if (cur->next)    c->users = cur->next;  else    c->users = NULL;    free(cur->nm);  if (cur->addr)    free(cur->addr);  free(cur);}/* find user in a channel or return NULL if not found */user_t *finduser(chans_t *c, char *nm){  user_t *cur;  if (!nm)    return(NULL);  for (cur=c->users;;cur=cur->next)  {    if (!cur)      return(NULL);    if (!strcasecmp(cur->nm, nm))      return(cur);  }}/* a callback function for timer to run a user command */void timed_command(void *data) {  char *cmd = (char *)data;  int s;  sock_t *sk;    wp(wchan, ""BRIGHT(BLUE)"* Timed event: "WHITE"%s\n", cmd);  drw(wchan);    sk = findsock("server");  s = sk ? sk->fd : -1;  parseout(s, cmd, wchan);}/* find an unused filename based on path/fn/suffix. Return 0 if the   filename was unchanged, >=1 if it was changed. Set *lfn to the new   full filename, and set *newfn to the new short filename. Note: we   do not check whether a file by the given name can actually be   created (directory exists, is writable, etc) - we simply return the   first filename which does not yet exist. */int unused_filename(const char *path, const char *fn, const char *suffix, char **lfn, char **newfn) {  char *fullname = NULL;  char *newname = NULL;  int n;  char *q;  struct stat st;  char *cpath, *base, *suf;  cpath = strdup(path);  if (cpath[strlen(cpath)-1] == '/') {    cpath[strlen(cpath)-1] = 0;  /* cosmetic */  }  base = strdup(fn);  if (suffix && *suffix) {    suf = strdup(suffix);  } else {    q = strrchr(base, '.');    if (q) {      suf = strdup(q);      *q = 0;    } else {      suf = strdup("");    }  }  msprintf(&newname, "%s%s", base, suf);  msprintf(&fullname, "%s/%s", cpath, newname);  n=0;  while (stat(fullname, &st)==0) {    n++;    msprintf(&newname, "%s-%d%s", base, n, suf);    msprintf(&fullname, "%s/%s", cpath, newname);  }  free(cpath);  free(base);  free(suf);  /* success */  if (lfn) {    *lfn = fullname;  } else {    free(fullname);  }  if (newfn) {    *newfn = newname;  } else {    free(newname);  }  return n;}/* Opens a new file, whose name is based on fn, in the incomplete   directory || download directory || cwd.  The file is renamed if a   file of the exact name already exists. Returns the file *f and its   name *lfn. Returns 0 on success, -1 on failure with errno set. In   case -1 is returned, *lfn is also set to the unsuccessful   filename. */int opendownloadfile(char *fn, FILE **f, char **lfn) {  char *path;  int r;  char *suffix = getval("incompletesuffix");  if (!suffix) {    suffix = ".incomplete";  }  path = getval("incomplete");  if (!path) {    path = getval("download");  }  /* if no download path given, use CWD, not HOME */  if (path) {    path = home_file(path);  } else {    path = strdup(".");  }  r = unused_filename(path, fn, suffix, lfn, NULL);  free(path);  *f = fopen(*lfn, "w");  if (!*f)   {    return(-1);  }    return(0);}/* connects to a napigator-style metaserver and sets the "servers"   user variable. Return -1, with *errmsg set, on error. Return   number of servers found on success. */int metaserver(char *url, int timeout, const char **errmsg) {  FILE *f;  char *servers;  int i, cnt;  char **tok;  char *b, *p;  int count;  /* number of servers */  f = open_url(url, timeout, errmsg);  if (!f)    return -1;  servers = strdup("");  count = 0;  /* parse each line of the file */  while ((b = nap_getline(f)) != NULL) {    char *ip = NULL;    char *port = NULL;    /* tokenize line */    tok = form_tokso(b, &cnt);    free(b);    /* check the format of the line just read. */    if (cnt == 7) {      /* If it consists of 7 tokens, it's in the old server list format.	 The first token is the IP address, the second is the port. */      ip = tok[0];      port = tok[1];    }    else if (cnt == 14) {      /* If it consists of 14 tokens, it's in the new server list format;	 the second token is the IP address and the third is the port. */      ip = tok[1];      port = tok[2];    }    else {      goto nextline;    }    for (p=ip; *p; p++) {      if ((*p < '0' || *p > '9') && *p != '.') 	goto nextline;    }    for (p=port; *p; p++) {      if (*p < '0' || *p > '9') 	goto nextline;    }    servers = realloc(servers, strlen(servers)+strlen(ip)+strlen(port)+3);    if (servers[0] != 0)      strcat(servers, ";");    strcat(servers, ip);    strcat(servers, ":");    strcat(servers, port);    count++;      nextline:    for (i=0; i<cnt; i++) {      free(tok[i]);    }    free(tok);  } /* while */  fclose(f);  if (!count) {    *errmsg = "invalid server list";    free(servers);    return -1;  }  chset("servers", servers);  free(servers);  return count;}/* decompose url into host, port, and path. Return 0 on success.   Return allocated strings. Pointers may be NULL, in which case the   corresponding result is not returned. */int decompose_url(const char *url, char **hostp, int *portp, char **pathp) {  char *p;  char *host;  char *path;  int port;  if (strncmp(url, "http://", 7) == 0) {    url += 7;  }  p = strchr(url, '/');  if (!p) {    path = strdup("/");    host = strdup(url);  } else {    path = strdup(p);    host = strdup(url);    host[p-url] = 0;  }  p = strchr(host, ':');  if (p) {    *p = 0;    port = atoi(p+1);  } else {    port = 80;   /* standard HTTP port */  }  if (hostp) {    *hostp = host;  } else {    free(host);  }  if (portp) {    *portp = port;  }  if (pathp) {    *pathp = path;  } else {    free(path);  }  return 0;}/* opens the given http-url for reading. Skips HTTP headers. Optional   "http://" at beginning of url is skipped.  On error, return NULL   with *errmsg set to a (static) error string. Otherwise, return file   open for reading. */FILE *open_url(const char *url, int timeout, const char **errmsg) {  char *path;  char *host;  int port;  int r, s;  struct sockaddr_in dst;  FILE *f;  char *b;  int i;  char **tok;  int cnt;  char *proxy;  char *urlhost;  proxy = getval("proxy");  if (proxy) {    decompose_url(proxy, &host, &port, NULL);    decompose_url(url, &urlhost, NULL, NULL);    path = strdup(url);  } else {    decompose_url(url, &host, &port, &path);    urlhost = strdup(host);  }  /* now, connect to host:port with path */  s = socket(AF_INET, SOCK_STREAM, 0);  dst.sin_port = htons(port);  dst.sin_family = AF_INET;  r = resolve(host, &dst.sin_addr);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -