Example #1
0
void
rcv_chat_invite (struct htlc_conn *htlc)
{
   struct htlc_conn *htlcp;
   u_int32_t uid = 0, ref = 0;
   u_int16_t uid16;

   dh_start(htlc)
      switch (dh_type) {
         case HTLC_DATA_UID:
            dh_getint(uid);
            break;
         case HTLC_DATA_CHAT_ID:
            dh_getint(ref);
            break;
      }
   dh_end()
   if (ref && uid) {
      if ((htlcp = isclient(htlc->sid, uid))) {
         struct htlc_chat *chat = chat_lookup_ref(ref);
         if (!chat || !chat_isset(htlc, chat, 0)) {
            send_taskerror(htlc, "who?!?");
            return;
         }
         if (chat_isset(htlcp, chat, 0)) {
            char buf[64];
            u_int16_t len;

            len = snprintf(buf, sizeof(buf),
                      "%s is already in chat 0x%x",
                  htlcp->name, chat->ref);
            if (len == (u_int16_t)-1)
               len = sizeof(buf);
            send_taskerror(htlc, buf);
            return;
         }
         chat_set(htlcp, chat, 1);
         hlwrite(htlc, HTLS_HDR_TASK, 0, 0);
         ref = htonl(ref);
         uid16 = htons(htlc->uid);
         hlwrite(htlcp, HTLS_HDR_CHAT_INVITE, 0, 3,
            HTLS_DATA_CHAT_ID, sizeof(ref), &ref,
            HTLS_DATA_UID, sizeof(uid16), &uid16,
            HTLS_DATA_NAME, strlen(htlc->name), htlc->name);
      } else
         send_taskerror(htlc, "who?!?");
   } else
      send_taskerror(htlc, "huh?!?");
}
Example #2
0
void
rcv_chat_part (struct htlc_conn *htlc)
{
   u_int32_t ref = 0;
   struct htlc_chat *chat;

   dh_start(htlc)
      if (dh_type != HTLC_DATA_CHAT_ID)
         continue;
      dh_getint(ref);
      if ((chat = chat_lookup_ref(ref)) && chat_isset(htlc, chat, 0)) {
         chat_clr(htlc, chat, 0);
         if (!chat->nusers)
            chat_delete(chat);
         else {
            struct htlc_conn *htlcp;
            u_int16_t uid;

            ref = htonl(ref);
            uid = htons(htlc->uid);
            for (htlcp = htlc_list->next; htlcp; htlcp = htlcp->next)
               if (chat_isset(htlcp, chat, 0))
                  hlwrite(htlcp, HTLS_HDR_CHAT_USER_PART, 0, 2,
                     HTLS_DATA_CHAT_ID, sizeof(ref), &ref,
                     HTLS_DATA_UID, sizeof(uid), &uid);
         }
      }
   dh_end()
}
Example #3
0
void
rcv_chat_create (struct htlc_conn *htlc)
{
   struct htlc_conn *htlcp;
   u_int32_t uid = 0, ref;
   u_int16_t uid16, icon, color;

   dh_start(htlc)
      if (dh_type != HTLC_DATA_UID)
         continue;
      dh_getint(uid);
      if ((htlcp = isclient(htlc->sid, uid))) {
         struct htlc_chat *chat = chat_new();

         chat_set(htlc, chat, 0);
         ref = htonl(chat->ref);
         uid16 = htons(htlc->uid);
         icon = htons(htlc->icon);
         color = htons(htlc->color);
         hlwrite(htlc, HTLS_HDR_TASK, 0, 5,
            HTLS_DATA_CHAT_ID, sizeof(ref), &ref,
            HTLS_DATA_UID, sizeof(uid16), &uid16,
            HTLS_DATA_ICON, sizeof(icon), &icon,
            HTLS_DATA_COLOUR, sizeof(color), &color,
            HTLS_DATA_NAME, strlen(htlc->name), htlc->name);
         if (htlc->uid != (u_int16_t)uid)
            hlwrite(htlcp, HTLS_HDR_CHAT_INVITE, 0, 3,
               HTLS_DATA_CHAT_ID, sizeof(ref), &ref,
               HTLS_DATA_UID, sizeof(uid16), &uid16,
               HTLS_DATA_NAME, strlen(htlc->name), htlc->name);
      } else
         send_taskerror(htlc, "who?!?");
   dh_end()
}
Example #4
0
File: files.c Project: Schala/mhxd
void
rcv_folder_put (struct htlc_conn *htlc)
{
	u_int16_t fnlen = 0, resume = 0;
	char path[MAXPATHLEN], dir[MAXPATHLEN], filename[NAME_MAX];
	char abuf[HOSTLEN+1], buf[128];
	struct stat sb;
	int err, siz, len;
	u_int32_t ref, data_pos = 0, rsrc_pos = 0, totalsize = 0, nfiles = 0;
	u_int8_t rflt[74];
	struct SOCKADDR_IN lsaddr;
	struct htxf_conn *htxf;
	u_int16_t i;

	if (htlc->nr_puts >= htlc->put_limit) {
		len = snprintf(buf, sizeof(buf), "%u at a time", htlc->put_limit);
		hlwrite(htlc, HTLS_HDR_TASK, 1, 1, HTLS_DATA_TASKERROR, len, buf);
		return;
	}
	if (nr_puts >= hxd_cfg.limits.total_uploads) {
		len = snprintf(buf, sizeof(buf), "maximum number of total uploads reached (%u >= %d)",
				   nr_gets, hxd_cfg.limits.total_uploads);
		hlwrite(htlc, HTLS_HDR_TASK, 1, 1, HTLS_DATA_TASKERROR, len, buf);
		return;
	}
	for (i = 0; i < HTXF_PUT_MAX; i++)
		if (!htlc->htxf_in[i])
			break;
	if (i == HTXF_PUT_MAX) {
		snd_strerror(htlc, EAGAIN);
		return;
	}

	dh_start(htlc)
		switch (dh_type) {
			case HTLC_DATA_FILE_NAME:
				fnlen = dh_len >= NAME_MAX ? NAME_MAX - 1 : dh_len;
				read_filename(filename, dh_data, fnlen);
				break;
			case HTLC_DATA_DIR:
				if ((err = hldir_to_path(dh, ROOTDIR, dir, dir))) {
					snd_strerror(htlc, err);
					return;
				}
				break;
			case HTLC_DATA_FILE_PREVIEW:
				dh_getint(resume);
				break;
			case HTLC_DATA_HTXF_SIZE:
				dh_getint(totalsize);
				break;
			case HTLC_DATA_FILE_NFILES:
				dh_getint(nfiles);
				break;
		}
	dh_end()

	if (!htlc->access.upload_anywhere && (!dir[0] || (!strcasestr(dir, "UPLOAD") && !strcasestr(dir, "DROP BOX")))) {
		snd_strerror(htlc, EPERM);
		return;
	}
	if (!fnlen && !dir[0]) {
		/* No file name given */
		hlwrite(htlc, HTLS_HDR_TASK, 1, 1, HTLS_DATA_TASKERROR, 6, "huh?!?");
		return;
	}

	if (dir[0]) {
		if (fnlen)
			snprintf(path, sizeof(path), "%s/%s", dir, filename);
		else
			strcpy(path, dir);
	} else {
		snprintf(path, sizeof(path), "%s/%s", ROOTDIR, filename);
	}
#ifdef HAVE_CORESERVICES
	resolve_alias_path(path, path);
#endif
	if (!resume) {
		if (!stat(path, &sb)) {
			snd_strerror(htlc, EEXIST);
			return;
		}
		if (errno != ENOENT) {
			snd_strerror(htlc, errno);
			return;
		}
		SYS_mkdir(path, hxd_cfg.permissions.directories);
	} else {
		if (stat(path, &sb)) {
			snd_strerror(htlc, errno);
			return;
		}
		if (!S_ISDIR(sb.st_mode)) {
			snd_strerror(htlc, ENOTDIR);
			return;
		}
	}

	ref = htxf_ref_new(htlc);
	ref = htonl(ref);

	siz = sizeof(struct SOCKADDR_IN);
	if (getsockname(htlc->fd, (struct sockaddr *)&lsaddr, &siz)) {
		hxd_log("rcv_file_get: getsockname: %s", strerror(errno));
		snd_strerror(htlc, errno);
		return;
	}
	htxf = htxf_new(htlc, 1);
	htxf->type = HTXF_TYPE_FOLDER;
	htxf->data_pos = data_pos;
	htxf->rsrc_pos = rsrc_pos;
	htxf->total_size = totalsize;
	htxf->ref = ref;
	htxf->sockaddr = htlc->sockaddr;
	htxf->listen_sockaddr = lsaddr;
	htxf->listen_sockaddr.SIN_PORT = htons(ntohs(htxf->listen_sockaddr.SIN_PORT) + 1);
	strcpy(htxf->path, path);

	htlc->nr_puts++;
	nr_puts++;
	if (log_upload) {
		inaddr2str(abuf, &htlc->sockaddr);
		hxd_log("%s@%s:%u - %s:%u:%u:%s - upload %s:%08x", htlc->userid, abuf, ntohs(htlc->sockaddr.SIN_PORT),
			htlc->name, htlc->icon, htlc->uid, htlc->login, htxf->path, htxf->ref);
	}
	if (!resume)
		hlwrite(htlc, HTLS_HDR_TASK, 0, 1,
			HTLS_DATA_HTXF_REF, sizeof(ref), &ref);
	else
		hlwrite(htlc, HTLS_HDR_TASK, 0, 2,
			HTLS_DATA_RFLT, 74, rflt,
			HTLS_DATA_HTXF_REF, sizeof(ref), &ref);
}
Example #5
0
File: files.c Project: Schala/mhxd
void
rcv_folder_get (struct htlc_conn *htlc)
{
	u_int16_t fnlen = 0, preview = 0;
	char path[MAXPATHLEN], dir[MAXPATHLEN], filename[NAME_MAX], pathbuf[MAXPATHLEN];
	char abuf[HOSTLEN+1], buf[128];
	struct stat sb;
	u_int32_t size = 0, data_size = 0, rsrc_size = 0, ref, 
		  data_pos = 0, rsrc_pos = 0, nfiles = 0;
	int err, siz, len;
	struct SOCKADDR_IN lsaddr;
	struct htxf_conn *htxf;
	u_int16_t i;
	DIR *dirp;
	struct dirent *de;

	dir[0] = 0;

	if (htlc->nr_gets >= htlc->get_limit) {
		len = snprintf(buf, sizeof(buf), "%u at a time", htlc->get_limit);
		hlwrite(htlc, HTLS_HDR_TASK, 1, 1, HTLS_DATA_TASKERROR, len, buf);
		return;
	}
	if (nr_gets >= hxd_cfg.limits.total_downloads) {
		len = snprintf(buf, sizeof(buf), "maximum number of total downloads reached (%u >= %d)",
			       nr_gets, hxd_cfg.limits.total_downloads);
		hlwrite(htlc, HTLS_HDR_TASK, 1, 1, HTLS_DATA_TASKERROR, len, buf);
		return;
	}
	for (i = 0; i < HTXF_GET_MAX; i++)
		if (!htlc->htxf_out[i])
			break;
	if (i == HTXF_GET_MAX) {
		snd_strerror(htlc, EAGAIN);
		return;
	}

	dh_start(htlc)
		switch (dh_type) {
			case HTLC_DATA_FILE_NAME:
				fnlen = dh_len >= NAME_MAX ? NAME_MAX - 1 : dh_len;
				read_filename(filename, dh_data, fnlen);
				break;
			case HTLC_DATA_DIR:
				if ((err = hldir_to_path(dh, ROOTDIR, dir, dir))) {
					snd_strerror(htlc, err);
					return;
				}
				break;
			case HTLC_DATA_RFLT:
				if (dh_len >= 50)
					L32NTOH(data_pos, &dh_data[46]);
				if (dh_len >= 66)
					L32NTOH(rsrc_pos, &dh_data[62]);
				break;
			case HTLC_DATA_FILE_PREVIEW:
				dh_getint(preview);
				break;
		}
	dh_end()

	if (!fnlen && !dir[0]) {
		/* No file name given */
		hlwrite(htlc, HTLS_HDR_TASK, 1, 1, HTLS_DATA_TASKERROR, 6, "huh?!?");
		return;
	}

	if (dir[0]) {
		if (fnlen)
			snprintf(path, sizeof(path), "%s/%s", dir, filename);
		else
			strcpy(path, dir);
	} else {
		snprintf(path, sizeof(path), "%s/%s", ROOTDIR, filename);
	}
#ifdef HAVE_CORESERVICES
	resolve_alias_path(path, path);
#endif
	if (check_dropbox(htlc, path)) {
		snd_strerror(htlc, EPERM);
		return;
	}

	if (stat(path, &sb)) {
		snd_strerror(htlc, errno);
		return;
	}

	if (!S_ISDIR(sb.st_mode)) {
		snd_strerror(htlc, ENOTDIR);
		return;
	}

	if (!(dirp = opendir(path))) {
		snd_strerror(htlc, errno);
		return;
	}
	while ((de = readdir(dirp))) {
		if (de->d_name[0] == '.')
			continue;
		nfiles++;
		snprintf(pathbuf, sizeof(pathbuf), "%s/%s", path, de->d_name);
		if (stat(pathbuf, &sb))
			continue;
		if (S_ISDIR(sb.st_mode))
			continue;
		data_size = sb.st_size;
		rsrc_size = resource_len(pathbuf);
		size += (data_size - data_pos) + (preview ? 0 : (rsrc_size - rsrc_pos));
		size += 133 + ((rsrc_size - rsrc_pos) ? 16 : 0) + comment_len(pathbuf);
	}
	closedir(dirp);

	if (!nfiles) {
		hlwrite(htlc, HTLS_HDR_TASK, 0, 2,
			HTLC_DATA_HTXF_SIZE, sizeof(size), &size,
			HTLC_DATA_FILE_NFILES, sizeof(nfiles), &nfiles);
		return;
	}

	ref = htxf_ref_new(htlc);
	ref = htonl(ref);

	siz = sizeof(struct SOCKADDR_IN);
	if (getsockname(htlc->fd, (struct sockaddr *)&lsaddr, &siz)) {
		hxd_log("rcv_file_get: getsockname: %s", strerror(errno));
		snd_strerror(htlc, errno);
		return;
	}
	htxf = htxf_new(htlc, 0);
	htxf->type = HTXF_TYPE_FOLDER;
	htxf->total_size = size;
	htxf->ref = ref;
	htxf->preview = preview;
	htxf->sockaddr = htlc->sockaddr;
	htxf->listen_sockaddr = lsaddr;
	htxf->listen_sockaddr.SIN_PORT = htons(ntohs(htxf->listen_sockaddr.SIN_PORT) + 1);
	strcpy(htxf->path, path);

	htlc->nr_gets++;
	nr_gets++;
	if (log_download) {
		inaddr2str(abuf, &htlc->sockaddr);
		hxd_log("%s@%s:%u - %s:%u:%u:%s - download %s:%08x", htlc->userid, abuf, ntohs(htlc->sockaddr.SIN_PORT),
			htlc->name, htlc->icon, htlc->uid, htlc->login, htxf->path, htxf->ref);
	}
	size = htonl(size);
	nfiles = htonl(nfiles);
	hlwrite(htlc, HTLS_HDR_TASK, 0, 3,
		HTLS_DATA_HTXF_SIZE, sizeof(size), &size,
		HTLS_DATA_FILE_NFILES, sizeof(nfiles), &nfiles,
		HTLS_DATA_HTXF_REF, sizeof(ref), &ref);
}
Example #6
0
File: files.c Project: Schala/mhxd
void
rcv_file_get (struct htlc_conn *htlc)
{
	u_int16_t fnlen = 0, preview = 0;
	char path[MAXPATHLEN], dir[MAXPATHLEN], filename[NAME_MAX];
	char abuf[HOSTLEN+1], buf[128];
	struct stat sb;
	u_int32_t size = 0, data_size = 0, rsrc_size = 0, ref, 
		  data_pos = 0, rsrc_pos = 0;
	int err, siz, len;
	struct SOCKADDR_IN lsaddr;
	struct htxf_conn *htxf;
	u_int16_t i;
#if defined(CONFIG_HTXF_QUEUE)
	u_int16_t queue_pos;
#endif

	dir[0] = 0;

	if (htlc->nr_gets >= htlc->get_limit) {
		for (i = 0; i < HTXF_GET_MAX; i++) {
			htxf = htlc->htxf_out[i];
			if (!htxf)
				continue;
			if ((htxf->total_pos == htxf->total_size)
			    || htxf->gone)
				goto ok;
		}
		len = snprintf(buf, sizeof(buf), "%u at a time", htlc->get_limit);
		hlwrite(htlc, HTLS_HDR_TASK, 1, 1, HTLS_DATA_TASKERROR, len, buf);
		return;
	}
ok:
#if defined(CONFIG_HTXF_QUEUE)
	if (!htlc->access_extra.ignore_queue && nr_queued >= hxd_cfg.limits.queue_size) {
#else
	if (nr_gets >= hxd_cfg.limits.total_downloads) {
#endif
#if defined(CONFIG_HTXF_QUEUE)
		len = snprintf(buf, sizeof(buf),
			       "queue is full (%u >= %d) please try again later",
			       nr_gets, hxd_cfg.limits.queue_size);
#else
		len = snprintf(buf, sizeof(buf),
			       "maximum number of total downloads reached (%u >= %d)",
			       nr_gets, hxd_cfg.limits.total_downloads);
#endif
		hlwrite(htlc, HTLS_HDR_TASK, 1, 1, HTLS_DATA_TASKERROR, len, buf);
		return;
	}
	for (i = 0; i < HTXF_GET_MAX; i++)
		if (!htlc->htxf_out[i])
			break;
	if (i == HTXF_GET_MAX) {
		snd_strerror(htlc, EAGAIN);
		return;
	}

	dh_start(htlc)
		switch (dh_type) {
			case HTLC_DATA_FILE_NAME:
				fnlen = dh_len >= NAME_MAX ? NAME_MAX - 1 : dh_len;
				read_filename(filename, dh_data, fnlen);
				break;
			case HTLC_DATA_DIR:
				if ((err = hldir_to_path(dh, ROOTDIR, dir, dir))) {
					snd_strerror(htlc, err);
					return;
				}
				break;
			case HTLC_DATA_RFLT:
				if (dh_len >= 50)
					L32NTOH(data_pos, &dh_data[46]);
				if (dh_len >= 66)
					L32NTOH(rsrc_pos, &dh_data[62]);
				break;
			case HTLC_DATA_FILE_PREVIEW:
				dh_getint(preview);
				break;
		}
	dh_end()

	if (!fnlen && !dir[0]) {
		/* No file name given */
		hlwrite(htlc, HTLS_HDR_TASK, 1, 1, HTLS_DATA_TASKERROR, 6, "huh?!?");
		return;
	}

	if (dir[0]) {
		if (fnlen)
			snprintf(path, sizeof(path), "%s/%s", dir, filename);
		else
			strcpy(path, dir);
	} else {
		snprintf(path, sizeof(path), "%s/%s", ROOTDIR, filename);
	}
#ifdef HAVE_CORESERVICES
	resolve_alias_path(path, path);
#endif
	if (check_dropbox(htlc, path)) {
		snd_strerror(htlc, EPERM);
		return;
	}

#ifdef CONFIG_HTXF_PREVIEW
	if (preview) {
		Image *img, *mimg;
		ImageInfo ii;
		ExceptionInfo ei;
		char previewpath[MAXPATHLEN];
		static int magick_inited = 0;

		if (!magick_inited) {
			InitializeMagick("hxd");
			magick_inited = 1;
		}

#if MaxTextExtent < MAXPATHLEN
		if (strlen(path) >= sizeof(ii.filename)) {
			hlwrite(htlc, HTLS_HDR_TASK, 1, 1, HTLS_DATA_TASKERROR,
				13, "path too long");
			return;
		}
#endif
		memset(&ii, 0, sizeof(ii));
		memset(&ei, 0, sizeof(ei));
		GetImageInfo(&ii);
		GetExceptionInfo(&ei);

		err = preview_path(previewpath, path, &sb);
		if (!err) {
			/* Preview file already exists */
			strcpy(ii.filename, previewpath);
			mimg = ReadImage(&ii, &ei);
		} else {
			/* Create preview file */
			strcpy(ii.filename, path);
			img = ReadImage(&ii, &ei);
			if (!img)
				goto text_preview;
			mimg = MinifyImage(img, &ei);
			DestroyImage(img);
		}
		if (!mimg) {
			hlwrite(htlc, HTLS_HDR_TASK, 1, 1, HTLS_DATA_TASKERROR,
				18, "MinifyImage failed");
			return;
		}
		if (err) {
			err = preview_path(previewpath, path, 0);
			if (err) {
				snd_strerror(htlc, err);
				DestroyImage(mimg);
				return;
			}
			strcpy(mimg->filename, previewpath);
			data_pos = 0;
			rsrc_pos = 0;
			WriteImage(&ii, mimg);
			DestroyImage(mimg);
		} else {
			DestroyImage(mimg);
		}
		strcpy(path, previewpath);
	}

text_preview:
#endif
	if (stat(path, &sb)) {
		snd_strerror(htlc, errno);
		return;
	}

	if (S_ISDIR(sb.st_mode)) {
		snd_strerror(htlc, EISDIR);
		return;
	}

	data_size = sb.st_size;
	size = (data_size - data_pos) + (preview ? 0 : 133);
#if defined(CONFIG_HFS)
	if (hxd_cfg.operation.hfs) {
		rsrc_size = resource_len(path);
		size += preview ? 0 : (rsrc_size - rsrc_pos);
		if (!preview)
			size += ((rsrc_size - rsrc_pos) ? 16 : 0) + comment_len(path);
	}
#endif

	ref = htxf_ref_new(htlc);
	ref = htonl(ref);

	siz = sizeof(struct SOCKADDR_IN);
	if (getsockname(htlc->fd, (struct sockaddr *)&lsaddr, &siz)) {
		hxd_log("rcv_file_get: getsockname: %s", strerror(errno));
		snd_strerror(htlc, errno);
		return;
	}
	htxf = htxf_new(htlc, 0);
	htxf->type = HTXF_TYPE_FILE;
	htxf->data_size = data_size;
	htxf->rsrc_size = rsrc_size;
	htxf->data_pos = data_pos;
	htxf->rsrc_pos = rsrc_pos;
	htxf->total_size = size;
	htxf->ref = ref;
	htxf->limit_out_Bps = htlc->nr_puts > 0 ?
		(htlc->limit_uploader_out_Bps ? htlc->limit_uploader_out_Bps : htlc->limit_out_Bps) :
		  htlc->limit_out_Bps;
	hxd_log("conf: %u!%u", htxf->limit_out_Bps, htlc->limit_out_Bps);
	htxf->preview = preview;
	htxf->sockaddr = htlc->sockaddr;
	htxf->listen_sockaddr = lsaddr;
	htxf->listen_sockaddr.SIN_PORT = htons(ntohs(htxf->listen_sockaddr.SIN_PORT) + 1);
	strcpy(htxf->path, path);

	htlc->nr_gets++;
	nr_gets++;
#if defined(CONFIG_HTXF_QUEUE)
	if (htlc->access_extra.ignore_queue)
		htxf->queue_pos = queue_pos = 0;
	else
		htxf->queue_pos = queue_pos = insert_into_queue(htlc);
#endif

	if (log_download) {
		inaddr2str(abuf, &htlc->sockaddr);
		hxd_log("%s@%s:%u - %s:%u:%u:%s - download %s:%08x", htlc->userid, abuf, ntohs(htlc->sockaddr.SIN_PORT),
			htlc->name, htlc->icon, htlc->uid, htlc->login, htxf->path, htxf->ref);
#if defined(CONFIG_SQL)
		sql_download(htlc->name, abuf, htlc->login, path);
#endif
	}
	size = htonl(size);
#if defined(CONFIG_HTXF_QUEUE)
	queue_pos = htons(queue_pos);
	hlwrite(htlc, HTLS_HDR_TASK, 0, 3,
		HTLS_DATA_HTXF_REF, sizeof(ref), &ref,
		HTLS_DATA_HTXF_SIZE, sizeof(size), &size,
		HTLS_DATA_QUEUE_POSITION, sizeof(queue_pos), &queue_pos);
#else
	hlwrite(htlc, HTLS_HDR_TASK, 0, 2,
		HTLS_DATA_HTXF_REF, sizeof(ref), &ref,
		HTLS_DATA_HTXF_SIZE, sizeof(size), &size);
#endif
}

void
rcv_file_put (struct htlc_conn *htlc)
{
	u_int16_t fnlen = 0, resume = 0;
	char path[MAXPATHLEN], dir[MAXPATHLEN], filename[NAME_MAX];
	char abuf[HOSTLEN+1], buf[128];
	struct stat sb;
	int err, siz, len;
	u_int32_t ref, data_pos = 0, rsrc_pos = 0, totalsize = 0;
	u_int8_t rflt[74];
	struct SOCKADDR_IN lsaddr;
	struct htxf_conn *htxf;
	u_int16_t i;

	dir[0] = 0;

	if (htlc->nr_puts >= htlc->put_limit) {
		len = snprintf(buf, sizeof(buf), "%u at a time", htlc->put_limit);
		hlwrite(htlc, HTLS_HDR_TASK, 1, 1, HTLS_DATA_TASKERROR, len, buf);
		return;
	}
	if (nr_puts >= hxd_cfg.limits.total_uploads) {
		len = snprintf(buf, sizeof(buf), "maximum number of total uploads reached (%u >= %d)",
			       nr_gets, hxd_cfg.limits.total_uploads);
		hlwrite(htlc, HTLS_HDR_TASK, 1, 1, HTLS_DATA_TASKERROR, len, buf);
		return;
	}
	for (i = 0; i < HTXF_PUT_MAX; i++)
		if (!htlc->htxf_in[i])
			break;
	if (i == HTXF_PUT_MAX) {
		snd_strerror(htlc, EAGAIN);
		return;
	}

	dh_start(htlc)
		switch (dh_type) {
			case HTLC_DATA_FILE_NAME:
				fnlen = dh_len >= NAME_MAX ? NAME_MAX - 1 : dh_len;
				read_filename(filename, dh_data, fnlen);
				break;
			case HTLC_DATA_DIR:
				if ((err = hldir_to_path(dh, ROOTDIR, dir, dir))) {
					snd_strerror(htlc, err);
					return;
				}
				break;
			case HTLC_DATA_FILE_PREVIEW:
				dh_getint(resume);
				break;
			case HTLC_DATA_HTXF_SIZE:
				dh_getint(totalsize);
				break;
		}
	dh_end()

	if (!htlc->access.upload_anywhere && (!dir[0] || (!strcasestr(dir, "UPLOAD") && !strcasestr(dir, "DROP BOX")))) {
		snd_strerror(htlc, EPERM);
		return;
	}
	if (!fnlen && !dir[0]) {
		/* No file name given */
		hlwrite(htlc, HTLS_HDR_TASK, 1, 1, HTLS_DATA_TASKERROR, 6, "huh?!?");
		return;
	}

	if (dir[0]) {
		if (fnlen)
			snprintf(path, sizeof(path), "%s/%s", dir, filename);
		else
			strcpy(path, dir);
	} else {
		snprintf(path, sizeof(path), "%s/%s", ROOTDIR, filename);
	}
#ifdef HAVE_CORESERVICES
	resolve_alias_path(path, path);
#endif
	if (!resume) {
		if (!stat(path, &sb)) {
			snd_strerror(htlc, EEXIST);
			return;
		}
		if (errno != ENOENT) {
			snd_strerror(htlc, errno);
			return;
		}
	} else {
		if (stat(path, &sb)) {
			snd_strerror(htlc, errno);
			return;
		}
		data_pos = sb.st_size;
#if defined(CONFIG_HFS)
		if (hxd_cfg.operation.hfs)
			rsrc_pos = resource_len(path);
#endif
		memcpy(rflt, "RFLT\0\1\
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
\0\0\0\2DATA\0\0\0\0\0\0\0\0\0\0\0\0MACR\0\0\0\0\0\0\0\0\0\0\0\0", 74);
		S32HTON(data_pos, &rflt[46]);
		S32HTON(rsrc_pos, &rflt[62]);
	}

	ref = htxf_ref_new(htlc);
	ref = htonl(ref);

	siz = sizeof(struct SOCKADDR_IN);
	if (getsockname(htlc->fd, (struct sockaddr *)&lsaddr, &siz)) {
		hxd_log("rcv_file_get: getsockname: %s", strerror(errno));
		snd_strerror(htlc, errno);
		return;
	}
	htxf = htxf_new(htlc, 1);
	htxf->type = HTXF_TYPE_FILE;
	htxf->data_pos = data_pos;
	htxf->rsrc_pos = rsrc_pos;
	htxf->total_size = totalsize;
	htxf->ref = ref;
	htxf->sockaddr = htlc->sockaddr;
	htxf->listen_sockaddr = lsaddr;
	htxf->listen_sockaddr.SIN_PORT = htons(ntohs(htxf->listen_sockaddr.SIN_PORT) + 1);
	strcpy(htxf->path, path);

	htlc->nr_puts++;
	nr_puts++;
	if (log_upload) {
		inaddr2str(abuf, &htlc->sockaddr);
		hxd_log("%s@%s:%u - %s:%u:%u:%s - upload %s:%08x", htlc->userid, abuf, ntohs(htlc->sockaddr.SIN_PORT),
			htlc->name, htlc->icon, htlc->uid, htlc->login, htxf->path, htxf->ref);
#if defined(CONFIG_SQL)
		sql_upload(htlc->name, abuf, htlc->login, path);
#endif
	}
	if (!resume)
		hlwrite(htlc, HTLS_HDR_TASK, 0, 1,
			HTLS_DATA_HTXF_REF, sizeof(ref), &ref);
	else
		hlwrite(htlc, HTLS_HDR_TASK, 0, 2,
			HTLS_DATA_RFLT, 74, rflt,
			HTLS_DATA_HTXF_REF, sizeof(ref), &ref);
}
Example #7
0
static void
rcv_task_login (struct htlc_conn *htlc, void *secure)
{
	char abuf[HOSTLEN+1];
	u_int32_t uid;
	u_int16_t icon16;
#ifdef CONFIG_HOPE
	u_int16_t hc;
	u_int8_t *p, *mal = 0;
	u_int16_t mal_len = 0;
	u_int16_t sklen = 0, macalglen = 0, secure_login = 0, secure_password = 0;
	u_int8_t password_mac[20];
	u_int8_t login[32];
	u_int16_t llen, pmaclen;
#ifdef CONFIG_CIPHER
	u_int8_t *s_cipher_al = 0, *c_cipher_al = 0;
	u_int16_t s_cipher_al_len = 0, c_cipher_al_len = 0;
	u_int8_t s_cipheralg[32], c_cipheralg[32];
	u_int16_t s_cipheralglen = 0, c_cipheralglen = 0;
	u_int8_t cipheralglist[64];
	u_int16_t cipheralglistlen;
#endif
#ifdef CONFIG_COMPRESS
	u_int8_t *s_compress_al = 0, *c_compress_al = 0;
	u_int16_t s_compress_al_len = 0, c_compress_al_len = 0;
	u_int8_t s_compressalg[32], c_compressalg[32];
	u_int16_t s_compressalglen = 0, c_compressalglen = 0;
	u_int8_t compressalglist[64];
	u_int16_t compressalglistlen;
#endif

	if (secure) {
		dh_start(htlc)
			switch (dh_type) {
				case HTLS_DATA_LOGIN:
					if (dh_len && dh_len == strlen(htlc->macalg) && !memcmp(htlc->macalg, dh_data, dh_len))
						secure_login = 1;
					break;
				case HTLS_DATA_PASSWORD:
					if (dh_len && dh_len == strlen(htlc->macalg) && !memcmp(htlc->macalg, dh_data, dh_len))
						secure_password = 1;
					break;
				case HTLS_DATA_MAC_ALG:
					mal_len = dh_len;
					mal = dh_data;
					break;
#ifdef CONFIG_CIPHER
				case HTLS_DATA_CIPHER_ALG:
					s_cipher_al_len = dh_len;
					s_cipher_al = dh_data;
					break;
				case HTLC_DATA_CIPHER_ALG:
					c_cipher_al_len = dh_len;
					c_cipher_al = dh_data;
					break;
				case HTLS_DATA_CIPHER_MODE:
					break;
				case HTLC_DATA_CIPHER_MODE:
					break;
				case HTLS_DATA_CIPHER_IVEC:
					break;
				case HTLC_DATA_CIPHER_IVEC:
					break;
#endif
#if defined(CONFIG_COMPRESS)
				case HTLS_DATA_COMPRESS_ALG:
					s_compress_al_len = dh_len;
					s_compress_al = dh_data;
					break;
				case HTLC_DATA_COMPRESS_ALG:
					c_compress_al_len = dh_len;
					c_compress_al = dh_data;
					break;
#endif
				case HTLS_DATA_CHECKSUM_ALG:
					break;
				case HTLC_DATA_CHECKSUM_ALG:
					break;
				case HTLS_DATA_SESSIONKEY:
					sklen = dh_len > sizeof(htlc->sessionkey) ? sizeof(htlc->sessionkey) : dh_len;
					memcpy(htlc->sessionkey, dh_data, sklen);
					htlc->sklen = sklen;
					break;
			}
		dh_end()

		if (!mal_len) {
no_mal:			hx_printf_prefix(htlc, 0, INFOPREFIX, "No macalg from server\n");
			hx_htlc_close(htlc);
			memset(htlc->password, 0, sizeof(htlc->password));
			return;
		}

		p = list_n(mal, mal_len, 0);
		if (!p || !*p)
			goto no_mal;
		macalglen = *p >= sizeof(htlc->macalg) ? sizeof(htlc->macalg)-1 : *p;
		memcpy(htlc->macalg, p+1, macalglen);
		htlc->macalg[macalglen] = 0;

		if (sklen < 32) {
			hx_printf_prefix(htlc, 0, INFOPREFIX,
					 "sessionkey length (%u) not big enough\n", sklen);
			hx_htlc_close(htlc);
			memset(htlc->password, 0, sizeof(htlc->password));
			return;
		}
#ifdef CONFIG_IPV6
		if (memcmp(htlc->sessionkey, &htlc->sockaddr.SIN_ADDR.S_ADDR, 16)
		    || *((u_int16_t *)(htlc->sessionkey + 16)) != htlc->sockaddr.SIN_PORT) {
#else
		if (*((u_int32_t *)(htlc->sessionkey)) != htlc->sockaddr.SIN_ADDR.S_ADDR
		    || *((u_int16_t *)(htlc->sessionkey + 4)) != htlc->sockaddr.SIN_PORT) {
#endif
			char fakeabuf[HOSTLEN+1], realabuf[HOSTLEN+1];
			struct IN_ADDR fakeinaddr;

#ifdef CONFIG_IPV6
			memcpy(&fakeinaddr.S_ADDR, htlc->sessionkey, 16);
			inet_ntop(AFINET, (char *)&fakeinaddr, fakeabuf, sizeof(fakeabuf));
			inet_ntop(AFINET, (char *)&htlc->sockaddr.SIN_ADDR, realabuf, sizeof(realabuf));
#else
			fakeinaddr.S_ADDR = *((u_int32_t *)(htlc->sessionkey));
			inet_ntoa_r(fakeinaddr, fakeabuf, sizeof(fakeabuf));
			inet_ntoa_r(htlc->sockaddr.SIN_ADDR, realabuf, sizeof(realabuf));
#endif
			hx_printf_prefix(htlc, 0, INFOPREFIX, "Server gave wrong address: %s:%u != %s:%u\n",
					 fakeabuf, ntohs(*((u_int16_t *)(htlc->sessionkey + 4))),
					 realabuf, ntohs(htlc->sockaddr.SIN_PORT));
			/* XXX HACK XXX */
			if (htlc->secure == 2) {
				hx_printf_prefix(htlc, 0, INFOPREFIX, "Possible man-in-the-middle attack! Connecting anyway.\n");
			} else {
				hx_printf_prefix(htlc, 0, INFOPREFIX, "Possible man-in-the-middle attack! Closing connection. Use -f to force connect.\n");
				hx_htlc_close(htlc);
				memset(htlc->password, 0, sizeof(htlc->password));
				return;
			}
		}
		if (task_inerror(htlc)) {
			hx_htlc_close(htlc);
			memset(htlc->password, 0, sizeof(htlc->password));
			return;
		}
		task_new(htlc, rcv_task_login, 0, 0, "login");
		icon16 = htons(htlc->icon);
		if (secure_login) {
			llen = hmac_xxx(login, htlc->login, strlen(htlc->login),
					htlc->sessionkey, sklen, htlc->macalg);
			if (!llen) {
				hx_printf_prefix(htlc, 0, INFOPREFIX,
						 "bad HMAC algorithm %s\n", htlc->macalg);
				hx_htlc_close(htlc);
				memset(htlc->password, 0, sizeof(htlc->password));
				return;
			}
		} else {
			llen = strlen(htlc->login);
			hl_encode(login, htlc->login, llen);
			login[llen] = 0;
		}
		pmaclen = hmac_xxx(password_mac, htlc->password, strlen(htlc->password),
				   htlc->sessionkey, sklen, htlc->macalg);
		if (!pmaclen) {	
			hx_printf_prefix(htlc, 0, INFOPREFIX,
					 "bad HMAC algorithm %s\n", htlc->macalg);
			hx_htlc_close(htlc);
			return;
		}
		hc = 4;
#ifdef CONFIG_COMPRESS
		if (!htlc->compressalg[0] || !strcmp(htlc->compressalg, "NONE")) {
			hx_printf_prefix(htlc, 0, INFOPREFIX,
					 "WARNING: this connection is not compressed\n");
			compressalglistlen = 0;
			goto no_compress;
		}
		if (!c_compress_al_len || !s_compress_al_len) {
no_compress_al:		hx_printf_prefix(htlc, 0, INFOPREFIX,
				 "No compress algorithm from server\n");
			hx_htlc_close(htlc);
			return;
		}
		p = list_n(s_compress_al, s_compress_al_len, 0);
		if (!p || !*p)
			goto no_compress_al;
		s_compressalglen = *p >= sizeof(s_compressalg) ? sizeof(s_compressalg)-1 : *p;
		memcpy(s_compressalg, p+1, s_compressalglen);
		s_compressalg[s_compressalglen] = 0;
		p = list_n(c_compress_al, c_compress_al_len, 0);
		if (!p || !*p)
			goto no_compress_al;
		c_compressalglen = *p >= sizeof(c_compressalg) ? sizeof(c_compressalg)-1 : *p;
		memcpy(c_compressalg, p+1, c_compressalglen);
		c_compressalg[c_compressalglen] = 0;
		if (!valid_compress(c_compressalg)) {
			hx_printf_prefix(htlc, 0, INFOPREFIX,
					 "Bad client compress algorithm %s\n", c_compressalg);
			goto ret_badcompress_a;
		} else if (!valid_compress(s_compressalg)) {
			hx_printf_prefix(htlc, 0, INFOPREFIX,
					 "Bad server compress algorithm %s\n", s_compressalg);
ret_badcompress_a:
			compressalglistlen = 0;
			hx_htlc_close(htlc);
			return;
		} else {
			S16HTON(1, compressalglist);
			compressalglistlen = 2;
			compressalglist[compressalglistlen] = s_compressalglen;
			compressalglistlen++;
			memcpy(compressalglist+compressalglistlen, s_compressalg, s_compressalglen);
			compressalglistlen += s_compressalglen;
		}
no_compress:
		hc++;
#endif
#ifdef CONFIG_CIPHER
		if (!htlc->cipheralg[0] || !strcmp(htlc->cipheralg, "NONE")) {
			hx_printf_prefix(htlc, 0, INFOPREFIX,
					 "WARNING: this connection is not encrypted\n");
			cipheralglistlen = 0;
			goto no_cipher;
		}
		if (!c_cipher_al_len || !s_cipher_al_len) {
no_cal:			hx_printf_prefix(htlc, 0, INFOPREFIX,
					 "No cipher algorithm from server\n");
			hx_htlc_close(htlc);
			return;
		}
		p = list_n(s_cipher_al, s_cipher_al_len, 0);
		if (!p || !*p)
			goto no_cal;
		s_cipheralglen = *p >= sizeof(s_cipheralg) ? sizeof(s_cipheralg)-1 : *p;
		memcpy(s_cipheralg, p+1, s_cipheralglen);
		s_cipheralg[s_cipheralglen] = 0;
		p = list_n(c_cipher_al, c_cipher_al_len, 0);
		if (!p || !*p)
			goto no_cal;
		c_cipheralglen = *p >= sizeof(c_cipheralg) ? sizeof(c_cipheralg)-1 : *p;
		memcpy(c_cipheralg, p+1, c_cipheralglen);
		c_cipheralg[c_cipheralglen] = 0;
		if (!valid_cipher(c_cipheralg)) {
			hx_printf_prefix(htlc, 0, INFOPREFIX,
					 "Bad client cipher algorithm %s\n", c_cipheralg);
			goto ret_badca;
		} else if (!valid_cipher(s_cipheralg)) {
			hx_printf_prefix(htlc, 0, INFOPREFIX,
					 "Bad server cipher algorithm %s\n", s_cipheralg);
ret_badca:
			cipheralglistlen = 0;
			hx_htlc_close(htlc);
			return;
		} else {
			S16HTON(1, cipheralglist);
			cipheralglistlen = 2;
			cipheralglist[cipheralglistlen] = s_cipheralglen;
			cipheralglistlen++;
			memcpy(cipheralglist+cipheralglistlen, s_cipheralg, s_cipheralglen);
			cipheralglistlen += s_cipheralglen;
		}

		/* server key first */
		pmaclen = hmac_xxx(htlc->cipher_decode_key, htlc->password, strlen(htlc->password),
				   password_mac, pmaclen, htlc->macalg);
		htlc->cipher_decode_keylen = pmaclen;
		pmaclen = hmac_xxx(htlc->cipher_encode_key, htlc->password, strlen(htlc->password),
				   htlc->cipher_decode_key, pmaclen, htlc->macalg);
		htlc->cipher_encode_keylen = pmaclen;
no_cipher:
		hc++;
#endif
		memset(htlc->password, 0, sizeof(htlc->password));
		hlwrite(htlc, HTLC_HDR_LOGIN, 0, hc,
			HTLC_DATA_LOGIN, llen, login,
			HTLC_DATA_PASSWORD, pmaclen, password_mac,
#ifdef CONFIG_CIPHER
			HTLS_DATA_CIPHER_ALG, cipheralglistlen, cipheralglist,
#endif
#ifdef CONFIG_COMPRESS
			HTLS_DATA_COMPRESS_ALG, compressalglistlen, compressalglist,
#endif
			HTLC_DATA_NAME, strlen(htlc->name), htlc->name,
			HTLC_DATA_ICON, 2, &icon16);
#ifdef CONFIG_COMPRESS
		if (compressalglistlen) {
			hx_printf_prefix(htlc, 0, INFOPREFIX, "compress: server %s client %s\n",
					 c_compressalg, s_compressalg);
			if (c_compress_al_len) {
				htlc->compress_encode_type = COMPRESS_GZIP;
				compress_encode_init(htlc);
			}
			if (s_compress_al_len) {
				htlc->compress_decode_type = COMPRESS_GZIP;
				compress_decode_init(htlc);
			}
		}
#endif
#ifdef CONFIG_CIPHER
		if (cipheralglistlen) {
			hx_printf_prefix(htlc, 0, INFOPREFIX, "cipher: server %s client %s\n",
					 c_cipheralg, s_cipheralg);
			if (!strcmp(s_cipheralg, "RC4"))
				htlc->cipher_decode_type = CIPHER_RC4;
			else if (!strcmp(s_cipheralg, "BLOWFISH"))
				htlc->cipher_decode_type = CIPHER_BLOWFISH;
			else if (!strcmp(s_cipheralg, "IDEA"))
				htlc->cipher_decode_type = CIPHER_IDEA;
			if (!strcmp(c_cipheralg, "RC4"))
				htlc->cipher_encode_type = CIPHER_RC4;
			else if (!strcmp(c_cipheralg, "BLOWFISH"))
				htlc->cipher_encode_type = CIPHER_BLOWFISH;
			else if (!strcmp(c_cipheralg, "IDEA"))
				htlc->cipher_encode_type = CIPHER_IDEA;
			cipher_encode_init(htlc);
			cipher_decode_init(htlc);
		}
#endif
	} else {
#endif /* CONFIG_HOPE */
		inaddr2str(abuf, &htlc->sockaddr);
		hx_printf_prefix(htlc, 0, INFOPREFIX, "%s:%u: login %s\n",
			  abuf, ntohs(htlc->sockaddr.SIN_PORT), task_inerror(htlc) ? "failed?" : "successful");

		if (!task_inerror(htlc)) {
			hx_chat_new(htlc, 0);
			play_sound(snd_login);
			dh_start(htlc)
				switch (dh_type) {
					case HTLS_DATA_UID:
						dh_getint(uid);
						htlc->uid = uid;
						break;
					case HTLS_DATA_SERVERVERSION:
						dh_getint(htlc->serverversion);
						break;
					case HTLS_DATA_BANNERID:
						break;
					case HTLS_DATA_SERVERNAME:
						hx_printf_prefix(htlc, 0, INFOPREFIX, "servername: %.*s\n", dh_len, dh_data);
						break;
				}
			dh_end()
			if (htlc->clientversion >= 150 && htlc->serverversion < 150) {
				icon16 = htons(htlc->icon);
				hlwrite(htlc, HTLC_HDR_USER_CHANGE, 0, 2,
					HTLC_DATA_NAME, strlen(htlc->name), htlc->name,
					HTLC_DATA_ICON, 2, &icon16);
			}
		hx_output.on_connect(htlc);
		}
#ifdef CONFIG_HOPE
	}
#endif
}
Example #8
0
void
rcv_chat_join (struct htlc_conn *htlc)
{
   u_int32_t ref = 0;
   u_int16_t passlen = 0;
   u_int16_t uid, icon16, color;
   u_int8_t *pass = 0;
   struct htlc_chat *chat;

   dh_start(htlc)
      switch (dh_type) {
         case HTLC_DATA_CHAT_ID:
            dh_getint(ref);
            break;
         case HTLC_DATA_PASSWORD:
            passlen = dh_len > 31 ? 31 : dh_len;
            pass = dh_data;
            break;
      }
   dh_end()

   if (!ref) {
      send_taskerror(htlc, "huh?!?");
      return;
   }

   chat = chat_lookup_ref(ref);
   if (!chat) {
      send_taskerror(htlc, "who?!?");
      return;
   }
   if (!chat_isset(htlc, chat, 1)) {
      if (chat->passwordlen && (passlen != chat->passwordlen || memcmp(chat->password, pass, passlen))) {
         send_taskerror(htlc, "Uh, no.");
         return;
      }
   } else
      chat_clr(htlc, chat, 1);
   chat_set(htlc, chat, 0);
   {
      struct qbuf *q = &htlc->out;
      u_int32_t this_off = q->pos + q->len, pos = this_off + SIZEOF_HL_HDR;
      u_int32_t len;
      struct hl_hdr h;
      struct hl_userlist_hdr uh;
      u_int16_t nlen;
      struct htlc_conn *htlcp;
      struct hl_data_hdr dh;
      u_int16_t slen;

      q->len += SIZEOF_HL_HDR;
      q->buf = xrealloc(q->buf, q->pos + q->len);
      ref = htonl(ref);
      uid = htons(htlc->uid);
      icon16 = htons(htlc->icon);
      color = htons(htlc->color);
      for (htlcp = htlc_list->next; htlcp; htlcp = htlcp->next) {
         if (!chat_isset(htlcp, chat, 0))
            continue;
         if (htlcp != htlc)
            hlwrite(htlcp, HTLS_HDR_CHAT_USER_CHANGE, 0, 5,
               HTLS_DATA_CHAT_ID, sizeof(ref), &ref,
               HTLS_DATA_UID, sizeof(uid), &uid,
               HTLS_DATA_ICON, sizeof(icon16), &icon16,
               HTLS_DATA_COLOUR, sizeof(color), &color,
               HTLS_DATA_NAME, strlen(htlc->name), htlc->name);
         nlen = strlen(htlcp->name);
         uh.type = htons(HTLS_DATA_USER_LIST);
         uh.len = htons(8 + nlen);
         uh.uid = htons(htlcp->uid);
         uh.icon = htons(htlcp->icon);
         uh.color = htons(htlcp->color);
         uh.nlen = htons(nlen);
         q->len += SIZEOF_HL_USERLIST_HDR + nlen;
         q->buf = xrealloc(q->buf, q->pos + q->len);
         memcpy(&q->buf[pos], &uh, SIZEOF_HL_USERLIST_HDR);
         pos += SIZEOF_HL_USERLIST_HDR;
         memcpy(&q->buf[pos], htlcp->name, nlen);
         pos += nlen;
      }

      slen = chat->subjectlen;
      q->len += SIZEOF_HL_DATA_HDR + slen;
      q->buf = xrealloc(q->buf, q->pos + q->len);
      dh.type = htons(HTLS_DATA_CHAT_SUBJECT);
      dh.len = htons(slen);
      memcpy(&q->buf[pos], &dh, SIZEOF_HL_DATA_HDR);
      pos += SIZEOF_HL_DATA_HDR;
      memcpy(&q->buf[pos], chat->subject, slen);
      pos += slen;

      h.type = htonl(HTLS_HDR_TASK);
      h.trans = htonl(htlc->trans);
      htlc->trans++;
      h.flag = 0;
      len = pos - this_off;
      h.len = h.len2 = htonl(len - (SIZEOF_HL_HDR - sizeof(h.hc)));
      h.hc = htons(chat->nusers + 1);
      memory_copy(q->buf + this_off, &h, SIZEOF_HL_HDR);
      FD_SET(htlc->fd, &hxd_wfds);
#ifdef CONFIG_COMPRESS
      if (htlc->compress_encode_type != COMPRESS_NONE)
         len = compress_encode(htlc, this_off, len);
#endif
#ifdef CONFIG_CIPHER
      if (htlc->cipher_encode_type != CIPHER_NONE)
         cipher_encode(htlc, this_off, len);
#endif

   }
}