urlencode.c - 9base - revived minimalist port of Plan 9 userland to Unix
(HTM) git clone git://git.suckless.org/9base
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) README
(DIR) LICENSE
---
urlencode.c (1546B)
---
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 int fd;
48
49 fd = open(*argv, OREAD);
50 if(fd < 0)
51 sysfatal("%r");
52 if(fd != 0) dup(fd, 0);
53 } else if(argc > 1)
54 usage();
55
56 Binit(&bin, 0, OREAD);
57 Binit(&bout, 1, OWRITE);
58
59 if(dflag){
60 while((c = Bgetc(&bin)) >= 0){
61 if(c == '%'){
62 int c1, c2, x1, x2;
63
64 if((c1 = Bgetc(&bin)) < 0)
65 break;
66 if((x1 = hexdigit(c1)) < 0){
67 Bungetc(&bin);
68 Bputc(&bout, c);
69 continue;
70 }
71 if((c2 = Bgetc(&bin)) < 0)
72 break;
73 if((x2 = hexdigit(c2)) < 0){
74 Bungetc(&bin);
75 Bputc(&bout, c);
76 Bputc(&bout, c1);
77 continue;
78 }
79 c = x1<<4 | x2;
80 } else if(c == '+')
81 c = ' ';
82 Bputc(&bout, c);
83 }
84 } else {
85 while((c = Bgetc(&bin)) >= 0){
86 if(c>0 && strchr("/$-_@.!*'(),", c)
87 || 'a'<=c && c<='z'
88 || 'A'<=c && c<='Z'
89 || '0'<=c && c<='9')
90 Bputc(&bout, c);
91 else if(c == ' ')
92 Bputc(&bout, '+');
93 else {
94 Bputc(&bout, '%');
95 Bputc(&bout, Hex[c>>4]);
96 Bputc(&bout, Hex[c&15]);
97 }
98 }
99 }
100
101 Bflush(&bout);
102 exits(0);
103 }