content.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <bio.h>
  4. #include "httpd.h"
  5. #include "httpsrv.h"
  6. typedef struct Suffix Suffix;
  7. struct Suffix
  8. {
  9. Suffix *next;
  10. char *suffix;
  11. char *generic;
  12. char *specific;
  13. char *encoding;
  14. };
  15. Suffix *suffixes = nil;
  16. static Suffix* parsesuffix(char*, Suffix*);
  17. static char* skipwhite(char*);
  18. static HContents suffixclass(char*);
  19. static char* towhite(char*);
  20. int
  21. updateQid(int fd, Qid *q)
  22. {
  23. Dir *dir;
  24. Qid dq;
  25. dir = dirfstat(fd);
  26. if(dir == nil)
  27. sysfatal("can't dirfstat");
  28. dq = dir->qid;
  29. free(dir);
  30. if(q->path == dq.path && q->vers == dq.vers && q->type == dq.type)
  31. return 0;
  32. *q = dq;
  33. return 1;
  34. }
  35. void
  36. contentinit(void)
  37. {
  38. static Biobuf *b = nil;
  39. static Qid qid;
  40. char *file, *s;
  41. Suffix *this;
  42. file = "/sys/lib/mimetype";
  43. if(b == nil){ /* first time */
  44. b = Bopen(file, OREAD);
  45. if(b == nil)
  46. sysfatal("can't read from %s", file);
  47. }
  48. if(updateQid(Bfildes(b), &qid) == 0)
  49. return;
  50. Bseek(b, 0, 0);
  51. while(suffixes!=nil){
  52. this = suffixes;
  53. suffixes = suffixes->next;
  54. free(this->suffix);
  55. free(this->generic);
  56. free(this->specific);
  57. free(this->encoding);
  58. free(this);
  59. }
  60. while((s = Brdline(b, '\n')) != nil){
  61. s[Blinelen(b) - 1] = 0;
  62. suffixes = parsesuffix(s, suffixes);
  63. }
  64. }
  65. static Suffix*
  66. parsesuffix(char *line, Suffix *suffix)
  67. {
  68. Suffix *s;
  69. char *p, *fields[5];
  70. int i, nf;
  71. p = strchr(line, '#');
  72. if(p != nil)
  73. *p = '\0';
  74. nf = tokenize(line, fields, 5);
  75. for(i = 0; i < 4; i++)
  76. if(i >= nf || fields[i][0] == '-')
  77. fields[i] = nil;
  78. if(fields[2] == nil)
  79. fields[1] = nil;
  80. if(fields[1] == nil && fields[3] == nil)
  81. return suffix;
  82. if(fields[0] == nil)
  83. return suffix;
  84. s = ezalloc(sizeof *s);
  85. s->next = suffix;
  86. s->suffix = estrdup(fields[0]);
  87. if(fields[1] != nil){
  88. s->generic = estrdup(fields[1]);
  89. s->specific = estrdup(fields[2]);
  90. }
  91. if(fields[3] != nil)
  92. s->encoding = estrdup(fields[3]);
  93. return s;
  94. }
  95. /*
  96. * classify by file name extensions
  97. */
  98. HContents
  99. uriclass(HConnect *hc, char *name)
  100. {
  101. HContents conts;
  102. Suffix *s;
  103. HContent *type, *enc;
  104. char *buf, *p;
  105. type = nil;
  106. enc = nil;
  107. if((p = strrchr(name, '/')) != nil)
  108. name = p + 1;
  109. buf = hstrdup(hc, name);
  110. while((p = strrchr(buf, '.')) != nil){
  111. for(s = suffixes; s; s = s->next){
  112. if(strcmp(p, s->suffix) == 0){
  113. if(s->generic != nil && type == nil)
  114. type = hmkcontent(hc, s->generic, s->specific, nil);
  115. if(s->encoding != nil && enc == nil)
  116. enc = hmkcontent(hc, s->encoding, nil, nil);
  117. }
  118. }
  119. *p = 0;
  120. }
  121. conts.type = type;
  122. conts.encoding = enc;
  123. return conts;
  124. }
  125. /*
  126. * classify by initial contents of file
  127. */
  128. HContents
  129. dataclass(HConnect *hc, char *buf, int n)
  130. {
  131. HContents conts;
  132. Rune r;
  133. int c, m;
  134. for(; n > 0; n -= m){
  135. c = *buf;
  136. if(c < Runeself){
  137. if(c < 32 && c != '\n' && c != '\r' && c != '\t' && c != '\v'){
  138. conts.type = nil;
  139. conts.encoding = nil;
  140. return conts;
  141. }
  142. m = 1;
  143. }else{
  144. m = chartorune(&r, buf);
  145. if(r == Runeerror){
  146. conts.type = nil;
  147. conts.encoding = nil;
  148. return conts;
  149. }
  150. }
  151. buf += m;
  152. }
  153. conts.type = hmkcontent(hc, "text", "plain", nil);
  154. conts.encoding = nil;
  155. return conts;
  156. }