9base

revived minimalist port of Plan 9 userland to Unix
git clone git://git.suckless.org/9base
Log | Files | Refs | README | 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 }