⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 imap4.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
	if(imap->mustssl){		memset(&conn, 0, sizeof conn);		sfd = tlsClient(imap->fd, &conn);		if(sfd < 0)			sysfatal("tlsClient: %r");		if(conn.cert==nil || conn.certlen <= 0)			sysfatal("server did not provide TLS certificate");		sha1(conn.cert, conn.certlen, digest, nil);		if(!imap->thumb || !okThumbprint(digest, imap->thumb)){			fmtinstall('H', encodefmt);			sysfatal("server certificate %.*H not recognized", SHA1dlen, digest);		}		free(conn.cert);		close(imap->fd);		imap->fd = sfd;		if(imap->debug){			char fn[128];			int fd;			snprint(fn, sizeof fn, "%s/ctl", conn.dir);			fd = open(fn, ORDWR);			if(fd < 0)				fprint(2, "opening ctl: %r\n");			if(fprint(fd, "debug") < 0)				fprint(2, "writing ctl: %r\n");			close(fd);		}	}	Binit(&imap->bin, imap->fd, OREAD);	Binit(&imap->bout, imap->fd, OWRITE);	if(err = imap4login(imap)) {		close(imap->fd);		return err;	}	return nil;}//// close connection//static voidimap4hangup(Imap *imap){	imap4cmd(imap, "LOGOUT");	imap4resp(imap);	close(imap->fd);}//// download a single message//static char*imap4fetch(Mailbox *mb, Message *m){	int i;	char *p, *s, sdigest[2*SHA1dlen+1];	Imap *imap;	imap = mb->aux;	imap->size = 0;	if(!isokay(s = imap4resp(imap)))		return s;	p = imap->base;	if(p == nil)		return "did not get message body";	removecr(p);	free(m->start);	m->start = p;	m->end = p+strlen(p);	m->bend = m->rbend = m->end;	m->header = m->start;	imap->base = nil;	imap->data = nil;	parse(m, 0, mb, 1);	// digest headers	sha1((uchar*)m->start, m->end - m->start, m->digest, nil);	for(i = 0; i < SHA1dlen; i++)		sprint(sdigest+2*i, "%2.2ux", m->digest[i]);	m->sdigest = s_copy(sdigest);	return nil;}//// check for new messages on imap4 server// download new messages, mark deleted messages//static char*imap4read(Imap *imap, Mailbox *mb, int doplumb){	char *s;	int i, ignore, nnew, t;	Message *m, *next, **l;	imap4cmd(imap, "STATUS %Z (MESSAGES UIDVALIDITY)", imap->mbox);	if(!isokay(s = imap4resp(imap)))		return s;	imap->nuid = 0;	imap->uid = erealloc(imap->uid, imap->nmsg*sizeof(imap->uid[0]));	imap->muid = imap->nmsg;	if(imap->nmsg > 0){		imap4cmd(imap, "UID FETCH 1:* UID");		if(!isokay(s = imap4resp(imap)))			return s;	}	l = &mb->root->part;	for(i=0; i<imap->nuid; i++){		ignore = 0;		while(*l != nil){			if((*l)->imapuid == imap->uid[i]){				ignore = 1;				l = &(*l)->next;				break;			}else{				// old mail, we don't have it anymore				if(doplumb)					mailplumb(mb, *l, 1);				(*l)->inmbox = 0;				(*l)->deleted = 1;				l = &(*l)->next;			}		}		if(ignore)			continue;		// new message		m = newmessage(mb->root);		m->mallocd = 1;		m->inmbox = 1;		m->imapuid = imap->uid[i];		// add to chain, will download soon		*l = m;		l = &m->next;	}	// whatever is left at the end of the chain is gone	while(*l != nil){		if(doplumb)			mailplumb(mb, *l, 1);		(*l)->inmbox = 0;		(*l)->deleted = 1;		l = &(*l)->next;	}	// download new messages	t = imap->tag;	if(pipeline)	switch(rfork(RFPROC|RFMEM)){	case -1:		sysfatal("rfork: %r");	default:		break;	case 0:		for(m = mb->root->part; m != nil; m = m->next){			if(m->start != nil)				continue;			if(imap->debug)				fprint(2, "9X%d UID FETCH %lud (UID RFC822.SIZE BODY[])\r\n",					t, (ulong)m->imapuid);			Bprint(&imap->bout, "9X%d UID FETCH %lud (UID RFC822.SIZE BODY[])\r\n",				t++, (ulong)m->imapuid);		}		Bflush(&imap->bout);		_exits(nil);	}	nnew = 0;	for(m=mb->root->part; m!=nil; m=next){		next = m->next;		if(m->start != nil)			continue;		if(!pipeline){			Bprint(&imap->bout, "9X%lud UID FETCH %lud (UID RFC822.SIZE BODY[])\r\n",				(ulong)imap->tag, (ulong)m->imapuid);			Bflush(&imap->bout);		}		if(s = imap4fetch(mb, m)){			// message disappeared?  unchain			fprint(2, "download %lud: %s\n", (ulong)m->imapuid, s);			delmessage(mb, m);			mb->root->subname--;			continue;		}		nnew++;		if(doplumb)			mailplumb(mb, m, 0);	}	if(pipeline)		waitpid();	if(nnew || mb->vers == 0){		mb->vers++;		henter(PATH(0, Qtop), mb->name,			(Qid){PATH(mb->id, Qmbox), mb->vers, QTDIR}, nil, mb);	}	return nil;}//// sync mailbox//static voidimap4purge(Imap *imap, Mailbox *mb){	int ndel;	Message *m, *next;	ndel = 0;	for(m=mb->root->part; m!=nil; m=next){		next = m->next;		if(m->deleted && m->refs==0){			if(m->inmbox && (ulong)(m->imapuid>>32)==imap->validity){				imap4cmd(imap, "UID STORE %lud +FLAGS (\\Deleted)", (ulong)m->imapuid);				if(isokay(imap4resp(imap))){					ndel++;					delmessage(mb, m);				}			}else				delmessage(mb, m);		}	}	if(ndel){		imap4cmd(imap, "EXPUNGE");		imap4resp(imap);	}}//// connect to imap4 server, sync mailbox//static char*imap4sync(Mailbox *mb, int doplumb){	char *err;	Imap *imap;	imap = mb->aux;	if(err = imap4dial(imap)){		mb->waketime = time(0) + imap->refreshtime;		return err;	}	if((err = imap4read(imap, mb, doplumb)) == nil){		imap4purge(imap, mb);		mb->d->atime = mb->d->mtime = time(0);	}	/*	 * don't hang up; leave connection open for next time.	 */	// imap4hangup(imap);	mb->waketime = time(0) + imap->refreshtime;	return err;}static char Eimap4ctl[] = "bad imap4 control message";static char*imap4ctl(Mailbox *mb, int argc, char **argv){	int n;	Imap *imap;	imap = mb->aux;	if(argc < 1)		return Eimap4ctl;	if(argc==1 && strcmp(argv[0], "debug")==0){		imap->debug = 1;		return nil;	}	if(argc==1 && strcmp(argv[0], "nodebug")==0){		imap->debug = 0;		return nil;	}	if(argc==1 && strcmp(argv[0], "thumbprint")==0){		if(imap->thumb)			freeThumbprints(imap->thumb);		imap->thumb = initThumbprints("/sys/lib/tls/mail", "/sys/lib/tls/mail.exclude");	}	if(strcmp(argv[0], "refresh")==0){		if(argc==1){			imap->refreshtime = 60;			return nil;		}		if(argc==2){			n = atoi(argv[1]);			if(n < 15)				return Eimap4ctl;			imap->refreshtime = n;			return nil;		}	}	return Eimap4ctl;}//// free extra memory associated with mb//static voidimap4close(Mailbox *mb){	Imap *imap;	imap = mb->aux;	free(imap->freep);	free(imap->base);	free(imap->uid);	if(imap->fd >= 0)		close(imap->fd);	free(imap);}//// open mailboxes of the form /imap/host/user//char*imap4mbox(Mailbox *mb, char *path){	char *f[10];	int mustssl, nf;	Imap *imap;	quotefmtinstall();	fmtinstall('Z', doublequote);	if(strncmp(path, "/imap/", 6) != 0 && strncmp(path, "/imaps/", 7) != 0)		return Enotme;	mustssl = (strncmp(path, "/imaps/", 7) == 0);	path = strdup(path);	if(path == nil)		return "out of memory";	nf = getfields(path, f, 5, 0, "/");	if(nf < 3){		free(path);		return "bad imap path syntax /imap[s]/system[/user[/mailbox]]";	}	imap = emalloc(sizeof(*imap));	imap->fd = -1;	imap->debug = debug;	imap->freep = path;	imap->mustssl = mustssl;	imap->host = f[2];	if(nf < 4)		imap->user = nil;	else		imap->user = f[3];	if(nf < 5)		imap->mbox = "Inbox";	else		imap->mbox = f[4];	imap->thumb = initThumbprints("/sys/lib/tls/mail", "/sys/lib/tls/mail.exclude");	mb->aux = imap;	mb->sync = imap4sync;	mb->close = imap4close;	mb->ctl = imap4ctl;	mb->d = emalloc(sizeof(*mb->d));	//mb->fetch = imap4fetch;	return nil;}//// Formatter for %"// Use double quotes to protect white space, frogs, \ and "//enum{	Qok = 0,	Qquote,	Qbackslash,};static intneedtoquote(Rune r){	if(r >= Runeself)		return Qquote;	if(r <= ' ')		return Qquote;	if(r=='\\' || r=='"')		return Qbackslash;	return Qok;}intdoublequote(Fmt *f){	char *s, *t;	int w, quotes;	Rune r;	s = va_arg(f->args, char*);	if(s == nil || *s == '\0')		return fmtstrcpy(f, "\"\"");	quotes = 0;	for(t=s; *t; t+=w){		w = chartorune(&r, t);		quotes |= needtoquote(r);	}	if(quotes == 0)		return fmtstrcpy(f, s);	fmtrune(f, '"');	for(t=s; *t; t+=w){		w = chartorune(&r, t);		if(needtoquote(r) == Qbackslash)			fmtrune(f, '\\');		fmtrune(f, r);	}	return fmtrune(f, '"');}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -