CVS update: /ccvs/src/
[email protected] 3 Jun 2005 18:26:12 -0000
| Newsgroups | gmane.comp.version-control.cvs.cvs |
|---|---|
| Message-ID | <[email protected]> |
User: dprice Date: 05/06/03 11:26:12 Modified: /ccvs/src/ ChangeLog, client.c, main.c, parseinfo.c, parseinfo.h, sanity.sh, server.c, zlib.c Log: * client.c (force_gzip): New static global. (handle_force_gzip): New function. (responses): Add `Force-gzip'. (start_server): Turn on encryption and compression before potentially sending other rooted requests. Turn on compression when requested by the user or the server. * main.c (opt_usage): Note that -z<level> *requests* compression <level> from the server. * parseinfo.c (new_config): Initialize MaxCompressionLevel. (parse_config): Parse MinCompressionLevel & MaxCompressionLevel. * parseinfo.h (struct config): Add MinCompressionLevel & MaxCompressionLevel. * server.c (pending_warning_text): New static global. (print_pending_error): Print pending warnings too. (warning_pending): New macro. (alloc_pending_internal): New function with much content... (alloc_pending): ...previously from here. (alloc_pending_warning): New function. (server_root, serve_gzip_contents, gzip_stream): Force gzip_level into configured restrictions. (serve_command_prep): Print pending errors. (requests): Make `Gzip-stream', `gzip-file-contents', `Kerberos-encrypt', `Gssapi-encrypt', & `Gssapi-authenticate' requests rootless to allow them before compression starts. (serve_valid_requests): Send `Force-gzip' response when needed. (server): Abort if a rootless compression request forced compression outside restricted levels. * zlib.c (struct compress_buffer, compress_buffer_initialize): Store compression level. (compress_buffer_output): Reset compression level when global gzip_level has changed. * sanity.sh (config2): New tests for compression restrictions. File Changes: Directory: /ccvs/src/ ===================== File [changed]: ChangeLog Url: https://ccvs.cvshome.org/source/browse/ccvs/src/ChangeLog?r1=1.3210&r2=1.3211 Delta lines: +35 -0 -------------------- --- ChangeLog 3 Jun 2005 16:27:21 -0000 1.3210 +++ ChangeLog 3 Jun 2005 18:26:08 -0000 1.3211 @@ -1,5 +1,40 @@ 2005-06-03 Derek Price <[email protected]> + * client.c (force_gzip): New static global. + (handle_force_gzip): New function. + (responses): Add `Force-gzip'. + (start_server): Turn on encryption and compression before potentially + sending other rooted requests. Turn on compression when requested by + the user or the server. + * main.c (opt_usage): Note that -z<level> *requests* compression + <level> from the server. + * parseinfo.c (new_config): Initialize MaxCompressionLevel. + (parse_config): Parse MinCompressionLevel & MaxCompressionLevel. + * parseinfo.h (struct config): Add MinCompressionLevel & + MaxCompressionLevel. + * server.c (pending_warning_text): New static global. + (print_pending_error): Print pending warnings too. + (warning_pending): New macro. + (alloc_pending_internal): New function with much content... + (alloc_pending): ...previously from here. + (alloc_pending_warning): New function. + (server_root, serve_gzip_contents, gzip_stream): Force gzip_level into + configured restrictions. + (serve_command_prep): Print pending errors. + (requests): Make `Gzip-stream', `gzip-file-contents', + `Kerberos-encrypt', `Gssapi-encrypt', & `Gssapi-authenticate' requests + rootless to allow them before compression starts. + (serve_valid_requests): Send `Force-gzip' response when needed. + (server): Abort if a rootless compression request forced compression + outside restricted levels. + * zlib.c (struct compress_buffer, compress_buffer_initialize): Store + compression level. + (compress_buffer_output): Reset compression level when global + gzip_level has changed. + * sanity.sh (config2): New tests for compression restrictions. + +2005-06-03 Derek Price <[email protected]> + * zlib.c (compress_buffer_input): Update comment. 2005-06-03 Derek Price <[email protected]> File [changed]: client.c Url: https://ccvs.cvshome.org/source/browse/ccvs/src/client.c?r1=1.427&r2=1.428 Delta lines: +148 -126 ----------------------- --- client.c 3 Jun 2005 13:14:41 -0000 1.427 +++ client.c 3 Jun 2005 18:26:08 -0000 1.428 @@ -444,6 +444,9 @@ #ifdef CLIENT_SUPPORT +/* Whether the server asked us to force compression. */ +static bool force_gzip; + /* * The Repository for the top level of this command (not necessarily * the CVSROOT, just the current directory at the time we do it). @@ -549,6 +552,12 @@ } } +static void +handle_force_gzip (char *args, size_t len) +{ + force_gzip = true; +} + /* Has the server told us its name since the last redirect? @@ -3046,6 +3055,8 @@ RSP_LINE("error", handle_error, response_type_error, rs_essential), RSP_LINE("Valid-requests", handle_valid_requests, response_type_normal, rs_essential), + RSP_LINE("Force-gzip", handle_force_gzip, response_type_normal, + rs_optional), RSP_LINE("Referrer", handle_referrer, response_type_normal, rs_optional), RSP_LINE("Redirect", handle_redirect, response_type_redirect, rs_optional), RSP_LINE("Checked-in", handle_checked_in, response_type_normal, @@ -3967,6 +3978,7 @@ { bool rootless; int status; + bool have_global; do { @@ -4032,6 +4044,119 @@ if (get_server_responses ()) exit (EXIT_FAILURE); + have_global = supported_request ("Global_option"); + + /* Encryption needs to come before compression. Good encryption can + * render compression useless in the other direction. + */ + if (cvsencrypt && !rootless) + { +#ifdef ENCRYPTION + /* Turn on encryption before turning on compression. We do + * not want to try to compress the encrypted stream. Instead, + * we want to encrypt the compressed stream. If we can't turn + * on encryption, bomb out; don't let the user think the data + * is being encrypted when it is not. + */ +# ifdef HAVE_KERBEROS + if (current_parsed_root->method == kserver_method) + { + if (!supported_request ("Kerberos-encrypt")) + error (1, 0, "This server does not support encryption"); + send_to_server ("Kerberos-encrypt\012", 0); + initialize_kerberos4_encryption_buffers (&global_to_server, + &global_from_server); + } + else +# endif /* HAVE_KERBEROS */ +# ifdef HAVE_GSSAPI + if (current_parsed_root->method == gserver_method) + { + if (!supported_request ("Gssapi-encrypt")) + error (1, 0, "This server does not support encryption"); + send_to_server ("Gssapi-encrypt\012", 0); + initialize_gssapi_buffers (&global_to_server, + &global_from_server); + cvs_gssapi_encrypt = 1; + } + else +# endif /* HAVE_GSSAPI */ + error (1, 0, +"Encryption is only supported when using GSSAPI or Kerberos"); +#else /* ! ENCRYPTION */ + error (1, 0, "This client does not support encryption"); +#endif /* ! ENCRYPTION */ + } + + /* Send this before compression to enable supression of the + * "Forcing compression level Z" messages. + */ + if (quiet) + { + if (have_global) + { + send_to_server ("Global_option -q\012", 0); + } + else + error (1, 0, + "This server does not support the global -q option."); + } + if (really_quiet) + { + if (have_global) + { + send_to_server ("Global_option -Q\012", 0); + } + else + error (1, 0, + "This server does not support the global -Q option."); + } + + /* Compression needs to come before any of the rooted requests to + * work with compression limits. + */ + if (!rootless && (gzip_level || force_gzip)) + { + if (supported_request ("Gzip-stream")) + { + char *gzip_level_buf = Xasprintf ("%d", gzip_level); + send_to_server ("Gzip-stream ", 0); + send_to_server (gzip_level_buf, 0); + free (gzip_level_buf); + send_to_server ("\012", 1); + + /* All further communication with the server will be + compressed. */ + + global_to_server = + compress_buffer_initialize (global_to_server, 0, + gzip_level, NULL); + global_from_server = + compress_buffer_initialize (global_from_server, 1, + gzip_level, NULL); + } +#ifndef NO_CLIENT_GZIP_PROCESS + else if (supported_request ("gzip-file-contents")) + { + char *gzip_level_buf = Xasprintf ("%d", gzip_level); + send_to_server ("gzip-file-contents ", 0); + send_to_server (gzip_level_buf, 0); + free (gzip_level_buf); + send_to_server ("\012", 1); + + file_gzip_level = gzip_level; + } +#endif + else + { + fprintf (stderr, "server doesn't support gzip-file-contents\n"); + /* Setting gzip_level to 0 prevents us from giving the + error twice if update has to contact the server again + to fetch unpatchable files. */ + gzip_level = 0; + } + } + if (client_referrer && supported_request ("Referrer")) { send_to_server ("Referrer ", 0); @@ -4067,10 +4192,6 @@ * * -l -t -r -w -q -n and -Q need to go to the server. */ - - { - bool have_global = supported_request ("Global_option"); - if (noexec) { if (have_global) @@ -4081,26 +4202,6 @@ error (1, 0, "This server does not support the global -n option."); } - if (quiet) - { - if (have_global) - { - send_to_server ("Global_option -q\012", 0); - } - else - error (1, 0, - "This server does not support the global -q option."); - } - if (really_quiet) - { - if (have_global) - { - send_to_server ("Global_option -Q\012", 0); - } - else - error (1, 0, - "This server does not support the global -Q option."); - } if (!cvswrite) { if (have_global) @@ -4122,7 +4223,6 @@ error (1, 0, "This server does not support the global -t option."); } - } /* Find out about server-side cvswrappers. An extra network turnaround for cvs import seems to be unavoidable, unless we @@ -4144,84 +4244,6 @@ } } - if (cvsencrypt && !rootless) - { -#ifdef ENCRYPTION - /* Turn on encryption before turning on compression. We do - not want to try to compress the encrypted stream. Instead, - we want to encrypt the compressed stream. If we can't turn - on encryption, bomb out; don't let the user think the data - is being encrypted when it is not. */ -#ifdef HAVE_KERBEROS - if (current_parsed_root->method == kserver_method) - { - if (! supported_request ("Kerberos-encrypt")) - error (1, 0, "This server does not support encryption"); - send_to_server ("Kerberos-encrypt\012", 0); - initialize_kerberos4_encryption_buffers (&global_to_server, - &global_from_server); - } - else -#endif /* HAVE_KERBEROS */ -#ifdef HAVE_GSSAPI - if (current_parsed_root->method == gserver_method) - { - if (! supported_request ("Gssapi-encrypt")) - error (1, 0, "This server does not support encryption"); - send_to_server ("Gssapi-encrypt\012", 0); - initialize_gssapi_buffers(&global_to_server, &global_from_server); - cvs_gssapi_encrypt = 1; - } - else -#endif /* HAVE_GSSAPI */ - error (1, 0, -"Encryption is only supported when using GSSAPI or Kerberos"); -#else /* ! ENCRYPTION */ - error (1, 0, "This client does not support encryption"); -#endif /* ! ENCRYPTION */ - } - - if (gzip_level && !rootless) - { - if (supported_request ("Gzip-stream")) - { - char *gzip_level_buf = Xasprintf ("%d", gzip_level); - send_to_server ("Gzip-stream ", 0); - send_to_server (gzip_level_buf, 0); - free (gzip_level_buf); - send_to_server ("\012", 1); - - /* All further communication with the server will be - compressed. */ - - global_to_server = compress_buffer_initialize (global_to_server, 0, - gzip_level, NULL); - global_from_server = compress_buffer_initialize (global_from_server, - 1, gzip_level, - NULL); - } -#ifndef NO_CLIENT_GZIP_PROCESS - else if (supported_request ("gzip-file-contents")) - { - char *gzip_level_buf = Xasprintf ("%d", gzip_level); - send_to_server ("gzip-file-contents ", 0); - send_to_server (gzip_level_buf, 0); - free (gzip_level_buf); - send_to_server ("\012", 1); - - file_gzip_level = gzip_level; - } -#endif - else - { - fprintf (stderr, "server doesn't support gzip-file-contents\n"); - /* Setting gzip_level to 0 prevents us from giving the - error twice if update has to contact the server again - to fetch unpatchable files. */ - gzip_level = 0; - } - } - if (cvsauthenticate && ! cvsencrypt && !rootless) { /* Turn on authentication after turning on compression, so File [changed]: main.c Url: https://ccvs.cvshome.org/source/browse/ccvs/src/main.c?r1=1.244&r2=1.245 Delta lines: +1 -1 ------------------- --- main.c 17 Mar 2005 17:15:19 -0000 1.244 +++ main.c 3 Jun 2005 18:26:08 -0000 1.245 @@ -258,7 +258,7 @@ " -d CVS_root Overrides $CVSROOT as the root of the CVS tree.\n", " -f Do not use the ~/.cvsrc file.\n", #ifdef CLIENT_SUPPORT - " -z # Use compression level '#' for net traffic.\n", + " -z # Request compression level '#' for net traffic.\n", #ifdef ENCRYPTION " -x Encrypt all net traffic.\n", #endif File [changed]: parseinfo.c Url: https://ccvs.cvshome.org/source/browse/ccvs/src/parseinfo.c?r1=1.77&r2=1.78 Delta lines: +11 -0 -------------------- --- parseinfo.c 3 Jun 2005 15:36:35 -0000 1.77 +++ parseinfo.c 3 Jun 2005 18:26:09 -0000 1.78 @@ -290,6 +290,9 @@ new->RereadLogAfterVerify = LOGMSG_REREAD_ALWAYS; new->UserAdminOptions = xstrdup ("k"); new->MaxCommentLeaderLength = 20; +#ifdef SERVER_SUPPORT + new->MaxCompressionLevel = 9; +#endif /* SERVER_SUPPORT */ #ifdef PROXY_SUPPORT new->MaxProxyBufferSize = (size_t)(8 * 1024 * 1024); /* 8 megabytes, * by default. @@ -584,6 +587,14 @@ else if (!strcmp (line, "UseArchiveCommentLeader")) readBool (infopath, "UseArchiveCommentLeader", p, &retval->UseArchiveCommentLeader); +#ifdef SERVER_SUPPORT + else if (!strcmp (line, "MinCompressionLevel")) + readSizeT (infopath, "MinCompressionLevel", p, + &retval->MinCompressionLevel); + else if (!strcmp (line, "MaxCompressionLevel")) + readSizeT (infopath, "MaxCompressionLevel", p, + &retval->MaxCompressionLevel); +#endif /* SERVER_SUPPORT */ else /* We may be dealing with a keyword which was added in a subsequent version of CVS. In that case it is a good idea File [changed]: parseinfo.h Url: https://ccvs.cvshome.org/source/browse/ccvs/src/parseinfo.h?r1=1.4&r2=1.5 Delta lines: +4 -0 ------------------- --- parseinfo.h 11 May 2005 20:01:47 -0000 1.4 +++ parseinfo.h 3 Jun 2005 18:26:09 -0000 1.5 @@ -51,6 +51,10 @@ #ifdef PROXY_SUPPORT size_t MaxProxyBufferSize; #endif /* PROXY_SUPPORT */ +#ifdef SERVER_SUPPORT + size_t MinCompressionLevel; + size_t MaxCompressionLevel; +#endif /* SERVER_SUPPORT */ #ifdef PRESERVE_PERMISSIONS_SUPPORT bool preserve_perms; #endif /* PRESERVE_PERMISSIONS_SUPPORT */ File [changed]: sanity.sh Url: https://ccvs.cvshome.org/source/browse/ccvs/src/sanity.sh?r1=1.1067&r2=1.1068 Delta lines: +82 -0 -------------------- --- sanity.sh 2 Jun 2005 19:05:18 -0000 1.1067 +++ sanity.sh 3 Jun 2005 18:26:09 -0000 1.1068 @@ -18685,6 +18685,7 @@ # postadmin: admin # postwatch: devcom3 # config: config + # config2: MinCompressionLevel and MaxCompressionLevel in config # On Windows, we can't check out CVSROOT, because the case # insensitivity means that this conflicts with cvsroot. @@ -19902,6 +19903,87 @@ + config2) + # Tests of the CVSROOT/config file. See the comment at the + # "info" tests for a full list of administrative file tests. + + # No point in testing compression effects in local mode. + if $remote; then :; else + remoteonly config2 + continue + fi + + # On Windows, we can't check out CVSROOT, because the case + # insensitivity means that this conflicts with cvsroot. + mkdir wnt + cd wnt + + # Set MinCompressionLevel and MaxCompressionLevel in config. + dotest config2-init-1 "$testcvs -q co CVSROOT" "U CVSROOT/$DOTSTAR" + cd CVSROOT + cat << EOF > config +MinCompressionLevel=5 +MaxCompressionLevel=6 +EOF + dotest config2-init-2 \ +"$testcvs -q ci -m set-compression-constraints" \ +"$CVSROOT_DIRNAME/CVSROOT/config,v <-- config +new revision: 1\.[0-9]*; previous revision: 1\.[0-9]* +$SPROG commit: Rebuilding administrative file database" + + # Verify that the server reports forcing compression to an allowed + # level. + + # Too high. + dotest config2-1 "$testcvs -z9 update" \ +"$SPROG server: Forcing compression level 6 (allowed: 5 <= z <= 6)\. +$SPROG update: Updating \." + # Too low. + dotest config2-2 "$testcvs -z1 update" \ +"$SPROG server: Forcing compression level 5 (allowed: 5 <= z <= 6)\. +$SPROG update: Updating \." + # From zero. + dotest config2-3 "$testcvs update" \ +"$SPROG server: Forcing compression level 5 (allowed: 5 <= z <= 6)\. +$SPROG update: Updating \." + # Just right. + dotest config2-3 "$testcvs -z5 update" \ +"$SPROG update: Updating \." + + # Check that compression may be forced to 0. + cat << EOF > config +MaxCompressionLevel=0 +EOF + dotest config2-init-3 "$testcvs -q ci -m no-compression" \ +"$CVSROOT_DIRNAME/CVSROOT/config,v <-- config +new revision: 1\.[0-9]*; previous revision: 1\.[0-9]* +$SPROG commit: Rebuilding administrative file database" + + # Too high. + dotest config2-5 "$testcvs -z9 update" \ +"$SPROG server: Forcing compression level 0 (allowed: 0 <= z <= 0)\. +$SPROG update: Updating \." + # Just right. + dotest config2-6 "$testcvs update" \ +"$SPROG update: Updating \." + + # And verify effect without restrictions. + echo '# No config is a good config' > config + dotest config2-init-4 "$testcvs -q ci -m change-to-comment" \ +"$CVSROOT_DIRNAME/CVSROOT/config,v <-- config +new revision: 1\.[0-9]*; previous revision: 1\.[0-9]* +$SPROG commit: Rebuilding administrative file database" + dotest config2-7 "$testcvs update" \ +"$SPROG update: Updating \." + + dokeep + restore_adm + cd ../.. + rm -r wnt + ;; + + + serverpatch) # Test remote CVS handling of unpatchable files. This isn't # much of a test for local CVS. File [changed]: server.c Url: https://ccvs.cvshome.org/source/browse/ccvs/src/server.c?r1=1.431&r2=1.432 Delta lines: +169 -46 ---------------------- --- server.c 26 May 2005 17:48:06 -0000 1.431 +++ server.c 3 Jun 2005 18:26:09 -0000 1.432 @@ -440,12 +440,34 @@ * last line should not end with a newline. */ static char *pending_error_text; +static char *pending_warning_text; /* If an error is pending, print it and return 1. If not, return 0. + Also prints pending warnings, but this does not affect the return value. Must be called only in contexts where it is OK to send output. */ static int print_pending_error (void) { + /* Check this case first since it usually means we are out of memory and + * the buffer output routines might try and allocate memory. + */ + if (!pending_error_text && pending_error) + { + print_error (pending_error); + pending_error = 0; + return 1; + } + + if (pending_warning_text) + { + buf_output0 (buf_to_net, pending_warning_text); + buf_append_char (buf_to_net, '\n'); + buf_flush (buf_to_net, 0); + + free (pending_warning_text); + pending_warning_text = NULL; + } + if (pending_error_text) { buf_output0 (buf_to_net, pending_error_text); @@ -462,18 +484,29 @@ pending_error_text = NULL; return 1; } - else if (pending_error) - { - print_error (pending_error); - pending_error = 0; - return 1; - } - else + return 0; } + + /* Is an error pending? */ # define error_pending() (pending_error || pending_error_text) +# define warning_pending() (pending_warning_text) + +/* Allocate SIZE bytes for pending_error_text and return nonzero + if we could do it. */ +static inline int +alloc_pending_internal (char **dest, size_t size) +{ + *dest = malloc (size); + if (!*dest) + { + pending_error = ENOMEM; + return 0; + } + return 1; +} @@ -487,13 +520,20 @@ this case. But we might as well handle it if they don't, I guess. */ return 0; - pending_error_text = xmalloc (size); - if (pending_error_text == NULL) - { - pending_error = ENOMEM; + return alloc_pending_internal (&pending_error_text, size); +} + + + +/* Allocate SIZE bytes for pending_error_text and return nonzero + if we could do it. */ +static int +alloc_pending_warning (size_t size) +{ + if (warning_pending ()) + /* Warnings can be lost here. */ return 0; - } - return 1; + return alloc_pending_internal (&pending_warning_text, size); } @@ -873,6 +913,35 @@ # endif /* PROXY_SUPPORT */ + /* Now that we have a config, verify our compression level. Since + * most clients do not send Gzip-stream requests until after the root + * request, wait until the first request following Root to verify that + * compression is being used when level 0 is not allowed. + */ + if (gzip_level) + { + bool forced = false; + + if (gzip_level < config->MinCompressionLevel) + { + gzip_level = config->MinCompressionLevel; + forced = true; + } + + if (gzip_level > config->MaxCompressionLevel) + { + gzip_level = config->MaxCompressionLevel; + forced = true; + } + + if (forced && !quiet + && alloc_pending_warning (120 + strlen (program_name))) + sprintf (pending_warning_text, +"E %s server: Forcing compression level %d (allowed: %d <= z <= %d).", + program_name, gzip_level, config->MinCompressionLevel, + config->MaxCompressionLevel); + } + path = xmalloc (strlen (current_parsed_root->directory) + sizeof (CVSROOTADM) + 2); @@ -5379,6 +5448,7 @@ serve_gzip_contents (char *arg) { int level; + bool forced = false; # ifdef PROXY_SUPPORT assert (!proxy_log); @@ -5387,7 +5457,26 @@ level = atoi (arg); if (level == 0) level = 6; - file_gzip_level = level; + + if (config && level < config->MinCompressionLevel) + { + level = config->MinCompressionLevel; + forced = true; + } + if (config && level > config->MaxCompressionLevel) + { + level = config->MaxCompressionLevel; + forced = true; + } + + if (forced && !quiet + && alloc_pending_warning (120 + strlen (program_name))) + sprintf (pending_warning_text, +"E %s server: Forcing compression level %d (allowed: %d <= z <= %d).", + program_name, level, config->MinCompressionLevel, + config->MaxCompressionLevel); + + gzip_level = file_gzip_level = level; } @@ -5396,23 +5485,43 @@ serve_gzip_stream (char *arg) { int level; - - /* If we received this request before the `Root' request, the buffer index - * maintained to allow the write proxy to replace the `Root' request would - * be relative to the decompressed stream rather than the secondary log. - */ - assert (current_parsed_root); + bool forced = false; level = atoi (arg); - if (level == 0) - level = 6; - /* All further communication with the client will be compressed. */ + if (config && level < config->MinCompressionLevel) + { + level = config->MinCompressionLevel; + forced = true; + } + if (config && level > config->MaxCompressionLevel) + { + level = config->MaxCompressionLevel; + forced = true; + } + + if (forced && !quiet + && alloc_pending_warning (120 + strlen (program_name))) + sprintf (pending_warning_text, +"E %s server: Forcing compression level %d (allowed: %d <= z <= %d).", + program_name, level, config->MinCompressionLevel, + config->MaxCompressionLevel); + + gzip_level = level; + + /* All further communication with the client will be compressed. + * + * The deflate buffers need to be initialized even for compression level + * 0, or the client will no longer be able to understand us. At + * compression level 0, the correct compression headers will be created and + * sent, but data will thereafter simply be copied to the network buffers. + */ /* This needs to be processed in both passes so that we may continue to * understand client requests on both the socket and from the log. */ - buf_from_net = compress_buffer_initialize (buf_from_net, 1, level, + buf_from_net = compress_buffer_initialize (buf_from_net, 1, + 0 /* Not used. */, buf_from_net->memory_error); /* This needs to be skipped in subsequent passes to avoid compressing data @@ -5618,7 +5727,7 @@ bool ditch_log; # endif /* PROXY_SUPPORT */ - if (error_pending ()) return; + if (print_pending_error ()) return; redirect_supported = supported_response ("Redirect"); if (redirect_supported @@ -5779,21 +5888,28 @@ REQ_LINE("Argument", serve_argument, RQ_ESSENTIAL), REQ_LINE("Argumentx", serve_argumentx, RQ_ESSENTIAL), REQ_LINE("Global_option", serve_global_option, RQ_ROOTLESS), - REQ_LINE("Gzip-stream", serve_gzip_stream, 0), + /* This is rootless, even though the client/server spec does not specify + * such, to allow error messages to be understood by the client when they are + * sent. + */ + REQ_LINE("Gzip-stream", serve_gzip_stream, RQ_ROOTLESS), REQ_LINE("wrapper-sendme-rcsOptions", serve_wrapper_sendme_rcs_options, 0), REQ_LINE("Set", serve_set, RQ_ROOTLESS), #ifdef ENCRYPTION + /* These are rootless despite what the client/server spec says for the same + * reasons as Gzip-stream. + */ # ifdef HAVE_KERBEROS - REQ_LINE("Kerberos-encrypt", serve_kerberos_encrypt, 0), + REQ_LINE("Kerberos-encrypt", serve_kerberos_encrypt, RQ_ROOTLESS), # endif # ifdef HAVE_GSSAPI - REQ_LINE("Gssapi-encrypt", serve_gssapi_encrypt, 0), + REQ_LINE("Gssapi-encrypt", serve_gssapi_encrypt, RQ_ROOTLESS), # endif #endif #ifdef HAVE_GSSAPI - REQ_LINE("Gssapi-authenticate", serve_gssapi_authenticate, 0), + REQ_LINE("Gssapi-authenticate", serve_gssapi_authenticate, RQ_ROOTLESS), #endif REQ_LINE("expand-modules", serve_expand_modules, 0), REQ_LINE("ci", serve_ci, RQ_ESSENTIAL), @@ -5813,7 +5929,7 @@ REQ_LINE("add", serve_add, 0), REQ_LINE("remove", serve_remove, 0), REQ_LINE("update-patches", serve_ignore, 0), - REQ_LINE("gzip-file-contents", serve_gzip_contents, 0), + REQ_LINE("gzip-file-contents", serve_gzip_contents, RQ_ROOTLESS), REQ_LINE("status", serve_status, 0), REQ_LINE("rdiff", serve_rdiff, 0), REQ_LINE("tag", serve_tag, 0), @@ -5874,6 +5990,14 @@ buf_output0 (buf_to_net, rq->name); } } + + if (config && config->MinCompressionLevel + && supported_response ("Force-gzip")) + { + buf_output0 (buf_to_net, "\n"); + buf_output0 (buf_to_net, "Force-gzip"); + } + buf_output0 (buf_to_net, "\nok\n"); /* The client is waiting for the list of valid requests, so we @@ -6368,27 +6492,26 @@ if (!(rq->flags & RQ_ROOTLESS) && current_parsed_root == NULL) { - /* For commands which change the way in which data - is sent and received, for example Gzip-stream, - this does the wrong thing. Since the client - assumes that everything is being compressed, - unconditionally, there is no way to give this - error to the client without turning on - compression. The obvious fix would be to make - Gzip-stream RQ_ROOTLESS (with the corresponding - change to the spec), and that might be a good - idea but then again I can see some settings in - CVSROOT about what compression level to allow. - I suppose a more baroque answer would be to - turn on compression (say, at level 1), just - enough to give the "Root request missing" - error. For now we just lose. */ if (alloc_pending (80)) sprintf (pending_error_text, "E Protocol error: Root request missing"); } else + { + if (config && config->MinCompressionLevel && !gzip_level + && !(rq->flags & RQ_ROOTLESS)) + { + /* This is a rootless request, a minimum compression + * level has been configured, and no compression has + * been requested by the client. + */ + if (alloc_pending (80 + strlen (program_name))) + sprintf (pending_error_text, +"E %s [server aborted]: Compression must be used with this server.", + program_name); + } (*rq->func) (cmd); + } break; } if (rq->name == NULL) File [changed]: zlib.c Url: https://ccvs.cvshome.org/source/browse/ccvs/src/zlib.c?r1=1.30&r2=1.31 Delta lines: +18 -1 -------------------- --- zlib.c 3 Jun 2005 16:27:21 -0000 1.30 +++ zlib.c 3 Jun 2005 18:26:09 -0000 1.31 @@ -46,8 +46,10 @@ { /* The underlying buffer. */ struct buffer *buf; + /* The compression information. */ z_stream zstr; + int level; }; static void compress_error (int, int, z_stream *, const char *); @@ -96,6 +98,7 @@ memset (n, 0, sizeof *n); n->buf = buf; + n->level = level; if (input) zstatus = inflateInit (&n->zstr); @@ -264,7 +267,15 @@ -/* Output data to a compression buffer. */ +extern int gzip_level; + +/* Output data to a compression buffer. + * + * GLOBALS + * gzip_level If GZIP_LEVEL has changed to a value different from + * CLOSURE->level, then set the compression level on the + * stream to the new value. + */ static int compress_buffer_output (void *closure, const char *data, size_t have, size_t *wrote) @@ -278,6 +289,12 @@ if (!buffer) buffer = pagealign_xalloc (BUFFER_DATA_SIZE); + if (cb->level != gzip_level) + { + cb->level = gzip_level; + deflateParams (&cb->zstr, gzip_level, Z_DEFAULT_STRATEGY); + } + cb->zstr.avail_in = have; cb->zstr.next_in = (unsigned char *) data;