ref: cbe4b116989c0bfec49b9ae7a1d9a85ead6648ae
dir: /sys/src/cmd/urlencode.c/
#include <u.h> #include <libc.h> #include <bio.h> Biobuf bin; Biobuf bout; int dflag; char hex[] = "0123456789abcdef"; char Hex[] = "0123456789ABCDEF"; int hexdigit(int c) { char *p; if(c > 0){ if((p = strchr(Hex, c)) != 0) return p - Hex; if((p = strchr(hex, c)) != 0) return p - hex; } return -1; } void usage(void) { fprint(2, "usage: %s [ -d ] [ file ]\n", argv0); exits("usage"); } void main(int argc, char *argv[]) { int c; ARGBEGIN { case 'd': dflag = 1; break; default: usage(); } ARGEND; if(argc == 1){ int fd; fd = open(*argv, OREAD); if(fd < 0) sysfatal("%r"); if(fd != 0) dup(fd, 0); } else if(argc > 1) usage(); Binit(&bin, 0, OREAD); Binit(&bout, 1, OWRITE); if(dflag){ while((c = Bgetc(&bin)) >= 0){ if(c == '%'){ int c1, c2, x1, x2; if((c1 = Bgetc(&bin)) < 0) break; if((x1 = hexdigit(c1)) < 0){ Bungetc(&bin); Bputc(&bout, c); continue; } if((c2 = Bgetc(&bin)) < 0) break; if((x2 = hexdigit(c2)) < 0){ Bungetc(&bin); Bputc(&bout, c); Bputc(&bout, c1); continue; } c = x1<<4 | x2; } else if(c == '+') c = ' '; Bputc(&bout, c); } } else { while((c = Bgetc(&bin)) >= 0){ if(c>0 && strchr("/$-_@.!*'(),", c) || 'a'<=c && c<='z' || 'A'<=c && c<='Z' || '0'<=c && c<='9') Bputc(&bout, c); else if(c == ' ') Bputc(&bout, '+'); else { Bputc(&bout, '%'); Bputc(&bout, Hex[c>>4]); Bputc(&bout, Hex[c&15]); } } } Bflush(&bout); exits(0); }