{"thread":{"id":"43063","subject":"Re: [PATCH 2/n] gitweb: Use '&iquot;' instead of '?' in esc_path","startedAt":"2006-10-30T18:53:01Z","lastAt":"2006-11-07T22:18:08Z","messageCount":46,"participants":["Junio C Hamano","Jakub Narebski","Petr Baudis"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"297641","messageId":"200610301953.01875.jnareb@gmail.com","threadId":"43063","inReplyTo":null,"subject":"[PATCH 0/n] gitweb: Better quoting and New improved patchset view","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-10-30T18:53:01Z","receivedAt":"2006-10-30T18:53:01Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"This series of patches is meant to introduce \n\"New improved patchset view\" in part-by-part\ncase.\n\nWould change only gitweb/gitweb.perl and gitweb/gitweb/css\n-- \nJakub Narebski\n"},{"id":"295072","messageId":"200610301958.23334.jnareb@gmail.com","threadId":"43063","inReplyTo":"200610301953.01875.jnareb@gmail.com","subject":"[PATCH/RFC 1/n] gitweb: Better git-unquoting and gitweb-quoting of pathnames","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-10-30T18:58:23Z","receivedAt":"2006-10-30T18:58:23Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Extend unquote subroutine, which unquotes quoted and escaped filenames\nwhich git may return, to deal not only with octal char sequence\nquoting, but also quoting ordinary characters including '\\\"' and '\\\\'\nwhich are respectively quoted '\"' and '\\', and to deal also with\nC escape sequences including '\\t' for TAB and '\\n' for LF.\n\nAdd esc_path subroutine for gitweb quoting and HTML escaping filenames\n(currently it does equivalent of ls' --hide-control-chars, which means\nshowing undisplayable characters (including '\\n' and '\\t') as '?'\n(question mark) character.  Convert gitweb to use esc_path instead of\nsimply esc_html to print pathnames.\n\nSigned-off-by: Jakub Narebski <jnareb@gmail.com>\n---\nBy the way, testing this patch uncovered some errors in gitweb, some\nrelated to files with strange name, some unrelated. I'll address them\nin further patches. They are:\n\n  1. Using m/..\\t(.+)$/; to catch filename instead of m/..\\t(.+)$/s;\n\n  2. Lack of '--' after $hash/$hash_base parameter which gives error\n     if there exist branch (ref) and file (or directory) with the same\n     name\n\nThe current implementation of esc_path is meant as preliminary: if you\nhave better idea for quoting names in gitweb, please tell us, or better\nsend code/patches.\n\n\n gitweb/gitweb.perl |   68 +++++++++++++++++++++++++++++++++++++--------------\n 1 files changed, 49 insertions(+), 19 deletions(-)\n\ndiff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl\nindex ec46b80..a15e916 100755\n--- a/gitweb/gitweb.perl\n+++ b/gitweb/gitweb.perl\n@@ -563,12 +563,42 @@ sub esc_html {\n \treturn $str;\n }\n \n+# quote unsafe characters and escape filename to HTML\n+sub esc_path {\n+\tmy $str = shift;\n+\t$str = esc_html($str);\n+\t$str =~ s/[[:cntrl:]\\a\\b\\e\\f\\n\\r\\t\\011]/?/g; # like --hide-control-chars in ls\n+\treturn $str;\n+}\n+\n # git may return quoted and escaped filenames\n sub unquote {\n \tmy $str = shift;\n+\n+\tsub unq {\n+\t\tmy $seq = shift;\n+\t\tmy %es = (\n+\t\t\t't' => \"\\t\", # tab            (HT, TAB)\n+\t\t\t'n' => \"\\n\", # newline        (NL)\n+\t\t\t'r' => \"\\r\", # return         (CR)\n+\t\t\t'f' => \"\\f\", # form feed      (FF)\n+\t\t\t'b' => \"\\b\", # backspace      (BS)\n+\t\t\t'a' => \"\\a\", # alarm (bell)   (BEL)\n+\t\t\t#'e' => \"\\e\", # escape        (ESC)\n+\t\t\t'v' => \"\\011\", # vertical tab (VT)\n+\t\t);\n+\n+\t\t# octal char sequence\n+\t\treturn chr(oct($seq))  if ($seq =~ m/^[0-7]{1,3}$/);\n+\t\t# C escape sequence (this includes '\\n' (LF) and '\\t' (TAB))\n+\t\treturn $es{$seq}       if ($seq =~ m/^[abefnrtv]$/);\n+\t\t# quted ordinary character (this includes '\\\\' and '\\\"')\n+\t\treturn $seq;\n+\t}\n+\n \tif ($str =~ m/^\"(.*)\"$/) {\n \t\t$str = $1;\n-\t\t$str =~ s/\\\\([0-7]{1,3})/chr(oct($1))/eg;\n+\t\t$str =~ s/\\\\([^0-7]|[0-7]{1,3})/unq($1)/eg;\n \t}\n \treturn $str;\n }\n@@ -1435,7 +1465,7 @@ sub git_header_html {\n \t\tif (defined $action) {\n \t\t\t$title .= \"/$action\";\n \t\t\tif (defined $file_name) {\n-\t\t\t\t$title .= \" - \" . esc_html($file_name);\n+\t\t\t\t$title .= \" - \" . esc_path($file_name);\n \t\t\t\tif ($action eq \"tree\" && $file_name !~ m|/$|) {\n \t\t\t\t\t$title .= \"/\";\n \t\t\t\t}\n@@ -1706,20 +1736,20 @@ sub git_print_page_path {\n \t\t\t$fullname .= ($fullname ? '/' : '') . $dir;\n \t\t\tprint $cgi->a({-href => href(action=>\"tree\", file_name=>$fullname,\n \t\t\t                             hash_base=>$hb),\n-\t\t\t              -title => $fullname}, esc_html($dir));\n+\t\t\t              -title => $fullname}, esc_path($dir));\n \t\t\tprint \" / \";\n \t\t}\n \t\tif (defined $type && $type eq 'blob') {\n \t\t\tprint $cgi->a({-href => href(action=>\"blob_plain\", file_name=>$file_name,\n \t\t\t                             hash_base=>$hb),\n-\t\t\t              -title => $name}, esc_html($basename));\n+\t\t\t              -title => $name}, esc_path($basename));\n \t\t} elsif (defined $type && $type eq 'tree') {\n \t\t\tprint $cgi->a({-href => href(action=>\"tree\", file_name=>$file_name,\n \t\t\t                             hash_base=>$hb),\n-\t\t\t              -title => $name}, esc_html($basename));\n+\t\t\t              -title => $name}, esc_path($basename));\n \t\t\tprint \" / \";\n \t\t} else {\n-\t\t\tprint esc_html($basename);\n+\t\t\tprint esc_path($basename);\n \t\t}\n \t}\n \tprint \"<br/></div>\\n\";\n@@ -1791,7 +1821,7 @@ sub git_print_tree_entry {\n \t\tprint \"<td class=\\\"list\\\">\" .\n \t\t\t$cgi->a({-href => href(action=>\"blob\", hash=>$t->{'hash'},\n \t\t\t                       file_name=>\"$basedir$t->{'name'}\", %base_key),\n-\t\t\t        -class => \"list\"}, esc_html($t->{'name'})) . \"</td>\\n\";\n+\t\t\t        -class => \"list\"}, esc_path($t->{'name'})) . \"</td>\\n\";\n \t\tprint \"<td class=\\\"link\\\">\";\n \t\tprint $cgi->a({-href => href(action=>\"blob\", hash=>$t->{'hash'},\n \t\t\t\t\t     file_name=>\"$basedir$t->{'name'}\", %base_key)},\n@@ -1818,7 +1848,7 @@ sub git_print_tree_entry {\n \t\tprint \"<td class=\\\"list\\\">\";\n \t\tprint $cgi->a({-href => href(action=>\"tree\", hash=>$t->{'hash'},\n \t\t                             file_name=>\"$basedir$t->{'name'}\", %base_key)},\n-\t\t              esc_html($t->{'name'}));\n+\t\t              esc_path($t->{'name'}));\n \t\tprint \"</td>\\n\";\n \t\tprint \"<td class=\\\"link\\\">\";\n \t\tprint $cgi->a({-href => href(action=>\"tree\", hash=>$t->{'hash'},\n@@ -1883,7 +1913,7 @@ sub git_difftree_body {\n \t\t\tprint \"<td>\";\n \t\t\tprint $cgi->a({-href => href(action=>\"blob\", hash=>$diff{'to_id'},\n \t\t\t                             hash_base=>$hash, file_name=>$diff{'file'}),\n-\t\t\t              -class => \"list\"}, esc_html($diff{'file'}));\n+\t\t\t              -class => \"list\"}, esc_path($diff{'file'}));\n \t\t\tprint \"</td>\\n\";\n \t\t\tprint \"<td>$mode_chng</td>\\n\";\n \t\t\tprint \"<td class=\\\"link\\\">\";\n@@ -1899,7 +1929,7 @@ sub git_difftree_body {\n \t\t\tprint \"<td>\";\n \t\t\tprint $cgi->a({-href => href(action=>\"blob\", hash=>$diff{'from_id'},\n \t\t\t                             hash_base=>$parent, file_name=>$diff{'file'}),\n-\t\t\t               -class => \"list\"}, esc_html($diff{'file'}));\n+\t\t\t               -class => \"list\"}, esc_path($diff{'file'}));\n \t\t\tprint \"</td>\\n\";\n \t\t\tprint \"<td>$mode_chng</td>\\n\";\n \t\t\tprint \"<td class=\\\"link\\\">\";\n@@ -1939,7 +1969,7 @@ sub git_difftree_body {\n \t\t\tprint \"<td>\";\n \t\t\tprint $cgi->a({-href => href(action=>\"blob\", hash=>$diff{'to_id'},\n \t\t\t                             hash_base=>$hash, file_name=>$diff{'file'}),\n-\t\t\t              -class => \"list\"}, esc_html($diff{'file'}));\n+\t\t\t              -class => \"list\"}, esc_path($diff{'file'}));\n \t\t\tprint \"</td>\\n\";\n \t\t\tprint \"<td>$mode_chnge</td>\\n\";\n \t\t\tprint \"<td class=\\\"link\\\">\";\n@@ -1979,11 +2009,11 @@ sub git_difftree_body {\n \t\t\tprint \"<td>\" .\n \t\t\t      $cgi->a({-href => href(action=>\"blob\", hash_base=>$hash,\n \t\t\t                             hash=>$diff{'to_id'}, file_name=>$diff{'to_file'}),\n-\t\t\t              -class => \"list\"}, esc_html($diff{'to_file'})) . \"</td>\\n\" .\n+\t\t\t              -class => \"list\"}, esc_path($diff{'to_file'})) . \"</td>\\n\" .\n \t\t\t      \"<td><span class=\\\"file_status $nstatus\\\">[$nstatus from \" .\n \t\t\t      $cgi->a({-href => href(action=>\"blob\", hash_base=>$parent,\n \t\t\t                             hash=>$diff{'from_id'}, file_name=>$diff{'from_file'}),\n-\t\t\t              -class => \"list\"}, esc_html($diff{'from_file'})) .\n+\t\t\t              -class => \"list\"}, esc_path($diff{'from_file'})) .\n \t\t\t      \" with \" . (int $diff{'similarity'}) . \"% similarity$mode_chng]</span></td>\\n\" .\n \t\t\t      \"<td class=\\\"link\\\">\";\n \t\t\tif ($diff{'to_id'} ne $diff{'from_id'}) {\n@@ -2113,7 +2143,7 @@ sub git_patchset_body {\n \t\t\t$file  ||= $diffinfo->{'file'};\n \t\t\t$file = $cgi->a({-href => href(action=>\"blob\", hash_base=>$hash_parent,\n \t\t\t                               hash=>$diffinfo->{'from_id'}, file_name=>$file),\n-\t\t\t                -class => \"list\"}, esc_html($file));\n+\t\t\t                -class => \"list\"}, esc_path($file));\n \t\t\t$patch_line =~ s|a/.*$|a/$file|g;\n \t\t\tprint \"<div class=\\\"diff from_file\\\">$patch_line</div>\\n\";\n \n@@ -2125,7 +2155,7 @@ sub git_patchset_body {\n \t\t\t$file  ||= $diffinfo->{'file'};\n \t\t\t$file = $cgi->a({-href => href(action=>\"blob\", hash_base=>$hash,\n \t\t\t                               hash=>$diffinfo->{'to_id'}, file_name=>$file),\n-\t\t\t                -class => \"list\"}, esc_html($file));\n+\t\t\t                -class => \"list\"}, esc_path($file));\n \t\t\t$patch_line =~ s|b/.*|b/$file|g;\n \t\t\tprint \"<div class=\\\"diff to_file\\\">$patch_line</div>\\n\";\n \n@@ -3373,8 +3403,8 @@ sub git_blobdiff {\n \n \t} else {\n \t\twhile (my $line = <$fd>) {\n-\t\t\t$line =~ s!a/($hash|$hash_parent)!'a/'.esc_html($diffinfo{'from_file'})!eg;\n-\t\t\t$line =~ s!b/($hash|$hash_parent)!'b/'.esc_html($diffinfo{'to_file'})!eg;\n+\t\t\t$line =~ s!a/($hash|$hash_parent)!'a/'.esc_path($diffinfo{'from_file'})!eg;\n+\t\t\t$line =~ s!b/($hash|$hash_parent)!'b/'.esc_path($diffinfo{'to_file'})!eg;\n \n \t\t\tprint $line;\n \n@@ -3729,7 +3759,7 @@ sub git_search {\n \t\t\t\t\t\tprint $cgi->a({-href => href(action=>\"blob\", hash_base=>$co{'id'},\n \t\t\t\t\t\t                             hash=>$set{'id'}, file_name=>$set{'file'}),\n \t\t\t\t\t\t              -class => \"list\"},\n-\t\t\t\t\t\t              \"<span class=\\\"match\\\">\" . esc_html($set{'file'}) . \"</span>\") .\n+\t\t\t\t\t\t              \"<span class=\\\"match\\\">\" . esc_path($set{'file'}) . \"</span>\") .\n \t\t\t\t\t\t      \"<br/>\\n\";\n \t\t\t\t\t}\n \t\t\t\t\tprint \"</td>\\n\" .\n@@ -3863,7 +3893,7 @@ XML\n \t\t\tif (!($line =~ m/^:([0-7]{6}) ([0-7]{6}) ([0-9a-fA-F]{40}) ([0-9a-fA-F]{40}) (.)([0-9]{0,3})\\t(.*)$/)) {\n \t\t\t\tnext;\n \t\t\t}\n-\t\t\tmy $file = esc_html(unquote($7));\n+\t\t\tmy $file = esc_path(unquote($7));\n \t\t\t$file = to_utf8($file);\n \t\t\tprint \"$file<br/>\\n\";\n \t\t}\n-- \n1.4.3.3\n"},{"id":"297999","messageId":"200610301959.05313.jnareb@gmail.com","threadId":"43063","inReplyTo":"200610301953.01875.jnareb@gmail.com","subject":"[PATCH 2/n] gitweb: Use '&iquot;' instead of '?' in esc_path","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-10-30T18:59:05Z","receivedAt":"2006-10-30T18:59:05Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Use \"&iquot;\" Latin 1 entity (\"&#191;\" -- inverted question mark =\nturned question mark, U+00BF ISOnum) instead '?' as replacements for\ncontrol characters and other undisplayable characters.\n\nSigned-off-by: Jakub Narebski <jnareb@gmail.com>\n---\n gitweb/gitweb.perl |    2 +-\n 1 files changed, 1 insertions(+), 1 deletions(-)\n\ndiff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl\nindex a15e916..edca27d 100755\n--- a/gitweb/gitweb.perl\n+++ b/gitweb/gitweb.perl\n@@ -567,7 +567,7 @@ sub esc_html {\n sub esc_path {\n \tmy $str = shift;\n \t$str = esc_html($str);\n-\t$str =~ s/[[:cntrl:]\\a\\b\\e\\f\\n\\r\\t\\011]/?/g; # like --hide-control-chars in ls\n+\t$str =~ s/[[:cntrl:]\\a\\b\\e\\f\\n\\r\\t\\011]/&iquest;/g; # like --hide-control-chars in ls\n \treturn $str;\n }\n \n-- \n1.4.3.3\n"},{"id":"296704","messageId":"200610302225.11897.jnareb@gmail.com","threadId":"43063","inReplyTo":"200610301953.01875.jnareb@gmail.com","subject":"[PATCH 3/n] gitweb: Use 's' regexp modifier to secure against filenames with LF","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-10-30T21:25:11Z","receivedAt":"2006-10-30T21:25:11Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Use 's' (treat string as single line) regexp modifier in\ngit_get_hash_by_path (against future changes, probably unnecessary)\nand in parse_ls_tree_line (when called with '-z'=>1 option) to secure\nagainst filenames containing newline.\n\nSigned-off-by: Jakub Narebski <jnareb@gmail.com>\n---\nWithout this patch filename with LF broke \"tree\" view.\n\n gitweb/gitweb.perl |    4 ++--\n 1 files changed, 2 insertions(+), 2 deletions(-)\n\ndiff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl\nindex edca27d..0fd1360 100755\n--- a/gitweb/gitweb.perl\n+++ b/gitweb/gitweb.perl\n@@ -890,7 +890,7 @@ sub git_get_hash_by_path {\n \tclose $fd or return undef;\n \n \t#'100644 blob 0fa3f3a66fb6a137f6ec2c19351ed4d807070ffa\tpanic.c'\n-\t$line =~ m/^([0-9]+) (.+) ([0-9a-fA-F]{40})\\t(.+)$/;\n+\t$line =~ m/^([0-9]+) (.+) ([0-9a-fA-F]{40})\\t(.+)$/s;\n \tif (defined $type && $type ne $2) {\n \t\t# type doesn't match\n \t\treturn undef;\n@@ -1305,7 +1305,7 @@ sub parse_ls_tree_line ($;%) {\n \tmy %res;\n \n \t#'100644 blob 0fa3f3a66fb6a137f6ec2c19351ed4d807070ffa\tpanic.c'\n-\t$line =~ m/^([0-9]+) (.+) ([0-9a-fA-F]{40})\\t(.+)$/;\n+\t$line =~ m/^([0-9]+) (.+) ([0-9a-fA-F]{40})\\t(.+)$/s;\n \n \t$res{'mode'} = $1;\n \t$res{'type'} = $2;\n-- \n1.4.3.3\n"},{"id":"297367","messageId":"200610302229.06957.jnareb@gmail.com","threadId":"43063","inReplyTo":"200610301953.01875.jnareb@gmail.com","subject":"[PATCH 4/n] gitweb: Secure against commit-ish/tree-ish with the same name as path","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-10-30T21:29:06Z","receivedAt":"2006-10-30T21:29:06Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Add \"--\" after <commit-ish> or <tree-ish> argument to clearly mark it\nas <commit-ish> or <tree-ish> and not pathspec, securing against refs\nwith the same names as files or directories in [live] repository.\n\nSome wrapping to reduce line length as well.\n\nSigned-off-by: Jakub Narebski <jnareb@gmail.com>\n---\nI uses branch named 'gitweb/test' to test gitweb against files with\nfunny characters (like '\"', '\\', TAB, LF) in filenames. I run gitweb\non \"live\" (not bare) repository, and there is directory 'gitweb/test'\nin it. So I had some parts of gitweb not functioning, and errors in\nthe web server logs. This patch fixes that issue.\n\n gitweb/gitweb.perl |   38 +++++++++++++++++++++++---------------\n 1 files changed, 23 insertions(+), 15 deletions(-)\n\ndiff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl\nindex 0fd1360..4554067 100755\n--- a/gitweb/gitweb.perl\n+++ b/gitweb/gitweb.perl\n@@ -1141,7 +1141,9 @@ sub parse_commit {\n \t\t@commit_lines = @$commit_text;\n \t} else {\n \t\tlocal $/ = \"\\0\";\n-\t\topen my $fd, \"-|\", git_cmd(), \"rev-list\", \"--header\", \"--parents\", \"--max-count=1\", $commit_id\n+\t\topen my $fd, \"-|\", git_cmd(), \"rev-list\",\n+\t\t\t\"--header\", \"--parents\", \"--max-count=1\",\n+\t\t\t$commit_id, \"--\"\n \t\t\tor return;\n \t\t@commit_lines = split '\\n', <$fd>;\n \t\tclose $fd or return;\n@@ -2559,7 +2561,7 @@ sub git_summary {\n \t}\n \n \topen my $fd, \"-|\", git_cmd(), \"rev-list\", \"--max-count=17\",\n-\t\tgit_get_head_hash($project)\n+\t\tgit_get_head_hash($project), \"--\"\n \t\tor die_error(undef, \"Open git-rev-list failed\");\n \tmy @revlist = map { chomp; $_ } <$fd>;\n \tclose $fd;\n@@ -2970,7 +2972,7 @@ sub git_tree {\n \t\t}\n \t}\n \t$/ = \"\\0\";\n-\topen my $fd, \"-|\", git_cmd(), \"ls-tree\", '-z', $hash\n+\topen my $fd, \"-|\", git_cmd(), \"ls-tree\", '-z', $hash, \"--\"\n \t\tor die_error(undef, \"Open git-ls-tree failed\");\n \tmy @entries = map { chomp; $_ } <$fd>;\n \tclose $fd or die_error(undef, \"Reading tree failed\");\n@@ -3102,7 +3104,7 @@ sub git_log {\n \tmy $refs = git_get_references();\n \n \tmy $limit = sprintf(\"--max-count=%i\", (100 * ($page+1)));\n-\topen my $fd, \"-|\", git_cmd(), \"rev-list\", $limit, $hash\n+\topen my $fd, \"-|\", git_cmd(), \"rev-list\", $limit, $hash, \"--\"\n \t\tor die_error(undef, \"Open git-rev-list failed\");\n \tmy @revlist = map { chomp; $_ } <$fd>;\n \tclose $fd;\n@@ -3160,7 +3162,7 @@ sub git_commit {\n \t\t$parent = \"--root\";\n \t}\n \topen my $fd, \"-|\", git_cmd(), \"diff-tree\", '-r', \"--no-commit-id\",\n-\t\t@diff_opts, $parent, $hash\n+\t\t@diff_opts, $parent, $hash, \"--\"\n \t\tor die_error(undef, \"Open git-diff-tree failed\");\n \tmy @difftree = map { chomp; $_ } <$fd>;\n \tclose $fd or die_error(undef, \"Reading git-diff-tree failed\");\n@@ -3265,7 +3267,8 @@ sub git_blobdiff {\n \tif (defined $hash_base && defined $hash_parent_base) {\n \t\tif (defined $file_name) {\n \t\t\t# read raw output\n-\t\t\topen $fd, \"-|\", git_cmd(), \"diff-tree\", '-r', @diff_opts, $hash_parent_base, $hash_base,\n+\t\t\topen $fd, \"-|\", git_cmd(), \"diff-tree\", '-r', @diff_opts,\n+\t\t\t\t$hash_parent_base, $hash_base,\n \t\t\t\t\"--\", $file_name\n \t\t\t\tor die_error(undef, \"Open git-diff-tree failed\");\n \t\t\t@difftree = map { chomp; $_ } <$fd>;\n@@ -3279,7 +3282,8 @@ sub git_blobdiff {\n \t\t\t# try to find filename from $hash\n \n \t\t\t# read filtered raw output\n-\t\t\topen $fd, \"-|\", git_cmd(), \"diff-tree\", '-r', @diff_opts, $hash_parent_base, $hash_base\n+\t\t\topen $fd, \"-|\", git_cmd(), \"diff-tree\", '-r', @diff_opts,\n+\t\t\t\t$hash_parent_base, $hash_base, \"--\"\n \t\t\t\tor die_error(undef, \"Open git-diff-tree failed\");\n \t\t\t@difftree =\n \t\t\t\t# ':100644 100644 03b21826... 3b93d5e7... M\tls-files.c'\n@@ -3349,7 +3353,8 @@ sub git_blobdiff {\n \t\t}\n \n \t\t# open patch output\n-\t\topen $fd, \"-|\", git_cmd(), \"diff\", '-p', @diff_opts, $hash_parent, $hash\n+\t\topen $fd, \"-|\", git_cmd(), \"diff\", '-p', @diff_opts,\n+\t\t\t$hash_parent, $hash, \"--\"\n \t\t\tor die_error(undef, \"Open git-diff failed\");\n \t} else  {\n \t\tdie_error('404 Not Found', \"Missing one of the blob diff parameters\")\n@@ -3480,8 +3485,8 @@ sub git_commitdiff {\n \tmy @difftree;\n \tif ($format eq 'html') {\n \t\topen $fd, \"-|\", git_cmd(), \"diff-tree\", '-r', @diff_opts,\n-\t\t\t\"--no-commit-id\",\n-\t\t\t\"--patch-with-raw\", \"--full-index\", $hash_parent, $hash\n+\t\t\t\"--no-commit-id\", \"--patch-with-raw\", \"--full-index\",\n+\t\t\t$hash_parent, $hash, \"--\"\n \t\t\tor die_error(undef, \"Open git-diff-tree failed\");\n \n \t\twhile (chomp(my $line = <$fd>)) {\n@@ -3492,7 +3497,7 @@ sub git_commitdiff {\n \n \t} elsif ($format eq 'plain') {\n \t\topen $fd, \"-|\", git_cmd(), \"diff-tree\", '-r', @diff_opts,\n-\t\t\t'-p', $hash_parent, $hash\n+\t\t\t'-p', $hash_parent, $hash, \"--\"\n \t\t\tor die_error(undef, \"Open git-diff-tree failed\");\n \n \t} else {\n@@ -3669,7 +3674,9 @@ sub git_search {\n \tmy $alternate = 1;\n \tif ($searchtype eq 'commit' or $searchtype eq 'author' or $searchtype eq 'committer') {\n \t\t$/ = \"\\0\";\n-\t\topen my $fd, \"-|\", git_cmd(), \"rev-list\", \"--header\", \"--parents\", $hash or next;\n+\t\topen my $fd, \"-|\", git_cmd(), \"rev-list\",\n+\t\t\t\"--header\", \"--parents\", $hash, \"--\"\n+\t\t\tor next;\n \t\twhile (my $commit_text = <$fd>) {\n \t\t\tif (!grep m/$searchtext/i, $commit_text) {\n \t\t\t\tnext;\n@@ -3815,7 +3822,7 @@ sub git_shortlog {\n \tmy $refs = git_get_references();\n \n \tmy $limit = sprintf(\"--max-count=%i\", (100 * ($page+1)));\n-\topen my $fd, \"-|\", git_cmd(), \"rev-list\", $limit, $hash\n+\topen my $fd, \"-|\", git_cmd(), \"rev-list\", $limit, $hash, \"--\"\n \t\tor die_error(undef, \"Open git-rev-list failed\");\n \tmy @revlist = map { chomp; $_ } <$fd>;\n \tclose $fd;\n@@ -3843,7 +3850,8 @@ sub git_shortlog {\n \n sub git_rss {\n \t# http://www.notestips.com/80256B3A007F2692/1/NAMO5P9UPQ\n-\topen my $fd, \"-|\", git_cmd(), \"rev-list\", \"--max-count=150\", git_get_head_hash($project)\n+\topen my $fd, \"-|\", git_cmd(), \"rev-list\", \"--max-count=150\",\n+\t\tgit_get_head_hash($project), \"--\"\n \t\tor die_error(undef, \"Open git-rev-list failed\");\n \tmy @revlist = map { chomp; $_ } <$fd>;\n \tclose $fd or die_error(undef, \"Reading git-rev-list failed\");\n@@ -3867,7 +3875,7 @@ XML\n \t\t}\n \t\tmy %cd = parse_date($co{'committer_epoch'});\n \t\topen $fd, \"-|\", git_cmd(), \"diff-tree\", '-r', @diff_opts,\n-\t\t\t$co{'parent'}, $co{'id'}\n+\t\t\t$co{'parent'}, $co{'id'}, \"--\"\n \t\t\tor next;\n \t\tmy @difftree = map { chomp; $_ } <$fd>;\n \t\tclose $fd\n-- \n1.4.3.3\n"},{"id":"296369","messageId":"7vzmbds4pw.fsf@assigned-by-dhcp.cox.net","threadId":"43063","inReplyTo":"200610301959.05313.jnareb@gmail.com","subject":"Re: [PATCH 2/n] gitweb: Use '&iquot;' instead of '?' in esc_path","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-10-31T00:34:35Z","receivedAt":"2006-10-31T00:34:35Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jakub Narebski <jnareb@gmail.com> writes:\n\n> Use \"&iquot;\" Latin 1 entity (\"&#191;\" -- inverted question mark =\n> turned question mark, U+00BF ISOnum) instead '?' as replacements for\n> control characters and other undisplayable characters.\n>\n> Signed-off-by: Jakub Narebski <jnareb@gmail.com>\n\nDo you have something against our Spanish and Latin American\nfriends?  ;-)\n\nI wonder if there is a more suitable replacement character that\nis accepted across scripts?\n\nJapanese printing industry has a long tradition of using U+3013\n(\"geta\") as a filler character.  Originally they placed a type\nof otherwise unused character upside down while packing types\ninto a row, and the reverse side of a type, when inked and\nprinted, left imprint that looked like footprint somebody who\nwore a \"geta\" (a traditional footware) would leave.\n\n\thttp://ja.wikipedia.org/wiki/%E4%B8%8B%E9%A7%84\n\nshows how a \"geta\" looks like, and\n\n\thttp://unicode.org/charts/PDF/U3000.pdf\n\nshows how the filler character looks like.\n\nNote that I am not suggesting to use &#3013; as a replacement at\nall.  I however think inverted question is inappropriate, and we\nshould pick something else if we are fixing the question mark\nwhich is obviously inappropriate.\n\n"},{"id":"294200","messageId":"7vvem1s29g.fsf@assigned-by-dhcp.cox.net","threadId":"43063","inReplyTo":"7vzmbds4pw.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH 2/n] gitweb: Use '&iquot;' instead of '?' in esc_path","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-10-31T01:27:39Z","receivedAt":"2006-10-31T01:27:39Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <junkio@cox.net> writes:\n\n> Jakub Narebski <jnareb@gmail.com> writes:\n>\n>> Use \"&iquot;\" Latin 1 entity (\"&#191;\" -- inverted question mark =\n>> turned question mark, U+00BF ISOnum) instead '?' as replacements for\n>> control characters and other undisplayable characters.\n>>\n>> Signed-off-by: Jakub Narebski <jnareb@gmail.com>\n>\n> Do you have something against our Spanish and Latin American\n> friends?  ;-)\n>\n> I wonder if there is a more suitable replacement character that\n> is accepted across scripts?\n\nI have a suspicion that instead of finding an exotic character,\njust showing the byte value in \\octal, perhaps in different\ncolor, might be more portable and easier.  For one thing, it\nhelps to show the exact byte value than just one substitution\ncharacter if you are troubleshooting gitweb.\n\n"},{"id":"296361","messageId":"200610311023.23409.jnareb@gmail.com","threadId":"43063","inReplyTo":"7vvem1s29g.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH 2/n] gitweb: Use '&iquot;' instead of '?' in esc_path","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-10-31T09:23:22Z","receivedAt":"2006-10-31T09:23:22Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Junio C Hamano wrote:\n>\n> Junio C Hamano <junkio@cox.net> writes:\n> \n>> Jakub Narebski <jnareb@gmail.com> writes:\n>>\n>>> Use \"&iquot;\" Latin 1 entity (\"&#191;\" -- inverted question mark =\n>>> turned question mark, U+00BF ISOnum) instead '?' as replacements for\n>>> control characters and other undisplayable characters.\n>>>\n>>> Signed-off-by: Jakub Narebski <jnareb@gmail.com>\n>>\n>> Do you have something against our Spanish and Latin American\n>> friends?  ;-)\n>>\n>> I wonder if there is a more suitable replacement character that\n>> is accepted across scripts?\n> \n> I have a suspicion that instead of finding an exotic character,\n> just showing the byte value in \\octal, perhaps in different\n> color, might be more portable and easier.  For one thing, it\n> helps to show the exact byte value than just one substitution\n> character if you are troubleshooting gitweb.\n\nWill do. Well, with the exception of control characters which have\nliteral escape characters, for example showing LF as \\n instead\nof \\octal. By the way, wouldn't \\xhex be better?\n\nDifferent color/style is good. Otherwise we would have escape escape\ncharacter, i.e. write '\\\\' and perhaps als mark filename as quoted.\ngit surrounds filename with doublequotes, \"<quoted filename>\", adding\n'\"' to the list of quoted characters: for gitweb this kind of marking\nfilename as quoted is PITA, as we first, don't want I think to include\n'\"' in link (\"_filename_\" vs _\"filename\"_), and second and more important\nif we hyperlink parts of filename we would want for quote to be placed\noutside whole filename (\"a/_filename_\" vs a/_\"filename\"_ and also\n\"_path_/_to_/_file_\" vs _path_/_to_/_\"file\"_).\n\nShould we mark only replaced character, or the whole filename?\n\n\nOn the technical side, should I send the patch as replacement for this\npatch, or on top of this patch?\n-- \nJakub Narebski\n"},{"id":"297434","messageId":"200610311522.32228.jnareb@gmail.com","threadId":"43063","inReplyTo":"200610301953.01875.jnareb@gmail.com","subject":"[PATCH 5/n] [take 3] gitweb: New improved patchset view","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-10-31T14:22:31Z","receivedAt":"2006-10-31T14:22:31Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Replace \"gitweb diff header\" with its full sha1 of blobs and replace\nit by \"git diff\" header and extended diff header. Change also somewhat\nhighlighting of diffs.\n\nAdded `file_type_long' subroutine to convert file mode in octal to\nfile type description (only for file modes which used by git).\n\nChanges:\n* \"gitweb diff header\" which looked for example like below:\n    file:_<sha1 before>_ -> file:_<sha1 after>_\n  where 'file' is file type and '<sha1>' is full sha1 of blob is\n  changed to\n    diff --git _a/<file before>_ _b/<file after>_\n  In both cases links are visible and use default link style. If file\n  is added, a/<file> is not hyperlinked, if file is deleted, b/<file>\n  is not hyperlinked.\n* there is added \"extended diff header\", with <path> and <hash>\n  hyperlinked (and <hash> shortened to 7 characters), and <mode>\n  explained: '<mode>' is extended to '<mode> (<file type description>)',\n  where added text is slightly lighter to easy distinguish that it\n  was added (and it is difference from git-diff output).\n* from-file/to-file two-line header lines have slightly darker color\n  than removed/added lines.\n* chunk header has now delicate line above for easier finding chunk\n  boundary, and top margin of 2px, both barely visible.\n\nSigned-off-by: Jakub Narebski <jnareb@gmail.com>\n---\nIt still does not output empty patches. This is to be adressed\nin later patch.\n\nAs usual, you can see it at work at my web page\n  http://roke (.) dyndns (.) info/cgi-bin/gitweb/gitweb.cgi\n\nComments?\n\n gitweb/gitweb.css  |   66 +++++++++++++++----\n gitweb/gitweb.perl |  187 \n++++++++++++++++++++++++++++++++++------------------\n 2 files changed, 176 insertions(+), 77 deletions(-)\n\ndiff --git a/gitweb/gitweb.css b/gitweb/gitweb.css\nindex 0eda982..87dbc52 100644\n--- a/gitweb/gitweb.css\n+++ b/gitweb/gitweb.css\n@@ -291,40 +291,82 @@ td.mode {\n \tfont-family: monospace;\n }\n \n-div.diff a.list {\n+/* styling of diffs (patchsets): commitdiff and blobdiff views */\n+div.diff.header,\n+div.diff.extended_header {\n+\twhite-space: normal;\n+}\n+\n+div.diff.header {\n+\tfont-weight: bold;\n+\n+\tbackground-color: #edece6;\n+\n+\tmargin-top: 4px;\n+\tpadding: 4px 0px 2px 0px;\n+\tborder: solid #d9d8d1;\n+\tborder-width: 1px 0px 1px 0px;\n+}\n+\n+div.diff.header a.path {\n+\ttext-decoration: underline;\n+}\n+\n+div.diff.extended_header,\n+div.diff.extended_header a.path,\n+div.diff.extended_header a.hash {\n+\tcolor: #777777;\n+}\n+\n+div.diff.extended_header .info {\n+\tcolor: #b0b0b0;\n+}\n+\n+div.diff.extended_header {\n+\tbackground-color: #f6f5ee;\n+\tpadding: 2px 0px 2px 0px;\n+}\n+\n+div.diff a.path,\n+div.diff a.hash {\n \ttext-decoration: none;\n }\n \n-div.diff a.list:hover {\n+div.diff a.path:hover,\n+div.diff a.hash:hover {\n \ttext-decoration: underline;\n }\n \n-div.diff.to_file a.list,\n-div.diff.to_file,\n+div.diff.to_file a.path,\n+div.diff.to_file {\n+\tcolor: #007000;\n+}\n+\n div.diff.add {\n \tcolor: #008800;\n }\n \n-div.diff.from_file a.list,\n-div.diff.from_file,\n+div.diff.from_file a.path,\n+div.diff.from_file {\n+\tcolor: #aa0000;\n+}\n+\n div.diff.rem {\n \tcolor: #cc0000;\n }\n \n div.diff.chunk_header {\n \tcolor: #990099;\n+\n+\tborder: dotted #ffe0ff;\n+\tborder-width: 1px 0px 0px 0px;\n+\tmargin-top: 2px;\n }\n \n div.diff.incomplete {\n \tcolor: #cccccc;\n }\n \n-div.diff_info {\n-\tfont-family: monospace;\n-\tcolor: #000099;\n-\tbackground-color: #edece6;\n-\tfont-style: italic;\n-}\n \n div.index_include {\n \tborder: solid #d9d8d1;\ndiff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl\nindex 4554067..c22fcc5 100755\n--- a/gitweb/gitweb.perl\n+++ b/gitweb/gitweb.perl\n@@ -732,6 +732,32 @@ sub file_type {\n \t}\n }\n \n+# convert file mode in octal to file type description string\n+sub file_type_long {\n+\tmy $mode = shift;\n+\n+\tif ($mode !~ m/^[0-7]+$/) {\n+\t\treturn $mode;\n+\t} else {\n+\t\t$mode = oct $mode;\n+\t}\n+\n+\tif (S_ISDIR($mode & S_IFMT)) {\n+\t\treturn \"directory\";\n+\t} elsif (S_ISLNK($mode)) {\n+\t\treturn \"symlink\";\n+\t} elsif (S_ISREG($mode)) {\n+\t\tif ($mode & S_IXUSR) {\n+\t\t\treturn \"executable\";\n+\t\t} else {\n+\t\t\treturn \"file\";\n+\t\t};\n+\t} else {\n+\t\treturn \"unknown\";\n+\t}\n+}\n+\n+\n ## \n----------------------------------------------------------------------\n ## functions returning short HTML fragments, or transforming HTML \nfragments\n ## which don't beling to other sections\n@@ -2055,7 +2081,9 @@ sub git_patchset_body {\n \tmy $patch_idx = 0;\n \tmy $in_header = 0;\n \tmy $patch_found = 0;\n+\tmy $skip_patch = 0;\n \tmy $diffinfo;\n+\tmy (%from, %to);\n \n \tprint \"<div class=\\\"patchset\\\">\\n\";\n \n@@ -2065,6 +2093,8 @@ sub git_patchset_body {\n \n \t\tif ($patch_line =~ m/^diff /) { # \"git diff\" header\n \t\t\t# beginning of patch (in patchset)\n+\t\t\t$skip_patch = 0;\n+\n \t\t\tif ($patch_found) {\n \t\t\t\t# close previous patch\n \t\t\t\tprint \"</div>\\n\"; # class=\"patch\"\n@@ -2074,96 +2104,123 @@ sub git_patchset_body {\n \t\t\t}\n \t\t\tprint \"<div class=\\\"patch\\\" id=\\\"patch\". ($patch_idx+1) .\"\\\">\\n\";\n \n+\t\t\t# read and prepare patch information\n \t\t\tif (ref($difftree->[$patch_idx]) eq \"HASH\") {\n+\t\t\t\t# pre-parsed (or generated by hand)\n \t\t\t\t$diffinfo = $difftree->[$patch_idx];\n \t\t\t} else {\n \t\t\t\t$diffinfo = parse_difftree_raw_line($difftree->[$patch_idx]);\n \t\t\t}\n+\t\t\t$from{'file'} = $diffinfo->{'from_file'} || $diffinfo->{'file'};\n+\t\t\t$to{'file'}   = $diffinfo->{'to_file'}   || $diffinfo->{'file'};\n+\t\t\tif ($diffinfo->{'status'} ne \"A\") { # not new (added) file\n+\t\t\t\t$from{'href'} = href(action=>\"blob\", hash_base=>$hash_parent,\n+\t\t\t\t                     hash=>$diffinfo->{'from_id'},\n+\t\t\t\t                     file_name=>$from{'file'});\n+\t\t\t}\n+\t\t\tif ($diffinfo->{'status'} ne \"D\") { # not deleted file\n+\t\t\t\t$to{'href'} = href(action=>\"blob\", hash_base=>$hash,\n+\t\t\t\t                   hash=>$diffinfo->{'to_id'},\n+\t\t\t\t                   file_name=>$to{'file'});\n+\t\t\t}\n \t\t\t$patch_idx++;\n \n-\t\t\t# for now, no extended header, hence we skip empty patches\n-\t\t\t# companion to\tnext LINE if $in_header;\n+\t\t\t# for now we skip empty patches\n \t\t\tif ($diffinfo->{'from_id'} eq $diffinfo->{'to_id'}) { # no change\n \t\t\t\t$in_header = 1;\n+\t\t\t\t$skip_patch = 0;\n \t\t\t\tnext LINE;\n \t\t\t}\n \n-\t\t\tif ($diffinfo->{'status'} eq \"A\") { # added\n-\t\t\t\tprint \"<div class=\\\"diff_info\\\">\" . \nfile_type($diffinfo->{'to_mode'}) . \":\" .\n-\t\t\t\t      $cgi->a({-href => href(action=>\"blob\", hash_base=>$hash,\n-\t\t\t\t                             hash=>$diffinfo->{'to_id'}, \nfile_name=>$diffinfo->{'file'})},\n-\t\t\t\t              $diffinfo->{'to_id'}) . \" (new)\" .\n-\t\t\t\t      \"</div>\\n\"; # class=\"diff_info\"\n-\n-\t\t\t} elsif ($diffinfo->{'status'} eq \"D\") { # deleted\n-\t\t\t\tprint \"<div class=\\\"diff_info\\\">\" . \nfile_type($diffinfo->{'from_mode'}) . \":\" .\n-\t\t\t\t      $cgi->a({-href => href(action=>\"blob\", \nhash_base=>$hash_parent,\n-\t\t\t\t                             hash=>$diffinfo->{'from_id'}, \nfile_name=>$diffinfo->{'file'})},\n-\t\t\t\t              $diffinfo->{'from_id'}) . \" (deleted)\" .\n-\t\t\t\t      \"</div>\\n\"; # class=\"diff_info\"\n-\n-\t\t\t} elsif ($diffinfo->{'status'} eq \"R\" || # renamed\n-\t\t\t         $diffinfo->{'status'} eq \"C\" || # copied\n-\t\t\t         $diffinfo->{'status'} eq \"2\") { # with two filenames (from \ngit_blobdiff)\n-\t\t\t\tprint \"<div class=\\\"diff_info\\\">\" .\n-\t\t\t\t      file_type($diffinfo->{'from_mode'}) . \":\" .\n-\t\t\t\t      $cgi->a({-href => href(action=>\"blob\", \nhash_base=>$hash_parent,\n-\t\t\t\t                             hash=>$diffinfo->{'from_id'}, \nfile_name=>$diffinfo->{'from_file'})},\n-\t\t\t\t              $diffinfo->{'from_id'}) .\n-\t\t\t\t      \" -> \" .\n-\t\t\t\t      file_type($diffinfo->{'to_mode'}) . \":\" .\n-\t\t\t\t      $cgi->a({-href => href(action=>\"blob\", hash_base=>$hash,\n-\t\t\t\t                             hash=>$diffinfo->{'to_id'}, \nfile_name=>$diffinfo->{'to_file'})},\n-\t\t\t\t              $diffinfo->{'to_id'});\n-\t\t\t\tprint \"</div>\\n\"; # class=\"diff_info\"\n-\n-\t\t\t} else { # modified, mode changed, ...\n-\t\t\t\tprint \"<div class=\\\"diff_info\\\">\" .\n-\t\t\t\t      file_type($diffinfo->{'from_mode'}) . \":\" .\n-\t\t\t\t      $cgi->a({-href => href(action=>\"blob\", \nhash_base=>$hash_parent,\n-\t\t\t\t                             hash=>$diffinfo->{'from_id'}, \nfile_name=>$diffinfo->{'file'})},\n-\t\t\t\t              $diffinfo->{'from_id'}) .\n-\t\t\t\t      \" -> \" .\n-\t\t\t\t      file_type($diffinfo->{'to_mode'}) . \":\" .\n-\t\t\t\t      $cgi->a({-href => href(action=>\"blob\", hash_base=>$hash,\n-\t\t\t\t                             hash=>$diffinfo->{'to_id'}, \nfile_name=>$diffinfo->{'file'})},\n-\t\t\t\t              $diffinfo->{'to_id'});\n-\t\t\t\tprint \"</div>\\n\"; # class=\"diff_info\"\n+\t\t\t# print \"git diff\" header\n+\t\t\t$patch_line =~ s!^(diff (.*?) )a/.*$!$1!;\n+\t\t\tif ($from{'href'}) {\n+\t\t\t\t$patch_line .= $cgi->a({-href => $from{'href'}, -class => \"path\"},\n+\t\t\t\t                       'a/' . esc_path($from{'file'}));\n+\t\t\t} else { # file was added\n+\t\t\t\t$patch_line .= 'a/' . esc_path($from{'file'});\n+\t\t\t}\n+\t\t\t$patch_line .= ' ';\n+\t\t\tif ($to{'href'}) {\n+\t\t\t\t$patch_line .= $cgi->a({-href => $to{'href'}, -class => \"path\"},\n+\t\t\t\t                       'b/' . esc_path($to{'file'}));\n+\t\t\t} else { # file was deleted\n+\t\t\t\t$patch_line .= 'b/' . esc_path($to{'file'});\n \t\t\t}\n \n-\t\t\t#print \"<div class=\\\"diff extended_header\\\">\\n\";\n+\t\t\tprint \"<div class=\\\"diff header\\\">$patch_line</div>\\n\";\n+\t\t\tprint \"<div class=\\\"diff extended_header\\\">\\n\";\n \t\t\t$in_header = 1;\n \t\t\tnext LINE;\n+\t\t} else {\n+\t\t\t# actual skipping of empty patches\n+\t\t\tnext LINE if $skip_patch;\n \t\t} # start of patch in patchset\n \n+\t\tif ($in_header) {\n+\t\t\tif ($patch_line !~ m/^---/) {\n+\t\t\t\t# match <path>\n+\t\t\t\tif ($patch_line =~ s!^((copy|rename) from ).*$!$1! && \n$from{'href'}) {\n+\t\t\t\t\t$patch_line .= $cgi->a({-href=>$from{'href'}, -class=>\"path\"},\n+\t\t\t\t\t                        esc_path($from{'file'}));\n+\t\t\t\t}\n+\t\t\t\tif ($patch_line =~ s!^((copy|rename) to ).*$!$1! && $to{'href'}) {\n+\t\t\t\t\t$patch_line = $cgi->a({-href=>$to{'href'}, -class=>\"path\"},\n+\t\t\t\t\t                      esc_path($to{'file'}));\n+\t\t\t\t}\n+\t\t\t\t# match <mode>\n+\t\t\t\tif ($patch_line =~ m/\\s(\\d{6})$/) {\n+\t\t\t\t\t$patch_line .= '<span class=\"info\"> (' .\n+\t\t\t\t\t               file_type_long($1) .\n+\t\t\t\t\t               ')</span>';\n+\t\t\t\t}\n+\t\t\t\t# match <hash>\n+\t\t\t\tif ($patch_line =~ m/^index/) {\n+\t\t\t\t\tmy ($from_link, $to_link);\n+\t\t\t\t\tif ($from{'href'}) {\n+\t\t\t\t\t\t$from_link = $cgi->a({-href=>$from{'href'}, -class=>\"hash\"},\n+\t\t\t\t\t\t                     substr($diffinfo->{'from_id'},0,7));\n+\t\t\t\t\t} else {\n+\t\t\t\t\t\t$from_link = '0' x 7;\n+\t\t\t\t\t}\n+\t\t\t\t\tif ($to{'href'}) {\n+\t\t\t\t\t\t$to_link = $cgi->a({-href=>$to{'href'}, -class=>\"hash\"},\n+\t\t\t\t\t\t                   substr($diffinfo->{'to_id'},0,7));\n+\t\t\t\t\t} else {\n+\t\t\t\t\t\t$to_link = '0' x 7;\n+\t\t\t\t\t}\n+\t\t\t\t\tmy ($from_id, $to_id) = ($diffinfo->{'from_id'}, \n$diffinfo->{'to_id'});\n+\t\t\t\t\t$patch_line =~ s!$from_id\\.\\.$to_id!$from_link..$to_link!;\n+\t\t\t\t}\n+\t\t\t\tprint $patch_line . \"<br/>\\n\";\n \n-\t\tif ($in_header && $patch_line =~ m/^---/) {\n-\t\t\t#print \"</div>\\n\"; # class=\"diff extended_header\"\n-\t\t\t$in_header = 0;\n+\t\t\t} else {\n+\t\t\t\t#$in_header && $patch_line =~ m/^---/;\n+\t\t\t\tprint \"</div>\\n\"; # class=\"diff extended_header\"\n+\t\t\t\t$in_header = 0;\n+\n+\t\t\t\tif ($from{'href'}) {\n+\t\t\t\t\t$patch_line = '--- a/' .\n+\t\t\t\t\t              $cgi->a({-href=>$from{'href'}, -class=>\"path\"},\n+\t\t\t\t\t                      esc_path($from{'file'}));\n+\t\t\t\t}\n+\t\t\t\tprint \"<div class=\\\"diff from_file\\\">$patch_line</div>\\n\";\n \n-\t\t\tmy $file = $diffinfo->{'from_file'};\n-\t\t\t$file  ||= $diffinfo->{'file'};\n-\t\t\t$file = $cgi->a({-href => href(action=>\"blob\", \nhash_base=>$hash_parent,\n-\t\t\t                               hash=>$diffinfo->{'from_id'}, \nfile_name=>$file),\n-\t\t\t                -class => \"list\"}, esc_path($file));\n-\t\t\t$patch_line =~ s|a/.*$|a/$file|g;\n-\t\t\tprint \"<div class=\\\"diff from_file\\\">$patch_line</div>\\n\";\n+\t\t\t\t$patch_line = <$fd>;\n+\t\t\t\tchomp $patch_line;\n \n-\t\t\t$patch_line = <$fd>;\n-\t\t\tchomp $patch_line;\n+\t\t\t\t#$patch_line =~ m/^+++/;\n+\t\t\t\tif ($to{'href'}) {\n+\t\t\t\t\t$patch_line = '+++ b/' .\n+\t\t\t\t\t              $cgi->a({-href=>$to{'href'}, -class=>\"path\"},\n+\t\t\t\t\t                      esc_html($to{'file'}));\n+\t\t\t\t}\n+\t\t\t\tprint \"<div class=\\\"diff to_file\\\">$patch_line</div>\\n\";\n \n-\t\t\t#$patch_line =~ m/^+++/;\n-\t\t\t$file    = $diffinfo->{'to_file'};\n-\t\t\t$file  ||= $diffinfo->{'file'};\n-\t\t\t$file = $cgi->a({-href => href(action=>\"blob\", hash_base=>$hash,\n-\t\t\t                               hash=>$diffinfo->{'to_id'}, \nfile_name=>$file),\n-\t\t\t                -class => \"list\"}, esc_path($file));\n-\t\t\t$patch_line =~ s|b/.*|b/$file|g;\n-\t\t\tprint \"<div class=\\\"diff to_file\\\">$patch_line</div>\\n\";\n+\t\t\t}\n \n \t\t\tnext LINE;\n \t\t}\n-\t\tnext LINE if $in_header;\n \n \t\tprint format_diff_line($patch_line);\n \t}\n-- \n1.4.3.3\n"},{"id":"296224","messageId":"200610311707.43054.jnareb@gmail.com","threadId":"43063","inReplyTo":"200610301953.01875.jnareb@gmail.com","subject":"[PATCH 6/n] gitweb: Remove redundant \"blob\" links from git_difftree_body","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-10-31T16:07:42Z","receivedAt":"2006-10-31T16:07:42Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"This revert parts of commit 4777b0141a4812177390da4b6ebc9d40ac3da4b5\n  \"gitweb: Restore object-named links in item lists\"\nby Petr Baudis, which bring back \"blob\" links in difftree-raw like\npart of \"commit\" and \"commitdiff\" views, namely in git_difftree_body\nsubroutine. First, it did that incompletely: it did not add \"blob\"\nlink for added files, and added block used mixture of tabs and spaces\nfor align. Second, in \"difftree\" view the \"blob\" link is not the most\ninteresting, *contrary* to \"blob\"/\"tree\" link in \"tree\" view, so it\nshould be enough to have hidden link in the form of file name entry.\n\nSigned-off-by: Jakub Narebski <jnareb@gmail.com>\n---\nI'm still for having those object-named links in \"tree\" view.\n\nBut perhaps it would be better to add \"blob\" links for all possible\nstatuses, including added files... Pasky, Luben, Junio?\n\n gitweb/gitweb.perl |    9 ---------\n 1 files changed, 0 insertions(+), 9 deletions(-)\n\ndiff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl\nindex c22fcc5..542dbca 100755\n--- a/gitweb/gitweb.perl\n+++ b/gitweb/gitweb.perl\n@@ -1967,9 +1967,6 @@ sub git_difftree_body {\n \t\t\t\tprint $cgi->a({-href => \"#patch$patchno\"}, \"patch\");\n \t\t\t\tprint \" | \";\n \t\t\t}\n-\t\t\tprint $cgi->a({-href => href(action=>\"blob\", hash=>$diff{'from_id'},\n-\t\t\t                             hash_base=>$parent, file_name=>$diff{'file'})},\n-\t\t\t\t      \"blob\") . \" | \";\n \t\t\tprint $cgi->a({-href => href(action=>\"blame\", hash_base=>$parent,\n \t\t\t                             file_name=>$diff{'file'})},\n \t\t\t              \"blame\") . \" | \";\n@@ -2015,9 +2012,6 @@ sub git_difftree_body {\n \t\t\t\t}\n \t\t\t\tprint \" | \";\n \t\t\t}\n-\t\t\tprint $cgi->a({-href => href(action=>\"blob\", hash=>$diff{'to_id'},\n-\t\t\t\t\t\t     hash_base=>$hash, file_name=>$diff{'file'})},\n-\t\t\t\t      \"blob\") . \" | \";\n \t\t\tprint $cgi->a({-href => href(action=>\"blame\", hash_base=>$hash,\n \t\t\t                             file_name=>$diff{'file'})},\n \t\t\t              \"blame\") . \" | \";\n@@ -2058,9 +2052,6 @@ sub git_difftree_body {\n \t\t\t\t}\n \t\t\t\tprint \" | \";\n \t\t\t}\n-\t\t\tprint $cgi->a({-href => href(action=>\"blob\", hash=>$diff{'from_id'},\n-\t\t\t\t\t\t     hash_base=>$parent, file_name=>$diff{'from_file'})},\n-\t\t\t\t      \"blob\") . \" | \";\n \t\t\tprint $cgi->a({-href => href(action=>\"blame\", hash_base=>$parent,\n \t\t\t                             file_name=>$diff{'from_file'})},\n \t\t\t              \"blame\") . \" | \";\n-- \n1.4.3.3\n"},{"id":"298542","messageId":"200610311736.27910.jnareb@gmail.com","threadId":"43063","inReplyTo":"200610301953.01875.jnareb@gmail.com","subject":"[PATCH 7/n] gitweb: Output also empty patches in \"commitdiff\" view","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-10-31T16:36:27Z","receivedAt":"2006-10-31T16:36:27Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Remove skipping over empty patches (i.e. patches which consist solely\nof extended headers) in git_patchset_body, and add links to those\nheader-only patches in git_difftree_body (but not generate blobdiff\nlinks when there were no change in file contents).\n\nSigned-off-by: Jakub Narebski <jnareb@gmail.com>\n---\nAs promised...\n\n gitweb/gitweb.perl |   67 +++++++++++++++++++++-------------------------------\n 1 files changed, 27 insertions(+), 40 deletions(-)\n\ndiff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl\nindex 542dbca..e0f7a3f 100755\n--- a/gitweb/gitweb.perl\n+++ b/gitweb/gitweb.perl\n@@ -1998,19 +1998,19 @@ sub git_difftree_body {\n \t\t\tprint \"</td>\\n\";\n \t\t\tprint \"<td>$mode_chnge</td>\\n\";\n \t\t\tprint \"<td class=\\\"link\\\">\";\n-\t\t\tif ($diff{'to_id'} ne $diff{'from_id'}) { # modified\n-\t\t\t\tif ($action eq 'commitdiff') {\n-\t\t\t\t\t# link to patch\n-\t\t\t\t\t$patchno++;\n-\t\t\t\t\tprint $cgi->a({-href => \"#patch$patchno\"}, \"patch\");\n-\t\t\t\t} else {\n-\t\t\t\t\tprint $cgi->a({-href => href(action=>\"blobdiff\",\n-\t\t\t\t\t                             hash=>$diff{'to_id'}, hash_parent=>$diff{'from_id'},\n-\t\t\t\t\t                             hash_base=>$hash, hash_parent_base=>$parent,\n-\t\t\t\t\t                             file_name=>$diff{'file'})},\n-\t\t\t\t\t              \"diff\");\n-\t\t\t\t}\n-\t\t\t\tprint \" | \";\n+\t\t\tif ($action eq 'commitdiff') {\n+\t\t\t\t# link to patch\n+\t\t\t\t$patchno++;\n+\t\t\t\tprint $cgi->a({-href => \"#patch$patchno\"}, \"patch\") .\n+\t\t\t\t      \" | \";\n+\t\t\t} elsif ($diff{'to_id'} ne $diff{'from_id'}) {\n+\t\t\t\t# \"commit\" view and modified file (not onlu mode changed)\n+\t\t\t\tprint $cgi->a({-href => href(action=>\"blobdiff\",\n+\t\t\t\t                             hash=>$diff{'to_id'}, hash_parent=>$diff{'from_id'},\n+\t\t\t\t                             hash_base=>$hash, hash_parent_base=>$parent,\n+\t\t\t\t                             file_name=>$diff{'file'})},\n+\t\t\t\t              \"diff\") .\n+\t\t\t\t      \" | \";\n \t\t\t}\n \t\t\tprint $cgi->a({-href => href(action=>\"blame\", hash_base=>$hash,\n \t\t\t                             file_name=>$diff{'file'})},\n@@ -2038,19 +2038,19 @@ sub git_difftree_body {\n \t\t\t              -class => \"list\"}, esc_path($diff{'from_file'})) .\n \t\t\t      \" with \" . (int $diff{'similarity'}) . \"% similarity$mode_chng]</span></td>\\n\" .\n \t\t\t      \"<td class=\\\"link\\\">\";\n-\t\t\tif ($diff{'to_id'} ne $diff{'from_id'}) {\n-\t\t\t\tif ($action eq 'commitdiff') {\n-\t\t\t\t\t# link to patch\n-\t\t\t\t\t$patchno++;\n-\t\t\t\t\tprint $cgi->a({-href => \"#patch$patchno\"}, \"patch\");\n-\t\t\t\t} else {\n-\t\t\t\t\tprint $cgi->a({-href => href(action=>\"blobdiff\",\n-\t\t\t\t\t                             hash=>$diff{'to_id'}, hash_parent=>$diff{'from_id'},\n-\t\t\t\t\t                             hash_base=>$hash, hash_parent_base=>$parent,\n-\t\t\t\t\t                             file_name=>$diff{'to_file'}, file_parent=>$diff{'from_file'})},\n-\t\t\t\t\t              \"diff\");\n-\t\t\t\t}\n-\t\t\t\tprint \" | \";\n+\t\t\tif ($action eq 'commitdiff') {\n+\t\t\t\t# link to patch\n+\t\t\t\t$patchno++;\n+\t\t\t\tprint $cgi->a({-href => \"#patch$patchno\"}, \"patch\") .\n+\t\t\t\t      \" | \";\n+\t\t\t} elsif ($diff{'to_id'} ne $diff{'from_id'}) {\n+\t\t\t\t# \"commit\" view and modified file (not only pure rename or copy)\n+\t\t\t\tprint $cgi->a({-href => href(action=>\"blobdiff\",\n+\t\t\t\t                             hash=>$diff{'to_id'}, hash_parent=>$diff{'from_id'},\n+\t\t\t\t                             hash_base=>$hash, hash_parent_base=>$parent,\n+\t\t\t\t                             file_name=>$diff{'to_file'}, file_parent=>$diff{'from_file'})},\n+\t\t\t\t              \"diff\") .\n+\t\t\t\t      \" | \";\n \t\t\t}\n \t\t\tprint $cgi->a({-href => href(action=>\"blame\", hash_base=>$parent,\n \t\t\t                             file_name=>$diff{'from_file'})},\n@@ -2072,7 +2072,6 @@ sub git_patchset_body {\n \tmy $patch_idx = 0;\n \tmy $in_header = 0;\n \tmy $patch_found = 0;\n-\tmy $skip_patch = 0;\n \tmy $diffinfo;\n \tmy (%from, %to);\n \n@@ -2084,8 +2083,6 @@ sub git_patchset_body {\n \n \t\tif ($patch_line =~ m/^diff /) { # \"git diff\" header\n \t\t\t# beginning of patch (in patchset)\n-\t\t\t$skip_patch = 0;\n-\n \t\t\tif ($patch_found) {\n \t\t\t\t# close previous patch\n \t\t\t\tprint \"</div>\\n\"; # class=\"patch\"\n@@ -2116,13 +2113,6 @@ sub git_patchset_body {\n \t\t\t}\n \t\t\t$patch_idx++;\n \n-\t\t\t# for now we skip empty patches\n-\t\t\tif ($diffinfo->{'from_id'} eq $diffinfo->{'to_id'}) { # no change\n-\t\t\t\t$in_header = 1;\n-\t\t\t\t$skip_patch = 0;\n-\t\t\t\tnext LINE;\n-\t\t\t}\n-\n \t\t\t# print \"git diff\" header\n \t\t\t$patch_line =~ s!^(diff (.*?) )a/.*$!$1!;\n \t\t\tif ($from{'href'}) {\n@@ -2143,10 +2133,7 @@ sub git_patchset_body {\n \t\t\tprint \"<div class=\\\"diff extended_header\\\">\\n\";\n \t\t\t$in_header = 1;\n \t\t\tnext LINE;\n-\t\t} else {\n-\t\t\t# actual skipping of empty patches\n-\t\t\tnext LINE if $skip_patch;\n-\t\t} # start of patch in patchset\n+\t\t}\n \n \t\tif ($in_header) {\n \t\t\tif ($patch_line !~ m/^---/) {\n-- \n1.4.3.3\n"},{"id":"297359","messageId":"200610311743.14032.jnareb@gmail.com","threadId":"43063","inReplyTo":"200610301953.01875.jnareb@gmail.com","subject":"[PATCH 8/n] gitweb: Fix two issues with quoted filenames in git_patchset_body","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-10-31T16:43:13Z","receivedAt":"2006-10-31T16:43:13Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"This fixes the following (minor) bugs:\n* gitweb didn't remove quoted filenames from \"git diff\" header\n* the filename in to-file +++ header used esc_html not esc_path\n\nSigned-off-by: Jakub Narebski <jnareb@gmail.com>\n---\n gitweb/gitweb.perl |    4 ++--\n 1 files changed, 2 insertions(+), 2 deletions(-)\n\ndiff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl\nindex e0f7a3f..837b88e 100755\n--- a/gitweb/gitweb.perl\n+++ b/gitweb/gitweb.perl\n@@ -2114,7 +2114,7 @@ sub git_patchset_body {\n \t\t\t$patch_idx++;\n \n \t\t\t# print \"git diff\" header\n-\t\t\t$patch_line =~ s!^(diff (.*?) )a/.*$!$1!;\n+\t\t\t$patch_line =~ s!^(diff (.*?) )\"?a/.*$!$1!;\n \t\t\tif ($from{'href'}) {\n \t\t\t\t$patch_line .= $cgi->a({-href => $from{'href'}, -class => \"path\"},\n \t\t\t\t                       'a/' . esc_path($from{'file'}));\n@@ -2191,7 +2191,7 @@ sub git_patchset_body {\n \t\t\t\tif ($to{'href'}) {\n \t\t\t\t\t$patch_line = '+++ b/' .\n \t\t\t\t\t              $cgi->a({-href=>$to{'href'}, -class=>\"path\"},\n-\t\t\t\t\t                      esc_html($to{'file'}));\n+\t\t\t\t\t                      esc_path($to{'file'}));\n \t\t\t\t}\n \t\t\t\tprint \"<div class=\\\"diff to_file\\\">$patch_line</div>\\n\";\n \n-- \n1.4.3.3\n"},{"id":"297498","messageId":"200610311753.20711.jnareb@gmail.com","threadId":"43063","inReplyTo":"200610302229.06957.jnareb@gmail.com","subject":"Re: [PATCH 4/n] gitweb: Secure against commit-ish/tree-ish with the same name as path","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-10-31T16:53:20Z","receivedAt":"2006-10-31T16:53:20Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Jakub Narebski wrote:\n> @@ -2970,7 +2972,7 @@ sub git_tree {\n>                 }\n>         }\n>         $/ = \"\\0\";\n> -       open my $fd, \"-|\", git_cmd(), \"ls-tree\", '-z', $hash\n> +       open my $fd, \"-|\", git_cmd(), \"ls-tree\", '-z', $hash, \"--\"\n>                 or die_error(undef, \"Open git-ls-tree failed\");\n>         my @entries = map { chomp; $_ } <$fd>;\n>         close $fd or die_error(undef, \"Reading tree failed\");\n\nPlease remove this chunk from patch!. It makes gitweb \"tree\" view\nempty. I have forgot that git-ls-tree _requires_ <tree-ish> so there\nis no way to mistake pathspec with <tree-ish>.\n\nBit overeager adding of \"--\"... \n-- \nJakub Narebski\n"},{"id":"294945","messageId":"7vejsoovxu.fsf@assigned-by-dhcp.cox.net","threadId":"43063","inReplyTo":"200610311753.20711.jnareb@gmail.com","subject":"Re: [PATCH 4/n] gitweb: Secure against commit-ish/tree-ish with the same name as path","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-11-01T00:24:45Z","receivedAt":"2006-11-01T00:24:45Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jakub Narebski <jnareb@gmail.com> writes:\n\n> Please remove this chunk from patch!. It makes gitweb \"tree\" view\n> empty. I have forgot that git-ls-tree _requires_ <tree-ish> so there\n> is no way to mistake pathspec with <tree-ish>.\n\nTo be honest, I dislike these */n series where the the end is\nunknown.  It just confuses me what's still surviving, what's\nalready shot down, and what's being rerolled.\n\nLet's step back a bit and see if we share the same view as to\nthe status of each one:\n\n[PATCH/RFC 1/n] gitweb: Better git-unquoting and gitweb-quoting of p...\n\nMarked preliminary, perhaps need some discussion and rerolling\nbut I haven't looked at it.\n\n[PATCH 2/n] gitweb: Use '&iquot;' instead of '?' in esc_path\n\nDiscussed; we agreed that showing byte values in different\ncolors is preferable.  Waiting for re-roll.\n\n[PATCH 3/n] gitweb: Use 's' regexp modifier to secure against filena...\n\nI looked at it although haven't said anything yet.  Probably a\nsafe and good change but I wonder how LF at the end of the line\nmatches /...(.+)$/s pattern; iow, if we do not use -z does it\nstill do the right thing?  Otherwise I suspect you would perhaps\nneed to chomp?\n\n[PATCH 4/n] gitweb: Secure against commit-ish/tree-ish with the same...\n\nGood fix and even improves readability; will apply after\ndropping -- from ls-tree args.\n\n[PATCH 5/n] [take 3] gitweb: New improved patchset view\n[PATCH 6/n] gitweb: Remove redundant \"blob\" links from git_difftree_...\n[PATCH 7/n] gitweb: Output also empty patches in \"commitdiff\" view\n[PATCH 8/n] gitweb: Fix two issues with quoted filenames in git_patc...\n\nHaven't looked at them and I do not think people have had enough\ntime to comment on them yet.\n"},{"id":"294820","messageId":"200611010140.56834.jnareb@gmail.com","threadId":"43063","inReplyTo":"7vejsoovxu.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH 4/n] gitweb: Secure against commit-ish/tree-ish with the same name as path","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-11-01T00:40:56Z","receivedAt":"2006-11-01T00:40:56Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Junio C Hamano wrote:\n> \n> To be honest, I dislike these */n series where the the end is\n> unknown.  It just confuses me what's still surviving, what's\n> already shot down, and what's being rerolled.\n\nWell, it looks like this patch series is closing to final patch.\nThe \"New improved patchset view\" is done.\n \n> Let's step back a bit and see if we share the same view as to\n> the status of each one:\n> \n> [PATCH/RFC 1/n] gitweb: Better git-unquoting and gitweb-quoting of p...\n> \n> Marked preliminary, perhaps need some discussion and rerolling\n> but I haven't looked at it.\n\nI'm not sure if without this patch (well, the unquote part) gitweb\ncan work with filenames which git quotes using escape sequences,\nlike \", \\, LF, TAB. Former version didn't unquote fully, and it\npassed partially unquoted filename to git.\n\n> [PATCH 2/n] gitweb: Use '&iquot;' instead of '?' in esc_path\n> \n> Discussed; we agreed that showing byte values in different\n> colors is preferable.  Waiting for re-roll.\n\nThe problem with using text color or background color is that\nthe filenames tends to be shown with different color and background\ncolor: \"tree\" view, parts of difftree, parts of diff header, etc.\nPerhaps text-decoration: overline;? Just kidding...\n\n> [PATCH 3/n] gitweb: Use 's' regexp modifier to secure against filena...\n> \n> I looked at it although haven't said anything yet.  Probably a\n> safe and good change but I wonder how LF at the end of the line\n> matches /...(.+)$/s pattern; iow, if we do not use -z does it\n> still do the right thing?  Otherwise I suspect you would perhaps\n> need to chomp?\n\nWe always pass chomped lines. First chunk is unnecessary (we care only\nfor type), without second \"tree\" view look strange for files with\nembedded newline in filename.\n\n> [PATCH 4/n] gitweb: Secure against commit-ish/tree-ish with the same...\n> \n> Good fix and even improves readability; will apply after\n> dropping -- from ls-tree args.\n\nAs I said, noticed while testing gitweb with strange filenames\nin 'gitweb/test' branch.\n\n> [PATCH 5/n] [take 3] gitweb: New improved patchset view\n> [PATCH 6/n] gitweb: Remove redundant \"blob\" links from git_difftree_...\n> [PATCH 7/n] gitweb: Output also empty patches in \"commitdiff\" view\n> [PATCH 8/n] gitweb: Fix two issues with quoted filenames in git_patc...\n> \n> Haven't looked at them and I do not think people have had enough\n> time to comment on them yet.\n\nWell, patch 5 and 8 could be collapsed.\n\n-- \nJakub Narebski\n"},{"id":"296427","messageId":"200611011433.22279.jnareb@gmail.com","threadId":"43063","inReplyTo":"200610301953.01875.jnareb@gmail.com","subject":"[PATCH 9/n] gitweb: Better support for non-CSS aware web browsers","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-11-01T13:33:21Z","receivedAt":"2006-11-01T13:33:21Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Add option to replace SPC (' ') with hard (non-breakable) space HTML\nentity '&nbsp;' in esc_html subroutine.\n\nReplace ' ' with '&nbsp;' for the code/diff display part in git_blob\nand git_patchset_body; this is to be able to view code and diffs in\nweb browsers which doesn't understand \"white-space: pre;\" CSS\ndeclaration.\n\nSigned-off-by: Jakub Narebski <jnareb@gmail.com>\n---\nFor people who want to use non-CSS aware browsers, like w3m, elinks, links\ntext browsers, for looking at \"blob\" and \"commitdiff\"/\"blobdiff\" views\nof gitweb.\n\nHTH.\n\n gitweb/gitweb.perl |   11 ++++++++---\n 1 files changed, 8 insertions(+), 3 deletions(-)\n\ndiff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl\nindex 5c82093..b8fcafc 100755\n--- a/gitweb/gitweb.perl\n+++ b/gitweb/gitweb.perl\n@@ -554,12 +554,17 @@ sub esc_url {\n }\n \n # replace invalid utf8 character with SUBSTITUTION sequence\n-sub esc_html {\n+sub esc_html ($;%) {\n \tmy $str = shift;\n+\tmy %opts = @_;\n+\n \t$str = to_utf8($str);\n \t$str = escapeHTML($str);\n \t$str =~ s/\\014/^L/g; # escape FORM FEED (FF) character (e.g. in COPYING file)\n \t$str =~ s/\\033/^[/g; # \"escape\" ESCAPE (\\e) character (e.g. commit 20a3847d8a5032ce41f90dcc68abfb36e6fee9b1)\n+\tif ($opts{'-nbsp'}) {\n+\t\t$str =~ s/ /&nbsp;/g;\n+\t}\n \treturn $str;\n }\n \n@@ -840,7 +845,7 @@ sub format_diff_line {\n \t\t$diff_class = \" incomplete\";\n \t}\n \t$line = untabify($line);\n-\treturn \"<div class=\\\"diff$diff_class\\\">\" . esc_html($line) . \"</div>\\n\";\n+\treturn \"<div class=\\\"diff$diff_class\\\">\" . esc_html($line, -nbsp=>1) . \"</div>\\n\";\n }\n \n ## ----------------------------------------------------------------------\n@@ -2985,7 +2990,7 @@ sub git_blob {\n \t\t$nr++;\n \t\t$line = untabify($line);\n \t\tprintf \"<div class=\\\"pre\\\"><a id=\\\"l%i\\\" href=\\\"#l%i\\\" class=\\\"linenr\\\">%4i</a> %s</div>\\n\",\n-\t\t       $nr, $nr, $nr, esc_html($line);\n+\t\t       $nr, $nr, $nr, esc_html($line, -nbsp=>1);\n \t}\n \tclose $fd\n \t\tor print \"Reading blob failed.\\n\";\n-- \n1.4.3.3\n"},{"id":"298381","messageId":"200611011436.08715.jnareb@gmail.com","threadId":"43063","inReplyTo":"200610301953.01875.jnareb@gmail.com","subject":"[PATCH 10/n] gitweb: New improved formatting of chunk header in diff","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-11-01T13:36:08Z","receivedAt":"2006-11-01T13:36:08Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"If we have provided enough info, and diff is not combined diff,\nand if provided diff line is chunk header, then:\n* split chunk header into .chunk_info and .section span elements,\n  first containing proper chunk header, second section heading\n  (aka. which function), for separate styling: the proper chunk\n  header is on non-white background, section heading part uses\n  slightly lighter color.\n* hyperlink from-file-range to starting line of from-file, if file\n  was not created.\n* hyperlink to-file-range to starting line of to-file, if file\n  was not deleted.\nLinks are of invisible variety (and \"list\" class).\n\nSigned-off-by: Jakub Narebski <jnareb@gmail.com>\n---\nAs usual, you can check out the new version of gitweb at work at my\nweb page:\n  http://roke_._dyndns_._info/cgi-bin/gitweb/gitweb.cgi\n\nThe actual formatting is open for discussion.\n\n gitweb/gitweb.css  |   13 +++++++++++++\n gitweb/gitweb.perl |   18 +++++++++++++++++-\n 2 files changed, 30 insertions(+), 1 deletions(-)\n\ndiff --git a/gitweb/gitweb.css b/gitweb/gitweb.css\nindex 87dbc52..41c3084 100644\n--- a/gitweb/gitweb.css\n+++ b/gitweb/gitweb.css\n@@ -327,11 +327,13 @@ div.diff.extended_header {\n \tpadding: 2px 0px 2px 0px;\n }\n \n+div.diff a.list,\n div.diff a.path,\n div.diff a.hash {\n \ttext-decoration: none;\n }\n \n+div.diff a.list:hover,\n div.diff a.path:hover,\n div.diff a.hash:hover {\n \ttext-decoration: underline;\n@@ -355,14 +357,25 @@ div.diff.rem {\n \tcolor: #cc0000;\n }\n \n+div.diff.chunk_header a,\n div.diff.chunk_header {\n \tcolor: #990099;\n+}\n \n+div.diff.chunk_header {\n \tborder: dotted #ffe0ff;\n \tborder-width: 1px 0px 0px 0px;\n \tmargin-top: 2px;\n }\n \n+div.diff.chunk_header span.chunk_info {\n+\tbackground-color: #ffeeff;\n+}\n+\n+div.diff.chunk_header span.section {\n+\tcolor: #aa22aa;\n+}\n+\n div.diff.incomplete {\n \tcolor: #cccccc;\n }\ndiff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl\nindex b8fcafc..a7739af 100755\n--- a/gitweb/gitweb.perl\n+++ b/gitweb/gitweb.perl\n@@ -830,6 +830,7 @@ sub format_subject_html {\n \n sub format_diff_line {\n \tmy $line = shift;\n+\tmy ($from, $to) = @_;\n \tmy $char = substr($line, 0, 1);\n \tmy $diff_class = \"\";\n \n@@ -845,6 +846,21 @@ sub format_diff_line {\n \t\t$diff_class = \" incomplete\";\n \t}\n \t$line = untabify($line);\n+\tif ($from && $to && $line =~ m/^\\@{2} /) {\n+\t\tmy ($from_text, $from_start, $from_lines, $to_text, $to_start, $to_lines, $section) =\n+\t\t\t$line =~ m/^\\@{2} (-(\\d+),(\\d+)) (\\+(\\d+),(\\d+)) \\@{2}(.*)$/;\n+\t\tif ($from->{'href'}) {\n+\t\t\t$from_text = $cgi->a({-href=>\"$from->{'href'}#l$from_start\",\n+\t\t\t                     -class=>\"list\"}, $from_text);\n+\t\t}\n+\t\tif ($to->{'href'}) {\n+\t\t\t$to_text   = $cgi->a({-href=>\"$to->{'href'}#l$to_start\",\n+\t\t\t                     -class=>\"list\"}, $to_text);\n+\t\t}\n+\t\t$line = \"<span class=\\\"chunk_info\\\">@@ $from_text $to_text @@</span>\" .\n+\t\t        \"<span class=\\\"section\\\">\" . esc_html($section, -nbsp=>1) . \"</span>\";\n+\t\treturn \"<div class=\\\"diff$diff_class\\\">$line</div>\\n\";\n+\t}\n \treturn \"<div class=\\\"diff$diff_class\\\">\" . esc_html($line, -nbsp=>1) . \"</div>\\n\";\n }\n \n@@ -2205,7 +2221,7 @@ sub git_patchset_body {\n \t\t\tnext LINE;\n \t\t}\n \n-\t\tprint format_diff_line($patch_line);\n+\t\tprint format_diff_line($patch_line, \\%from, \\%to);\n \t}\n \tprint \"</div>\\n\" if $patch_found; # class=\"patch\"\n \n-- \n1.4.3.3\n"},{"id":"294964","messageId":"20061101133844.GG20017@pasky.or.cz","threadId":"43063","inReplyTo":"200611011433.22279.jnareb@gmail.com","subject":"Re: [PATCH 9/n] gitweb: Better support for non-CSS aware web browsers","fromName":"Petr Baudis","fromEmail":"pasky@suse.cz","sentAt":"2006-11-01T13:38:44Z","receivedAt":"2006-11-01T13:38:44Z","isPatch":true,"sender":{"key":"pasky@ucw.cz","avatar":"https://avatars.githubusercontent.com/u/18439?v=4"},"body":"Dear diary, on Wed, Nov 01, 2006 at 02:33:21PM CET, I got a letter\nwhere Jakub Narebski <jnareb@gmail.com> said that...\n> For people who want to use non-CSS aware browsers, like w3m, elinks, links\n> text browsers, for looking at \"blob\" and \"commitdiff\"/\"blobdiff\" views\n> of gitweb.\n\nJFYI, ELinks supports CSS. (Well, not completely, but it does handle\nwhite-space: pre.)\n\n-- \n\t\t\t\tPetr \"Pasky\" Baudis\nStuff: http://pasky.or.cz/\n#!/bin/perl -sp0777i<X+d*lMLa^*lN%0]dsXx++lMlN/dsM0<j]dsj\n$/=unpack('H*',$_);$_=`echo 16dio\\U$k\"SK$/SM$n\\EsN0p[lN*1\n"},{"id":"295226","messageId":"200611011952.32979.jnareb@gmail.com","threadId":"43063","inReplyTo":"200610301953.01875.jnareb@gmail.com","subject":"Re: [PATCH 00/10] gitweb: Better quoting and New improved patchset view","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-11-01T18:52:32Z","receivedAt":"2006-11-01T18:52:32Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Jakub Narebski wrote:\n> This series of patches is meant to introduce \n> \"New improved patchset view\" in part-by-part\n> case.\n\nAnd thus endeth \"New inproved patchset view\" saga.\n\nPatches in series:\n [PATCH 01/10] gitweb: Better git-unquoting and gitweb-quoting of\n               pathnames\n [PATCH 02/10] gitweb: Use '&iquot;' instead of '?' in esc_path\n [PATCH 03/10] gitweb: Use 's' regexp modifier to secure against\n               filenames with LF\n [PATCH 04/10] gitweb: Secure against commit-ish/tree-ish with\n               the same name as path\n [PATCH 05/10] gitweb: New improved patchset view\n [PATCH 06/10] gitweb: Remove redundant \"blob\" links from\n               git_difftree_body\n [PATCH 07/10] gitweb: Output also empty patches in \"commitdiff\" view\n [PATCH 08/10] gitweb: Fix two issues with quoted filenames\n               in git_patchset_body\n [PATCH 09/10] gitweb: Better support for non-CSS aware web browsers\n [PATCH 10/10] gitweb: New improved formatting of chunk header in diff\n\nDiffstat:\n gitweb/gitweb.css  |   79 +++++++++--\n gitweb/gitweb.perl |  378 ++++++++++++++++++++++++++++++++--------------------\n 2 files changed, 303 insertions(+), 154 deletions(-)\n\nShortlog:\nJakub Narebski (11):\n      gitweb: Better git-unquoting and gitweb-quoting of pathnames\n      gitweb: Use '&iquot;' instead of '?' in esc_path\n      gitweb: Use 's' regexp modifier to secure against filenames with LF\n      gitweb: Secure against commit-ish/tree-ish with the same name as path\n      gitweb: New improved patchset view\n      gitweb: Remove redundant \"blob\" links from git_difftree_body\n      gitweb: Output also empty patches in \"commitdiff\" view\n      gitweb: Fix two issues with quoted filenames in git_patchset_body\n[*1*] gitweb: Remove \"--\" from \"git ls-tree -z <hash> --\", added overeagerily\n      gitweb: Better support for non-CSS aware web browsers\n      gitweb: New improved formatting of chunk header in diff\n\n[*1*] Not send as patch itself, but as comment about patch\n-- \nJakub Narebski\n"},{"id":"294870","messageId":"7vac3awtj4.fsf@assigned-by-dhcp.cox.net","threadId":"43063","inReplyTo":"200611010140.56834.jnareb@gmail.com","subject":"Re: [PATCH 4/n] gitweb: Secure against commit-ish/tree-ish with the same name as path","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-11-02T01:01:51Z","receivedAt":"2006-11-02T01:01:51Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jakub Narebski <jnareb@gmail.com> writes:\n\n>> [PATCH/RFC 1/n] gitweb: Better git-unquoting and gitweb-quoting of p...\n>> \n>> Marked preliminary, perhaps need some discussion and rerolling\n>> but I haven't looked at it.\n>\n> I'm not sure if without this patch (well, the unquote part) gitweb\n> can work with filenames which git quotes using escape sequences,\n\nI am reasonably sure it wouldn't, and it sounded like you wanted\nto fix it better than the preliminary one, so I think we are in\nagreement.\n\n>> [PATCH 2/n] gitweb: Use '&iquot;' instead of '?' in esc_path\n>> \n>> Discussed; we agreed that showing byte values in different\n>> colors is preferable.  Waiting for re-roll.\n>\n> The problem with using text color or background color is that\n> the filenames tends to be shown with different color and background\n> color: \"tree\" view, parts of difftree, parts of diff header, etc.\n> Perhaps text-decoration: overline;? Just kidding...\n\nUse of overstrike may actually not be a bad thing.  It _is_\nunusual situation after all.\n\n>> [PATCH 3/n] gitweb: Use 's' regexp modifier to secure against filena...\n>> \n>> I looked at it although haven't said anything yet.  Probably a\n>> safe and good change but I wonder how LF at the end of the line\n>> matches /...(.+)$/s pattern; iow, if we do not use -z does it\n>> still do the right thing?  Otherwise I suspect you would perhaps\n>> need to chomp?\n>\n> We always pass chomped lines. First chunk is unnecessary (we care only\n> for type), without second \"tree\" view look strange for files with\n> embedded newline in filename.\n\nThe codepath affected by the first chunk does not chomp, which\nwas what I was referring to.  So in the meantime will apply only\nthe second hunk.\n\n>> [PATCH 4/n] gitweb: Secure against commit-ish/tree-ish with the same...\n>> \n>> Good fix and even improves readability; will apply after\n>> dropping -- from ls-tree args.\n\nI just applied this.  I'll be pushing out a \"master\" update\nsometime today, and do not expect to be able to get to your \"n\nturned out to be ten\" series, so it might be worthwhile to\nreroll the remaining bits that you still care about on top of\nwhat I push out tonight to make sure we are on the same page.\n\nPreferably:\n\n - you should avoid making a series out of more-or-less\n   unrelated things;\n\n - if you are doing related things in one series, do not send\n   half-baked early parts out until you are finished and are\n   confident with it.  If you do not know how many patches you\n   need to complete that logically single topic yet, that is a\n   sure sign that you are not done.  Instead, finish writing and\n   testing it, and if your test finds an earlier mistake,\n   especially a trivial one, go back and fix it in the earlier\n   patch in the series.  Everybody makes mistakes so fixing up\n   before submission is a norm, and other people do not have to\n   be forced to see your \"oops\" in the development history.\n\nThanks.\n"},{"id":"297620","messageId":"200611020949.34276.jnareb@gmail.com","threadId":"43063","inReplyTo":"7vac3awtj4.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH 4/n] gitweb: Secure against commit-ish/tree-ish with the same name as path","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-11-02T08:49:33Z","receivedAt":"2006-11-02T08:49:33Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Junio C Hamano wrote:\n\n> I'll be pushing out a \"master\" update\n> sometime today, and do not expect to be able to get to your \"n\n> turned out to be ten\" series, so it might be worthwhile to\n> reroll the remaining bits that you still care about on top of\n> what I push out tonight to make sure we are on the same page.\n\nI'll wait a while if there are any comments (for example on formatting\nused), and resend cleaned-up series.\n\n> Preferably:\n>\n>  - you should avoid making a series out of more-or-less\n>    unrelated things;\n\nWell, truly unrelated were adding \"--\" to secure against ref with\nthe same name as path in the repository (but it was discovered\nduring testing the series) and replacing ' ' with '&nbsp;' in blob\nand diff body for non-CSS aware browsers.\n\nBetter quoting and unquoting was needed for better commitdiff view.\nAh, well, perhaps it is unrelated.\n\nSecuring against filenames with LF for example has sense only if\nthere can be filenames with LF, and earlier gitweb unquoted it halfway\nleaving '\\n' instead of LF.\n\n>  - if you are doing related things in one series, do not send\n>    half-baked early parts out until you are finished and are\n>    confident with it.\n\nI've send series early to get some comments, but I see while I got\nsome comments on \"take 1\" and \"take 2\" on _single_ \"new commitdiff\"\nRFC patch, I got comments only about half-baked '&iquot;' idea.\n-- \nJakub Narebski\n"},{"id":"297032","messageId":"7vhcxhjbog.fsf@assigned-by-dhcp.cox.net","threadId":"43063","inReplyTo":"200611020949.34276.jnareb@gmail.com","subject":"Re: [PATCH 4/n] gitweb: Secure against commit-ish/tree-ish with the same name as path","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-11-03T06:18:07Z","receivedAt":"2006-11-03T06:18:07Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jakub Narebski <jnareb@gmail.com> writes:\n\n> Junio C Hamano wrote:\n>\n>> I'll be pushing out a \"master\" update\n>> sometime today, and do not expect to be able to get to your \"n\n>> turned out to be ten\" series, so it might be worthwhile to\n>> reroll the remaining bits that you still care about on top of\n>> what I push out tonight to make sure we are on the same page.\n>\n> I'll wait a while if there are any comments (for example on formatting\n> used), and resend cleaned-up series.\n> ...\n> I've send series early to get some comments, but I see while I got\n> some comments on \"take 1\" and \"take 2\" on _single_ \"new commitdiff\"\n> RFC patch, I got comments only about half-baked '&iquot;' idea.\n\nWell, I think some of the major reasons you did not get any\nresponse were:\n\n (1) it was unclear where it started, where it was heading to,\n     and where it ended until you sent out \"by the way n=10\"\n     message at the end;\n\n (2) the first major oand interesting one in the series (5/n)\n     were linewrapped and could not be applied;\n\nand it is rather hard to comment on gitweb changes unless you\nview two instances of gitweb output side-by-side for before and\nafter each patch.\n\nI'd see if I can add some constructive comments on patches 5-10\ntonight, but I'm in the middle of other things so don't hold\nyour breath ;-).\n"},{"id":"298131","messageId":"7v3b91jalp.fsf@assigned-by-dhcp.cox.net","threadId":"43063","inReplyTo":"200610311707.43054.jnareb@gmail.com","subject":"Re: [PATCH 6/n] gitweb: Remove redundant \"blob\" links from git_difftree_body","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-11-03T06:41:22Z","receivedAt":"2006-11-03T06:41:22Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jakub Narebski <jnareb@gmail.com> writes:\n\n> ... First, it did that incompletely: it did not add \"blob\"\n> link for added files, and added block used mixture of tabs and spaces\n> for align. Second, in \"difftree\" view the \"blob\" link is not the most\n> interesting, *contrary* to \"blob\"/\"tree\" link in \"tree\" view, so it\n> should be enough to have hidden link in the form of file name entry.\n\nI think these \"blob\" links are good thing to have, and if you\nthink the earlier work was incomplete and know some cases are\nnot covered I think it would be better to help completing it\nrather than reverting.\n\nI do not understand why you feel \"blob\" is not the most\ninteresting.  Often, when it is not obvious if a patch is\ncorrect only with the context, it is useful to view the whole\npostimage after applying the patch, and the \"blob\" link helps\nthat.\n"},{"id":"293829","messageId":"7vlkmtgd3o.fsf@assigned-by-dhcp.cox.net","threadId":"43063","inReplyTo":"200610301958.23334.jnareb@gmail.com","subject":"Re: [PATCH/RFC 1/n] gitweb: Better git-unquoting and gitweb-quoting of pathnames","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-11-03T08:15:39Z","receivedAt":"2006-11-03T08:15:39Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jakub Narebski <jnareb@gmail.com> writes:\n\n> diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl\n> index ec46b80..a15e916 100755\n> --- a/gitweb/gitweb.perl\n> +++ b/gitweb/gitweb.perl\n> @@ -563,12 +563,42 @@ sub esc_html {\n>  \treturn $str;\n>  }\n>  \n> +# quote unsafe characters and escape filename to HTML\n> +sub esc_path {\n> +\tmy $str = shift;\n> +\t$str = esc_html($str);\n> +\t$str =~ s/[[:cntrl:]\\a\\b\\e\\f\\n\\r\\t\\011]/?/g; # like --hide-control-chars in ls\n> +\treturn $str;\n> +}\n> +\n\nWhen you say \"[:cntrl:]\" do you need to say anything more?\n\nI was initially puzzled by \"\\t\\011\" bit, but I realize that is a\nbug that is consistent with the next part I'll comment on.\n\n>  # git may return quoted and escaped filenames\n>  sub unquote {\n>  \tmy $str = shift;\n> +\n> +\tsub unq {\n> +\t\tmy $seq = shift;\n> +\t\tmy %es = (\n> +\t\t\t't' => \"\\t\", # tab            (HT, TAB)\n> +\t\t\t'n' => \"\\n\", # newline        (NL)\n> +\t\t\t'r' => \"\\r\", # return         (CR)\n> +\t\t\t'f' => \"\\f\", # form feed      (FF)\n> +\t\t\t'b' => \"\\b\", # backspace      (BS)\n> +\t\t\t'a' => \"\\a\", # alarm (bell)   (BEL)\n> +\t\t\t#'e' => \"\\e\", # escape        (ESC)\n> +\t\t\t'v' => \"\\011\", # vertical tab (VT)\n> +\t\t);\n> +\n> +\t\t# octal char sequence\n> +\t\treturn chr(oct($seq))  if ($seq =~ m/^[0-7]{1,3}$/);\n> +\t\t# C escape sequence (this includes '\\n' (LF) and '\\t' (TAB))\n> +\t\treturn $es{$seq}       if ($seq =~ m/^[abefnrtv]$/);\n\nProblems in this part of the code X-<.\n\n * Was there a reason not to unwrap '\\e' to \"\\e\"?\n\n * The vertical tab is \\013 (decimal 11), not \\011 (which is TAB).\n\n * The name and the abbreviated name of the character \"\\n\" are\n   \"line feed\" and \"LF\"; I personally do not think these\n   character name comments are needed in this part of the code,\n   but I do not object if you want to have them there, as long\n   as you spell them correctly. cf. ISO/IEC 6429:1992 or\n   http://www.unicode.org/charts/PDF/U0000.pdf for example.\n\n * The hash %es and the pattern /[abef...]/ must be kept in\n   sync; it is a maintenance nightmare,\n\n * Worse yet, they do not agree even in this initial version,\n   which proves the previous point.\n\nPerhaps this is better written as:\n\n\tif (exists $es{$seq}) {\n        \treturn $es{$seq};\n\t}\n\nThe rest must have been a lot of work to sift through esc_html\nand identify which is path and which is not.  Much appreciated\nand expect a cleaned up patch to be applied.\n"},{"id":"295112","messageId":"7vlkmseutr.fsf@assigned-by-dhcp.cox.net","threadId":"43063","inReplyTo":"7vhcxhjbog.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH 4/n] gitweb: Secure against commit-ish/tree-ish with the same name as path","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-11-03T09:35:44Z","receivedAt":"2006-11-03T09:35:44Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <junkio@cox.net> writes:\n\n> I'd see if I can add some constructive comments on patches 5-10\n> tonight, but I'm in the middle of other things so don't hold\n> your breath ;-).\n\n7 and 9 look obviously good, so I've applied them without\nothers.\n\n        gitweb: Output also empty patches in \"commitdiff\" view\n        gitweb: Better support for non-CSS aware web browsers\n\n5 is terminally linewrapped and rather big to comment on without\ncomparing pre- and post- patch outputs, so I'll refrain from\ncommenting on it.  8 is \"oops, I made a mistake when I did 5\",\nwhich discourages me even more from looking at 5 X-<.\n"},{"id":"296833","messageId":"200611031126.05080.jnareb@gmail.com","threadId":"43063","inReplyTo":"200610311522.32228.jnareb@gmail.com","subject":"[PATCH 5/10] gitweb: New improved patchset view","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-11-03T10:26:04Z","receivedAt":"2006-11-03T10:26:04Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Replace \"gitweb diff header\" with its full sha1 of blobs and replace\nit by \"git diff\" header and extended diff header. Change also somewhat\nhighlighting of diffs.\n\nAdded `file_type_long' subroutine to convert file mode in octal to\nfile type description (only for file modes which used by git).\n\nChanges:\n* \"gitweb diff header\" which looked for example like below:\n    file:_<sha1 before>_ -> file:_<sha1 after>_\n  where 'file' is file type and '<sha1>' is full sha1 of blob is\n  changed to\n    diff --git _a/<file before>_ _b/<file after>_\n  In both cases links are visible and use default link style. If file\n  is added, a/<file> is not hyperlinked, if file is deleted, b/<file>\n  is not hyperlinked.\n* there is added \"extended diff header\", with <path> and <hash>\n  hyperlinked (and <hash> shortened to 7 characters), and <mode>\n  explained: '<mode>' is extended to '<mode> (<file type description>)',\n  where added text is slightly lighter to easy distinguish that it\n  was added (and it is difference from git-diff output).\n* from-file/to-file two-line header lines have slightly darker color\n  than removed/added lines.\n* chunk header has now delicate line above for easier finding chunk\n  boundary, and top margin of 2px, both barely visible.\n\nSigned-off-by: Jakub Narebski <jnareb@gmail.com>\n---\nI'm very sorry, previous version was linewrapped.\n\nAs usual, you can see new gitweb in action (after all the series,\nincluding this patch) at my site\n  http://roke . dyndns . info/cgi-bin/gitweb/gitweb.cgi\n(anti-anti-spam protected against \"DOT info\" being vger banned word).\n\nYou can doenload and view snapshots at:\n  http://repo.or.cz/w/git/jnareb-git.git/gitweb/test:gitweb/snapshots/\n(before means current 'master' gitweb, middle means after this patch,\nafter means after all patches in the series).\n\n gitweb/gitweb.css  |   66 +++++++++++++++----\n gitweb/gitweb.perl |  187 ++++++++++++++++++++++++++++++++++------------------\n 2 files changed, 176 insertions(+), 77 deletions(-)\n\ndiff --git a/gitweb/gitweb.css b/gitweb/gitweb.css\nindex 0eda982..87dbc52 100644\n--- a/gitweb/gitweb.css\n+++ b/gitweb/gitweb.css\n@@ -291,40 +291,82 @@ td.mode {\n \tfont-family: monospace;\n }\n \n-div.diff a.list {\n+/* styling of diffs (patchsets): commitdiff and blobdiff views */\n+div.diff.header,\n+div.diff.extended_header {\n+\twhite-space: normal;\n+}\n+\n+div.diff.header {\n+\tfont-weight: bold;\n+\n+\tbackground-color: #edece6;\n+\n+\tmargin-top: 4px;\n+\tpadding: 4px 0px 2px 0px;\n+\tborder: solid #d9d8d1;\n+\tborder-width: 1px 0px 1px 0px;\n+}\n+\n+div.diff.header a.path {\n+\ttext-decoration: underline;\n+}\n+\n+div.diff.extended_header,\n+div.diff.extended_header a.path,\n+div.diff.extended_header a.hash {\n+\tcolor: #777777;\n+}\n+\n+div.diff.extended_header .info {\n+\tcolor: #b0b0b0;\n+}\n+\n+div.diff.extended_header {\n+\tbackground-color: #f6f5ee;\n+\tpadding: 2px 0px 2px 0px;\n+}\n+\n+div.diff a.path,\n+div.diff a.hash {\n \ttext-decoration: none;\n }\n \n-div.diff a.list:hover {\n+div.diff a.path:hover,\n+div.diff a.hash:hover {\n \ttext-decoration: underline;\n }\n \n-div.diff.to_file a.list,\n-div.diff.to_file,\n+div.diff.to_file a.path,\n+div.diff.to_file {\n+\tcolor: #007000;\n+}\n+\n div.diff.add {\n \tcolor: #008800;\n }\n \n-div.diff.from_file a.list,\n-div.diff.from_file,\n+div.diff.from_file a.path,\n+div.diff.from_file {\n+\tcolor: #aa0000;\n+}\n+\n div.diff.rem {\n \tcolor: #cc0000;\n }\n \n div.diff.chunk_header {\n \tcolor: #990099;\n+\n+\tborder: dotted #ffe0ff;\n+\tborder-width: 1px 0px 0px 0px;\n+\tmargin-top: 2px;\n }\n \n div.diff.incomplete {\n \tcolor: #cccccc;\n }\n \n-div.diff_info {\n-\tfont-family: monospace;\n-\tcolor: #000099;\n-\tbackground-color: #edece6;\n-\tfont-style: italic;\n-}\n \n div.index_include {\n \tborder: solid #d9d8d1;\ndiff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl\nindex 4554067..c22fcc5 100755\n--- a/gitweb/gitweb.perl\n+++ b/gitweb/gitweb.perl\n@@ -732,6 +732,32 @@ sub file_type {\n \t}\n }\n \n+# convert file mode in octal to file type description string\n+sub file_type_long {\n+\tmy $mode = shift;\n+\n+\tif ($mode !~ m/^[0-7]+$/) {\n+\t\treturn $mode;\n+\t} else {\n+\t\t$mode = oct $mode;\n+\t}\n+\n+\tif (S_ISDIR($mode & S_IFMT)) {\n+\t\treturn \"directory\";\n+\t} elsif (S_ISLNK($mode)) {\n+\t\treturn \"symlink\";\n+\t} elsif (S_ISREG($mode)) {\n+\t\tif ($mode & S_IXUSR) {\n+\t\t\treturn \"executable\";\n+\t\t} else {\n+\t\t\treturn \"file\";\n+\t\t};\n+\t} else {\n+\t\treturn \"unknown\";\n+\t}\n+}\n+\n+\n ## ----------------------------------------------------------------------\n ## functions returning short HTML fragments, or transforming HTML fragments\n ## which don't beling to other sections\n@@ -2055,7 +2081,9 @@ sub git_patchset_body {\n \tmy $patch_idx = 0;\n \tmy $in_header = 0;\n \tmy $patch_found = 0;\n+\tmy $skip_patch = 0;\n \tmy $diffinfo;\n+\tmy (%from, %to);\n \n \tprint \"<div class=\\\"patchset\\\">\\n\";\n \n@@ -2065,6 +2093,8 @@ sub git_patchset_body {\n \n \t\tif ($patch_line =~ m/^diff /) { # \"git diff\" header\n \t\t\t# beginning of patch (in patchset)\n+\t\t\t$skip_patch = 0;\n+\n \t\t\tif ($patch_found) {\n \t\t\t\t# close previous patch\n \t\t\t\tprint \"</div>\\n\"; # class=\"patch\"\n@@ -2074,96 +2104,123 @@ sub git_patchset_body {\n \t\t\t}\n \t\t\tprint \"<div class=\\\"patch\\\" id=\\\"patch\". ($patch_idx+1) .\"\\\">\\n\";\n \n+\t\t\t# read and prepare patch information\n \t\t\tif (ref($difftree->[$patch_idx]) eq \"HASH\") {\n+\t\t\t\t# pre-parsed (or generated by hand)\n \t\t\t\t$diffinfo = $difftree->[$patch_idx];\n \t\t\t} else {\n \t\t\t\t$diffinfo = parse_difftree_raw_line($difftree->[$patch_idx]);\n \t\t\t}\n+\t\t\t$from{'file'} = $diffinfo->{'from_file'} || $diffinfo->{'file'};\n+\t\t\t$to{'file'}   = $diffinfo->{'to_file'}   || $diffinfo->{'file'};\n+\t\t\tif ($diffinfo->{'status'} ne \"A\") { # not new (added) file\n+\t\t\t\t$from{'href'} = href(action=>\"blob\", hash_base=>$hash_parent,\n+\t\t\t\t                     hash=>$diffinfo->{'from_id'},\n+\t\t\t\t                     file_name=>$from{'file'});\n+\t\t\t}\n+\t\t\tif ($diffinfo->{'status'} ne \"D\") { # not deleted file\n+\t\t\t\t$to{'href'} = href(action=>\"blob\", hash_base=>$hash,\n+\t\t\t\t                   hash=>$diffinfo->{'to_id'},\n+\t\t\t\t                   file_name=>$to{'file'});\n+\t\t\t}\n \t\t\t$patch_idx++;\n \n-\t\t\t# for now, no extended header, hence we skip empty patches\n-\t\t\t# companion to\tnext LINE if $in_header;\n+\t\t\t# for now we skip empty patches\n \t\t\tif ($diffinfo->{'from_id'} eq $diffinfo->{'to_id'}) { # no change\n \t\t\t\t$in_header = 1;\n+\t\t\t\t$skip_patch = 0;\n \t\t\t\tnext LINE;\n \t\t\t}\n \n-\t\t\tif ($diffinfo->{'status'} eq \"A\") { # added\n-\t\t\t\tprint \"<div class=\\\"diff_info\\\">\" . file_type($diffinfo->{'to_mode'}) . \":\" .\n-\t\t\t\t      $cgi->a({-href => href(action=>\"blob\", hash_base=>$hash,\n-\t\t\t\t                             hash=>$diffinfo->{'to_id'}, file_name=>$diffinfo->{'file'})},\n-\t\t\t\t              $diffinfo->{'to_id'}) . \" (new)\" .\n-\t\t\t\t      \"</div>\\n\"; # class=\"diff_info\"\n-\n-\t\t\t} elsif ($diffinfo->{'status'} eq \"D\") { # deleted\n-\t\t\t\tprint \"<div class=\\\"diff_info\\\">\" . file_type($diffinfo->{'from_mode'}) . \":\" .\n-\t\t\t\t      $cgi->a({-href => href(action=>\"blob\", hash_base=>$hash_parent,\n-\t\t\t\t                             hash=>$diffinfo->{'from_id'}, file_name=>$diffinfo->{'file'})},\n-\t\t\t\t              $diffinfo->{'from_id'}) . \" (deleted)\" .\n-\t\t\t\t      \"</div>\\n\"; # class=\"diff_info\"\n-\n-\t\t\t} elsif ($diffinfo->{'status'} eq \"R\" || # renamed\n-\t\t\t         $diffinfo->{'status'} eq \"C\" || # copied\n-\t\t\t         $diffinfo->{'status'} eq \"2\") { # with two filenames (from git_blobdiff)\n-\t\t\t\tprint \"<div class=\\\"diff_info\\\">\" .\n-\t\t\t\t      file_type($diffinfo->{'from_mode'}) . \":\" .\n-\t\t\t\t      $cgi->a({-href => href(action=>\"blob\", hash_base=>$hash_parent,\n-\t\t\t\t                             hash=>$diffinfo->{'from_id'}, file_name=>$diffinfo->{'from_file'})},\n-\t\t\t\t              $diffinfo->{'from_id'}) .\n-\t\t\t\t      \" -> \" .\n-\t\t\t\t      file_type($diffinfo->{'to_mode'}) . \":\" .\n-\t\t\t\t      $cgi->a({-href => href(action=>\"blob\", hash_base=>$hash,\n-\t\t\t\t                             hash=>$diffinfo->{'to_id'}, file_name=>$diffinfo->{'to_file'})},\n-\t\t\t\t              $diffinfo->{'to_id'});\n-\t\t\t\tprint \"</div>\\n\"; # class=\"diff_info\"\n-\n-\t\t\t} else { # modified, mode changed, ...\n-\t\t\t\tprint \"<div class=\\\"diff_info\\\">\" .\n-\t\t\t\t      file_type($diffinfo->{'from_mode'}) . \":\" .\n-\t\t\t\t      $cgi->a({-href => href(action=>\"blob\", hash_base=>$hash_parent,\n-\t\t\t\t                             hash=>$diffinfo->{'from_id'}, file_name=>$diffinfo->{'file'})},\n-\t\t\t\t              $diffinfo->{'from_id'}) .\n-\t\t\t\t      \" -> \" .\n-\t\t\t\t      file_type($diffinfo->{'to_mode'}) . \":\" .\n-\t\t\t\t      $cgi->a({-href => href(action=>\"blob\", hash_base=>$hash,\n-\t\t\t\t                             hash=>$diffinfo->{'to_id'}, file_name=>$diffinfo->{'file'})},\n-\t\t\t\t              $diffinfo->{'to_id'});\n-\t\t\t\tprint \"</div>\\n\"; # class=\"diff_info\"\n+\t\t\t# print \"git diff\" header\n+\t\t\t$patch_line =~ s!^(diff (.*?) )a/.*$!$1!;\n+\t\t\tif ($from{'href'}) {\n+\t\t\t\t$patch_line .= $cgi->a({-href => $from{'href'}, -class => \"path\"},\n+\t\t\t\t                       'a/' . esc_path($from{'file'}));\n+\t\t\t} else { # file was added\n+\t\t\t\t$patch_line .= 'a/' . esc_path($from{'file'});\n+\t\t\t}\n+\t\t\t$patch_line .= ' ';\n+\t\t\tif ($to{'href'}) {\n+\t\t\t\t$patch_line .= $cgi->a({-href => $to{'href'}, -class => \"path\"},\n+\t\t\t\t                       'b/' . esc_path($to{'file'}));\n+\t\t\t} else { # file was deleted\n+\t\t\t\t$patch_line .= 'b/' . esc_path($to{'file'});\n \t\t\t}\n \n-\t\t\t#print \"<div class=\\\"diff extended_header\\\">\\n\";\n+\t\t\tprint \"<div class=\\\"diff header\\\">$patch_line</div>\\n\";\n+\t\t\tprint \"<div class=\\\"diff extended_header\\\">\\n\";\n \t\t\t$in_header = 1;\n \t\t\tnext LINE;\n+\t\t} else {\n+\t\t\t# actual skipping of empty patches\n+\t\t\tnext LINE if $skip_patch;\n \t\t} # start of patch in patchset\n \n+\t\tif ($in_header) {\n+\t\t\tif ($patch_line !~ m/^---/) {\n+\t\t\t\t# match <path>\n+\t\t\t\tif ($patch_line =~ s!^((copy|rename) from ).*$!$1! && $from{'href'}) {\n+\t\t\t\t\t$patch_line .= $cgi->a({-href=>$from{'href'}, -class=>\"path\"},\n+\t\t\t\t\t                        esc_path($from{'file'}));\n+\t\t\t\t}\n+\t\t\t\tif ($patch_line =~ s!^((copy|rename) to ).*$!$1! && $to{'href'}) {\n+\t\t\t\t\t$patch_line = $cgi->a({-href=>$to{'href'}, -class=>\"path\"},\n+\t\t\t\t\t                      esc_path($to{'file'}));\n+\t\t\t\t}\n+\t\t\t\t# match <mode>\n+\t\t\t\tif ($patch_line =~ m/\\s(\\d{6})$/) {\n+\t\t\t\t\t$patch_line .= '<span class=\"info\"> (' .\n+\t\t\t\t\t               file_type_long($1) .\n+\t\t\t\t\t               ')</span>';\n+\t\t\t\t}\n+\t\t\t\t# match <hash>\n+\t\t\t\tif ($patch_line =~ m/^index/) {\n+\t\t\t\t\tmy ($from_link, $to_link);\n+\t\t\t\t\tif ($from{'href'}) {\n+\t\t\t\t\t\t$from_link = $cgi->a({-href=>$from{'href'}, -class=>\"hash\"},\n+\t\t\t\t\t\t                     substr($diffinfo->{'from_id'},0,7));\n+\t\t\t\t\t} else {\n+\t\t\t\t\t\t$from_link = '0' x 7;\n+\t\t\t\t\t}\n+\t\t\t\t\tif ($to{'href'}) {\n+\t\t\t\t\t\t$to_link = $cgi->a({-href=>$to{'href'}, -class=>\"hash\"},\n+\t\t\t\t\t\t                   substr($diffinfo->{'to_id'},0,7));\n+\t\t\t\t\t} else {\n+\t\t\t\t\t\t$to_link = '0' x 7;\n+\t\t\t\t\t}\n+\t\t\t\t\tmy ($from_id, $to_id) = ($diffinfo->{'from_id'}, $diffinfo->{'to_id'});\n+\t\t\t\t\t$patch_line =~ s!$from_id\\.\\.$to_id!$from_link..$to_link!;\n+\t\t\t\t}\n+\t\t\t\tprint $patch_line . \"<br/>\\n\";\n \n-\t\tif ($in_header && $patch_line =~ m/^---/) {\n-\t\t\t#print \"</div>\\n\"; # class=\"diff extended_header\"\n-\t\t\t$in_header = 0;\n+\t\t\t} else {\n+\t\t\t\t#$in_header && $patch_line =~ m/^---/;\n+\t\t\t\tprint \"</div>\\n\"; # class=\"diff extended_header\"\n+\t\t\t\t$in_header = 0;\n+\n+\t\t\t\tif ($from{'href'}) {\n+\t\t\t\t\t$patch_line = '--- a/' .\n+\t\t\t\t\t              $cgi->a({-href=>$from{'href'}, -class=>\"path\"},\n+\t\t\t\t\t                      esc_path($from{'file'}));\n+\t\t\t\t}\n+\t\t\t\tprint \"<div class=\\\"diff from_file\\\">$patch_line</div>\\n\";\n \n-\t\t\tmy $file = $diffinfo->{'from_file'};\n-\t\t\t$file  ||= $diffinfo->{'file'};\n-\t\t\t$file = $cgi->a({-href => href(action=>\"blob\", hash_base=>$hash_parent,\n-\t\t\t                               hash=>$diffinfo->{'from_id'}, file_name=>$file),\n-\t\t\t                -class => \"list\"}, esc_path($file));\n-\t\t\t$patch_line =~ s|a/.*$|a/$file|g;\n-\t\t\tprint \"<div class=\\\"diff from_file\\\">$patch_line</div>\\n\";\n+\t\t\t\t$patch_line = <$fd>;\n+\t\t\t\tchomp $patch_line;\n \n-\t\t\t$patch_line = <$fd>;\n-\t\t\tchomp $patch_line;\n+\t\t\t\t#$patch_line =~ m/^+++/;\n+\t\t\t\tif ($to{'href'}) {\n+\t\t\t\t\t$patch_line = '+++ b/' .\n+\t\t\t\t\t              $cgi->a({-href=>$to{'href'}, -class=>\"path\"},\n+\t\t\t\t\t                      esc_html($to{'file'}));\n+\t\t\t\t}\n+\t\t\t\tprint \"<div class=\\\"diff to_file\\\">$patch_line</div>\\n\";\n \n-\t\t\t#$patch_line =~ m/^+++/;\n-\t\t\t$file    = $diffinfo->{'to_file'};\n-\t\t\t$file  ||= $diffinfo->{'file'};\n-\t\t\t$file = $cgi->a({-href => href(action=>\"blob\", hash_base=>$hash,\n-\t\t\t                               hash=>$diffinfo->{'to_id'}, file_name=>$file),\n-\t\t\t                -class => \"list\"}, esc_path($file));\n-\t\t\t$patch_line =~ s|b/.*|b/$file|g;\n-\t\t\tprint \"<div class=\\\"diff to_file\\\">$patch_line</div>\\n\";\n+\t\t\t}\n \n \t\t\tnext LINE;\n \t\t}\n-\t\tnext LINE if $in_header;\n \n \t\tprint format_diff_line($patch_line);\n \t}\n-- \n1.4.3.3\n"},{"id":"297695","messageId":"200611031149.59329.jnareb@gmail.com","threadId":"43063","inReplyTo":"7vlkmseutr.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH 4/n] gitweb: Secure against commit-ish/tree-ish with the same name as path","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-11-03T10:49:59Z","receivedAt":"2006-11-03T10:49:59Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Junio C Hamano wrote:\n> Junio C Hamano <junkio@cox.net> writes:\n> \n>> I'd see if I can add some constructive comments on patches 5-10\n>> tonight, but I'm in the middle of other things so don't hold\n>> your breath ;-).\n> \n> 7 and 9 look obviously good, so I've applied them without\n> others.\n> \n>         gitweb: Output also empty patches in \"commitdiff\" view\n\nThis patch in my opinion has no sense without having extended diff\nheader in commitdiff view, i.e. without \"New improved patchset view\"\n(I have send non-line wrapped version).\n\n>         gitweb: Better support for non-CSS aware web browsers\n\nThats independent from other changes, true.\n\n> 5 is terminally linewrapped and rather big to comment on without\n> comparing pre- and post- patch outputs, so I'll refrain from\n> commenting on it. \n\nYou can check out new gitweb at work at my site (when it is up)\n  http://roke . dyndns . info/cgi-bin/gitweb/gitweb.cgi\n\n>                    8 is \"oops, I made a mistake when I did 5\", \n> which discourages me even more from looking at 5 X-<.\n\nWell, you wouldn't notice error corrected by 8 unless you have\nfiles with funny filenames.\n-- \nJakub Narebski\n"},{"id":"295263","messageId":"200611031159.02065.jnareb@gmail.com","threadId":"43063","inReplyTo":"7vlkmtgd3o.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH/RFC 1/n] gitweb: Better git-unquoting and gitweb-quoting of pathnames","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-11-03T10:59:01Z","receivedAt":"2006-11-03T10:59:01Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Junio C Hamano wrote:\n> Jakub Narebski <jnareb@gmail.com> writes:\n> \n> > diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl\n> > index ec46b80..a15e916 100755\n> > --- a/gitweb/gitweb.perl\n> > +++ b/gitweb/gitweb.perl\n> > @@ -563,12 +563,42 @@ sub esc_html {\n> >  \treturn $str;\n> >  }\n> >  \n> > +# quote unsafe characters and escape filename to HTML\n> > +sub esc_path {\n> > +\tmy $str = shift;\n> > +\t$str = esc_html($str);\n> > +\t$str =~ s/[[:cntrl:]\\a\\b\\e\\f\\n\\r\\t\\011]/?/g; # like --hide-control-chars in ls\n> > +\treturn $str;\n> > +}\n> > +\n> \n> When you say \"[:cntrl:]\" do you need to say anything more?\n\nOoops. Yes, the \\a\\b\\e\\f\\n\\r\\t\\011 part is redundant.\n\n> >  # git may return quoted and escaped filenames\n> >  sub unquote {\n> >  \tmy $str = shift;\n> > +\n> > +\tsub unq {\n> > +\t\tmy $seq = shift;\n> > +\t\tmy %es = (\n> > +\t\t\t't' => \"\\t\", # tab            (HT, TAB)\n> > +\t\t\t'n' => \"\\n\", # newline        (NL)\n> > +\t\t\t'r' => \"\\r\", # return         (CR)\n> > +\t\t\t'f' => \"\\f\", # form feed      (FF)\n> > +\t\t\t'b' => \"\\b\", # backspace      (BS)\n> > +\t\t\t'a' => \"\\a\", # alarm (bell)   (BEL)\n> > +\t\t\t#'e' => \"\\e\", # escape        (ESC)\n> > +\t\t\t'v' => \"\\011\", # vertical tab (VT)\n> > +\t\t);\n> > +\n> > +\t\t# octal char sequence\n> > +\t\treturn chr(oct($seq))  if ($seq =~ m/^[0-7]{1,3}$/);\n> > +\t\t# C escape sequence (this includes '\\n' (LF) and '\\t' (TAB))\n> > +\t\treturn $es{$seq}       if ($seq =~ m/^[abefnrtv]$/);\n> \n> Problems in this part of the code X-<.\n> \n>  * Was there a reason not to unwrap '\\e' to \"\\e\"?\n\nIt was not mentioned in description of git pathname quoting in the\nmessage\n  http://marc.theaimsgroup.com/?l=git&m=112927316408690&w=2;\n\n>  * The vertical tab is \\013 (decimal 11), not \\011 (which is TAB).\n\nOops. ASCII 11 is decimal 11.\n\n>  * The name and the abbreviated name of the character \"\\n\" are\n>    \"line feed\" and \"LF\"; I personally do not think these\n>    character name comments are needed in this part of the code,\n>    but I do not object if you want to have them there, as long\n>    as you spell them correctly. cf. ISO/IEC 6429:1992 or\n>    http://www.unicode.org/charts/PDF/U0000.pdf for example.\n\nPerhaps it should be \"LF ('\\n') and TAB ('\\t')\".\n\n>  * The hash %es and the pattern /[abef...]/ must be kept in\n>    sync; it is a maintenance nightmare,\n> \n>  * Worse yet, they do not agree even in this initial version,\n>    which proves the previous point.\n> \n> Perhaps this is better written as:\n> \n> \tif (exists $es{$seq}) {\n>         \treturn $es{$seq};\n> \t}\n\nFact.\n\nOr\n\treturn $es{$seq} if exists $es{$seq};\n\n-- \nJakub Narebski\n"},{"id":"298228","messageId":"200611031201.46991.jnareb@gmail.com","threadId":"43063","inReplyTo":"7v3b91jalp.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH 6/n] gitweb: Remove redundant \"blob\" links from git_difftree_body","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-11-03T11:01:46Z","receivedAt":"2006-11-03T11:01:46Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Junio C Hamano wrote:\n> Jakub Narebski <jnareb@gmail.com> writes:\n> \n>> ... First, it did that incompletely: it did not add \"blob\"\n>> link for added files, and added block used mixture of tabs and spaces\n>> for align. Second, in \"difftree\" view the \"blob\" link is not the most\n>> interesting, *contrary* to \"blob\"/\"tree\" link in \"tree\" view, so it\n>> should be enough to have hidden link in the form of file name entry.\n> \n> I think these \"blob\" links are good thing to have, and if you\n> think the earlier work was incomplete and know some cases are\n> not covered I think it would be better to help completing it\n> rather than reverting.\n> \n> I do not understand why you feel \"blob\" is not the most\n> interesting.  Often, when it is not obvious if a patch is\n> correct only with the context, it is useful to view the whole\n> postimage after applying the patch, and the \"blob\" link helps\n> that.\n\nO.K. I'll choose the \"add blob links where there are none in difftree view\"\napproach in cleaned up and resend series.\n\nI'll wait a while (a day or two) for further comments before redoing\nthe series.\n\nP.S. Remove empty patches might produce incorrect HTML (one of <div>\nis not closed). I'll correct it on resend.\n-- \nJakub Narebski\n"},{"id":"294517","messageId":"200611031256.37927.jnareb@gmail.com","threadId":"43063","inReplyTo":"200610311736.27910.jnareb@gmail.com","subject":"Re: [PATCH 7/n] gitweb: Output also empty patches in \"commitdiff\" view","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-11-03T11:56:37Z","receivedAt":"2006-11-03T11:56:37Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Jakub Narebski wrote:\n> Remove skipping over empty patches (i.e. patches which consist solely\n> of extended headers) in git_patchset_body, and add links to those\n> header-only patches in git_difftree_body (but not generate blobdiff\n> links when there were no change in file contents).\n\nAttention: I think this patch causes that in some cases gitweb generates\nincorrect HTML (one of <div> elements is not closed).\n-- \nJakub Narebski\n"},{"id":"298164","messageId":"7vodro91ye.fsf@assigned-by-dhcp.cox.net","threadId":"43063","inReplyTo":"200611031159.02065.jnareb@gmail.com","subject":"Re: [PATCH/RFC 1/n] gitweb: Better git-unquoting and gitweb-quoting of pathnames","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-11-03T11:58:17Z","receivedAt":"2006-11-03T11:58:17Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jakub Narebski <jnareb@gmail.com> writes:\n\n> Perhaps it should be \"LF ('\\n') and TAB ('\\t')\".\n\nOfficial terminology seems to call \\t \"HT\", but my feeling is\nthat we would not need that comment there.\n\n> Or\n> \treturn $es{$seq} if exists $es{$seq};\n\nAlthough gitweb is full of that syntax, I personally do not like\nit very much.  It is really hard to read when you are trying to\nskim through the code quickly.  You would have to say \"why\nreturn it?  ah -- only when it exists, then it makes sense\",\nwhich is a hiccup that disrupts the thought process.\n"},{"id":"294147","messageId":"200611031309.07180.jnareb@gmail.com","threadId":"43063","inReplyTo":"7vodro91ye.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH/RFC 1/n] gitweb: Better git-unquoting and gitweb-quoting of pathnames","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-11-03T12:09:06Z","receivedAt":"2006-11-03T12:09:06Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Dnia piątek 3. listopada 2006 12:58, Junio C Hamano napisał:\n> Jakub Narebski <jnareb@gmail.com> writes:\n> \n>> Perhaps it should be \"LF ('\\n') and TAB ('\\t')\".\n> \n> Official terminology seems to call \\t \"HT\", but my feeling is\n> that we would not need that comment there.\n\nO.K. I'll remove that comment.\n\n>> Or\n>> \treturn $es{$seq} if exists $es{$seq};\n> \n> Although gitweb is full of that syntax, I personally do not like\n> it very much.  It is really hard to read when you are trying to\n> skim through the code quickly.  You would have to say \"why\n> return it?  ah -- only when it exists, then it makes sense\",\n> which is a hiccup that disrupts the thought process.\n\nO.K., I'll change style from\n\n\treturn chr(oct($seq))  if ($seq =~ m/^[0-7]{1,3}$/);\n\treturn $es{$seq}       if exists $es{$seq};\n\treturn $seq;\n\nto the more readable form\n\n\tif ($seq =~ m/^[0-7]{1,3}$/) {\n\t\treturn chr(oct($seq));\n\t} elsif (exists $es{$seq}) {\n\t\treturn $es{$seq};\n\t}\n\treturn $seq;\n\nI think it is better to leave final \"return $seq;\" outside else block.\n-- \nJakub Narebski\n"},{"id":"296609","messageId":"200611031719.13073.jnareb@gmail.com","threadId":"43063","inReplyTo":"7vvem1s29g.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH 2/n] gitweb: Use '&iquot;' instead of '?' in esc_path","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-11-03T16:19:12Z","receivedAt":"2006-11-03T16:19:12Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":" Junio C Hamano wrote:\n>\n> Junio C Hamano <junkio@cox.net> writes:\n> \n>> Jakub Narebski <jnareb@gmail.com> writes:\n>>\n>>> Use \"&iquot;\" Latin 1 entity (\"&#191;\" -- inverted question mark =\n>>> turned question mark, U+00BF ISOnum) instead '?' as replacements for\n>>> control characters and other undisplayable characters.\n>>>\n>>> Signed-off-by: Jakub Narebski <jnareb@gmail.com>\n>>\n>> Do you have something against our Spanish and Latin American\n>> friends?  ;-)\n>>\n>> I wonder if there is a more suitable replacement character that\n>> is accepted across scripts?\n> \n> I have a suspicion that instead of finding an exotic character,\n> just showing the byte value in \\octal, perhaps in different\n> color, might be more portable and easier.  For one thing, it\n> helps to show the exact byte value than just one substitution\n> character if you are troubleshooting gitweb.\n \nOr perhaps we can use Unicode Control Pictures U+2400 – U+243F \n(9216–9279) (\"Unicode quoting\"):\n\nhttp://www.alanwood.net/unicode/control_pictures.html\nhttp://www.unicode.org/charts/PDF/U2400.pdf\n\n# quote unsafe characters and escape filename to HTML\nsub esc_path {\n\tmy $str = shift;\n\t$str = esc_html($str);\n\t$str =~ s!([[:cntrl:]])!sprintf('<span class=\"cntrl\">&#%04d;</span>', 9216+ord($1))!eg;\n\treturn $str;\n}\n\nwith perhaps the following CSS\n\nspan.cntrl {\n\tborder: dashed #aaaaaa;\n\tborder-width: 1px;\n\tpadding: 0px 2px 0px 2px;\n\tmargin:  0px 2px 0px 2px;\n}\n\nWhat do you think of it?\n-- \nJakub Narebski\n"},{"id":"293799","messageId":"7virhw5hoi.fsf@assigned-by-dhcp.cox.net","threadId":"43063","inReplyTo":"200611031719.13073.jnareb@gmail.com","subject":"Re: [PATCH 2/n] gitweb: Use '&iquot;' instead of '?' in esc_path","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-11-03T21:44:29Z","receivedAt":"2006-11-03T21:44:29Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jakub Narebski <jnareb@gmail.com> writes:\n\n> # quote unsafe characters and escape filename to HTML\n> sub esc_path {\n> \tmy $str = shift;\n> \t$str = esc_html($str);\n> \t$str =~ s!([[:cntrl:]])!sprintf('<span class=\"cntrl\">&#%04d;</span>', 9216+ord($1))!eg;\n> \treturn $str;\n> }\n>\n> with perhaps the following CSS\n>\n> span.cntrl {\n> \tborder: dashed #aaaaaa;\n> \tborder-width: 1px;\n> \tpadding: 0px 2px 0px 2px;\n> \tmargin:  0px 2px 0px 2px;\n> }\n>\n> What do you think of it?\n\nProbably \"# quote unsafe characters\" is not what it does yet (it\njust quotes controls currently and nothing else), but we have to\nstart somewhere and I think this is a good start.\n\n"},{"id":"295434","messageId":"200611032333.49794.jnareb@gmail.com","threadId":"43063","inReplyTo":"7virhw5hoi.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH 2/n] gitweb: Use '&iquot;' instead of '?' in esc_path","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-11-03T22:33:49Z","receivedAt":"2006-11-03T22:33:49Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Junio C Hamano wrote:\n> Jakub Narebski <jnareb@gmail.com> writes:\n> \n>> # quote unsafe characters and escape filename to HTML\n>> sub esc_path {\n>> \tmy $str = shift;\n>> \t$str = esc_html($str);\n>> \t$str =~ s!([[:cntrl:]])!sprintf('<span \nclass=\"cntrl\">&#%04d;</span>', 9216+ord($1))!eg;\n>> \treturn $str;\n>> }\n>>\n>> with perhaps the following CSS\n>>\n>> span.cntrl {\n>> \tborder: dashed #aaaaaa;\n>> \tborder-width: 1px;\n>> \tpadding: 0px 2px 0px 2px;\n>> \tmargin:  0px 2px 0px 2px;\n>> }\n>>\n>> What do you think of it?\n> \n> Probably \"# quote unsafe characters\" is not what it does yet (it\n> just quotes controls currently and nothing else), but we have to\n> start somewhere and I think this is a good start.\n\nWell, control characters (at least some of them) are not correct\ncharacters in UTF-8 HTML output; Mozilla in strict XHTML mode complains.\nCurrently for example esc_html escapes FORM FEED (FF) and ESCAPE (ESC)\ncharacters, because they happened to be present in git.git repository\n(in COPYING file and in commit v1.4.2.1-g20a3847 respectively).\n\nAs I see it, we can either replace non-safe characters (control\ncharacters) by single characters a la --hide-control-chars: that\nis minimal solution, or we can quote unseafe characters somewhat,\nbut if we do that we have to indicate that we quote. Git core and\nls encloses material which needs escaping with quotes; in gitweb\nit is somewhat impractical; besides we have more possibilities\nto mark fragment of text (span element encompassing representation\nof escaped characters for example).\n\nI have thought of the following escaping:\n\n1. Hide control characters using '?' or other similar character like\n   &cdot; for example\n2. Use \"Unicode\" quoting, i.e. replace control characters by their\n   Unicode Printable Representation (PR), as shown above. Has the\n   advantage that it is simple and does not need theoretically marking\n   that it is quoted; has the disadvantage that browser must support\n   this part of Unicode, and that those characters are less than\n   readable with default font size gitweb uses.\n3. Use Character Escape Codes (CEC), using alphabetic and octal\n   backslash sequences like those used in C. Probably need to escape\n   backslash (quoting character) too. Has the advantage of being widely\n   understood in POSIX world. Has the disadvantage of need for escape\n   sequence table/hash. Has the advantage that it works for all\n   characters - simple octal backslash sequence if they have no special\n   escape sequence.\n4. Control key Sequence (CS), like the one used in esc_html currently,\n   replacing control characters by key sequence that produces them,\n   for example replacing LF with ^J, CR with ^M, FF with ^L, ESC with\n   ^[, TAB with ^I. Has the advantage of being undestodd I think in\n   MS-DOS/MS WIndows world. Has the advantage of being used in esc_html.\n   Has the advantage that some text editors use this representation.\n   Has the disadvantage of need for large key sequence table/hash.\n   Has the disadvantage that less common control characters have cryptic\n   control key sequences.\n5. Percent encoding, also know as URL encoding. Use %<hex> encoding used\n   in URL, taken for example from core of esc_url/esc_param subroutine.\n   Simple, but does need marking that is escaped. Disadvantage of hardly\n   readable.\n\nWhich solution do you think it's best? Or perhaps other solution, like \nusing Unicode Printable Representation, or Character Escape Codes with \nthe exception of LF which would be replaced by &para; (paragraph sign), \nRET by &crarr; and TAB by either &thorn;, &#8614; or &rarr;.\n\n-- \nJakub Narebski\n"},{"id":"296503","messageId":"7vwt6c40bj.fsf@assigned-by-dhcp.cox.net","threadId":"43063","inReplyTo":"200611032333.49794.jnareb@gmail.com","subject":"Re: [PATCH 2/n] gitweb: Use '&iquot;' instead of '?' in esc_path","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-11-03T22:44:48Z","receivedAt":"2006-11-03T22:44:48Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jakub Narebski <jnareb@gmail.com> writes:\n\n> Well, control characters (at least some of them) are not correct\n> characters in UTF-8 HTML output; Mozilla in strict XHTML mode complains.\n> Currently...\n\nI said you quote controls (and only controls) as unsafe, so you\nare not disagreeing with me here.  However \"controls are unsafe\"\ndoes not necessarily mean \"unsafe characters are all controls\",\ndoes it?  That was what my comments abuot the comment before the\nfunction was.\n\n> Which solution do you think it's best?\n\nSorry, if it was not clear in my message, I wanted to say that I\nkinda liked those \"control pictures\" in U+2400 range.\n"},{"id":"295269","messageId":"20061103225041.GQ20017@pasky.or.cz","threadId":"43063","inReplyTo":"7vwt6c40bj.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH 2/n] gitweb: Use '&iquot;' instead of '?' in esc_path","fromName":"Petr Baudis","fromEmail":"pasky@suse.cz","sentAt":"2006-11-03T22:50:41Z","receivedAt":"2006-11-03T22:50:41Z","isPatch":true,"sender":{"key":"pasky@ucw.cz","avatar":"https://avatars.githubusercontent.com/u/18439?v=4"},"body":"Dear diary, on Fri, Nov 03, 2006 at 11:44:48PM CET, I got a letter\nwhere Junio C Hamano <junkio@cox.net> said that...\n> Jakub Narebski <jnareb@gmail.com> writes:\n> > Which solution do you think it's best?\n> \n> Sorry, if it was not clear in my message, I wanted to say that I\n> kinda liked those \"control pictures\" in U+2400 range.\n\nIn principle, right now it should be pretty easy for a project that for\nsome reason does not use UTF-8 in commits etc. to adjust gitweb to work\nproperly, right? Just change the encoding in HTTP headers and you're\ndone, I think.\n\nIs it worth trying to preserve that flexibility?\n\n-- \n\t\t\t\tPetr \"Pasky\" Baudis\nStuff: http://pasky.or.cz/\n#!/bin/perl -sp0777i<X+d*lMLa^*lN%0]dsXx++lMlN/dsM0<j]dsj\n$/=unpack('H*',$_);$_=`echo 16dio\\U$k\"SK$/SM$n\\EsN0p[lN*1\n"},{"id":"296804","messageId":"eigjmh$ql$1@sea.gmane.org","threadId":"43063","inReplyTo":"20061103225041.GQ20017@pasky.or.cz","subject":"Re: [PATCH 2/n] gitweb: Use '&iquot;' instead of '?' in esc_path","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-11-03T23:35:11Z","receivedAt":"2006-11-03T23:35:11Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Petr Baudis wrote:\n\n> Dear diary, on Fri, Nov 03, 2006 at 11:44:48PM CET, I got a letter\n> where Junio C Hamano <junkio@cox.net> said that...\n>> Jakub Narebski <jnareb@gmail.com> writes:\n>> > Which solution do you think it's best?\n>> \n>> Sorry, if it was not clear in my message, I wanted to say that I\n>> kinda liked those \"control pictures\" in U+2400 range.\n> \n> In principle, right now it should be pretty easy for a project that for\n> some reason does not use UTF-8 in commits etc. to adjust gitweb to work\n> properly, right? Just change the encoding in HTTP headers and you're\n> done, I think.\n> \n> Is it worth trying to preserve that flexibility?\n\nIt should be also quite easy to change to_uft8 subroutine to actually\nconvert to utf8. But even if we don't use UTF-8 encoding for HTML in\ngitweb, numerical character entities (and that's how those \"control\npictures\" are entered) should work equally well regardless of encoding.\n-- \nJakub Narebski\nWarsaw, Poland\nShadeHawk on #git\n\n"},{"id":"296469","messageId":"7vr6wk3wpo.fsf@assigned-by-dhcp.cox.net","threadId":"43063","inReplyTo":"20061103225041.GQ20017@pasky.or.cz","subject":"Re: [PATCH 2/n] gitweb: Use '&iquot;' instead of '?' in esc_path","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-11-04T00:02:43Z","receivedAt":"2006-11-04T00:02:43Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Petr Baudis <pasky@suse.cz> writes:\n\n> Dear diary, on Fri, Nov 03, 2006 at 11:44:48PM CET, I got a letter\n> where Junio C Hamano <junkio@cox.net> said that...\n>> Jakub Narebski <jnareb@gmail.com> writes:\n>> > Which solution do you think it's best?\n>> \n>> Sorry, if it was not clear in my message, I wanted to say that I\n>> kinda liked those \"control pictures\" in U+2400 range.\n>\n> In principle, right now it should be pretty easy for a project that for\n> some reason does not use UTF-8 in commits etc. to adjust gitweb to work\n> properly, right? Just change the encoding in HTTP headers and you're\n> done, I think.\n>\n> Is it worth trying to preserve that flexibility?\n\nAbsolutely, and I got your point.  Maybe <blink>\\011</blink>\nwould be more portable and appropriate.\n\nAlso munging [:cntrl:] would break iso-2022 encoding if it\nmunges ESC, but the function under discussion was only for paths\nand I think no sane platform would use iso-2022 for filenames.\n\nEach repository has commit charset/encoding configuration item\nif I am not mistaken, so it is probably a sane thing to do to\nconvert commit messages from that uniformly to utf-8, I think.\n\n"},{"id":"297113","messageId":"20061104103156.GS20017@pasky.or.cz","threadId":"43063","inReplyTo":"7vr6wk3wpo.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH 2/n] gitweb: Use '&iquot;' instead of '?' in esc_path","fromName":"Petr Baudis","fromEmail":"pasky@suse.cz","sentAt":"2006-11-04T10:31:56Z","receivedAt":"2006-11-04T10:31:56Z","isPatch":true,"sender":{"key":"pasky@ucw.cz","avatar":"https://avatars.githubusercontent.com/u/18439?v=4"},"body":"Dear diary, on Sat, Nov 04, 2006 at 01:02:43AM CET, I got a letter\nwhere Junio C Hamano <junkio@cox.net> said that...\n> Petr Baudis <pasky@suse.cz> writes:\n> \n> > Dear diary, on Fri, Nov 03, 2006 at 11:44:48PM CET, I got a letter\n> > where Junio C Hamano <junkio@cox.net> said that...\n> >> Jakub Narebski <jnareb@gmail.com> writes:\n> >> > Which solution do you think it's best?\n> >> \n> >> Sorry, if it was not clear in my message, I wanted to say that I\n> >> kinda liked those \"control pictures\" in U+2400 range.\n> >\n> > In principle, right now it should be pretty easy for a project that for\n> > some reason does not use UTF-8 in commits etc. to adjust gitweb to work\n> > properly, right? Just change the encoding in HTTP headers and you're\n> > done, I think.\n> >\n> > Is it worth trying to preserve that flexibility?\n> \n> Absolutely, and I got your point.  Maybe <blink>\\011</blink>\n> would be more portable and appropriate.\n\nActually Jakub is right, &#number; is always a Unicode codepoint,\nregardless of document encoding.\n\nAnything but <blink>! ;-)\n\n-- \n\t\t\t\tPetr \"Pasky\" Baudis\nStuff: http://pasky.or.cz/\n#!/bin/perl -sp0777i<X+d*lMLa^*lN%0]dsXx++lMlN/dsM0<j]dsj\n$/=unpack('H*',$_);$_=`echo 16dio\\U$k\"SK$/SM$n\\EsN0p[lN*1\n"},{"id":"296268","messageId":"200611062258.08320.jnareb@gmail.com","threadId":"43063","inReplyTo":"200611032333.49794.jnareb@gmail.com","subject":"Re: [PATCH 2/n] gitweb: Use '&iquot;' instead of '?' in esc_path","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-11-06T21:58:08Z","receivedAt":"2006-11-06T21:58:08Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Jakub Narebski wrote:\n> 3. Use Character Escape Codes (CEC), using alphabetic and octal\n>    backslash sequences like those used in C. Probably need to escape\n>    backslash (quoting character) too. Has the advantage of being widely\n>    understood in POSIX world. Has the disadvantage of need for escape\n>    sequence table/hash. Has the advantage that it works for all\n>    characters - simple octal backslash sequence if they have no special\n>    escape sequence.\n\nHere is example code for this:\n\n\tsub esc_path {\n\t\tmy $str = shift;\n\n\t\tsub quot {\n\t\t\tmy $seq = shift;\n\t\t\tmy %es = (\n\t\t\t\t\"\\t\" => '\\t', # tab            (HT, TAB)\n\t\t\t\t\"\\n\" => '\\n', # newline        (NL)\n\t\t\t\t\"\\r\" => '\\r', # return         (CR)\n\t\t\t\t\"\\f\" => '\\f', # form feed      (FF)\n\t\t\t\t\"\\b\" => '\\b', # backspace      (BS)\n\t\t\t\t\"\\a\" => '\\a', # alarm (bell)   (BEL)\n\t\t\t\t\"\\e\" => '\\e', # escape        (ESC)\n\t\t\t\t\"\\013\" => '\\v', # vertical tab (VT)\n\t\t\t);\n\n\t\t\tif (exists $es{seq}) {\n\t\t\t\treturn $es{$seq};\n\t\t\t}\n\t\t\treturn sprintf(\"\\\\%03o\", ord($seq));\n\t\t}\n\t\t\n\t\t$str = esc_html($str);\n\t\t$str =~ s/([[:cntrl:]])/'<span class=\"cntrl\">' . quot($1) . '</span>'/eg;\n\t\treturn $str;\n\t}\n\n-- \nJakub Narebski\n"},{"id":"297230","messageId":"7v8xiochw0.fsf@assigned-by-dhcp.cox.net","threadId":"43063","inReplyTo":"200611062258.08320.jnareb@gmail.com","subject":"Re: [PATCH 2/n] gitweb: Use '&iquot;' instead of '?' in esc_path","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-11-06T22:47:11Z","receivedAt":"2006-11-06T22:47:11Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jakub Narebski <jnareb@gmail.com> writes:\n\n> Here is example code for this:\n\nOk.  The issues I raised in the previous round seem to have been\naddressed.  Maybe you would want not to use nested 'sub' and it\nis good to go, I think.\n"},{"id":"295450","messageId":"eiofmt$8nc$1@sea.gmane.org","threadId":"43063","inReplyTo":"7v8xiochw0.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH 2/n] gitweb: Use '&iquot;' instead of '?' in esc_path","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-11-06T23:16:22Z","receivedAt":"2006-11-06T23:16:22Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Junio C Hamano wrote:\n\n> Jakub Narebski <jnareb@gmail.com> writes:\n> \n>> Here is example code for this:\n> \n> Ok.  The issues I raised in the previous round seem to have been\n> addressed.  Maybe you would want not to use nested 'sub' and it\n> is good to go, I think.\n \nNested sub makes it easy to change gitweb quoting from Character Escape\nCodes (CEC) to e.g. Unicode Printable Representation (PR).\n\n-- \nJakub Narebski\nWarsaw, Poland\nShadeHawk on #git\n\n"},{"id":"297555","messageId":"200611070102.15662.jnareb@gmail.com","threadId":"43063","inReplyTo":"7vwt68b0f3.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH 2/n] gitweb: Use '&iquot;' instead of '?' in esc_path","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-11-07T00:02:15Z","receivedAt":"2006-11-07T00:02:15Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Junio C Hamano wrote:\n> Jakub Narebski <jnareb@gmail.com> writes:\n> \n>> Junio C Hamano wrote:\n>>\n>>> Jakub Narebski <jnareb@gmail.com> writes:\n>>> \n>>>> Here is example code for this:\n>>> \n>>> Ok.  The issues I raised in the previous round seem to have been\n>>> addressed.  Maybe you would want not to use nested 'sub' and it\n>>> is good to go, I think.\n>>  \n>> Nested sub makes it easy to change gitweb quoting from Character Escape\n>> Codes (CEC) to e.g. Unicode Printable Representation (PR).\n> \n> Yes, sub makes it easy, it is not needed to be nested.\n\nWell, this sub is of no use (I think) ourside esc_path subroutine.\nSimilarly for unq sub nested in unescape in PATCH 1/10.\n\n-- \nJakub Narebski\n"},{"id":"294983","messageId":"200611072253.34291.jnareb@gmail.com","threadId":"43063","inReplyTo":"7v8xiochw0.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH 2/n] gitweb: Use '&iquot;' instead of '?' in esc_path","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-11-07T21:53:33Z","receivedAt":"2006-11-07T21:53:33Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Junio C Hamano wrote:\n> Jakub Narebski <jnareb@gmail.com> writes:\n> \n>> Here is example code for this:\n> \n> Ok.  The issues I raised in the previous round seem to have been\n> addressed.  Maybe you would want not to use nested 'sub' and it\n> is good to go, I think.\n\nShould I understand this as a statement that you prefer backslash \nsequences aka. Character Escape Codes (CEC) than \"Unicode\" escaping \naka. Unicode Printable Representation (PR)?\n\nShould I send better quoting/unquoting work as two patches: unquote \ncorrection plus '?' using esc_path + esc_path which uses backslash \nsequences and span.cntrl element, or should it be send as one, \nadmittedly quite large patch. \n\nI don't think it would be good idea to separate unquote correction with \nesc_path work, because havin unquote which unquotes fully means that we \ncan have filenames which have for exampl newline characters in them, \nhence the need of separate quoting subroutine, esc_path, and using it \nfor filename escaping.\n-- \nJakub Narebski\n"},{"id":"297644","messageId":"7v64dq3nq7.fsf@assigned-by-dhcp.cox.net","threadId":"43063","inReplyTo":"200611072253.34291.jnareb@gmail.com","subject":"Re: [PATCH 2/n] gitweb: Use '&iquot;' instead of '?' in esc_path","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-11-07T22:18:08Z","receivedAt":"2006-11-07T22:18:08Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jakub Narebski <jnareb@gmail.com> writes:\n\n> I don't think it would be good idea to separate unquote correction with \n> esc_path work, because havin unquote which unquotes fully means that we \n> can have filenames which have for exampl newline characters in them, \n> hence the need of separate quoting subroutine, esc_path, and using it \n> for filename escaping.\n\nYeah, I think that makes sense.\n\nNo matter what escaping we would end up picking in the second\npart, we should do the unquote plus esc_path anyway, so I think\na two patch series to replace to '?' first and then pretty-print\nthat '?' with whatever encoding and span.cntrl is a very\nsensible way to go.\n\nAs to backslash, cute control pictures and just plain '?', I do\nnot have a strong preference among them.  Especially if you have\nthe span.cntrl around them, we can tell even a plain '?' from\nthe substitution of funny byte values, so it probably is just a\nmatter of taste and I'd leave that up to you and gitweb cabal on\nthe list ;-).\n\n"}]}