diff -urpN jumbo-unstable3/src/cracker.c jumbo-unstable2/src/cracker.c
--- jumbo-unstable3/src/cracker.c	2012-05-29 02:08:19.656250000 +0000
+++ jumbo-unstable2/src/cracker.c	2012-05-25 16:30:06.593750000 +0000
@@ -37,6 +37,16 @@ static struct db_keys *crk_guesses;
 static int64 *crk_timestamps;
 static char crk_stdout_key[PLAINTEXT_BUFFER_SIZE];
 
+static char *get_source(struct db_password *current_pw)
+{
+	static char SourceBuf[LINE_BUFFER_SIZE];
+	char *cp;
+	if (current_pw->source) return current_pw->source;
+	cp = crk_db->format->methods.get_source(current_pw->binary, NULL, SourceBuf);
+	current_pw->source = str_alloc_copy(cp);
+	return current_pw->source;
+}
+
 static void crk_dummy_set_salt(void *salt)
 {
 }
@@ -216,7 +226,7 @@ static int crk_process_guess(struct db_s
 		}
 	}
 	log_guess(crk_db->options->flags & DB_LOGIN ? replogin : "?",
-		dupe ? NULL : pw->source, repkey, key, crk_db->options->field_sep_char);
+		dupe ? NULL : get_source(pw), repkey, key, crk_db->options->field_sep_char);
 
 	if (options.flags & FLG_CRKSTAT)
 		event_pending = event_status = 1;
@@ -287,7 +297,7 @@ static int crk_password_loop(struct db_s
 			if (crk_methods.cmp_all(pw->binary, crk_key_index))
 			for (index = 0; index < crk_key_index; index++)
 			if (crk_methods.cmp_one(pw->binary, index))
-			if (crk_methods.cmp_exact(pw->source, index)) {
+			if (!pw->source || crk_methods.cmp_exact(pw->source, index)) {
 				if (crk_process_guess(salt, pw, index))
 					return 1;
 				else {
@@ -301,7 +311,7 @@ static int crk_password_loop(struct db_s
 		if ((pw = salt->hash[salt->index(index)]))
 		do {
 			if (crk_methods.cmp_one(pw->binary, index))
-			if (crk_methods.cmp_exact(pw->source, index))
+			if (!pw->source || crk_methods.cmp_exact(pw->source, index))
 			if (crk_process_guess(salt, pw, index))
 				return 1;
 		} while ((pw = pw->next_hash));
diff -urpN jumbo-unstable3/src/dynamic.h jumbo-unstable2/src/dynamic.h
--- jumbo-unstable3/src/dynamic.h	2012-05-29 02:08:20.906250000 +0000
+++ jumbo-unstable2/src/dynamic.h	2012-05-25 17:20:09.078125000 +0000
@@ -85,6 +85,8 @@ typedef struct DYNAMIC_Constants_t
 #define MGF_RAW_SHA1_INPUT               0x0200
 #define MGF_KEYS_INPUT_BE_SAFE           0x0400
 #define MGF_SET_INP2LEN32                0x0800
+#define MGF_GET_SOURCE                   0x2000
+#define MGF_GET_SOURCE_SHA               0x4000
 
 typedef struct DYNAMIC_Setup_t
 {
diff -urpN jumbo-unstable3/src/dynamic_fmt.c jumbo-unstable2/src/dynamic_fmt.c
--- jumbo-unstable3/src/dynamic_fmt.c	2012-05-29 02:08:20.953125000 +0000
+++ jumbo-unstable2/src/dynamic_fmt.c	2012-05-25 18:17:31.093750000 +0000
@@ -845,10 +845,11 @@ static void init(struct fmt_main *pFmt)
  *********************************************************************************/
 static char *prepare(char *split_fields[10], struct fmt_main *pFmt)
 {
+	static char ct[512];
 	char Tmp[80];
 	int i;
 
-	char *cpBuilding=split_fields[1], *cpTmp=NULL;
+	char *cpBuilding=split_fields[1];
 
 	init(pFmt);
 
@@ -865,7 +866,6 @@ static char *prepare(char *split_fields[
 	// $dynamic_x$ will be written out (into .pot, output lines, etc).
 	if (!strncmp(cpBuilding, "md5_gen(", 8))
 	{
-		char *ct = mem_alloc_tiny(strlen(cpBuilding) + 6, MEM_ALIGN_NONE);
 		char *cp = &cpBuilding[8], *cpo = &ct[sprintf(ct, "$dynamic_")];
 		while (*cp >= '0' && *cp <= '9')
 			*cpo++ = *cp++;
@@ -884,7 +884,6 @@ static char *prepare(char *split_fields[
 	/* the ONE exception to this, is if there is a NULL byte in the $HEX$ string, then we MUST leave that $HEX$ string */
 	/* alone, and let the later calls in dynamic.c handle them. */
 	if (strstr(cpBuilding, "$HEX$")) {
-		char *ct = mem_alloc_tiny(strlen(cpBuilding)+1, MEM_ALIGN_NONE);
 		char *cp, *cpo;
 		int bGood=1;
 
@@ -926,16 +925,14 @@ static char *prepare(char *split_fields[
 		if (cp)
 			userName = &cp[1];
 		userName = HandleCase(userName, curdat.nUserName);
-		cpTmp = mem_alloc_tiny(strlen(cpBuilding) + 1 + 3 + strlen(userName), MEM_ALIGN_NONE);
-		sprintf (cpTmp, "%s$$U%s", cpBuilding, userName);
-		cpBuilding = cpTmp;
+		sprintf (ct, "%s$$U%s", cpBuilding, userName);
+		cpBuilding = ct;
 	}
 	for (i = 0; i <= 8; ++i) {
 		sprintf(Tmp, "$$F%d", i);
 		if ( split_fields[i] &&  (curdat.FldMask&(MGF_FLDx_BIT<<i)) && !strstr(cpBuilding, Tmp)) {
-			cpTmp = mem_alloc_tiny(strlen(cpBuilding) + 1 + 4 + strlen(split_fields[i]), MEM_ALIGN_NONE);
-			sprintf (cpTmp, "%s$$F%d%s", cpBuilding, i, split_fields[i]);
-			cpBuilding = cpTmp;
+			sprintf (ct, "%s$$F%d%s", cpBuilding, i, split_fields[i]);
+			cpBuilding = ct;
 		}
 	}
 	return cpBuilding;
@@ -2099,6 +2096,39 @@ static void *binary(char *_ciphertext)
 	}
 	return (void *)realcipher;
 }
+
+static char *get_source(void *bin, void *salt, char Buf[LINE_BUFFER_SIZE] )
+{
+	char *cpo = Buf;
+	unsigned char *cpi;
+	int i;
+	cpo += sprintf(Buf, "%s", curdat.dynamic_WHICH_TYPE_SIG);
+	cpi = (unsigned char*)bin;
+	for (i = 0; i < 16; ++i) {
+		*cpo++ = itoa16[(*cpi)>>4];
+		*cpo++ = itoa16[*cpi&0xF];
+		++cpi;
+	}
+	*cpo = 0;
+	return Buf;
+}
+
+static char *get_source_sha(void *bin, void *salt, char Buf[LINE_BUFFER_SIZE] )
+{
+	char *cpo = Buf;
+	unsigned char *cpi;
+	int i;
+	cpo += sprintf(Buf, "%s", curdat.dynamic_WHICH_TYPE_SIG);
+	cpi = (unsigned char*)bin;
+	for (i = 0; i < 20; ++i) {
+		*cpo++ = itoa16[(*cpi)>>4];
+		*cpo++ = itoa16[*cpi&0xF];
+		++cpi;
+	}
+	*cpo = 0;
+	return Buf;
+}
+
 /*********************************************************************************
  * Gets the binary value from a base-64 hash (such as phpass)
  *********************************************************************************/
@@ -2268,7 +2298,8 @@ struct fmt_main fmt_Dynamic =
 		},
 		cmp_all,
 		cmp_one,
-		cmp_exact
+		cmp_exact,
+		fmt_default_get_source
 	}
 };
 
@@ -6945,6 +6976,7 @@ int dynamic_SETUP(DYNAMIC_Setup *Setup,
 	pFmt->methods.binary = binary;
 	pFmt->methods.cmp_all=cmp_all;
 	pFmt->methods.cmp_one=cmp_one;
+	pFmt->methods.get_source=fmt_default_get_source;
 	pFmt->methods.salt = salt;
 	pFmt->methods.set_salt = set_salt;
 	pFmt->methods.salt_hash = salt_hash;
@@ -7093,6 +7125,9 @@ int dynamic_SETUP(DYNAMIC_Setup *Setup,
 	curdat.store_keys_in_input = !!(Setup->startFlags&MGF_KEYS_INPUT );
 	curdat.input2_set_len32 = !!(Setup->startFlags&MGF_SET_INP2LEN32);
 
+	if (Setup->startFlags&MGF_GET_SOURCE) pFmt->methods.get_source = get_source;
+	if (Setup->startFlags&MGF_GET_SOURCE_SHA) pFmt->methods.get_source = get_source_sha;
+
 	if (!curdat.store_keys_in_input && Setup->startFlags&MGF_KEYS_INPUT_BE_SAFE)
 		curdat.store_keys_in_input = 3;
 
@@ -7578,6 +7613,7 @@ struct fmt_main *dynamic_THIN_FORMAT_LIN
 	pFmt->methods.cmp_all    = pFmtLocal->methods.cmp_all;
 	pFmt->methods.cmp_one    = pFmtLocal->methods.cmp_one;
 	pFmt->methods.cmp_exact  = pFmtLocal->methods.cmp_exact;
+	pFmt->methods.get_source = pFmtLocal->methods.get_source;
 	pFmt->methods.set_salt   = pFmtLocal->methods.set_salt;
 	pFmt->methods.salt       = pFmtLocal->methods.salt;
 	pFmt->methods.salt_hash  = pFmtLocal->methods.salt_hash;
diff -urpN jumbo-unstable3/src/dynamic_parser.c jumbo-unstable2/src/dynamic_parser.c
--- jumbo-unstable3/src/dynamic_parser.c	2012-05-29 02:08:20.984375000 +0000
+++ jumbo-unstable2/src/dynamic_parser.c	2012-05-25 17:00:42.750000000 +0000
@@ -357,6 +357,9 @@ static MD5Gen_Str_Flag_t MD5Gen_Str_sFla
 	{ "MGF_RAW_SHA1_INPUT",               MGF_RAW_SHA1_INPUT },
 	{ "MGF_KEYS_INPUT_BE_SAFE",           MGF_KEYS_INPUT_BE_SAFE },  // big endian safe, i.e. the input will NEVER get swapped.  Only SHA1 is 'safe'.
 	{ "MGF_SET_INP2LEN32",                MGF_SET_INP2LEN32 }, // this sets the input2 lens (in SSE2) to 32 bytes long, but only in init() call
+	{ "MGF_GET_SOURCE",                   MGF_GET_SOURCE },
+	{ "MGF_GET_SOURCE_SHA",               MGF_GET_SOURCE_SHA },
+
 	{ NULL, 0 }};
 
 static DYNAMIC_Setup Setup;
diff -urpN jumbo-unstable3/src/dynamic_preloads.c jumbo-unstable2/src/dynamic_preloads.c
--- jumbo-unstable3/src/dynamic_preloads.c	2012-05-29 02:08:21.000000000 +0000
+++ jumbo-unstable2/src/dynamic_preloads.c	2012-05-25 17:19:08.453125000 +0000
@@ -865,7 +865,7 @@ static DYNAMIC_Constants _ConstDefault[]
 // Here are the 'prebuilt' dynamic objects, ready to be 'loaded'
 static DYNAMIC_Setup Setups[] =
 {
-	{ "dynamic_0: md5($p)  (raw-md5) ",           _Funcs_0, _Preloads_0, _ConstDefault, MGF_NO_FLAG, MGF_KEYS_INPUT },
+	{ "dynamic_0: md5($p)  (raw-md5) ",           _Funcs_0, _Preloads_0, _ConstDefault, MGF_NO_FLAG, MGF_KEYS_INPUT|MGF_GET_SOURCE },
 #if defined (MMX_COEF)
 	{ "dynamic_1: md5($p.$s)  (joomla) ",         _Funcs_1, _Preloads_1, _ConstDefault, MGF_SALTED, MGF_NO_FLAG, -32, 23 },
 #else
diff -urpN jumbo-unstable3/src/formats.c jumbo-unstable2/src/formats.c
--- jumbo-unstable3/src/formats.c	2012-05-29 02:08:21.140625000 +0000
+++ jumbo-unstable2/src/formats.c	2012-05-29 03:37:46.671875000 +0000
@@ -10,6 +10,7 @@
 
 #include "params.h"
 #include "formats.h"
+#include "memory.h"
 #ifndef BENCH_BUILD
 #include "options.h"
 #endif
@@ -53,6 +54,32 @@ char *fmt_self_test(struct fmt_main *for
 	int ntests, done, index, max, size;
 	void *binary, *salt;
 
+	// for now, simple set these pointers here.  Later when we merge into jumbo, ALL
+	// of them will be properly set withing the format structures. But for now, this
+	// makes the patch file MUCH smaller
+	if (format->methods.get_source == NULL)
+		format->methods.get_source = fmt_default_get_source;
+
+	// validate that there are no NULL function pointers
+	if (format->methods.init == NULL)       return "method init NULL";
+	if (format->methods.prepare == NULL)    return "method prepare NULL";
+	if (format->methods.valid == NULL)      return "method valid NULL";
+	if (format->methods.split == NULL)      return "method split NULL";
+	if (format->methods.binary == NULL)     return "method binary NULL";
+	if (format->methods.salt == NULL)       return "method salt NULL";
+	if (!format->methods.binary_hash[0])    return "method binary_hash[0] NULL";
+	if (format->methods.salt_hash == NULL)  return "method salt_hash NULL";
+	if (format->methods.set_salt == NULL)   return "method set_salt NULL";
+	if (format->methods.set_key == NULL)    return "method set_key NULL";
+	if (format->methods.get_key == NULL)    return "method get_key NULL";
+	if (format->methods.clear_keys == NULL) return "method clear_keys NULL";
+	if (format->methods.crypt_all == NULL)  return "method crypt_all NULL";
+	if (format->methods.get_hash[0]==NULL)  return "method get_hash[0] NULL";
+	if (format->methods.cmp_all == NULL)    return "method cmp_all NULL";
+	if (format->methods.cmp_one == NULL)    return "method cmp_one NULL";
+	if (format->methods.cmp_exact == NULL)  return "method cmp_exact NULL";
+	if (format->methods.get_source == NULL) return "method get_source NULL";
+
 	if (format->params.plaintext_length > PLAINTEXT_BUFFER_SIZE - 3)
 		return "length";
 
@@ -70,7 +97,7 @@ char *fmt_self_test(struct fmt_main *for
 	done = 0;
 	index = 0; max = format->params.max_keys_per_crypt;
 	do {
-		char *prepared;
+		char *prepared, *sourced, Buf[LINE_BUFFER_SIZE];
 		current->flds[1] = current->ciphertext;
 		prepared = format->methods.prepare(current->flds, format);
 		if (!prepared || strlen(prepared) < 7) // $dummy$ can be just 7 bytes long.
@@ -82,6 +109,24 @@ char *fmt_self_test(struct fmt_main *for
 
 		binary = format->methods.binary(ciphertext);
 		salt = format->methods.salt(ciphertext);
+		if (format->methods.get_source != fmt_default_get_source) {
+			sourced = format->methods.get_source(binary, salt, Buf);
+			if (stricmp(sourced, ciphertext)) {
+				void *binary2;
+				if (format->methods.valid(sourced,format) != 1) return "get_source";
+				binary2 = mem_alloc_tiny(format->params.binary_size, MEM_ALIGN_NONE);
+				memcpy(binary2, binary, format->params.binary_size);
+				binary = format->methods.binary(sourced);
+				if (memcmp(binary,binary2,format->params.binary_size)) return "get_source";
+				if (format->params.salt_size) {
+					void *salt2;
+					salt2 = mem_alloc_tiny(format->params.salt_size, MEM_ALIGN_NONE);
+					memcpy(salt2, salt, format->params.salt_size);
+					salt = format->methods.salt(sourced);
+					if (memcmp(salt,salt2,format->params.salt_size)) return "get_source";
+				}
+			}
+		}
 
 		if ((unsigned int)format->methods.salt_hash(salt) >=
 		    SALT_HASH_SIZE)
@@ -199,3 +244,9 @@ int fmt_default_get_hash(int index)
 {
 	return 0;
 }
+
+char *fmt_default_get_source(void *binary_hash, void *salt, char ReturnBuf[LINE_BUFFER_SIZE]) 
+{
+	*ReturnBuf = 0;
+	return ReturnBuf;
+}
diff -urpN jumbo-unstable3/src/formats.h jumbo-unstable2/src/formats.h
--- jumbo-unstable3/src/formats.h	2012-05-29 02:08:21.156250000 +0000
+++ jumbo-unstable2/src/formats.h	2012-05-25 15:47:59.562500000 +0000
@@ -176,6 +176,16 @@ struct fmt_methods {
 
 /* Compares an ASCII ciphertext against a particular crypt_all() output */
 	int (*cmp_exact)(char *source, int index);
+
+/* The format is able to reconstruct the original source hash, from the binary,
+ * and salt. The format will have to store the entire binary in the return from
+ * binary().  This is an optional method, and if set DOES cause JtR to have 
+ * different behavoior. If this pointer is set to fmt_default_get_source, then
+ * JtR will operate in legacy mode.  If this method IS implemented by a format,
+ * then JtR will no longer store the source hashes in memory, and will not call
+ * the cmp_exact() function (i.e. cmp_one must return true only for a FULL match)
+ * and this function must be able to reconstruct the original source hash. */
+	char *(*get_source)(void *binary_hash, void *salt, char ReturnBuf[LINE_BUFFER_SIZE]);
 };
 
 /*
@@ -232,6 +242,8 @@ extern int fmt_default_salt_hash(void *s
 extern void fmt_default_set_salt(void *salt);
 extern void fmt_default_clear_keys(void);
 extern int fmt_default_get_hash(int index);
+extern char *fmt_default_get_source(void *binary_hash, void *salt, char ReturnBuf[LINE_BUFFER_SIZE]);
+
 
 /*
  * Dummy hash function to use for salts with no hash table.
diff -urpN jumbo-unstable3/src/loader.c jumbo-unstable2/src/loader.c
--- jumbo-unstable3/src/loader.c	2012-05-29 02:08:21.859375000 +0000
+++ jumbo-unstable2/src/loader.c	2012-05-29 03:21:53.375000000 +0000
@@ -51,6 +51,15 @@ int ldr_in_pot = 0;
 
 static char *no_username = "?";
 
+static char *get_source(struct db_main *db, struct db_password *current_pw) {
+	static char SourceBuf[LINE_BUFFER_SIZE];
+	char *cp;
+	if (current_pw->source) return current_pw->source;
+	cp = db->format->methods.get_source(current_pw->binary, NULL, SourceBuf);
+	current_pw->source = str_alloc_copy(cp);
+	return current_pw->source;
+}
+
 static void read_file(struct db_main *db, char *name, int flags,
 	void (*process_line)(struct db_main *db, char *line))
 {
@@ -481,7 +490,7 @@ static void ldr_load_pw_line(struct db_m
 			do {
 				if (!memcmp(current_pw->binary, binary,
 				    format->params.binary_size) &&
-				    !strcmp(current_pw->source, piece)) {
+				    (!current_pw->source || !strcmp(current_pw->source, piece)) ) {
 					db->options->flags |= DB_NODUP;
 					break;
 				}
@@ -562,7 +571,10 @@ static void ldr_load_pw_line(struct db_m
 		current_pw->binary = mem_alloc_copy(
 			format->params.binary_size, MEM_ALIGN_WORD, binary);
 
-		current_pw->source = str_alloc_copy(piece);
+		if (format->methods.get_source == fmt_default_get_source)
+			current_pw->source = str_alloc_copy(piece);
+		else
+			current_pw->source = NULL;
 
 		if (db->options->flags & DB_WORDS) {
 			if (!words)
@@ -632,9 +644,10 @@ static void ldr_load_pot_line(struct db_
 			}
 			//else if (db->options->regen_lost_salts == 6 && !strncmp(current->source, "???????????", 11))
 		}
+		// NOTE, if !current->source, then it is a get_source() hash, so we have not stored it, so we avoid the strcmp of the original source strings.
 		if (current->binary && !memcmp(current->binary, binary,
 		    format->params.binary_size) &&
-		    !strcmp(current->source, ciphertext))
+		    (!current->source || !strcmp(current->source, ciphertext)))
 			current->binary = NULL;
 	} while ((current = current->next_hash));
 }
@@ -704,9 +717,9 @@ static void ldr_remove_marked(struct db_
 					if (!options.utf8 && options.report_utf8) {
 						UTF8 utf8login[PLAINTEXT_BUFFER_SIZE + 1];
 						enc_to_utf8_r(current_pw->login, utf8login, PLAINTEXT_BUFFER_SIZE);
-						printf("%s%c%s\n",utf8login,db->options->field_sep_char,current_pw->source);
+						printf("%s%c%s\n",utf8login,db->options->field_sep_char,get_source(db, current_pw));
 					} else
-						printf("%s%c%s\n",current_pw->login,db->options->field_sep_char,current_pw->source);
+						printf("%s%c%s\n",current_pw->login,db->options->field_sep_char,get_source(db, current_pw));
 				}
 			}
 		} while ((current_pw = current_pw->next));
diff -urpN jumbo-unstable3/src/NT_fmt_plug.c jumbo-unstable2/src/NT_fmt_plug.c
--- jumbo-unstable3/src/NT_fmt_plug.c	2012-05-29 02:08:18.781250000 +0000
+++ jumbo-unstable2/src/NT_fmt_plug.c	2012-05-25 16:45:00.046875000 +0000
@@ -630,6 +630,37 @@ static int cmp_exact(char *source, int i
 {
 	return 1;
 }
+static char *get_source(void *bin, void *salt, char Buf[LINE_BUFFER_SIZE] )
+{
+	unsigned int out[4];
+	unsigned char *cpi;
+	char *cpo;
+	int i;
+
+	strcpy(Buf, "$NT$");
+	cpo = &Buf[4];
+
+	// we have to 'undo' the stuff done in the get_binary() function, to get back to the 'original' hash value.
+	memcpy(out, bin, 16);
+	out[1] += SQRT_3;
+	out[1]  = (out[1] >> 17) | (out[1] << 15);
+	out[1] += SQRT_3 + (out[2] ^ out[3] ^ out[0]);
+	out[1]  = (out[1] >> 17) | (out[1] << 15);
+	out[0] += INIT_A;
+	out[1] += INIT_B;
+	out[2] += INIT_C;
+	out[3] += INIT_D;
+
+	cpi = (unsigned char*)out;
+
+	for (i = 0; i < 16; ++i) {
+		*cpo++ = itoa16[(*cpi)>>4];
+		*cpo++ = itoa16[*cpi&0xF];
+		++cpi;
+	}
+	*cpo = 0;
+	return Buf;
+}
 
 // This is common code for the SSE/MMX/generic variants of non-UTF8 set_key
 static inline void set_key_helper(unsigned int * keybuffer,
@@ -968,6 +999,7 @@ struct fmt_main fmt_NT = {
 		},
 		cmp_all,
 		cmp_one,
-		cmp_exact
+		cmp_exact,
+		get_source
 	}
 };
diff -urpN jumbo-unstable3/src/nt2_fmt_plug.c jumbo-unstable2/src/nt2_fmt_plug.c
--- jumbo-unstable3/src/nt2_fmt_plug.c	2012-05-29 02:08:22.812500000 +0000
+++ jumbo-unstable2/src/nt2_fmt_plug.c	2012-05-28 01:05:49.078125000 +0000
@@ -669,6 +669,26 @@ static int get_hash_5(int index) { retur
 static int get_hash_6(int index) { return ((ARCH_WORD_32*)crypt_key)[index] & 0x7ffffff; }
 #endif
 
+static char *get_source(void *bin, void *salt, char Buf[LINE_BUFFER_SIZE] )
+{
+	unsigned char *cpi;
+	char *cpo;
+	int i;
+
+	strcpy(Buf, "$NT$");
+	cpo = &Buf[4];
+
+	cpi = (unsigned char*)bin;
+
+	for (i = 0; i < 16; ++i) {
+		*cpo++ = itoa16[(*cpi)>>4];
+		*cpo++ = itoa16[*cpi&0xF];
+		++cpi;
+	}
+	*cpo = 0;
+	return Buf;
+}
+
 struct fmt_main fmt_magnumNT = {
 	{
 		FORMAT_LABEL,
@@ -719,6 +739,7 @@ struct fmt_main fmt_magnumNT = {
 		},
 		cmp_all,
 		cmp_one,
-		cmp_exact
+		cmp_exact,
+		get_source
 	}
 };
diff -urpN jumbo-unstable3/src/rawMD5_fmt_plug.c jumbo-unstable2/src/rawMD5_fmt_plug.c
--- jumbo-unstable3/src/rawMD5_fmt_plug.c	2012-05-29 02:08:24.718750000 +0000
+++ jumbo-unstable2/src/rawMD5_fmt_plug.c	2012-05-28 01:14:28.953125000 +0000
@@ -279,6 +279,26 @@ static int cmp_one(void *binary, int ind
 #endif
 }
 
+static char *get_source(void *bin, void *salt, char Buf[LINE_BUFFER_SIZE] )
+{
+	unsigned char *cpi;
+	char *cpo;
+	int i;
+
+	strcpy(Buf, FORMAT_TAG);
+	cpo = &Buf[TAG_LENGTH];
+
+	cpi = (unsigned char*)bin;
+
+	for (i = 0; i < BINARY_SIZE; ++i) {
+		*cpo++ = itoa16[(*cpi)>>4];
+		*cpo++ = itoa16[*cpi&0xF];
+		++cpi;
+	}
+	*cpo = 0;
+	return Buf;
+}
+
 struct fmt_main fmt_rawMD5 = {
 	{
 		FORMAT_LABEL,
@@ -326,6 +346,7 @@ struct fmt_main fmt_rawMD5 = {
 		},
 		cmp_all,
 		cmp_one,
-		cmp_exact
+		cmp_exact,
+		get_source
 	}
 };
diff -urpN jumbo-unstable3/src/rawSHA1_fmt_plug.c jumbo-unstable2/src/rawSHA1_fmt_plug.c
--- jumbo-unstable3/src/rawSHA1_fmt_plug.c	2012-05-29 02:08:24.734375000 +0000
+++ jumbo-unstable2/src/rawSHA1_fmt_plug.c	2012-05-28 01:14:39.531250000 +0000
@@ -294,6 +294,31 @@ static int get_hash_5(int index) { retur
 static int get_hash_6(int index) { return ((unsigned int *)crypt_key)[0] & 0x7ffffff; }
 #endif
 
+static char *get_source(void *bin, void *salt, char Buf[LINE_BUFFER_SIZE] )
+{
+	unsigned char realcipher[BINARY_SIZE];
+	unsigned char *cpi;
+	char *cpo;
+	int i;
+
+	memcpy(realcipher, bin, BINARY_SIZE);
+#ifdef MMX_COEF
+	alter_endianity(realcipher, BINARY_SIZE);
+#endif
+	strcpy(Buf, FORMAT_TAG);
+	cpo = &Buf[TAG_LENGTH];
+
+	cpi = realcipher;
+
+	for (i = 0; i < BINARY_SIZE; ++i) {
+		*cpo++ = itoa16[(*cpi)>>4];
+		*cpo++ = itoa16[*cpi&0xF];
+		++cpi;
+	}
+	*cpo = 0;
+	return Buf;
+}
+
 struct fmt_main fmt_rawSHA1 = {
 	{
 		FORMAT_LABEL,
@@ -341,6 +366,7 @@ struct fmt_main fmt_rawSHA1 = {
 		},
 		rawsha1_cmp_all,
 		rawsha1_cmp_one,
-		rawsha1_cmp_exact
+		rawsha1_cmp_exact,
+		get_source
 	}
 };
