diff --git a/src/sbbs3/js_file.c b/src/sbbs3/js_file.c
index 0db1a596ffcd2f2baaed6bab42ad90d8e7b71654..40edec9fc79a6e95bd9ddbcc5bd1c38b4f63522b 100644
--- a/src/sbbs3/js_file.c
+++ b/src/sbbs3/js_file.c
@@ -50,6 +50,7 @@ typedef struct
 	uchar	etx;
 	BOOL	external;	/* externally created, don't close */
 	BOOL	debug;
+	BOOL	rot13;
 	BOOL	uuencoded;
 	BOOL	b64encoded;
 	BOOL	network_byte_order;
@@ -241,6 +242,9 @@ js_read(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 		if(cp) *cp=0; 
 	}
 
+	if(p->rot13)
+		rot13(buf);
+
 	if(p->uuencoded || p->b64encoded) {
 		uulen=len*2;
 		if((uubuf=malloc(uulen))==NULL)
@@ -304,6 +308,8 @@ js_readln(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 			cp=strchr(buf,p->etx);
 			if(cp) *cp=0; 
 		}
+		if(p->rot13)
+			rot13(buf);
 		if((js_str=JS_NewStringCopyZ(cx,buf))!=NULL)
 			*rval = STRING_TO_JSVAL(js_str);
 	}
@@ -426,6 +432,9 @@ js_write(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 		cp=uubuf;
 	}
 
+	if(p->rot13)
+		rot13(cp);
+
 	tlen=len;
 	if(argc>1) {
 		JS_ValueToInt32(cx,argv[1],(int32*)&tlen);
@@ -480,6 +489,9 @@ js_writeln(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 		cp = JS_GetStringBytes(str);
 	}
 
+	if(p->rot13)
+		rot13(cp);
+
 	if(fprintf(p->fp,"%s\n",cp)!=0)
 		*rval = JSVAL_TRUE;
 
@@ -780,6 +792,7 @@ enum {
 	,FILE_PROP_ATTRIBUTES
 	,FILE_PROP_UUENCODED
 	,FILE_PROP_B64ENCODED
+	,FILE_PROP_ROT13
 	,FILE_PROP_NETWORK_ORDER
 	/* dynamically calculated */
 	,FILE_PROP_CHKSUM
@@ -814,6 +827,9 @@ static JSBool js_file_set(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
 		case FILE_PROP_B64ENCODED:
 			JS_ValueToBoolean(cx,*vp,&(p->b64encoded));
 			break;
+		case FILE_PROP_ROT13:
+			JS_ValueToBoolean(cx,*vp,&(p->rot13));
+			break;
 		case FILE_PROP_NETWORK_ORDER:
 			JS_ValueToBoolean(cx,*vp,&(p->network_byte_order));
 			break;
@@ -918,6 +934,9 @@ static JSBool js_file_get(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
 		case FILE_PROP_B64ENCODED:
 			*vp = BOOLEAN_TO_JSVAL(p->b64encoded);
 			break;
+		case FILE_PROP_ROT13:
+			*vp = BOOLEAN_TO_JSVAL(p->rot13);
+			break;
 		case FILE_PROP_NETWORK_ORDER:
 			*vp = BOOLEAN_TO_JSVAL(p->network_byte_order);
 			break;
@@ -1003,6 +1022,7 @@ static struct JSPropertySpec js_file_properties[] = {
 	{	"length"			,FILE_PROP_LENGTH		,JSPROP_ENUMERATE,	NULL,NULL},
 	{	"attributes"		,FILE_PROP_ATTRIBUTES	,JSPROP_ENUMERATE,	NULL,NULL},
 	{	"network_byte_order",FILE_PROP_NETWORK_ORDER,JSPROP_ENUMERATE,	NULL,NULL},
+	{	"rot13"				,FILE_PROP_ROT13		,JSPROP_ENUMERATE,	NULL,NULL},
 	{	"uue"				,FILE_PROP_UUENCODED	,JSPROP_ENUMERATE,	NULL,NULL},
 	{	"base64"			,FILE_PROP_B64ENCODED	,JSPROP_ENUMERATE,	NULL,NULL},
 	/* dynamically calculated */
@@ -1030,6 +1050,7 @@ static char* file_prop_desc[] = {
 	,"the current length of the file (in bytes)"
 	,"file mode/attributes"
 	,"set to <i>true</i> if binary data is to be written and read in Network Byte Order (big end first)"
+	,"set to <i>true</i> to enable automatic ROT13 translatation of text"
 	,"set to <i>true</i> to enable automatic unix-to-unix encode and decode on <tt>read</tt> and <tt>write</tt> calls"
 	,"set to <i>true</i> to enable automatic base64 encode and decode on <tt>read</tt> and <tt>write</tt> calls"
 	,"calculated 16-bit CRC of file contents - <small>READ ONLY</small>"
diff --git a/src/sbbs3/js_global.c b/src/sbbs3/js_global.c
index 7bc9bf2fa4a2c101a2cf1fb7d8547cd4cd20d705..6884826f50505844a0bb6f512f2c2c048e15c942 100644
--- a/src/sbbs3/js_global.c
+++ b/src/sbbs3/js_global.c
@@ -571,7 +571,27 @@ js_quote_msg(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 	return(JS_TRUE);
 }
 
+static JSBool
+js_rot13(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+	char*		p;
+	char*		str;
+	JSString*	js_str;
 
+	if((str=JS_GetStringBytes(JS_ValueToString(cx, argv[0])))==NULL) 
+		return(JS_FALSE);
+
+	if((p=dupestr(str))==NULL)
+		return(JS_FALSE);
+
+	js_str = JS_NewStringCopyZ(cx, rot13(p));
+	free(p);
+	if(js_str==NULL)
+		return(JS_FALSE);
+
+	*rval = STRING_TO_JSVAL(js_str);
+	return(JS_TRUE);
+}
 
 /* This table is used to convert between IBM ex-ASCII and HTML character entities */
 /* Much of this table supplied by Deuce (thanks!) */
@@ -1422,6 +1442,9 @@ static jsMethodSpec js_global_functions[] = {
 	,JSDOCSTR("returns a quoted version of the message text string argumnet, <i>line_length</i> defaults to <i>79</i>, "
 		"<i>prefix</i> defaults to <tt>\" > \"</tt>")
 	},
+	{"rot13_translate",	js_rot13,			1,	JSTYPE_STRING,	JSDOCSTR("string text")
+	,JSDOCSTR("returns ROT13-translated version of text string (will encode or decode text)")
+	},
 	{"base64_encode",	js_b64_encode,		1,	JSTYPE_STRING,	JSDOCSTR("string text")
 	,JSDOCSTR("returns base64-encoded version of text string or <i>null</i> on error")
 	},
diff --git a/src/sbbs3/sbbs.h b/src/sbbs3/sbbs.h
index e147aa2c964885838a173935e4cb7378b07d7317..7f937924a665d61791aac7ec133cdb137c4947e4 100644
--- a/src/sbbs3/sbbs.h
+++ b/src/sbbs3/sbbs.h
@@ -793,6 +793,7 @@ extern "C" {
 	DLLEXPORT char *	DLLCALL get_msgid(scfg_t* cfg, uint subnum, smbmsg_t* msg);
 	DLLEXPORT BOOL		DLLCALL get_msg_by_id(scfg_t* scfg, smb_t* smb, char* id, smbmsg_t* msg);
 	DLLEXPORT char *	DLLCALL ultoac(ulong l,char *str);
+	DLLEXPORT char *	DLLCALL rot13(char* str);
 
 
 	/* date_str.c */
diff --git a/src/sbbs3/str_util.c b/src/sbbs3/str_util.c
index d82f4f2ec6832514659a1c0c080eca399d5ef537..583af89eadcc045b88f852b0b2a583c0038e2d83 100644
--- a/src/sbbs3/str_util.c
+++ b/src/sbbs3/str_util.c
@@ -256,6 +256,25 @@ char* DLLCALL truncstr(char* str, const char* set)
 	return(p);
 }
 
+/****************************************************************************/
+/* rot13 encoder/decoder - courtesy of Mike Acar							*/
+/****************************************************************************/
+char* DLLCALL rot13(char* str)
+{
+	char ch, cap;
+	char* p;
+  
+	p=str;
+	while((ch=*p)!=0) {
+		cap = ch & 32;
+		ch &= ~cap;
+		ch = ((ch >= 'A') && (ch <= 'Z') ? ((ch - 'A' + 13) % 26 + 'A') : ch) | cap;
+		*(p++)=ch;
+    }
+
+	return(str);
+}
+
 /****************************************************************************/
 /* Puts a backslash on path strings if not just a drive letter and colon	*/
 /****************************************************************************/