int
syncjar(Jar *jar)
{
- int i, fd;
+ int i, fd, doread, dowrite;
char *line;
- Dir *d;
Biobuf *b;
+ Dir *d;
Qid q;
if(jar->file==nil)
return 0;
- memset(&q, 0, sizeof q);
- if((d = dirstat(jar->file)) != nil){
- q = d->qid;
- if(d->qid.path != jar->qid.path || d->qid.vers != jar->qid.vers)
- jar->dirty = 1;
+ doread = 0;
+ dowrite = jar->dirty;
+
+ q = jar->qid;
+ if((d = dirstat(jar->file)) == nil)
+ dowrite = 1;
+ else {
+ if(q.path != d->qid.path || q.vers != d->qid.vers){
+ q = d->qid;
+ doread = 1;
+ }
free(d);
}
- if(jar->dirty == 0)
+ if(!doread && !dowrite)
return 0;
fd = -1;
for(i=0; i<50; i++){
- if((fd = create(jar->lockfile, OWRITE, DMEXCL|0666)) < 0){
+ if((fd = create(jar->lockfile, OWRITE, DMEXCL|0600)) < 0){
sleep(100);
continue;
}
return -1;
}
- for(i=0; i<jar->nc; i++) /* mark is cleared by addcookie */
- jar->c[i].mark = jar->c[i].ondisk;
+ if(doread){
+ for(i=0; i<jar->nc; i++) /* mark is cleared by addcookie */
+ jar->c[i].mark = jar->c[i].ondisk;
- if((b = Bopen(jar->file, OREAD)) == nil){
- if(debug)
- fprint(2, "Bopen %s: %r", jar->file);
- werrstr("cannot read cookie file %s: %r", jar->file);
- close(fd);
- return -1;
- }
- for(; (line = Brdstr(b, '\n', 1)) != nil; free(line)){
- if(*line == '#')
- continue;
- addtojar(jar, line, 1);
- }
- Bterm(b);
+ if((b = Bopen(jar->file, OREAD)) == nil){
+ if(debug)
+ fprint(2, "Bopen %s: %r", jar->file);
+ werrstr("cannot read cookie file %s: %r", jar->file);
+ close(fd);
+ return -1;
+ }
+ for(; (line = Brdstr(b, '\n', 1)) != nil; free(line)){
+ if(*line == '#')
+ continue;
+ addtojar(jar, line, 1);
+ }
+ Bterm(b);
- for(i=0; i<jar->nc; i++)
- if(jar->c[i].mark)
- delcookie(jar, &jar->c[i]);
+ for(i=0; i<jar->nc; i++)
+ if(jar->c[i].mark)
+ delcookie(jar, &jar->c[i]);
+ }
purgejar(jar);
- b = Bopen(jar->file, OWRITE);
- if(b == nil){
- if(debug)
- fprint(2, "Bopen write %s: %r", jar->file);
- close(fd);
- return -1;
- }
- Bprint(b, "# webcookies cookie jar\n");
- Bprint(b, "# comments and non-standard fields will be lost\n");
- for(i=0; i<jar->nc; i++){
- if(jar->c[i].expire == ~0)
- continue;
- Bprint(b, "%K\n", &jar->c[i]);
- jar->c[i].ondisk = 1;
+ if(dowrite){
+ i = create(jar->file, OWRITE, 0600);
+ if(i < 0 || (b = Bfdopen(i, OWRITE)) == nil){
+ if(debug)
+ fprint(2, "Bopen write %s: %r", jar->file);
+ if(i >= 0)
+ close(i);
+ close(fd);
+ return -1;
+ }
+ Bprint(b, "# webcookies cookie jar\n");
+ Bprint(b, "# comments and non-standard fields will be lost\n");
+ for(i=0; i<jar->nc; i++){
+ if(jar->c[i].expire == ~0)
+ continue;
+ Bprint(b, "%K\n", &jar->c[i]);
+ jar->c[i].ondisk = 1;
+ }
+ Bflush(b);
+ if((d = dirfstat(Bfildes(b))) != nil){
+ q = d->qid;
+ free(d);
+ }
+ Bterm(b);
}
- Bterm(b);
+ jar->qid = q;
jar->dirty = 0;
+
close(fd);
- if((d = dirstat(jar->file)) != nil){
- jar->qid = d->qid;
- free(d);
- }
return 0;
}
+void
+closejar(Jar *jar)
+{
+ int i;
+
+ if(jar == nil)
+ return;
+ expirejar(jar, 0);
+ if(jar->dirty)
+ if(syncjar(jar) < 0)
+ fprint(2, "warning: cannot rewrite cookie jar: %r\n");
+
+ for(i=0; i<jar->nc; i++)
+ freecookie(&jar->c[i]);
+
+ free(jar->lockfile);
+ free(jar->file);
+ free(jar->c);
+ free(jar);
+}
+
Jar*
readjar(char *file)
{
Jar *jar;
jar = newjar();
+ file = estrdup9p(file);
lock = emalloc9p(strlen(file)+10);
strcpy(lock, file);
if((p = strrchr(lock, '/')) != nil)
p[1] = '.';
jar->lockfile = lock;
jar->file = file;
- jar->dirty = 1;
+ jar->dirty = 0;
if(syncjar(jar) < 0){
- free(jar->file);
- free(jar->lockfile);
- free(jar);
+ closejar(jar);
return nil;
}
return jar;
}
-void
-closejar(Jar *jar)
-{
- int i;
-
- expirejar(jar, 0);
- if(syncjar(jar) < 0)
- fprint(2, "warning: cannot rewrite cookie jar: %r\n");
-
- for(i=0; i<jar->nc; i++)
- freecookie(&jar->c[i]);
-
- free(jar->file);
- free(jar);
-}
/*
* Domain name matching is per RFC2109, section 2:
{
int lname, lpattern;
- if(cistrcmp(name, pattern)==0)
+ if(cistrcmp(name, pattern + (pattern[0]=='.'))==0)
return 1;
if(strcmp(ipattr(name), "dom")==0 && pattern[0]=='.'){
{
int i;
Jar *j;
+ Cookie *c;
uint now;
now = time(0);
j = newjar();
- for(i=0; i<jar->nc; i++)
- if((issecure || !jar->c[i].secure) && iscookiematch(&jar->c[i], dom, path, now))
- addcookie(j, &jar->c[i]);
+ for(i=0; i<jar->nc; i++){
+ c = &jar->c[i];
+ if(!c->deleted && (issecure || !c->secure) && iscookiematch(c, dom, path, now))
+ addcookie(j, c);
+ }
if(j->nc == 0){
closejar(j);
werrstr("no cookies found");
if(c->explicitdom && c->dom[0] != '.')
return "cookie domain doesn't start with dot";
- if(memchr(c->dom+1, '.', strlen(c->dom)-1-1) == nil)
+ if(strlen(c->dom)<=2 || memchr(c->dom+1, '.', strlen(c->dom)-2) == nil)
return "cookie domain doesn't have embedded dots";
if(!isdomainmatch(dom, c->dom))
return "request host does not match cookie domain";
- if(strcmp(ipattr(dom), "dom")==0
+ if(strcmp(ipattr(dom), "dom")==0 && strlen(dom)>strlen(c->dom)
&& memchr(dom, '.', strlen(dom)-strlen(c->dom)) != nil)
return "request host contains dots before cookie domain";
return -1;
}
- tm.hour = atoi(s);
- tm.min = atoi(s+3);
- tm.sec = atoi(s+6);
+ tm.hour = strtol(s, 0, 10);
+ tm.min = strtol(s+3, 0, 10);
+ tm.sec = strtol(s+6, 0, 10);
if(tm.hour >= 24 || tm.min >= 60 || tm.sec >= 60){
if(debug)
fprint(2, "invalid time (%s)\n", os);
if(cistrcmp(attr, "secure") == 0)
c->secure = 1;
}
+ *e = p;
- if(c->dom)
+ if(c->dom){
+ /* add leading dot for explicit domain */
+ if(c->dom[0] != '.' && strcmp(ipattr(c->dom), "dom") == 0){
+ static char ddom[1024];
+
+ ddom[0] = '.';
+ ddom[sizeof(ddom)-1] = '\0';
+ strncpy(ddom+1, c->dom, sizeof(ddom)-2);
+ c->dom = ddom;
+ }
c->explicitdom = 1;
- else
+ }else
c->dom = dom;
if(c->path)
c->explicitpath = 1;
- else{
- c->path = path;
- if((t = strchr(c->path, '?')) != 0)
- *t = '\0';
- if((t = strrchr(c->path, '/')) != 0)
- *t = '\0';
+ else {
+ static char dpath[1024];
+
+ /* implicit path is "directory" of request-uri's path component */
+ dpath[sizeof(dpath)-1] = '\0';
+ strncpy(dpath, path, sizeof(dpath)-1);
+ if((t = strrchr(dpath, '/')) != nil)
+ t[1] = '\0';
+ c->path = dpath;
}
c->netscapestyle = isns;
- *e = p;
return nil;
}
p = strchr(buf+hlen, '/');
if(p == nil)
a->path = estrdup9p("/");
- else{
+ else {
a->path = estrdup9p(p);
*p = '\0';
+
+ if((p = strchr(a->path, '#')) != nil)
+ *p = '\0';
+ if((p = strchr(a->path, '?')) != nil)
+ *p = '\0';
}
a->dom = estrdup9p(buf+hlen);
a->state = HaveUrl;
}
}
snprint(a->outhttp, AuxBuf, "%J", j);
- if(j)
- closejar(j);
+ closejar(j);
}else{
if(strlen(a->inhttp)+r->ifcall.count >= AuxBuf){
respond(r, "http headers too large");
delcookie(jar, &jar->c[i]);
break;
}
- syncjar(jar);
+ if(jar->dirty)
+ syncjar(jar);
free(a->dom);
free(a->path);
free(a->inhttp);
strcpy(file, home);
strcat(file, "/lib/webcookies");
}
- if(access(file, AEXIST) < 0)
- close(create(file, OWRITE, 0666));
jar = readjar(file);
if(jar == nil)