From 49771f4fb03349d87e42c12305ebd5b307f3c2bd Mon Sep 17 00:00:00 2001 From: Bram Moolenaar <Bram@vim.org> Date: Tue, 20 Jul 2010 17:32:38 +0200 Subject: [PATCH] Change 'cryptmethod' from a number to a string option. Make it global-local. --- runtime/doc/editing.txt | 15 ++++-- runtime/doc/options.txt | 18 ++++--- runtime/doc/todo.txt | 11 +---- runtime/doc/version7.txt | 7 ++- src/buffer.c | 3 ++ src/ex_docmd.c | 2 +- src/fileio.c | 20 ++++---- src/memline.c | 13 ++--- src/misc2.c | 35 +++++++++++++ src/option.c | 104 +++++++++++++++++++++++++++------------ src/option.h | 3 ++ src/proto/misc2.pro | 3 ++ src/structs.h | 6 +-- src/testdir/test71.in | 18 +++---- 14 files changed, 176 insertions(+), 82 deletions(-) diff --git a/runtime/doc/editing.txt b/runtime/doc/editing.txt index ba4da029ce..4d5b00fb90 100644 --- a/runtime/doc/editing.txt +++ b/runtime/doc/editing.txt @@ -1371,10 +1371,17 @@ the file is encrypted. To disable the encryption, reset the 'key' option to an empty value: > :set key= -You can use the 'cryptmethod' option to select the type of encryption. Do -this before writing the file. When reading an encrypted file it will be set -automatically to the method used when that file was written. You can change -'cryptmethod' before writing that file to change the method. +You can use the 'cryptmethod' option to select the type of encryption, use one +of these two: > + :setlocal cm=zip " weak method, backwards compatible + :setlocal cm=blowfish " strong method +Do this before writing the file. When reading an encrypted file it will be +set automatically to the method used when that file was written. You can +change 'cryptmethod' before writing that file to change the method. +To set the default method, used for new files, use one of these in your +|vimrc| file: > + set cm=zip + set cm=blowfish When writing an undo file, the same key and method will be used for the text in the undo file. |persistent-undo|. diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index 776717771a..c8c3130397 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -2074,15 +2074,15 @@ A jump table for the options with a short description can be found at |Q_op|. *'cryptmethod'* *'cm'* -'cryptmethod' number (default 0) - local to buffer +'cryptmethod' string (default "zip") + global or local to buffer |global-local| {not in Vi} Method used for encryption when the buffer is written to a file: *pkzip* - 0 PkZip compatible method. A weak kind of encryption. + zip PkZip compatible method. A weak kind of encryption. Backwards compatible with Vim 7.2 and older. *blowfish* - 1 Blowfish method. Strong encryption. Requires Vim 7.3 + blowfish Blowfish method. Strong encryption. Requires Vim 7.3 or later, files can NOT be read by Vim 7.2 and older. This adds a "seed" to the file, every time you write the file the encrypted bytes will be different. @@ -2091,10 +2091,16 @@ A jump table for the options with a short description can be found at |Q_op|. to the detected method of the file being read. Thus if you write it without changing 'cryptmethod' the same method will be used. Changing 'cryptmethod' does not mark the file as modified, you have to - explicitly write it when not making modifications. - Also see |:X|. + explicitly write it, you don't get a warning unless there are other + modifications. Also see |:X|. + + When setting the global value to an empty string, it will end up with + the value "zip". When setting the local value to an empty string the + buffer will use the global value. + When a new encryption method is added in a later version of Vim, and the current version does not recognize it, you will get *E821* . + You need to edit this file with the later version of Vim. *'cscopepathcomp'* *'cspc'* diff --git a/runtime/doc/todo.txt b/runtime/doc/todo.txt index 40d4b672a7..1dabb75f05 100644 --- a/runtime/doc/todo.txt +++ b/runtime/doc/todo.txt @@ -30,19 +30,10 @@ be worked on, but only if you sponsor Vim development. See |sponsor|. *known-bugs* -------------------- Known bugs and current work ----------------------- -GTK: torn-off menu doesn't work. Because of patch for file selector? - -Win64: diff.exe crashes on Win64. (Julianne Bailey, 2006 Dec 12) -Build another diff.exe somehow? +GTK: torn-off menu doesn't work. :find completion has duplicates. (Bjorn Winckler, 2010 Jul 18) -Conceal: don't show for 'hlmatch' when 'modifiable' is off? -And don't care about 'cursorline'. - -Make 'cryptmethod' global-local, so that a default specified in a .vimrc file -is used for new files. (Christian J. Robinson) - Cursor positioning wrong with 0x200e character. (John Becket, 2010 May 6) Test 69 breaks on MS-Windows, both 32 and 64 builds. (George Reilly, 2010 Feb diff --git a/runtime/doc/version7.txt b/runtime/doc/version7.txt index 8763661d39..6254937fee 100644 --- a/runtime/doc/version7.txt +++ b/runtime/doc/version7.txt @@ -7265,7 +7265,7 @@ Added the |strchars()|, |strwidth()| and |strdisplaywidth()| functions. Support GDK_SUPER_MASK for GTK on Mac. (Stephan Schulz) -Made CTRL modifier work for mouse wheel. (Benjamin Haskell) +Made CTRL and ALT modifier work for mouse wheel. (Benjamin Haskell) When the buffer is in diff mode, have :TOhtml create HTML to show the diff side-by-side. (Christian Brabandt) @@ -10031,5 +10031,10 @@ Window title not updated after file dropped. "g8" doesn't work properly on a NUL. +Fixed crash for ":find" completion, might also happen in other path expansion +usage. + +When 'searchhl' causes a hang make CTRL-C disable 'shearchhl'. + vim:tw=78:ts=8:ft=help:norl: diff --git a/src/buffer.c b/src/buffer.c index e7fecd7da8..a8808d396d 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -1756,6 +1756,9 @@ free_buf_options(buf, free_p_ff) #if defined(FEAT_BEVAL) && defined(FEAT_EVAL) clear_string_option(&buf->b_p_bexpr); #endif +#if defined(FEAT_CRYPT) + clear_string_option(&buf->b_p_cm); +#endif #if defined(FEAT_EVAL) clear_string_option(&buf->b_p_fex); #endif diff --git a/src/ex_docmd.c b/src/ex_docmd.c index b56fb670b1..2d1a893d5a 100644 --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -11189,7 +11189,7 @@ ex_match(eap) ex_X(eap) exarg_T *eap UNUSED; { - if (curbuf->b_p_cm == 0 || blowfish_self_test() == OK) + if (get_crypt_method(curbuf) == 0 || blowfish_self_test() == OK) (void)get_crypt_key(TRUE, TRUE); } #endif diff --git a/src/fileio.c b/src/fileio.c index d467ebad0f..aa3143efb3 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -63,7 +63,7 @@ static char_u *readfile_charconvert __ARGS((char_u *fname, char_u *fenc, int *fd static void check_marks_read __ARGS((void)); #endif #ifdef FEAT_CRYPT -static int get_crypt_method __ARGS((char *ptr, int len)); +static int crypt_method_from_magic __ARGS((char *ptr, int len)); static char_u *check_for_cryptkey __ARGS((char_u *cryptkey, char_u *ptr, long *sizep, off_t *filesizep, int newfile, char_u *fname, int *did_ask)); #endif #ifdef UNIX @@ -2855,7 +2855,7 @@ check_marks_read() * Returns -1 when no encryption used. */ static int -get_crypt_method(ptr, len) +crypt_method_from_magic(ptr, len) char *ptr; int len; { @@ -2892,11 +2892,11 @@ check_for_cryptkey(cryptkey, ptr, sizep, filesizep, newfile, fname, did_ask) char_u *fname; /* file name to display */ int *did_ask; /* flag: whether already asked for key */ { - int method = get_crypt_method((char *)ptr, *sizep); + int method = crypt_method_from_magic((char *)ptr, *sizep); if (method >= 0) { - curbuf->b_p_cm = method; + set_crypt_method(curbuf, method); if (method > 0) (void)blowfish_self_test(); if (cryptkey == NULL && !*did_ask) @@ -2968,11 +2968,11 @@ prepare_crypt_read(fp) if (fread(buffer, CRYPT_MAGIC_LEN, 1, fp) != 1) return FAIL; - method = get_crypt_method((char *)buffer, + method = crypt_method_from_magic((char *)buffer, CRYPT_MAGIC_LEN + CRYPT_SEED_LEN_MAX + CRYPT_SALT_LEN_MAX); - if (method < 0 || method != curbuf->b_p_cm) + if (method < 0 || method != get_crypt_method(curbuf)) return FAIL; crypt_push_state(); @@ -3003,8 +3003,8 @@ prepare_crypt_write(buf, lenp) int *lenp; { char_u *header; - int seed_len = crypt_seed_len[buf->b_p_cm]; - int salt_len = crypt_salt_len[buf->b_p_cm]; + int seed_len = crypt_seed_len[get_crypt_method(buf)]; + int salt_len = crypt_salt_len[get_crypt_method(buf)]; char_u *salt; char_u *seed; @@ -3013,10 +3013,10 @@ prepare_crypt_write(buf, lenp) if (header != NULL) { crypt_push_state(); - use_crypt_method = buf->b_p_cm; /* select pkzip or blowfish */ + use_crypt_method = get_crypt_method(buf); /* select zip or blowfish */ vim_strncpy(header, (char_u *)crypt_magic[use_crypt_method], CRYPT_MAGIC_LEN); - if (buf->b_p_cm == 0) + if (use_crypt_method == 0) crypt_init_keys(buf->b_p_key); else { diff --git a/src/memline.c b/src/memline.c index 0268087ab1..0f7b1d11c7 100644 --- a/src/memline.c +++ b/src/memline.c @@ -441,7 +441,7 @@ ml_set_b0_crypt(buf, b0p) b0p->b0_id[1] = BLOCK0_ID1; else { - if (buf->b_p_cm == 0) + if (get_crypt_method(buf) == 0) b0p->b0_id[1] = BLOCK0_ID1_C0; else { @@ -458,8 +458,8 @@ ml_set_b0_crypt(buf, b0p) * Will apply this to the swapfile. * "old_key" is the previous key. It is equal to buf->b_p_key when * 'cryptmethod' is changed. - * "old_cm" is the previous 'cryptmethod'. It is equal to buf->b_p_cm when - * 'key' is changed. + * "old_cm" is the previous 'cryptmethod'. It is equal to the current + * 'cryptmethod' when 'key' is changed. */ void ml_set_crypt_key(buf, old_key, old_cm) @@ -1250,12 +1250,13 @@ ml_recover() #ifdef FEAT_CRYPT if (b0p->b0_id[1] == BLOCK0_ID1_C0) - buf->b_p_cm = b0_cm = 0; + b0_cm = 0; else if (b0p->b0_id[1] == BLOCK0_ID1_C1) { - buf->b_p_cm = b0_cm = 1; + b0_cm = 1; mch_memmove(mfp->mf_seed, &b0p->b0_seed, MF_SEED_LEN); } + set_crypt_method(buf, b0_cm); #else if (b0p->b0_id[1] != BLOCK0_ID1) { @@ -4908,7 +4909,7 @@ ml_crypt_prepare(mfp, offset, reading) } else { - method = buf->b_p_cm; + method = get_crypt_method(buf); key = buf->b_p_key; seed = mfp->mf_seed; } diff --git a/src/misc2.c b/src/misc2.c index 1eb4e8a160..9327e891a9 100644 --- a/src/misc2.c +++ b/src/misc2.c @@ -3750,6 +3750,41 @@ static int crypt_busy = 0; static ulg saved_keys[3]; static int saved_crypt_method; +/* + * Return int value for crypt method string: + * 0 for "zip", the old method. Also for any non-valid value. + * 1 for "blowfish". + */ + int +crypt_method_from_string(s) + char_u *s; +{ + return *s == 'b' ? 1 : 0; +} + +/* + * Get the crypt method for buffer "buf" as a number. + */ + int +get_crypt_method(buf) + buf_T *buf; +{ + return crypt_method_from_string(*buf->b_p_cm == NUL ? p_cm : buf->b_p_cm); +} + +/* + * Set the crypt method for buffer "buf" to "method" using the int value as + * returned by crypt_method_from_string(). + */ + void +set_crypt_method(buf, method) + buf_T *buf; + int method; +{ + free_string_option(buf->b_p_cm); + buf->b_p_cm = vim_strsave((char_u *)(method == 0 ? "zip" : "blowfish")); +} + /* * Prepare for initializing encryption. If already doing encryption then save * the state. diff --git a/src/option.c b/src/option.c index 27a82fde20..63c0f2efb5 100644 --- a/src/option.c +++ b/src/option.c @@ -77,7 +77,7 @@ #if defined(FEAT_SMARTINDENT) || defined(FEAT_CINDENT) # define PV_CINW OPT_BUF(BV_CINW) #endif -#define PV_CM OPT_BUF(BV_CM) +#define PV_CM OPT_BOTH(OPT_BUF(BV_CM)) #ifdef FEAT_FOLDING # define PV_CMS OPT_BUF(BV_CMS) #endif @@ -287,9 +287,6 @@ static char_u *p_cino; #if defined(FEAT_SMARTINDENT) || defined(FEAT_CINDENT) static char_u *p_cinw; #endif -#ifdef FEAT_CRYPT -static long p_cm; -#endif #ifdef FEAT_COMMENTS static char_u *p_com; #endif @@ -866,13 +863,15 @@ static struct vimoption (char_u *)&p_cpo, PV_NONE, {(char_u *)CPO_VI, (char_u *)CPO_VIM} SCRIPTID_INIT}, - {"cryptmethod", "cm", P_NUM|P_VI_DEF|P_VIM, + {"cryptmethod", "cm", P_STRING|P_ALLOCED|P_VI_DEF, #ifdef FEAT_CRYPT (char_u *)&p_cm, PV_CM, + {(char_u *)"zip", (char_u *)0L} #else (char_u *)NULL, PV_NONE, + {(char_u *)0L, (char_u *)0L} #endif - {(char_u *)0L, (char_u *)0L} SCRIPTID_INIT}, + SCRIPTID_INIT}, {"cscopepathcomp", "cspc", P_NUM|P_VI_DEF|P_VIM, #ifdef FEAT_CSCOPE (char_u *)&p_cspc, PV_NONE, @@ -2915,6 +2914,9 @@ static char *(p_ambw_values[]) = {"single", "double", NULL}; static char *(p_bg_values[]) = {"light", "dark", NULL}; static char *(p_nf_values[]) = {"octal", "hex", "alpha", NULL}; static char *(p_ff_values[]) = {FF_UNIX, FF_DOS, FF_MAC, NULL}; +#ifdef FEAT_CRYPT +static char *(p_cm_values[]) = {"zip", "blowfish", NULL}; +#endif #ifdef FEAT_CMDL_COMPL static char *(p_wop_values[]) = {"tagfile", NULL}; #endif @@ -5215,6 +5217,9 @@ check_buf_options(buf) #if defined(FEAT_BEVAL) && defined(FEAT_EVAL) check_string_option(&buf->b_p_bexpr); #endif +#if defined(FEAT_CRYPT) + check_string_option(&buf->b_p_cm); +#endif #if defined(FEAT_EVAL) check_string_option(&buf->b_p_fex); #endif @@ -5998,7 +6003,57 @@ did_set_string_option(opt_idx, varp, new_value_alloced, oldval, errbuf, # endif if (STRCMP(curbuf->b_p_key, oldval) != 0) /* Need to update the swapfile. */ - ml_set_crypt_key(curbuf, oldval, curbuf->b_p_cm); + ml_set_crypt_key(curbuf, oldval, get_crypt_method(curbuf)); + } + + else if (gvarp == &p_cm) + { + if (opt_flags & OPT_LOCAL) + p = curbuf->b_p_cm; + else + p = p_cm; + if (check_opt_strings(p, p_cm_values, TRUE) != OK) + errmsg = e_invarg; + else if (get_crypt_method(curbuf) > 0 && blowfish_self_test() == FAIL) + errmsg = e_invarg; + else + { + /* When setting the global value to empty, make it "zip". */ + if (*p_cm == NUL) + { + if (new_value_alloced) + free_string_option(p_cm); + p_cm = vim_strsave((char_u *)"zip"); + new_value_alloced = TRUE; + } + + /* Need to update the swapfile when the effective method changed. + * Set "s" to the effective old value, "p" to the effective new + * method and compare. */ + if ((opt_flags & OPT_LOCAL) && *oldval == NUL) + s = p_cm; /* was previously using the global value */ + else + s = oldval; + if (*curbuf->b_p_cm == NUL) + p = p_cm; /* is now using the global value */ + else + p = curbuf->b_p_cm; + if (STRCMP(s, p) != 0) + ml_set_crypt_key(curbuf, curbuf->b_p_key, + crypt_method_from_string(s)); + + /* If the global value changes need to update the swapfile for all + * buffers using that value. */ + if ((opt_flags & OPT_GLOBAL) && STRCMP(p_cm, oldval) != 0) + { + buf_T *buf; + + for (buf = firstbuf; buf != NULL; buf = buf->b_next) + if (buf != curbuf && *buf->b_p_cm == NUL) + ml_set_crypt_key(buf, buf->b_p_key, + crypt_method_from_string(oldval)); + } + } } #endif @@ -8048,28 +8103,6 @@ set_num_option(opt_idx, varp, value, errbuf, errbuflen, opt_flags) #endif -#ifdef FEAT_CRYPT - else if (pp == &curbuf->b_p_cm) - { - if (curbuf->b_p_cm < 0) - { - errmsg = e_positive; - curbuf->b_p_cm = old_value; - } - if (curbuf->b_p_cm > 1) - { - errmsg = e_invarg; - curbuf->b_p_cm = old_value; - } - if (curbuf->b_p_cm > 0 && blowfish_self_test() == FAIL) - curbuf->b_p_cm = old_value; - - if (curbuf->b_p_cm != old_value && *curbuf->b_p_key != NUL) - /* Need to update the swapfile. */ - ml_set_crypt_key(curbuf, curbuf->b_p_key, old_value); - } -#endif - #ifdef FEAT_WINDOWS /* (re)set last window status line */ else if (pp == &p_ls) @@ -9383,6 +9416,9 @@ get_varp_scope(p, opt_flags) #if defined(FEAT_BEVAL) && defined(FEAT_EVAL) case PV_BEXPR: return (char_u *)&(curbuf->b_p_bexpr); #endif +#if defined(FEAT_CRYPT) + case PV_CM: return (char_u *)&(curbuf->b_p_cm); +#endif #ifdef FEAT_STL_OPT case PV_STL: return (char_u *)&(curwin->w_p_stl); #endif @@ -9442,6 +9478,10 @@ get_varp(p) case PV_BEXPR: return *curbuf->b_p_bexpr != NUL ? (char_u *)&(curbuf->b_p_bexpr) : p->var; #endif +#if defined(FEAT_CRYPT) + case PV_CM: return *curbuf->b_p_cm != NUL + ? (char_u *)&(curbuf->b_p_cm) : p->var; +#endif #ifdef FEAT_STL_OPT case PV_STL: return *curwin->w_p_stl != NUL ? (char_u *)&(curwin->w_p_stl) : p->var; @@ -9525,9 +9565,6 @@ get_varp(p) case PV_CINK: return (char_u *)&(curbuf->b_p_cink); case PV_CINO: return (char_u *)&(curbuf->b_p_cino); #endif -#ifdef FEAT_CRYPT - case PV_CM: return (char_u *)&(curbuf->b_p_cm); -#endif #if defined(FEAT_SMARTINDENT) || defined(FEAT_CINDENT) case PV_CINW: return (char_u *)&(curbuf->b_p_cinw); #endif @@ -9994,6 +10031,9 @@ buf_copy_options(buf, flags) #if defined(FEAT_BEVAL) && defined(FEAT_EVAL) buf->b_p_bexpr = empty_option; #endif +#if defined(FEAT_CRYPT) + buf->b_p_cm = empty_option; +#endif #ifdef FEAT_PERSISTENT_UNDO buf->b_p_udf = p_udf; #endif diff --git a/src/option.h b/src/option.h index 1693622dd7..817e337ff6 100644 --- a/src/option.h +++ b/src/option.h @@ -333,6 +333,9 @@ EXTERN char_u *p_bex; /* 'backupext' */ #ifdef FEAT_WILDIGN EXTERN char_u *p_bsk; /* 'backupskip' */ #endif +#ifdef FEAT_CRYPT +EXTERN char_u *p_cm; /* 'cryptmethod' */ +#endif #ifdef FEAT_BEVAL EXTERN long p_bdlay; /* 'balloondelay' */ EXTERN int p_beval; /* 'ballooneval' */ diff --git a/src/proto/misc2.pro b/src/proto/misc2.pro index 8d3397fc12..3fa0c9b3b8 100644 --- a/src/proto/misc2.pro +++ b/src/proto/misc2.pro @@ -80,6 +80,9 @@ int illegal_slash __ARGS((char *name)); char_u *parse_shape_opt __ARGS((int what)); int get_shape_idx __ARGS((int mouse)); void update_mouseshape __ARGS((int shape_idx)); +int crypt_method_from_string __ARGS((char_u *s)); +int get_crypt_method __ARGS((buf_T *buf)); +void set_crypt_method __ARGS((buf_T *buf, int method)); void crypt_push_state __ARGS((void)); void crypt_pop_state __ARGS((void)); void crypt_encode __ARGS((char_u *from, size_t len, char_u *to)); diff --git a/src/structs.h b/src/structs.h index ebcc3cffed..42b1d2abc3 100644 --- a/src/structs.h +++ b/src/structs.h @@ -1450,9 +1450,6 @@ struct file_buffer #ifdef FEAT_INS_EXPAND char_u *b_p_cpt; /* 'complete' */ #endif -#ifdef FEAT_CRYPT - long b_p_cm; /* 'cryptmethod' */ -#endif #ifdef FEAT_COMPL_FUNC char_u *b_p_cfu; /* 'completefunc' */ char_u *b_p_ofu; /* 'omnifunc' */ @@ -1574,6 +1571,9 @@ struct file_buffer char_u *b_p_bexpr; /* 'balloonexpr' local value */ long_u b_p_bexpr_flags;/* flags for 'balloonexpr' */ #endif +#ifdef FEAT_CRYPT + char_u *b_p_cm; /* 'cryptmethod' */ +#endif /* When a buffer is created, it starts without a swap file. b_may_swap is * then set to indicate that a swap file may be opened later. It is reset diff --git a/src/testdir/test71.in b/src/testdir/test71.in index 56dee55741..7de293054b 100644 --- a/src/testdir/test71.in +++ b/src/testdir/test71.in @@ -4,9 +4,9 @@ STARTTEST :so small.vim :/^start of text/+1 :let text_lines = getline('.', line('.') + 2) -:/^start of cm=0 bytes/+1 +:/^start of cm=zip bytes/+1 :let cm0_bytes = getline('.', '.') -:/^start of cm=1 bytes/+1 +:/^start of cm=blowfish bytes/+1 :let cm1_bytes = getline('.', '.') :bwipe :call append(0, text_lines) @@ -20,9 +20,9 @@ foobar foobar :let cm0_read_back = getline('.', '$') :set key= -:set cryptmethod=1 -:" If the blowfish test fails 'cryptmethod' will be 0 now. -:%s/^/\=&cryptmethod == 1 ? "OK " : "blowfish test failed "/ +:set cryptmethod=blowfish +:" If the blowfish test fails 'cryptmethod' will be 'zip' now. +:%s/^/\=&cryptmethod == 'blowfish' ? "OK " : "blowfish test failed "/ :X barfoo barfoo @@ -66,10 +66,10 @@ line 2 foo bar blah line 3 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx end of text -start of cm=0 bytes +start of cm=zip bytes VimCrypt~01!lV'Þ}Mg ê£V©çE#3Ž2Ué— -end of cm=0 bytes +end of cm=zip bytes -start of cm=1 bytes +start of cm=blowfish bytes VimCrypt~02!k)¾—#ÝSœõ=ºàÈ#¥M´†JÃAÍ¥M´†!€›õáÒ‚˜÷ Ú -end of cm=1 bytes +end of cm=blowfish bytes -- GitLab