diff -urpN jumbo-unstable3/src/common.c jumbo-unstable2/src/common.c
--- jumbo-unstable3/src/common.c	2012-06-03 18:08:57.281250000 +0000
+++ jumbo-unstable2/src/common.c	2012-06-03 18:16:29.968750000 +0000
@@ -14,6 +14,8 @@ char atoi64[0x100];
 
 char itoa16[16] =
 	"0123456789abcdef";
+char itoa16u[16] =
+	"0123456789ABCDEF";
 char atoi16[0x100];
 
 static int initialized = 0;
diff -urpN jumbo-unstable3/src/common.h jumbo-unstable2/src/common.h
--- jumbo-unstable3/src/common.h	2012-06-03 18:08:57.281250000 +0000
+++ jumbo-unstable2/src/common.h	2012-06-03 18:16:29.984375000 +0000
@@ -53,6 +53,7 @@ typedef unsigned int ARCH_WORD_32;
  */
 extern char itoa64[64], atoi64[0x100];
 extern char itoa16[16], atoi16[0x100];
+extern char itoa16u[16]; // uppercase
 
 /*
  * Initializes the tables.
diff -urpN jumbo-unstable3/src/cracker.c jumbo-unstable2/src/cracker.c
--- jumbo-unstable3/src/cracker.c	2012-06-03 18:08:57.328125000 +0000
+++ jumbo-unstable2/src/cracker.c	2012-06-03 18:16:30.000000000 +0000
@@ -158,7 +158,7 @@ static int crk_process_guess(struct db_s
 	UTF8 utf8login[PLAINTEXT_BUFFER_SIZE + 1];
 	char tmp8[PLAINTEXT_BUFFER_SIZE + 1];
 	int dupe;
-	char *key, *utf8key, *repkey, *replogin;
+	char *key, *utf8key, *repkey, *replogin, get_src_buf[LINE_BUFFER_SIZE];
 
 	dupe = !memcmp(&crk_timestamps[index], &status.crypts, sizeof(int64));
 	crk_timestamps[index] = status.crypts;
@@ -216,7 +216,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 : crk_db->format->methods.get_source(pw, get_src_buf), repkey, key, crk_db->options->field_sep_char);
 
 	if (options.flags & FLG_CRKSTAT)
 		event_pending = event_status = 1;
@@ -267,6 +267,7 @@ static int crk_password_loop(struct db_s
 {
 	struct db_password *pw;
 	int index;
+	char get_src_buf[LINE_BUFFER_SIZE];
 
 #if !OS_TIMER
 	sig_timer_emu_tick();
@@ -287,7 +288,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 (crk_methods.cmp_exact(crk_db->format->methods.get_source(pw, get_src_buf), index)) {
 				if (crk_process_guess(salt, pw, index))
 					return 1;
 				else {
@@ -301,7 +302,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 (crk_methods.cmp_exact(crk_db->format->methods.get_source(pw, get_src_buf), index))
 			if (crk_process_guess(salt, pw, index))
 				return 1;
 		} while ((pw = pw->next_hash));
diff -urpN jumbo-unstable3/src/crc32_fmt_plug.c jumbo-unstable2/src/crc32_fmt_plug.c
--- jumbo-unstable3/src/crc32_fmt_plug.c	2012-06-03 18:08:57.343750000 +0000
+++ jumbo-unstable2/src/crc32_fmt_plug.c	2012-06-03 18:16:30.015625000 +0000
@@ -28,6 +28,7 @@
 #include "common.h"
 #include "formats.h"
 #include "pkzip.h"  // includes the 'inline' crc table.
+#include "loader.h"
 
 #ifdef _OPENMP
 #include <omp.h>
@@ -139,6 +140,16 @@ static void *salt(char *ciphertext)
 	return out;
 }
 
+static char *get_source(struct db_password *pw, char Buf[LINE_BUFFER_SIZE] )
+{
+	ARCH_WORD_32 s = *(ARCH_WORD_32*)(pw->source);
+	ARCH_WORD_32 b = *(ARCH_WORD_32*)(pw->binary);
+	s = ~s;
+	b = ~b;
+	sprintf(Buf, "$crc32$%08x.%08x", s,b);
+	return Buf;
+}
+
 static void set_salt(void *salt)
 {
 	crcsalt = *((ARCH_WORD_32 *)salt);
@@ -238,6 +249,7 @@ struct fmt_main fmt_crc32 = {
 		},
 		cmp_all,
 		cmp_one,
-		cmp_exact
+		cmp_exact,
+		get_source
 	}
 };
diff -urpN jumbo-unstable3/src/dynamic.h jumbo-unstable2/src/dynamic.h
--- jumbo-unstable3/src/dynamic.h	2012-06-03 18:08:57.656250000 +0000
+++ jumbo-unstable2/src/dynamic.h	2012-06-03 18:16:30.046875000 +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-06-03 18:08:57.656250000 +0000
+++ jumbo-unstable2/src/dynamic_fmt.c	2012-06-03 18:16:30.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,40 @@ static void *binary(char *_ciphertext)
 	}
 	return (void *)realcipher;
 }
+
+// NOTE NOTE NOTE, we have currently ONLY implemented a non-salted function!!!
+static char *get_source(struct db_password *pw, 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*)(pw->binary);
+	for (i = 0; i < 16; ++i) {
+		*cpo++ = itoa16[(*cpi)>>4];
+		*cpo++ = itoa16[*cpi&0xF];
+		++cpi;
+	}
+	*cpo = 0;
+	return Buf;
+}
+
+static char *get_source_sha(struct db_password *pw, 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*)(pw->binary);
+	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 +2299,8 @@ struct fmt_main fmt_Dynamic =
 		},
 		cmp_all,
 		cmp_one,
-		cmp_exact
+		cmp_exact,
+		fmt_default_get_source
 	}
 };
 
@@ -6945,6 +6977,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 +7126,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 +7614,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-06-03 18:08:57.671875000 +0000
+++ jumbo-unstable2/src/dynamic_parser.c	2012-06-03 18:16:30.109375000 +0000
@@ -64,7 +64,6 @@
 #include "formats.h"
 #include "config.h"
 #include "md5.h"
-#include "loader.h"
 #include "options.h"
 #ifdef HAVE_MPI
 #include "john-mpi.h"
@@ -357,6 +356,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-06-03 18:08:57.671875000 +0000
+++ jumbo-unstable2/src/dynamic_preloads.c	2012-06-03 18:16:30.125000000 +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-06-03 18:08:57.703125000 +0000
+++ jumbo-unstable2/src/formats.c	2012-06-03 17:56:45.968750000 +0000
@@ -10,6 +10,7 @@
 
 #include "params.h"
 #include "formats.h"
+#include "memory.h"
 #ifndef BENCH_BUILD
 #include "options.h"
 #endif
@@ -30,6 +31,12 @@ void fmt_init(struct fmt_main *format)
 	if (!format->private.initialized) {
 		format->methods.init(format);
 		format->private.initialized = 1;
+
+		// 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;
 	}
 #ifndef BENCH_BUILD
 	if (options.mkpc) {
@@ -52,6 +59,27 @@ char *fmt_self_test(struct fmt_main *for
 	char *ciphertext, *plaintext;
 	int ntests, done, index, max, size;
 	void *binary, *salt;
+	struct db_password pw;
+
+	// 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 +98,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, 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.
@@ -83,6 +111,20 @@ char *fmt_self_test(struct fmt_main *for
 		binary = format->methods.binary(ciphertext);
 		salt = format->methods.salt(ciphertext);
 
+/* 
+ * get_source testing is a little 'different', because the source pointer
+ * of the db_password structure will point to either the source or to the
+ * salt, depending upon if the get_source is implemented or not. For
+ * testing, we HAVE to observe the exact same behavior here.
+ */
+		pw.binary = binary;
+		if (format->methods.get_source == fmt_default_get_source)
+			pw.source = ciphertext;
+		else
+			pw.source = (char*)salt;
+		if (strcmp(format->methods.get_source(&pw, Buf), ciphertext)) 
+			return "get_source";
+
 		if ((unsigned int)format->methods.salt_hash(salt) >=
 		    SALT_HASH_SIZE)
 			return "salt_hash";
@@ -199,3 +241,8 @@ int fmt_default_get_hash(int index)
 {
 	return 0;
 }
+
+char *fmt_default_get_source(struct db_password *current_pw, char ReturnBuf[LINE_BUFFER_SIZE]) 
+{
+	return current_pw->source;
+}
diff -urpN jumbo-unstable3/src/formats.h jumbo-unstable2/src/formats.h
--- jumbo-unstable3/src/formats.h	2012-06-03 18:08:57.703125000 +0000
+++ jumbo-unstable2/src/formats.h	2012-06-03 18:16:30.156250000 +0000
@@ -16,6 +16,7 @@
 #include "misc.h"
 
 struct fmt_main;
+struct db_password;
 
 /*
  * Format property flags.
@@ -176,6 +177,19 @@ 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 salt is stored in the 'source' pointer for the format IF
+ * this method IS implemented within a format. The format will have to store
+ * the entire binary in the return from binary().  This is an optional method.
+ * If this pointer is set to fmt_default_get_source, then JtR will operate in
+ * legacy mode, storing the FULL source string in source.  The fmt_default_get_source
+ * simply returns the source. If this method IS implemented by a format,
+ * then JtR will no longer store the source hashes into source, but puts a pointer
+ * to the PROPER salt into this pointer. Then the format within get_source can
+ * rebuild the source from the pw->binary and pw->source (the pw->source is the salt).
+ */
+	char *(*get_source)(struct db_password *current_pw, char ReturnBuf[LINE_BUFFER_SIZE]);
 };
 
 /*
@@ -232,6 +246,7 @@ 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(struct db_password *current_pw, 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-06-03 18:08:57.906250000 +0000
+++ jumbo-unstable2/src/loader.c	2012-06-03 18:16:30.171875000 +0000
@@ -435,7 +435,7 @@ static void ldr_load_pw_line(struct db_m
 	struct fmt_main *format;
 	int index, count;
 	char *login, *ciphertext, *gecos, *home;
-	char *piece;
+	char *piece, get_src_buf[LINE_BUFFER_SIZE];
 	void *binary, *salt;
 	int salt_hash, pw_hash;
 	struct db_salt *current_salt, *last_salt;
@@ -481,7 +481,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)) {
+				    !strcmp(format->methods.get_source(current_pw, get_src_buf), piece)) {
 					db->options->flags |= DB_NODUP;
 					break;
 				}
@@ -562,7 +562,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 = (char*)current_salt->salt;
 
 		if (db->options->flags & DB_WORDS) {
 			if (!words)
@@ -596,7 +599,7 @@ void ldr_load_pw_file(struct db_main *db
 static void ldr_load_pot_line(struct db_main *db, char *line)
 {
 	struct fmt_main *format = db->format;
-	char *ciphertext, *unprepared;
+	char *ciphertext, *unprepared, get_src_buf[LINE_BUFFER_SIZE];
 	void *binary;
 	int hash;
 	struct db_password *current;
@@ -634,7 +637,7 @@ static void ldr_load_pot_line(struct db_
 		}
 		if (current->binary && !memcmp(current->binary, binary,
 		    format->params.binary_size) &&
-		    !strcmp(current->source, ciphertext))
+			!strcmp(format->methods.get_source(current, get_src_buf), ciphertext))
 			current->binary = NULL;
 	} while ((current = current->next_hash));
 }
@@ -683,6 +686,7 @@ static void ldr_remove_marked(struct db_
 {
 	struct db_salt *current_salt, *last_salt;
 	struct db_password *current_pw, *last_pw;
+	char get_src_buf[LINE_BUFFER_SIZE];
 
 	last_salt = NULL;
 	if ((current_salt = db->salts))
@@ -704,9 +708,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,db->format->methods.get_source(current_pw, get_src_buf));
 					} 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,db->format->methods.get_source(current_pw, get_src_buf));
 				}
 			}
 		} while ((current_pw = current_pw->next));
diff -urpN jumbo-unstable3/src/loader.h jumbo-unstable2/src/loader.h
--- jumbo-unstable3/src/loader.h	2012-06-03 18:08:57.906250000 +0000
+++ jumbo-unstable2/src/loader.h	2012-06-03 18:16:30.187500000 +0000
@@ -31,6 +31,8 @@ struct db_password {
 	void *binary;
 
 /* ASCII ciphertext for exact comparison and saving with cracked passwords */
+/* NOTE, for formats which implement get_source(), this pointer will point */
+/* to a salt. NOTE, it is (void *salt, so should be retypecast to void*    */
 	char *source;
 
 /* Login field from the password file, with ":1" or ":2" appended if the
diff -urpN jumbo-unstable3/src/NT_fmt_plug.c jumbo-unstable2/src/NT_fmt_plug.c
--- jumbo-unstable3/src/NT_fmt_plug.c	2012-06-03 18:08:57.062500000 +0000
+++ jumbo-unstable2/src/NT_fmt_plug.c	2012-06-03 18:16:30.187500000 +0000
@@ -630,6 +630,37 @@ static int cmp_exact(char *source, int i
 {
 	return 1;
 }
+static char *get_source(struct db_password *pw, 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, pw->binary, 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-06-03 18:08:58.140625000 +0000
+++ jumbo-unstable2/src/nt2_fmt_plug.c	2012-06-03 18:16:30.203125000 +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(struct db_password *pw, char Buf[LINE_BUFFER_SIZE] )
+{
+	unsigned char *cpi;
+	char *cpo;
+	int i;
+
+	strcpy(Buf, "$NT$");
+	cpo = &Buf[4];
+
+	cpi = (unsigned char*)(pw->binary);
+
+	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,
@@ -684,7 +704,7 @@ struct fmt_main fmt_magnumNT = {
 #if (BLOCK_LOOPS > 1) && defined(SSE_MD4_PARA)
 		FMT_OMP |
 #endif
-		FMT_CASE | FMT_8_BIT | FMT_UNICODE | FMT_UTF8,
+		FMT_CASE | FMT_8_BIT | FMT_SPLIT_UNIFIES_CASE | FMT_UNICODE | FMT_UTF8,
 		tests
 	}, {
 		init,
@@ -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-06-03 18:08:59.046875000 +0000
+++ jumbo-unstable2/src/rawMD5_fmt_plug.c	2012-06-03 18:16:30.203125000 +0000
@@ -13,6 +13,7 @@
 #include "common.h"
 #include "formats.h"
 #include "params.h"
+#include "loader.h"
 
 #define FORMAT_LABEL		"raw-md5"
 #define FORMAT_NAME			"Raw MD5"
@@ -279,6 +280,26 @@ static int cmp_one(void *binary, int ind
 #endif
 }
 
+static char *get_source(struct db_password *pw, char Buf[LINE_BUFFER_SIZE] )
+{
+	unsigned char *cpi;
+	char *cpo;
+	int i;
+
+	strcpy(Buf, FORMAT_TAG);
+	cpo = &Buf[TAG_LENGTH];
+
+	cpi = (unsigned char*)(pw->binary);
+
+	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 +347,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-06-03 18:08:59.046875000 +0000
+++ jumbo-unstable2/src/rawSHA1_fmt_plug.c	2012-06-03 18:16:30.218750000 +0000
@@ -22,6 +22,7 @@
 #include "formats.h"
 #include "sha.h"
 #include "johnswap.h"
+#include "loader.h"
 
 #define FORMAT_LABEL			"raw-sha1"
 #define FORMAT_NAME			"Raw SHA-1"
@@ -294,6 +295,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(struct db_password *pw, char Buf[LINE_BUFFER_SIZE] )
+{
+	unsigned char realcipher[BINARY_SIZE];
+	unsigned char *cpi;
+	char *cpo;
+	int i;
+
+	memcpy(realcipher, pw->binary, 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 +367,7 @@ struct fmt_main fmt_rawSHA1 = {
 		},
 		rawsha1_cmp_all,
 		rawsha1_cmp_one,
-		rawsha1_cmp_exact
+		rawsha1_cmp_exact,
+		get_source
 	}
 };
diff -urpN jumbo-unstable3/src/sapG_fmt_plug.c jumbo-unstable2/src/sapG_fmt_plug.c
--- jumbo-unstable3/src/sapG_fmt_plug.c	2012-06-03 18:08:59.140625000 +0000
+++ jumbo-unstable2/src/sapG_fmt_plug.c	2012-06-03 18:16:30.234375000 +0000
@@ -608,6 +608,33 @@ static void *binary(char *ciphertext)
 	return (void*)realcipher;
 }
 
+static char *get_source(struct db_password *pw, char Buf[LINE_BUFFER_SIZE] )
+{
+	struct saltstruct *salt_s = (struct saltstruct*)(pw->source);
+	unsigned char realcipher[BINARY_SIZE];
+	unsigned char *cpi;
+	char *cpo;
+	int i;
+
+	memcpy(realcipher, pw->binary, BINARY_SIZE);
+#ifdef MMX_COEF
+	alter_endianity(realcipher, BINARY_SIZE);
+#endif
+	memcpy(Buf, salt_s->s, salt_s->l);
+	cpo = &Buf[salt_s->l];
+	*cpo++ = '$';
+
+	cpi = realcipher;
+
+	for (i = 0; i < BINARY_SIZE; ++i) {
+		*cpo++ = itoa16u[(*cpi)>>4];
+		*cpo++ = itoa16u[*cpi&0xF];
+		++cpi;
+	}
+	*cpo = 0;
+	return Buf;
+}
+
 static int binary_hash_0(void *binary) { return ((ARCH_WORD_32*)binary)[0] & 0xf; }
 static int binary_hash_1(void *binary) { return ((ARCH_WORD_32*)binary)[0] & 0xff; }
 static int binary_hash_2(void *binary) { return ((ARCH_WORD_32*)binary)[0] & 0xfff; }
@@ -721,6 +748,7 @@ struct fmt_main fmt_sapG = {
 		},
 		cmp_all,
 		cmp_one,
-		cmp_exact
+		cmp_exact,
+		get_source
 	}
 };
