Przeglądaj źródła

encrypt_stream, compress_stream

David Rose 16 lat temu
rodzic
commit
00ef315ae0

+ 2 - 21
panda/src/downloadertools/pdecrypt.cxx

@@ -13,7 +13,7 @@
 ////////////////////////////////////////////////////////////////////
 
 #include "filename.h"
-#include "encryptStream.h"
+#include "encrypt_string.h"
 #include "pnotify.h"
 
 #ifndef HAVE_GETOPT
@@ -27,25 +27,6 @@
 string password;
 bool got_password = false;
 
-bool
-do_decrypt(istream &read_stream, ostream &write_stream) {
-  IDecryptStream decrypt(&read_stream, false, password);
-
-  static const size_t buffer_size = 1024;
-  char buffer[buffer_size];
-
-  decrypt.read(buffer, buffer_size);
-  size_t count = decrypt.gcount();
-  while (count != 0) {
-    write_stream.write(buffer, count);
-    decrypt.read(buffer, buffer_size);
-    count = decrypt.gcount();
-  }
-  
-  return !decrypt.fail() || decrypt.eof() &&
-    (!write_stream.fail() || write_stream.eof());
-}
-
 void 
 usage() {
   cerr
@@ -152,7 +133,7 @@ main(int argc, char *argv[]) {
           }
 
           cerr << dest_file << "\n";
-          bool success = do_decrypt(read_stream, write_stream);
+          bool success = decrypt_stream(read_stream, write_stream, password);
           
           read_stream.close();
           write_stream.close();

+ 5 - 34
panda/src/downloadertools/pencrypt.cxx

@@ -13,7 +13,7 @@
 ////////////////////////////////////////////////////////////////////
 
 #include "filename.h"
-#include "encryptStream.h"
+#include "encrypt_string.h"
 #include "pnotify.h"
 
 #ifndef HAVE_GETOPT
@@ -28,41 +28,11 @@ string password;
 bool got_password = false;
 string algorithm;
 bool got_algorithm = false;
-int key_length = 0;
+int key_length = -1;
 bool got_key_length = false;
-int iteration_count = 0;
+int iteration_count = -1;
 bool got_iteration_count = false;
 
-bool
-do_encrypt(istream &read_stream, ostream &write_stream) {
-  OEncryptStream encrypt;
-  if (got_algorithm) {
-    encrypt.set_algorithm(algorithm);
-  }
-  if (got_key_length) {
-    encrypt.set_key_length(key_length);
-  }
-  if (got_iteration_count) {
-    encrypt.set_iteration_count(iteration_count);
-  }
-  encrypt.open(&write_stream, false, password);
-    
-  static const size_t buffer_size = 1024;
-  char buffer[buffer_size];
-
-  read_stream.read(buffer, buffer_size);
-  size_t count = read_stream.gcount();
-  while (count != 0) {
-    encrypt.write(buffer, count);
-    read_stream.read(buffer, buffer_size);
-    count = read_stream.gcount();
-  }
-  encrypt.close();
-
-  return !read_stream.fail() || read_stream.eof() &&
-    (!encrypt.fail() || encrypt.eof());
-}
-
 void 
 usage() {
   cerr
@@ -209,7 +179,8 @@ main(int argc, char *argv[]) {
           }
 
           cerr << dest_file << "\n";
-          bool success = do_encrypt(read_stream, write_stream);
+          bool success = encrypt_stream(read_stream, write_stream, password,
+                                        algorithm, key_length, iteration_count);
           
           read_stream.close();
           write_stream.close();

+ 23 - 22
panda/src/downloadertools/punzip.cxx

@@ -13,7 +13,7 @@
 ////////////////////////////////////////////////////////////////////
 
 #include "filename.h"
-#include "zStream.h"
+#include "compress_string.h"
 #include "pnotify.h"
 
 #ifndef HAVE_GETOPT
@@ -24,30 +24,12 @@
   #endif
 #endif
 
-bool
-do_decompress(istream &read_stream, ostream &write_stream) {
-  IDecompressStream decompress(&read_stream, false);
-
-  static const size_t buffer_size = 1024;
-  char buffer[buffer_size];
-
-  decompress.read(buffer, buffer_size);
-  size_t count = decompress.gcount();
-  while (count != 0) {
-    write_stream.write(buffer, count);
-    decompress.read(buffer, buffer_size);
-    count = decompress.gcount();
-  }
-  
-  return !decompress.fail() || decompress.eof() &&
-    (!write_stream.fail() || write_stream.eof());
-}
-
 void
 usage() {
   cerr
     << "\nUsage:\n"
     << "   punzip file.pz [file2.pz file3.pz ...]\n"
+    << "   punzip -c <file >dest_file\n"
     << "   punzip -o dest_file file.pz\n\n"
     
     << "This program reverses the operation of a previous pzip command.  It\n"
@@ -59,10 +41,11 @@ int
 main(int argc, char *argv[]) {
   extern char *optarg;
   extern int optind;
-  const char *optstr = "o:h";
+  const char *optstr = "o:ch";
 
   Filename dest_filename;
   bool got_dest_filename = false;
+  bool use_stdout = false;
 
   int flag = getopt(argc, argv, optstr);
 
@@ -73,6 +56,10 @@ main(int argc, char *argv[]) {
       got_dest_filename = true;
       break;
 
+    case 'c':
+      use_stdout = true;
+      break;
+
     case 'h':
     case '?':
     default:
@@ -85,6 +72,20 @@ main(int argc, char *argv[]) {
   argc -= (optind-1);
   argv += (optind-1);
 
+  if (use_stdout) {
+    if (argc > 1) {
+      cerr << "No filenames allowed in conjunction with -c.\n";
+      return 1;
+    }
+
+    bool success = decompress_stream(cin, cout);
+    if (!success) {
+      cerr << "Failure compressing standard input\n";
+      return 1;
+    }
+    return 0;
+  }
+
   if (argc < 2) {
     usage();
     return 1;
@@ -126,7 +127,7 @@ main(int argc, char *argv[]) {
 
         } else {
           cerr << dest_file << "\n";
-          bool success = do_decompress(read_stream, write_stream);
+          bool success = decompress_stream(read_stream, write_stream);
           
           read_stream.close();
           write_stream.close();

+ 69 - 25
panda/src/downloadertools/pzip.cxx

@@ -13,7 +13,7 @@
 ////////////////////////////////////////////////////////////////////
 
 #include "filename.h"
-#include "zStream.h"
+#include "compress_string.h"
 #include "pnotify.h"
 
 #ifndef HAVE_GETOPT
@@ -24,33 +24,14 @@
   #endif
 #endif
 
-bool
-do_compress(istream &read_stream, ostream &write_stream) {
-  OCompressStream compress(&write_stream, false);
-
-  static const size_t buffer_size = 1024;
-  char buffer[buffer_size];
-
-  read_stream.read(buffer, buffer_size);
-  size_t count = read_stream.gcount();
-  while (count != 0) {
-    compress.write(buffer, count);
-    read_stream.read(buffer, buffer_size);
-    count = read_stream.gcount();
-  }
-  compress.close();
-
-  return !read_stream.fail() || read_stream.eof() &&
-    (!compress.fail() || compress.eof());
-}
-
 void
 usage() {
   cerr
     << "\nUsage:\n"
     << "   pzip file [file2 file3 ...]\n"
+    << "   pzip -c <file >dest_file\n"
     << "   pzip -o dest_file file\n\n"
-    
+
     << "This program compresses the named file(s) using the Panda native\n"
     << "compression algorithm (gzip in practice, but with a different file\n"
     << "header).  The compressed versions are written to a file with the\n"
@@ -70,17 +51,26 @@ usage() {
 
     << "Note that if you are adding files to a Panda multifile (.mf file) with\n"
     << "the multify command, it is not necessary to compress them separately;\n"
-    << "multify has an inline compression option.\n\n";
+    << "multify has an inline compression option.\n\n"
+
+    << "Options:\n\n"
+
+    << "  -1  compress faster\n"
+    << "  -6  compress default\n"
+    << "  -9  compress better (intermediate compression levels supported also)\n\n";
+    
 }
 
 int
 main(int argc, char *argv[]) {
   extern char *optarg;
   extern int optind;
-  const char *optstr = "o:h";
+  const char *optstr = "o:c123456789h";
 
   Filename dest_filename;
   bool got_dest_filename = false;
+  bool use_stdout = false;
+  int compression_level = 6;
 
   int flag = getopt(argc, argv, optstr);
 
@@ -91,6 +81,46 @@ main(int argc, char *argv[]) {
       got_dest_filename = true;
       break;
 
+    case 'c':
+      use_stdout = true;
+      break;
+
+    case '1':
+      compression_level = 1;
+      break;
+
+    case '2':
+      compression_level = 2;
+      break;
+
+    case '3':
+      compression_level = 3;
+      break;
+
+    case '4':
+      compression_level = 4;
+      break;
+
+    case '5':
+      compression_level = 5;
+      break;
+
+    case '6':
+      compression_level = 6;
+      break;
+
+    case '7':
+      compression_level = 7;
+      break;
+
+    case '8':
+      compression_level = 8;
+      break;
+
+    case '9':
+      compression_level = 9;
+      break;
+
     case 'h':
     case '?':
     default:
@@ -103,6 +133,20 @@ main(int argc, char *argv[]) {
   argc -= (optind-1);
   argv += (optind-1);
 
+  if (use_stdout) {
+    if (argc > 1) {
+      cerr << "No filenames allowed in conjunction with -c.\n";
+      return 1;
+    }
+
+    bool success = compress_stream(cin, cout, compression_level);
+    if (!success) {
+      cerr << "Failure compressing standard input\n";
+      return 1;
+    }
+    return 0;
+  }
+
   if (argc < 2) {
     usage();
     return 1;
@@ -141,7 +185,7 @@ main(int argc, char *argv[]) {
 
         } else {
           cerr << dest_file << "\n";
-          bool success = do_compress(read_stream, write_stream);
+          bool success = compress_stream(read_stream, write_stream, compression_level);
           
           read_stream.close();
           write_stream.close();

+ 3 - 0
panda/src/express/Sources.pp

@@ -13,6 +13,7 @@
     checksumHashGenerator.I checksumHashGenerator.h circBuffer.I \
     circBuffer.h \
     config_express.h \
+    compress_string.h \
     datagram.I datagram.h datagramGenerator.I \
     datagramGenerator.h \
     datagramIterator.I datagramIterator.h datagramSink.I datagramSink.h \
@@ -72,6 +73,7 @@
   #define INCLUDED_SOURCES  \
     buffer.cxx checksumHashGenerator.cxx \
     config_express.cxx \
+    compress_string.cxx \
     datagram.cxx datagramGenerator.cxx \
     datagramIterator.cxx \
     datagramSink.cxx dcast.cxx \
@@ -122,6 +124,7 @@
     checksumHashGenerator.I checksumHashGenerator.h circBuffer.I \
     circBuffer.h \
     config_express.h \
+    compress_string.h \
     datagram.I datagram.h datagramGenerator.I \
     datagramGenerator.h \
     datagramIterator.I datagramIterator.h datagramSink.I datagramSink.h \

+ 199 - 0
panda/src/express/compress_string.cxx

@@ -0,0 +1,199 @@
+// Filename: compress_string.cxx
+// Created by:  drose (09Aug09)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+#include "compress_string.h"
+
+#ifdef HAVE_ZLIB
+#include "zStream.h"
+#include "virtualFileSystem.h"
+#include "config_express.h"
+
+////////////////////////////////////////////////////////////////////
+//     Function: compress_string
+//       Access: Published
+//  Description: Compress the indicated source string at the given
+//               compression level (1 through 9).  Returns the
+//               compressed string.
+////////////////////////////////////////////////////////////////////
+string
+compress_string(const string &source, int compression_level) {
+  ostringstream dest;
+
+  {
+    OCompressStream compress;
+    compress.open(&dest, false, compression_level);
+    compress.write(source.data(), source.length());
+
+    if (compress.fail()) {
+      return string();
+    }
+  }
+
+  return dest.str();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: decompress_string
+//       Access: Published
+//  Description: Decompresss the previously-compressed string()).  The
+//               return value is the decompressed string.
+//
+//               Note that a decompression error cannot easily be
+//               detected, and the return value may simply be a
+//               garbage or truncated string.
+////////////////////////////////////////////////////////////////////
+string
+decompress_string(const string &source) {
+  istringstream source_stream(source);
+  ostringstream dest_stream;
+
+  if (!decompress_stream(source_stream, dest_stream)) {
+    return string();
+  }
+
+  return dest_stream.str();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: compress_file
+//       Access: Published
+//  Description: Compresss the data from the source file at the given
+//               compression level (1 through 9).  The source file is
+//               read in its entirety, and the compressed results are
+//               written to the dest file, overwriting its contents.
+//               The return value is bool on success, or false on
+//               failure.
+////////////////////////////////////////////////////////////////////
+EXPCL_PANDAEXPRESS bool 
+compress_file(const Filename &source, const Filename &dest, int compression_level) {
+  Filename source_filename = Filename::binary_filename(source);
+  VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
+  istream *source_stream = vfs->open_read_file(source_filename, true);
+  if (source_stream == NULL) {
+    express_cat.info() << "Couldn't open file " << source_filename << "\n";
+    return false;
+  }
+  
+  Filename dest_filename = Filename::binary_filename(dest);
+  pofstream dest_stream;
+  if (!dest_filename.open_write(dest_stream)) {
+    express_cat.info() << "Couldn't open file " << dest_filename << "\n";
+    vfs->close_read_file(source_stream);
+    return false;
+  }
+    
+  bool result = compress_stream(*source_stream, dest_stream, compression_level);
+  vfs->close_read_file(source_stream);
+  return result;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: decompress_file
+//       Access: Published
+//  Description: Decompresss the data from the source file.  The
+//               source file is read in its entirety, and the
+//               decompressed results are written to the dest file,
+//               overwriting its contents.  The return value is bool
+//               on success, or false on failure.
+//
+//               Note that a decompression error cannot easily be
+//               detected, and the output may simply be a garbage
+//               or truncated string.
+////////////////////////////////////////////////////////////////////
+EXPCL_PANDAEXPRESS bool 
+decompress_file(const Filename &source, const Filename &dest) {
+  Filename source_filename = Filename::binary_filename(source);
+  VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
+  istream *source_stream = vfs->open_read_file(source_filename, true);
+  if (source_stream == NULL) {
+    express_cat.info() << "Couldn't open file " << source_filename << "\n";
+    return false;
+  }
+  
+  Filename dest_filename = Filename::binary_filename(dest);
+  pofstream dest_stream;
+  if (!dest_filename.open_write(dest_stream)) {
+    express_cat.info() << "Couldn't open file " << dest_filename << "\n";
+    vfs->close_read_file(source_stream);
+    return false;
+  }
+    
+  bool result = decompress_stream(*source_stream, dest_stream);
+  vfs->close_read_file(source_stream);
+  return result;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: compress_stream
+//       Access: Published
+//  Description: Compresss the data from the source stream at the
+//               given compression level (1 through 9).  The source
+//               stream is read from its current position to the
+//               end-of-file, and the compressed results are written
+//               to the dest stream.  The return value is bool on
+//               success, or false on failure.
+////////////////////////////////////////////////////////////////////
+bool
+compress_stream(istream &source, ostream &dest, int compression_level) {
+  OCompressStream compress;
+  compress.open(&dest, false, compression_level);
+    
+  static const size_t buffer_size = 4096;
+  char buffer[buffer_size];
+
+  source.read(buffer, buffer_size);
+  size_t count = source.gcount();
+  while (count != 0) {
+    compress.write(buffer, count);
+    source.read(buffer, buffer_size);
+    count = source.gcount();
+  }
+  compress.close();
+
+  return (!source.fail() || source.eof()) && (!compress.fail());
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: decompress_stream
+//       Access: Published
+//  Description: Decompresss the data from the previously-compressed
+//               source stream.  The source stream is read from its
+//               current position to the end-of-file, and the
+//               decompressed results are written to the dest stream.
+//               The return value is bool on success, or false on
+//               failure.
+//
+//               Note that a decompression error cannot easily be
+//               detected, and the output may simply be a garbage
+//               or truncated string.
+////////////////////////////////////////////////////////////////////
+bool
+decompress_stream(istream &source, ostream &dest) {
+  IDecompressStream decompress(&source, false);
+
+  static const size_t buffer_size = 4096;
+  char buffer[buffer_size];
+
+  decompress.read(buffer, buffer_size);
+  size_t count = decompress.gcount();
+  while (count != 0) {
+    dest.write(buffer, count);
+    decompress.read(buffer, buffer_size);
+    count = decompress.gcount();
+  }
+  
+  return (!decompress.fail() || decompress.eof()) && (!dest.fail());
+}
+
+#endif // HAVE_ZLIB

+ 46 - 0
panda/src/express/compress_string.h

@@ -0,0 +1,46 @@
+// Filename: compress_string.h
+// Created by:  drose (09Aug09)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef COMPRESS_STRING_H
+#define COMPRESS_STRING_H
+
+#include "pandabase.h"
+
+#ifdef HAVE_ZLIB
+
+#include "filename.h"
+
+BEGIN_PUBLISH
+
+EXPCL_PANDAEXPRESS string
+compress_string(const string &source, int compression_level);
+
+EXPCL_PANDAEXPRESS string
+decompress_string(const string &source);
+
+EXPCL_PANDAEXPRESS bool
+compress_file(const Filename &source, const Filename &dest, int compression_level);
+EXPCL_PANDAEXPRESS bool
+decompress_file(const Filename &source, const Filename &dest);
+
+EXPCL_PANDAEXPRESS bool
+compress_stream(istream &source, ostream &dest, int compression_level);
+EXPCL_PANDAEXPRESS bool
+decompress_stream(istream &source, ostream &dest);
+
+END_PUBLISH
+
+#endif  // HAVE_ZLIB
+
+#endif

+ 3 - 0
panda/src/express/config_express.N

@@ -16,6 +16,9 @@ forcetype NeverFreeMemory
 forcetype IFileStream
 forcetype OFileStream
 forcetype FileStream
+renametype IFileStream IFileStream
+renametype OFileStream OFileStream
+renametype FileStream FileStream
 forcetype IDecryptStream
 forcetype OEncryptStream
 

+ 176 - 19
panda/src/express/encrypt_string.cxx

@@ -13,9 +13,12 @@
 ////////////////////////////////////////////////////////////////////
 
 #include "encrypt_string.h"
-#include "encryptStream.h"
 
 #ifdef HAVE_OPENSSL
+#include "encryptStream.h"
+#include "virtualFileSystem.h"
+#include "config_express.h"
+
 ////////////////////////////////////////////////////////////////////
 //     Function: encrypt_string
 //       Access: Published
@@ -24,15 +27,30 @@
 //               encryption-algorithm.  Returns the encrypted string.
 ////////////////////////////////////////////////////////////////////
 string
-encrypt_string(const string &source, const string &password) {
-  ostringstream output;
+encrypt_string(const string &source, const string &password,
+               const string &algorithm, int key_length, int iteration_count) {
+  ostringstream dest;
 
   {
-    OEncryptStream encrypt(&output, false, password);
+    OEncryptStream encrypt;
+    if (!algorithm.empty()) {
+      encrypt.set_algorithm(algorithm);
+    }
+    if (key_length > 0) {
+      encrypt.set_key_length(key_length);
+    }
+    if (iteration_count >= 0) {
+      encrypt.set_iteration_count(iteration_count);
+    }
+    encrypt.open(&dest, false, password);
     encrypt.write(source.data(), source.length());
+
+    if (encrypt.fail()) {
+      return string();
+    }
   }
 
-  return output.str();
+  return dest.str();
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -41,27 +59,166 @@ encrypt_string(const string &source, const string &password) {
 //  Description: Decrypts the previously-encrypted string using the
 //               given password (which must be the same password
 //               passed to encrypt()).  The return value is the
-//               decrypted string.  Note that a decryption error,
-//               including an incorrect password, cannot easily be
-//               detected, and the return value may simply be a
-//               garbage string.
+//               decrypted string.
+//
+//               Note that a decryption error, including an incorrect
+//               password, cannot easily be detected, and the return
+//               value may simply be a garbage string.
 ////////////////////////////////////////////////////////////////////
 string
 decrypt_string(const string &source, const string &password) {
-  istringstream input(source);
-  ostringstream output;
+  istringstream source_stream(source);
+  ostringstream dest_stream;
 
-  {
-    IDecryptStream decrypt(&input, false, password);
+  if (!decrypt_stream(source_stream, dest_stream, password)) {
+    return string();
+  }
+
+  return dest_stream.str();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: encrypt_file
+//       Access: Published
+//  Description: Encrypts the data from the source file using the
+//               given password.  The source file is read in its
+//               entirety, and the encrypted results are written to
+//               the dest file, overwriting its contents.  The return
+//               value is bool on success, or false on failure.
+////////////////////////////////////////////////////////////////////
+EXPCL_PANDAEXPRESS bool 
+encrypt_file(const Filename &source, const Filename &dest, const string &password,
+             const string &algorithm, int key_length, int iteration_count) {
+  Filename source_filename = Filename::binary_filename(source);
+  VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
+  istream *source_stream = vfs->open_read_file(source_filename, true);
+  if (source_stream == NULL) {
+    express_cat.info() << "Couldn't open file " << source_filename << "\n";
+    return false;
+  }
+  
+  Filename dest_filename = Filename::binary_filename(dest);
+  pofstream dest_stream;
+  if (!dest_filename.open_write(dest_stream)) {
+    express_cat.info() << "Couldn't open file " << dest_filename << "\n";
+    vfs->close_read_file(source_stream);
+    return false;
+  }
     
-    int ch = decrypt.get();
-    while (!decrypt.eof() && !decrypt.fail()) {
-      output.put(ch);
-      ch = decrypt.get();
-    }
+  bool result = encrypt_stream(*source_stream, dest_stream, password,
+                               algorithm, key_length, iteration_count);
+  vfs->close_read_file(source_stream);
+  return result;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: decrypt_file
+//       Access: Published
+//  Description: Decrypts the data from the source file using the
+//               given password (which must match the same password
+//               passed to encrypt()).  The source file is read in its
+//               entirety, and the decrypted results are written to
+//               the dest file, overwriting its contents.  The return
+//               value is bool on success, or false on failure.
+//
+//               Note that a decryption error, including an incorrect
+//               password, cannot easily be detected, and the output
+//               may simply be a garbage string.
+////////////////////////////////////////////////////////////////////
+EXPCL_PANDAEXPRESS bool 
+decrypt_file(const Filename &source, const Filename &dest, const string &password) {
+  Filename source_filename = Filename::binary_filename(source);
+  VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
+  istream *source_stream = vfs->open_read_file(source_filename, true);
+  if (source_stream == NULL) {
+    express_cat.info() << "Couldn't open file " << source_filename << "\n";
+    return false;
+  }
+  
+  Filename dest_filename = Filename::binary_filename(dest);
+  pofstream dest_stream;
+  if (!dest_filename.open_write(dest_stream)) {
+    express_cat.info() << "Couldn't open file " << dest_filename << "\n";
+    vfs->close_read_file(source_stream);
+    return false;
+  }
+    
+  bool result = decrypt_stream(*source_stream, dest_stream, password);
+  vfs->close_read_file(source_stream);
+  return result;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: encrypt_stream
+//       Access: Published
+//  Description: Encrypts the data from the source stream using the
+//               given password.  The source stream is read from its
+//               current position to the end-of-file, and the
+//               encrypted results are written to the dest stream.
+//               The return value is bool on success, or false on
+//               failure.
+////////////////////////////////////////////////////////////////////
+bool
+encrypt_stream(istream &source, ostream &dest, const string &password,
+               const string &algorithm, int key_length, int iteration_count) {
+  OEncryptStream encrypt;
+  if (!algorithm.empty()) {
+    encrypt.set_algorithm(algorithm);
+  }
+  if (key_length > 0) {
+    encrypt.set_key_length(key_length);
+  }
+  if (iteration_count >= 0) {
+    encrypt.set_iteration_count(iteration_count);
   }
+  encrypt.open(&dest, false, password);
+    
+  static const size_t buffer_size = 4096;
+  char buffer[buffer_size];
+
+  source.read(buffer, buffer_size);
+  size_t count = source.gcount();
+  while (count != 0) {
+    encrypt.write(buffer, count);
+    source.read(buffer, buffer_size);
+    count = source.gcount();
+  }
+  encrypt.close();
+
+  return (!source.fail() || source.eof()) && (!encrypt.fail());
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: decrypt_stream
+//       Access: Published
+//  Description: Decrypts the data from the previously-encrypted
+//               source stream using the given password (which must be
+//               the same password passed to encrypt()).  The source
+//               stream is read from its current position to the
+//               end-of-file, and the decrypted results are written to
+//               the dest stream.  The return value is bool on
+//               success, or false on failure.
+//
+//               Note that a decryption error, including an incorrect
+//               password, cannot easily be detected, and the output
+//               may simply be a garbage string.
+////////////////////////////////////////////////////////////////////
+bool
+decrypt_stream(istream &source, ostream &dest, const string &password) {
+  IDecryptStream decrypt(&source, false, password);
+
+  static const size_t buffer_size = 4096;
+  char buffer[buffer_size];
 
-  return output.str();
+  decrypt.read(buffer, buffer_size);
+  size_t count = decrypt.gcount();
+  while (count != 0) {
+    dest.write(buffer, count);
+    decrypt.read(buffer, buffer_size);
+    count = decrypt.gcount();
+  }
+  
+  return (!decrypt.fail() || decrypt.eof()) && (!dest.fail());
 }
 
 #endif // HAVE_OPENSSL

+ 24 - 2
panda/src/express/encrypt_string.h

@@ -19,9 +19,31 @@
 
 #ifdef HAVE_OPENSSL
 
+#include "filename.h"
+
 BEGIN_PUBLISH
-EXPCL_PANDAEXPRESS string encrypt_string(const string &source, const string &password);
-EXPCL_PANDAEXPRESS string decrypt_string(const string &source, const string &password);
+
+EXPCL_PANDAEXPRESS string
+encrypt_string(const string &source, const string &password,
+               const string &algorithm = string(), int key_length = -1, 
+               int iteration_count = -1);
+EXPCL_PANDAEXPRESS string
+decrypt_string(const string &source, const string &password);
+
+EXPCL_PANDAEXPRESS bool
+encrypt_file(const Filename &source, const Filename &dest, const string &password,
+             const string &algorithm = string(), int key_length = -1, 
+             int iteration_count = -1);
+EXPCL_PANDAEXPRESS bool
+decrypt_file(const Filename &source, const Filename &dest, const string &password);
+
+EXPCL_PANDAEXPRESS bool
+encrypt_stream(istream &source, ostream &dest, const string &password,
+               const string &algorithm = string(), int key_length = -1, 
+               int iteration_count = -1);
+EXPCL_PANDAEXPRESS bool
+decrypt_stream(istream &source, ostream &dest, const string &password);
+
 END_PUBLISH
 
 #endif  // HAVE_OPENSSL

+ 1 - 0
panda/src/express/express_composite1.cxx

@@ -1,6 +1,7 @@
 #include "buffer.cxx"
 #include "checksumHashGenerator.cxx"
 #include "config_express.cxx"
+#include "compress_string.cxx"
 #include "datagram.cxx"
 #include "datagramGenerator.cxx"
 #include "datagramIterator.cxx"

+ 1 - 1
panda/src/express/zStream.h

@@ -65,7 +65,7 @@ PUBLISHED:
                            int compression_level = 6);
 
   INLINE OCompressStream &open(ostream *dest, bool owns_dest, 
-                                 int compression_level = 6);
+                               int compression_level = 6);
   INLINE OCompressStream &close();
 
 private: