]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/urlencode.c
urlencode: fix null byte hexdigit() bug
[plan9front.git] / sys / src / cmd / urlencode.c
1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4
5 Biobuf  bin;
6 Biobuf  bout;
7 int     dflag;
8
9 char    hex[] = "0123456789abcdef";
10 char    Hex[] = "0123456789ABCDEF";
11
12 int
13 hexdigit(int c)
14 {
15         char *p;
16
17         if(c > 0){
18                 if((p = strchr(Hex, c)) != 0)
19                         return p - Hex;
20                 if((p = strchr(hex, c)) != 0)
21                         return p - hex;
22         }
23         return -1;
24 }
25
26 void
27 usage(void)
28 {
29         fprint(2, "Usage: %s [ -d ] [ file ]\n", argv0);
30         exits("usage");
31 }
32
33 void
34 main(int argc, char *argv[])
35 {
36         int c;
37
38         ARGBEGIN {
39         case 'd':
40                 dflag = 1;
41                 break;
42         default:
43                 usage();
44         } ARGEND;
45
46         if(argc == 1){
47                 close(0);
48                 if(open(*argv, OREAD) < 0)
49                         sysfatal("%r");
50         } else if(argc > 1)
51                 usage();
52
53         Binit(&bin, 0, OREAD);
54         Binit(&bout, 1, OWRITE);
55
56         if(dflag){
57                 while((c = Bgetc(&bin)) >= 0){
58                         if(c == '%'){
59                                 int c1, c2, x1, x2;
60
61                                 if((c1 = Bgetc(&bin)) < 0)
62                                         break;
63                                 if((x1 = hexdigit(c1)) < 0){
64                                         Bungetc(&bin);
65                                         Bputc(&bout, c);
66                                         continue;
67                                 }
68                                 if((c2 = Bgetc(&bin)) < 0)
69                                         break;
70                                 if((x2 = hexdigit(c2)) < 0){
71                                         Bungetc(&bin);
72                                         Bputc(&bout, c);
73                                         Bputc(&bout, c1);
74                                         continue;
75                                 }
76                                 c = x1<<4 | x2;
77                         } else if(c == '+')
78                                 c = ' ';
79                         Bputc(&bout, c);
80                 }
81         } else {
82                 while((c = Bgetc(&bin)) >= 0){
83                         if(strchr("/$-_@.!*'(),", c)
84                         || 'a'<=c && c<='z'
85                         || 'A'<=c && c<='Z'
86                         || '0'<=c && c<='9')
87                                 Bputc(&bout, c);
88                         else if(c == ' ')
89                                 Bputc(&bout, '+');
90                         else {
91                                 Bputc(&bout, '%');
92                                 Bputc(&bout, Hex[c>>4]);
93                                 Bputc(&bout, Hex[c&15]);
94                         }
95                 }
96         }
97
98         Bflush(&bout);
99         exits(0);
100 }