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 }