Index: ChangeLog
===================================================================
--- ChangeLog	(revision 5b85d1961e3bc41db16d76039f47ae0030762c90)
+++ ChangeLog	(revision 9ceee9d93177e80e7794f45d5ba9e611169e4d55)
@@ -3,4 +3,6 @@
 2.0.7-pre-2
 	Don't allow zwrite if zephyr isn't present
+	There is now a zcrypt command
+	Replies to zcrypted messages now work
 	
 2.0.7-pre-1
Index: commands.c
===================================================================
--- commands.c	(revision 5b85d1961e3bc41db16d76039f47ae0030762c90)
+++ commands.c	(revision 9ceee9d93177e80e7794f45d5ba9e611169e4d55)
@@ -127,5 +127,4 @@
 	      "Send an aim message to a user.\n"),
 
-  /*
   OWLCMD_ARGS("zcrypt", owl_command_zcrypt, OWL_CTX_INTERACTIVE,
 	      "send an encrypted zephyr",
@@ -133,5 +132,4 @@
 	      "Behaves like zwrite but uses encryption.  Not for use with\n"
 	      "personal messages\n"),
-  */
   
   OWLCMD_ARGS("reply", owl_command_reply,  OWL_CTX_INTERACTIVE,
@@ -1660,11 +1658,15 @@
 char *owl_command_zcrypt(int argc, char **argv, char *buff)
 {
+#ifdef OWL_ENABLE_ZCRYPT
   owl_zwrite z;
 
-  /* check for a zwrite -m */
+  if (!owl_global_is_havezephyr(&g)) {
+    owl_function_makemsg("Zephyr is not available");
+    return(NULL);
+  }
+  /* check for a zcrypt -m */
   owl_zwrite_create_from_line(&z, buff);
   if (owl_zwrite_is_message_set(&z)) {
-    owl_zwrite_send_message(&z);
-    owl_function_make_outgoing_zephyr(owl_zwrite_get_message(&z), buff, owl_zwrite_get_zsig(&z));
+    owl_function_zcrypt(buff, NULL);
     owl_zwrite_free(&z);
     return (NULL);
@@ -1677,4 +1679,7 @@
   }
   return(NULL);
+#else
+  owl_function_makemsg("This Owl does not support zcrypt");
+#endif
 }
 
Index: functions.c
===================================================================
--- functions.c	(revision 5b85d1961e3bc41db16d76039f47ae0030762c90)
+++ functions.c	(revision 9ceee9d93177e80e7794f45d5ba9e611169e4d55)
@@ -255,56 +255,4 @@
 }
 
-
-
-void owl_function_zcrypt_setup(char *line)
-{
-  owl_editwin *e;
-  char buff[1024];
-  owl_zwrite z;
-  int ret;
-
-  /* check the arguments */
-  ret=owl_zwrite_create_from_line(&z, line);
-  if (ret) {
-    owl_function_makemsg("Error in zwrite arugments");
-    owl_zwrite_free(&z);
-    return;
-  }
-
-  if (owl_zwrite_get_numrecips(&z)>0) {
-    owl_function_makemsg("You may not specifiy a recipient for a zcrypt message");
-    owl_zwrite_free(&z);
-    return;
-  }
-
-  /* send a ping if necessary */
-  if (owl_global_is_txping(&g)) {
-    owl_zwrite_send_ping(&z);
-  }
-  owl_zwrite_free(&z);
-
-  /* create and setup the editwin */
-  e=owl_global_get_typwin(&g);
-  owl_editwin_new_style(e, OWL_EDITWIN_STYLE_MULTILINE, owl_global_get_msg_history(&g));
-
-  if (!owl_global_get_lockout_ctrld(&g)) {
-    owl_function_makemsg("Type your zephyr below.  End with ^D or a dot on a line by itself.  ^C will quit.");
-  } else {
-    owl_function_makemsg("Type your zephyr below.  End with a dot on a line by itself.  ^C will quit.");
-  }
-
-  owl_editwin_clear(e);
-  owl_editwin_set_dotsend(e);
-  strcpy(buff, "----> ");
-  strcat(buff, line);
-  strcat(buff, "\n");
-  owl_editwin_set_locktext(e, buff);
-
-  /* make it active */
-  owl_global_set_typwin_active(&g);
-
-  owl_global_set_buffercommand(&g, line);
-}
-
 /* send, log and display an outgoing zephyr.  If 'msg' is NULL
  * the message is expected to be set from the zwrite line itself
@@ -341,4 +289,59 @@
 
   /* free the zwrite */
+  owl_zwrite_free(&z);
+}
+
+/* send, log and display an outgoing zcrypt zephyr.  If 'msg' is NULL
+ * the message is expected to be set from the zwrite line itself
+ */
+void owl_function_zcrypt(char *line, char *msg)
+{
+  owl_zwrite z;
+  int i, j, ret;
+  char *mymsg;
+  char *cryptmsg;
+
+  /* create the zwrite and send the message */
+  owl_zwrite_create_from_line(&z, line);
+  if (msg) {
+    owl_zwrite_set_message(&z, msg);
+  }
+
+  mymsg=owl_zwrite_get_message(&z);
+#ifdef OWL_ENABLE_ZCRYPT
+  cryptmsg=owl_malloc(strlen(mymsg)*4);
+  ret=owl_zcrypt_encrypt(cryptmsg, mymsg, owl_zwrite_get_class(&z), owl_zwrite_get_instance(&z));
+  if (ret) {
+    owl_function_makemsg("Error in zcrypt, possibly no key found.  Message not sent.");
+    owl_function_beep();
+    owl_free(cryptmsg);
+    return;
+  }
+#else
+  cryptmsg=owl_strdup(mymsg);
+#endif
+
+  owl_zwrite_set_message(&z, cryptmsg);
+  owl_zwrite_set_opcode(&z, "crypt");
+  mymsg=cryptmsg;
+    
+  owl_zwrite_send_message(&z);
+  owl_function_makemsg("Waiting for ack...");
+
+  /* display the message as an outgoing message in the receive window */
+  if (owl_global_is_displayoutgoing(&g) && owl_zwrite_is_personal(&z)) {
+    owl_function_make_outgoing_zephyr(mymsg, line, owl_zwrite_get_zsig(&z));
+  }
+
+  /* log it if we have logging turned on */
+  if (owl_global_is_logging(&g) && owl_zwrite_is_personal(&z)) {
+    j=owl_zwrite_get_numrecips(&z);
+    for (i=0; i<j; i++) {
+      owl_log_outgoing_zephyr(owl_zwrite_get_recip_n(&z, i), mymsg);
+    }
+  }
+
+  /* free the zwrite */
+  owl_free(cryptmsg);
   owl_zwrite_free(&z);
 }
@@ -1087,4 +1090,6 @@
   if (!strncmp(buff, "zwrite ", 7)) {
     owl_function_zwrite(buff, owl_editwin_get_text(owl_global_get_typwin(&g)));
+  } else if (!strncmp(buff, "zcrypt ", 7)) {
+    owl_function_zcrypt(buff, owl_editwin_get_text(owl_global_get_typwin(&g)));
   } else if (!strncmp(buff, "aimwrite ", 9)) {
     owl_function_aimwrite(buff+9);
@@ -1774,11 +1779,4 @@
     /* zephyr */
     if (owl_message_is_type_zephyr(m)) {
-      /* for now we disable replies to zcrypt messages, since we can't
-	 support an encrypted reply */
-      if (!strcasecmp(owl_message_get_opcode(m), "crypt")) {
-	owl_function_makemsg("Replies to zcrypt messages are not enabled in this release");
-	return;
-      }
-
       /* if it's a zephyr we sent, send it out the same way again */
       if (owl_message_is_direction_out(m)) {
@@ -1824,5 +1822,9 @@
 	
       /* create the command line */
-      buff = owl_strdup("zwrite");
+      if (!strcasecmp(owl_message_get_opcode(m), "CRYPT")) {
+	buff=owl_strdup("zcrypt");
+      } else {
+	buff = owl_strdup("zwrite");
+      }
       if (strcasecmp(class, "message")) {
 	buff = owl_sprintf("%s -c %s%s%s", oldbuff=buff, owl_getquoting(class), class, owl_getquoting(class));
Index: message.c
===================================================================
--- message.c	(revision 09489b896891e6c4e2b0a2a7d622c25749410cf1)
+++ message.c	(revision 9ceee9d93177e80e7794f45d5ba9e611169e4d55)
@@ -699,5 +699,5 @@
 
     out=owl_malloc(strlen(owl_message_get_body(m))*16+20);
-    ret=zcrypt_decrypt(out, owl_message_get_body(m), owl_message_get_class(m), owl_message_get_instance(m));
+    ret=owl_zcrypt_decrypt(out, owl_message_get_body(m), owl_message_get_class(m), owl_message_get_instance(m));
     if (ret==0) {
       owl_message_set_body(m, out);
@@ -743,6 +743,8 @@
   owl_message_set_class(m, owl_zwrite_get_class(&z));
   owl_message_set_instance(m, owl_zwrite_get_instance(&z));
-  owl_message_set_recipient(m,
-			    long_zuser(owl_zwrite_get_recip_n(&z, 0))); /* only gets the first user, must fix */
+  if (owl_zwrite_get_numrecips(&z)>0) {
+    owl_message_set_recipient(m,
+			      long_zuser(owl_zwrite_get_recip_n(&z, 0))); /* only gets the first user, must fix */
+  }
   owl_message_set_opcode(m, owl_zwrite_get_opcode(&z));
   owl_message_set_realm(m, owl_zwrite_get_realm(&z)); /* also a hack, but not here */
Index: zcrypt.c
===================================================================
--- zcrypt.c	(revision 09489b896891e6c4e2b0a2a7d622c25749410cf1)
+++ zcrypt.c	(revision 9ceee9d93177e80e7794f45d5ba9e611169e4d55)
@@ -267,7 +267,12 @@
 }
 
-int zcrypt_decrypt(char *out, char *in, char *class, char *instance) {
-  /* written by kretch for owl. */
-  /* return 0 on success, otherwise -1 */
+/* The 'owl_zcrypt_decrypt' function was written by kretch for Owl.
+ * Decrypt the message in 'in' on class 'class' and instance
+ * 'instance' and leave the result in 'out'.  Out must be a buffer
+ * allocated by the caller.
+ *
+ * return 0 on success, otherwise -1
+ */
+int owl_zcrypt_decrypt(char *out, char *in, char *class, char *instance) {
   char *fname, keystring[MAX_KEY], *inptr, *endptr;
   FILE *fkey;
@@ -278,4 +283,5 @@
   
   fname=GetZephyrVarKeyFile("zcrypt", class, instance);
+  if (!fname) return(-1);
   fkey=fopen(fname, "r");
   if (!fkey) return(-1);
@@ -314,5 +320,65 @@
 }
 
-int zcrypt_encrypt(char *out, char *in, char *class, char *instance) {
+int owl_zcrypt_encrypt(char *out, char *in, char *class, char *instance) {
+  /*  static int do_encrypt(char *keystring, int zephyr, char *class, char *instance, ZWRITEOPTIONS *zoptions, char* keyfile) { */
+  char *fname, keystring[MAX_KEY];
+  FILE *fkey;
+  des_cblock key;
+  des_key_schedule schedule;
+  char input[8], output[8];
+  int size, length, i;
+  char *inbuff = NULL, *inptr;
+  int use_buffer = FALSE;
+  int num_blocks=0, last_block_size=0;
+
+  fname=GetZephyrVarKeyFile("zcrypt", class, instance);
+  if (!fname) return(-1);
+  fkey=fopen(fname, "r");
+  if (!fkey) return(-1);
+  fgets(keystring, MAX_KEY-1, fkey);
+  fclose(fkey);
+
+  des_string_to_key(keystring, key);
+  des_key_sched(key, schedule);
+
+  inbuff=in;
+  length=strlen(inbuff);
+  num_blocks=(length+7)/8;
+  last_block_size=((length+7)%8)+1;
+  use_buffer=TRUE;
+
+  strcpy(out, "");
+  
+  inptr=inbuff;
+  while (TRUE) {
+    /* Get 8 bytes from buffer */
+    if (num_blocks > 1) {
+      size = 8;
+      memcpy(input, inptr, size);
+      inptr+=8;
+      num_blocks--;
+    } else if (num_blocks == 1) {
+      size=last_block_size;
+      memcpy(input, inptr, size);
+      num_blocks--;
+    } else {
+      size=0;
+    }
+
+    /* Check for EOF and pad the string to 8 chars, if needed */
+    if (size == 0) break;     /* END OF INPUT: BREAK FROM while LOOP! */
+      
+    if (size<8) memset(input + size, 0, 8 - size);
+
+    /* Encrypt and output the block */
+    des_ecb_encrypt(input, output, schedule, TRUE);
+
+    for (i = 0; i < 8; i++) {
+      sprintf(out, "%s%c", out, ((output[i] & 0xf0) >> 4) + BASE_CODE);
+      sprintf(out, "%s%c", out, (output[i] & 0x0f)        + BASE_CODE);
+    }
+
+    if (size < 8) break;
+  }
   return(0);
 }
@@ -367,6 +433,5 @@
   /* Determine names to look for in .crypt-table */
   if (instance) {
-    sprintf(varname[numsearch++], "crypt-%s-%s:", (class?class:"message"), 
-	    instance);
+    sprintf(varname[numsearch++], "crypt-%s-%s:", (class?class:"message"), instance);
   }
   if (class) {
@@ -413,5 +478,5 @@
 
     if (keyfile == NULL) {
-      printf("Could not find key table entry.\n");
+      /* printf("Could not find key table entry.\n"); */
     } else {
       /* Prepare result to be returned */
@@ -421,5 +486,5 @@
 	strcpy(keyfile, temp);
       } else {
-	printf("Memory allocation error.\n");
+	/* printf("Memory allocation error.\n"); */
       }
     }
@@ -427,5 +492,5 @@
     fclose(fsearch);
   } else {
-    printf("Could not open key table file: %s\n", filename);
+    /* printf("Could not open key table file: %s\n", filename); */
   }
 
Index: zwrite.c
===================================================================
--- zwrite.c	(revision 09489b896891e6c4e2b0a2a7d622c25749410cf1)
+++ zwrite.c	(revision 9ceee9d93177e80e7794f45d5ba9e611169e4d55)
@@ -306,4 +306,10 @@
 }
 
+void owl_zwrite_set_opcode(owl_zwrite *z, char *opcode)
+{
+  if (z->opcode) owl_free(z->opcode);
+  z->opcode=owl_strdup(opcode);
+}
+
 char *owl_zwrite_get_realm(owl_zwrite *z)
 {
