Пример #1
0
/**
 * Print EDonkey 2000 url for given file to a stream.
 *
 * @param out the stream where to print url to
 * @param filename the file name
 * @param filesize the file size
 * @param sums the file hash sums
 */
static void fprint_ed2k_url(FILE* out, struct file_info *info, int print_type)
{
	const char *filename = get_basename(file_info_get_utf8_print_path(info));
	int upper_case = (print_type & PRINT_FLAG_UPPERCASE ? RHPR_UPPERCASE : 0);
	int len = urlencode(NULL, filename) + int_len(info->size) + (info->sums_flags & RHASH_AICH ? 84 : 49);
	char* buf = (char*)rsh_malloc( len + 1 );
	char* dst = buf;

	assert(info->sums_flags & (RHASH_ED2K|RHASH_AICH));
	assert(info->rctx);

	strcpy(dst, "ed2k://|file|");
	dst += 13;
	dst += urlencode(dst, filename);
	*dst++ = '|';
	sprintI64(dst, info->size, 0);
	dst += strlen(dst);
	*dst++ = '|';
	rhash_print(dst, info->rctx, RHASH_ED2K, upper_case);
	dst += 32;
	if((info->sums_flags & RHASH_AICH) != 0) {
		strcpy(dst, "|h=");
		rhash_print(dst += 3, info->rctx, RHASH_AICH, RHPR_BASE32 | upper_case);
		dst += 32;
	}
	strcpy(dst, "|/");
	fprintf(out, "%s", buf);
	free(buf);
}
Пример #2
0
/**
 * Print verbose error on hash sums mismatch.
 *
 * @param info file information with path and its hash sums.
 */
static void print_verbose_error(struct file_info *info)
{
	char actual[130], expected[130];
	assert(HC_FAILED(info->hc.flags));

	rsh_fprintf(rhash_data.out, _("ERROR"));

	if (HC_WRONG_FILESIZE & info->hc.flags) {
		sprintI64(actual, info->rctx->msg_size, 0);
		sprintI64(expected, info->hc.file_size, 0);
		rsh_fprintf(rhash_data.out, _(", size is %s should be %s"), actual, expected);
	}

	if (HC_WRONG_EMBCRC32 & info->hc.flags) {
		rhash_print(expected, info->rctx, RHASH_CRC32, RHPR_UPPERCASE);
		rsh_fprintf(rhash_data.out, _(", embedded CRC32 should be %s"), expected);
	}

	if (HC_WRONG_HASHES & info->hc.flags) {
		int i;
		unsigned reported = 0;
		for (i = 0; i < info->hc.hashes_num; i++) {
			hash_value *hv = &info->hc.hashes[i];
			char *expected_hash = info->hc.data + hv->offset;
			unsigned hid = hv->hash_id;
			int pflags;
			if ((info->hc.wrong_hashes & (1 << i)) == 0) continue;

			assert(hid != 0);

			/* if can't detect precise hash */
			if ((hid & (hid - 1)) != 0) {
				/* guess the hash id */
				if (hid & opt.sum_flags) hid &= opt.sum_flags;
				if (hid & ~info->hc.found_hash_ids) hid &= ~info->hc.found_hash_ids;
				if (hid & ~reported) hid &= ~reported; /* avoiding repeating */
				if (hid & REPORT_FIRST_MASK) hid &= REPORT_FIRST_MASK;
				hid &= -(int)hid; /* take the lowest bit */
			}
			assert(hid != 0 && (hid & (hid - 1)) == 0); /* single bit only */
			reported |= hid;

			pflags = (hv->length == (rhash_get_digest_size(hid) * 2) ?
				(RHPR_HEX | RHPR_UPPERCASE) : (RHPR_BASE32 | RHPR_UPPERCASE));
			rhash_print(actual, info->rctx, hid, pflags);
			rsh_fprintf(rhash_data.out, _(", %s is %s should be %s"),
				rhash_get_name(hid), actual, expected_hash);
		}
	}

	rsh_fprintf(rhash_data.out, "\n");
}
Пример #3
0
/**
 * Verify for all algorithms, that rhash_final() returns the same result as
 * rhash_print().
 */
static void test_results_consistency(void)
{
	const char * msg = "a";
	size_t msg_size = strlen(msg);

	size_t digest_size;
	struct rhash_context *ctx;
	unsigned char res1[70];
	char res2[70];
	unsigned i, hash_id;

	for(i = 0, hash_id = 1; (hash_id & RHASH_ALL_HASHES); hash_id <<= 1, i++) {
		digest_size = rhash_get_digest_size(hash_id);
		assert(digest_size < 70);

		ctx = rhash_init(hash_id);

#ifdef USE_BTIH_WITH_TEST_FILENAME
		if((hash_id & RHASH_BTIH) != 0) {
			unsigned long long total_size = msg_size;
			rhash_transmit(RMSG_BT_ADD_FILE, ctx, RHASH_STR2UPTR("test.txt"), (rhash_uptr_t)&total_size);
		}
#endif

		rhash_update(ctx, msg, msg_size);
		rhash_final(ctx, res1);
		rhash_print(res2, ctx, hash_id, RHPR_RAW);
		rhash_free(ctx);

		if(memcmp(res1, res2, digest_size) != 0) {
			log_message("failed: inconsistent %s(\"%s\") hash results\n", rhash_get_name(hash_id), msg);
		}
	}
}
Пример #4
0
/*
 * Class:     org_sf_rhash_Bindings
 * Method:    rhash_print
 * Signature: (JI)J
 */
JNIEXPORT jlong JNICALL Java_org_sf_rhash_Bindings_rhash_1print
(JNIEnv *env, jclass clz, jlong context, jint hash_id) {
	Digest obj = malloc(sizeof(DigestStruct));
	obj->hash_len  = rhash_get_digest_size(hash_id);
	obj->hash_data = calloc(obj->hash_len, sizeof(unsigned char));
	rhash_print((char*)obj->hash_data, TO_RHASH(context), hash_id, RHPR_RAW);
	return TO_JLONG(obj);
}
Пример #5
0
/**
 * Calculate hash of the message specified by chunk string, repeated until
 * the given length is reached.
 *
 * @param chunk a null-terminated string representing the chunk
 * @param msg_size the total message length
 * @param length the total length of the message
 * @param hash_id id of the hash algorithm to use
 */
static char* calc_sums_c(const char* chunk, size_t msg_size, size_t length, unsigned hash_id)
{
    struct rhash_context *ctx;
    static char out[130];
    size_t i;

    ctx = rhash_init(hash_id);
    for(i = 0; i < length; i += msg_size) {
        rhash_update(ctx, (const unsigned char*)chunk,
                     ((i + msg_size) <= length ? msg_size : length % msg_size));
    }
    rhash_final(ctx, hash_id, 0);
    rhash_print(out, ctx, hash_id, RHPR_UPPERCASE);
    rhash_free(ctx);
    return out;
}
Пример #6
0
/**
 * Calculate hash of the message specified by chunk string, repeated until
 * the given length is reached.
 *
 * @param hash_id id of the hash algorithm to use
 * @param msg_chunk the message chunk as a null-terminated string
 * @param chunk_size the size of the chunk in bytes
 * @param count the number of chunks in the message
 * @param set_filename need to set a filename for BTIH hash
 */
static char* repeat_hash(unsigned hash_id, const char* chunk, size_t chunk_size, size_t msg_size, int set_filename)
{
	struct rhash_context *ctx;
	size_t left, size;
	static char out[130];
	assert(rhash_get_hash_length(hash_id) < 130);

	ctx = rhash_init(hash_id);

	if((hash_id & RHASH_BTIH) && set_filename) {
		unsigned long long total_size = msg_size;
		rhash_transmit(RMSG_BT_ADD_FILE, ctx, RHASH_STR2UPTR("test.txt"), (rhash_uptr_t)&total_size);
	}

	for(left = msg_size; left > 0; left -= size) {
		size = (left > chunk_size ? chunk_size : left);
		rhash_update(ctx, (const unsigned char*)chunk, size);
	}
	rhash_final(ctx, 0);
	rhash_print(out, ctx, hash_id, RHPR_UPPERCASE);
	rhash_free(ctx);
	return out;
}
Пример #7
0
/**
 * Rename given file inserting its crc32 sum enclosed into square braces
 * and placing it right before the file extension.
 *
 * @param info pointer to the data of the file to rename.
 * @return 0 on success, -1 on fail with error code in errno
 */
int rename_file_by_embeding_crc32(struct file_info *info)
{
	size_t len = strlen(info->full_path);
	const char* p = info->full_path + len;
	const char* c = p - 1;
	char* new_path;
	char* insertion_point;
	unsigned crc32_be;
	assert((info->rctx->hash_id & RHASH_CRC32) != 0);

	/* check if the filename contains a CRC32 hash sum */
	if(find_embedded_crc32(info->print_path, &crc32_be)) {
		unsigned char* c =
			(unsigned char*)rhash_get_context_ptr(info->rctx, RHASH_CRC32);
		unsigned actual_crc32 = ((unsigned)c[0] << 24) |
			((unsigned)c[1] << 16) | ((unsigned)c[2] << 8) | (unsigned)c[3];

		/* compare with calculated CRC32 */
		if(crc32_be != actual_crc32) {
			char crc32_str[9];
			rhash_print(crc32_str, info->rctx, RHASH_CRC32, RHPR_UPPERCASE);
			/* TRANSLATORS: sample filename with embedded CRC32: file_[A1B2C3D4].mkv */
			log_warning(_("wrong embedded CRC32, should be %s\n"), crc32_str);
		} else return 0;
	}

	/* find file extension (as the place to insert the hash sum) */
	for(; c >= info->full_path && !IS_PATH_SEPARATOR(*c); c--) {
		if(*c == '.') {
			p = c;
			break;
		}
	}

	/* now p is the point to insert delimiter + hash string in brackets */
	new_path = (char*)rsh_malloc(len + 12);
	insertion_point = new_path + (p - info->full_path);
	memcpy(new_path, info->full_path, p - info->full_path);
	if(opt.embed_crc_delimiter && *opt.embed_crc_delimiter) *(insertion_point++) = *opt.embed_crc_delimiter;
	rhash_print(insertion_point+1, info->rctx, RHASH_CRC32, RHPR_UPPERCASE);
	insertion_point[0] = '[';
	insertion_point[9] = ']'; /* ']' overrides '\0' inserted by rhash_print_sum() */
	strcpy(insertion_point + 10, p); /* append file extension */

	/* rename the file */
	if(rename(info->full_path, new_path) < 0) {
		log_error(_("can't move %s to %s: %s\n"), info->full_path, new_path,
			strerror(errno));
		free(new_path);
		return -1;
	}

	/* change file name in the file info structure */
	if(info->print_path >= info->full_path && info->print_path < p) {
		file_info_set_print_path(info, new_path + len - strlen(info->print_path));
	} else {
		file_info_set_print_path(info, new_path);
	}

	free(info->full_path);
	info->full_path = new_path;
	return 0;
}
Пример #8
0
/**
 * Print formated file information to given output stream.
 *
 * @param out the stream to print information to
 * @param list the format according to which information shall be printed
 * @param info the file information
 */
void print_line(FILE* out, print_item* list, struct file_info *info)
{
	const char* basename = get_basename(info->print_path), *tmp;
	char *url = NULL, *ed2k_url = NULL;
	char buffer[130];

	for(; list; list = list->next) {
		int print_type = list->flags & ~(PRINT_FLAGS_ALL);
		size_t len;

		/* output a hash function digest */
		if(list->hash_id && print_type != PRINT_ED2K_LINK) {
			unsigned hash_id = list->hash_id;
			int print_flags = (list->flags & PRINT_FLAG_UPPERCASE ? RHPR_UPPERCASE : 0)
				| (list->flags & PRINT_FLAG_RAW ? RHPR_RAW : 0)
				| (list->flags & PRINT_FLAG_BASE32 ? RHPR_BASE32 : 0)
				| (list->flags & PRINT_FLAG_BASE64 ? RHPR_BASE64 : 0)
				| (list->flags & PRINT_FLAG_HEX ? RHPR_HEX : 0);
			if((hash_id == RHASH_GOST || hash_id == RHASH_GOST_CRYPTOPRO) && (opt.flags & OPT_GOST_REVERSE))
				print_flags |= RHPR_REVERSE;

			len = rhash_print(buffer, info->rctx, hash_id, print_flags);
			assert(len < sizeof(buffer));

			/* output the hash, exit on fail */
			if(fwrite(buffer, 1, len, out) != len) break;
			continue;
		}

		/* output other special items: filepath, URL-encoded filename etc. */
		switch(print_type) {
			case PRINT_STR:
				fprintf(out, "%s", list->data);
				break;
			case PRINT_ZERO: /* the '\0' character */
				fprintf(out, "%c", 0);
				break;
			case PRINT_FILEPATH:
				fprintf(out, "%s", info->print_path);
				break;
			case PRINT_BASENAME: /* the filename without directory */
				fprintf(out, "%s", basename);
				break;
			case PRINT_URLNAME: /* URL-encoded filename */
				if(!url) {
					tmp = get_basename(file_info_get_utf8_print_path(info));
					url = (char*)rsh_malloc(urlencode(NULL, tmp) + 1);
					urlencode(url, tmp);
				}
				fprintf(out, "%s", url);
				break;
			case PRINT_MTIME: /* the last-modified tine of the filename */
				print_time(out, info->stat_buf.st_mtime);
				break;
			case PRINT_SIZE: /* file size */
				fprintI64(out, info->size, list->width, (list->flags & PRINT_FLAG_PAD_WITH_ZERO));
				break;
			case PRINT_ED2K_LINK:
				fprint_ed2k_url(out, info, list->flags);
				break;
		}
	}
	free(url);
	free(ed2k_url);
}