Пример #1
0
int
httpopen(Client *c, Url *url)
{
	int fd, code, redirect, authenticate;
	char *cookies;
	Ioproc *io;
	HttpState *hs;
	char *service;

	if(httpdebug)
		fprint(2, "httpopen\n");
	io = c->io;
	hs = emalloc(sizeof(*hs));
	hs->c = c;

	if(url->port)
		service = url->port;
	else
		service = url->scheme;
	hs->netaddr = estrdup(netmkaddr(url->host, 0, service));
	c->aux = hs;
	if(httpdebug){
		fprint(2, "dial %s\n", hs->netaddr);
		fprint(2, "dial port: %s\n", url->port);
	}
	fd = iotlsdial(io, hs->netaddr, 0, 0, 0, url->ischeme==UShttps);
	if(fd < 0){
	Error:
		if(httpdebug)
			fprint(2, "iodial: %r\n");
		free(hs->location);
		free(hs->setcookie);
		free(hs->netaddr);
		free(hs->credentials);
		if(fd >= 0)
			ioclose(io, hs->fd);
		hs->fd = -1;
		free(hs);
		c->aux = nil;
		return -1;
	}
	hs->fd = fd;
	if(httpdebug)
		fprint(2, "<- %s %s HTTP/1.0\n<- Host: %s\n",
			c->havepostbody? "POST": "GET", url->http.page_spec, url->host);
	ioprint(io, fd, "%s %s HTTP/1.0\r\nHost: %s\r\n",
		c->havepostbody? "POST" : "GET", url->http.page_spec, url->host);
	if(httpdebug)
		fprint(2, "<- User-Agent: %s\n", c->ctl.useragent);
	if(c->ctl.useragent)
		ioprint(io, fd, "User-Agent: %s\r\n", c->ctl.useragent);
	if(c->ctl.sendcookies){
		/* should we use url->page here?  sometimes it is nil. */
		cookies = httpcookies(url->host, url->http.page_spec,
			url->ischeme == UShttps);
		if(cookies && cookies[0])
			ioprint(io, fd, "%s", cookies);
		if(httpdebug)
			fprint(2, "<- %s", cookies);
		free(cookies);
	}
	if(c->havepostbody){
		ioprint(io, fd, "Content-type: %s\r\n", PostContentType);
		ioprint(io, fd, "Content-length: %ud\r\n", c->npostbody);
		if(httpdebug){
			fprint(2, "<- Content-type: %s\n", PostContentType);
			fprint(2, "<- Content-length: %ud\n", c->npostbody);
		}
	}
	if(c->authenticate){
		ioprint(io, fd, "Authorization: %s\r\n", c->authenticate);
		if(httpdebug)
			fprint(2, "<- Authorization: %s\n", c->authenticate);
	}
	ioprint(io, fd, "\r\n");
	if(c->havepostbody)
		if(iowrite(io, fd, c->postbody, c->npostbody) != c->npostbody)
			goto Error;

	redirect = 0;
	authenticate = 0;
	initibuf(&hs->b, io, fd);
	code = httprcode(hs);

	switch(code){
	case -1:	/* connection timed out */
		goto Error;

/*
	case Eof:
		werrstr("EOF from HTTP server");
		goto Error;
*/

	case 200:	/* OK */
	case 201:	/* Created */
	case 202:	/* Accepted */
	case 204:	/* No Content */
	case 205: /* Reset Content */
#ifdef NOT_DEFINED
		if(ofile == nil && r->start != 0)
			sysfatal("page changed underfoot");
#endif
		break;

	case 206:	/* Partial Content */
		werrstr("Partial Content (206)");
		goto Error;

	case 301:	/* Moved Permanently */
	case 302:	/* Moved Temporarily */
	case 303:	/* See Other */
	case 307: /* Temporary Redirect  */
		redirect = 1;
		break;

	case 304:	/* Not Modified */
		break;

	case 400:	/* Bad Request */
		werrstr("Bad Request (400)");
		goto Error;

	case 401:	/* Unauthorized */
		if(c->authenticate){
			werrstr("Authentication failed (401)");
			goto Error;
		}
		authenticate = 1;
		break;
	case 402:	/* Payment Required */
		werrstr("Payment Required (402)");
		goto Error;

	case 403:	/* Forbidden */
		werrstr("Forbidden by server (403)");
		goto Error;

	case 404:	/* Not Found */
		werrstr("Not found on server (404)");
		goto Error;

	case 405:	/* Method Not Allowed  */
		werrstr("Method not allowed (405)");
		goto Error;

	case 406: /* Not Acceptable */
		werrstr("Not Acceptable (406)");
		goto Error;

	case 407:	/* Proxy auth */
		werrstr("Proxy authentication required (407)");
		goto Error;

	case 408: /* Request Timeout */
		werrstr("Request Timeout (408)");
		goto Error;

	case 409: /* Conflict */
		werrstr("Conflict  (409)");
		goto Error;
	
	case 410: /* Gone */
		werrstr("Gone  (410)");
		goto Error;
	
	case 411: /* Length Required */
		werrstr("Length Required  (411)");
		goto Error;
	
	case 412: /* Precondition Failed */
		werrstr("Precondition Failed  (412)");
		goto Error;
	
	case 413: /* Request Entity Too Large */
		werrstr("Request Entity Too Large  (413)");
		goto Error;
	
	case 414: /* Request-URI Too Long */
		werrstr("Request-URI Too Long  (414)");
		goto Error;
	
	case 415: /* Unsupported Media Type */
		werrstr("Unsupported Media Type  (415)");
		goto Error;
	
	case 416: /* Requested Range Not Satisfiable */
		werrstr("Requested Range Not Satisfiable  (416)");
		goto Error;
	
	case 417: /* Expectation Failed */
		werrstr("Expectation Failed  (417)");
		goto Error;

	case 500:	/* Internal server error */
		werrstr("Server choked (500)");
		goto Error;

	case 501:	/* Not implemented */
		werrstr("Server can't do it (501)");
		goto Error;

	case 502:	/* Bad gateway */
		werrstr("Bad gateway (502)");
		goto Error;

	case 503:	/* Service unavailable */
		werrstr("Service unavailable (503)");
		goto Error;
	
	default:
		/* Bogus: we should treat unknown code XYZ as code X00 */
		werrstr("Unknown response code %d", code);
		goto Error;
	}

	if(httpheaders(hs) < 0)
		goto Error;
	if(c->ctl.acceptcookies && hs->setcookie)
		httpsetcookie(hs->setcookie, url->host, url->path);
	if(authenticate){
		if(!hs->credentials){
			if(hs->autherror[0])
				werrstr("%s", hs->autherror);
			else
				werrstr("unauthorized; no www-authenticate: header");
			goto Error;
		}
		c->authenticate = hs->credentials;
		hs->credentials = nil;
	}else if(c->authenticate)
		c->authenticate = 0;
	if(redirect){
		if(!hs->location){
			werrstr("redirection without Location: header");
			goto Error;
		}
		c->redirect = hs->location;
		hs->location = nil;
	}
	return 0;
}
Пример #2
0
int init_buffer(int buf, btype type, const char *bname, int nlines)
{
	bufs[buf].type=type;
	bufs[buf].bname=strdup(bname);
	if(type==SERVER)
		bufs[buf].serverloc=strdup(bname);
	else
		bufs[buf].serverloc=NULL;
	bufs[buf].realsname=NULL;
	bufs[buf].nlist=NULL;
	bufs[buf].us=NULL;
	bufs[buf].ilist=NULL;
	bufs[buf].handle=0;
	bufs[buf].server=0;
	bufs[buf].nick=NULL;
	bufs[buf].topic=NULL;
	bufs[buf].logf=NULL;
	bufs[buf].nlines=nlines;
	bufs[buf].ptr=0;
	bufs[buf].scroll=0;
	bufs[buf].ascroll=0;
	bufs[buf].lm=malloc(nlines*sizeof(mtype));
	bufs[buf].lq=malloc(nlines*sizeof(prio));
	bufs[buf].lp=malloc(nlines);
	bufs[buf].ls=malloc(nlines*sizeof(bool));
	bufs[buf].lt=malloc(nlines*sizeof(char *));
	int i;
	for(i=0;i<bufs[buf].nlines;i++)
	{
		bufs[buf].lt[i]=NULL;
	}
	bufs[buf].ltag=malloc(nlines*sizeof(char *));
	for(i=0;i<bufs[buf].nlines;i++)
	{
		bufs[buf].ltag[i]=NULL;
	}
	bufs[buf].lpl=malloc(nlines*sizeof(int));
	bufs[buf].lpc=malloc(nlines*sizeof(colour));
	bufs[buf].lpt=malloc(nlines*sizeof(char **));
	for(i=0;i<nlines;i++)
	{
		bufs[buf].lpl[i]=0;
		bufs[buf].lpc[i]=(colour){.fore=7, .back=0, .hi=false, .ul=false};
		bufs[buf].lpt[i]=NULL;
	}
	bufs[buf].dirty=false;
	bufs[buf].ts=malloc(nlines*sizeof(time_t));
	bufs[buf].filled=false;
	bufs[buf].alert=false;
	bufs[buf].hi_alert=0;
	bufs[buf].ping=0;
	bufs[buf].last=time(NULL);
	bufs[buf].namreply=false;
	bufs[buf].live=false;
	bufs[buf].conninpr=false;
	initibuf(&bufs[buf].input);
	bufs[buf].casemapping=RFC1459;
	if(type==SERVER)
	{
		bufs[buf].npfx=2;
		bufs[buf].prefixes=malloc(2*sizeof(prefix));
		bufs[buf].prefixes[0]=(prefix){.letter='o', .pfx='@'};
		bufs[buf].prefixes[1]=(prefix){.letter='v', .pfx='+'};
	}
	else
	{
		bufs[buf].npfx=0;
		bufs[buf].prefixes=NULL;
	}
	bufs[buf].autoent=NULL;
	bufs[buf].conf=conf;
	bufs[buf].key=NULL;
	bufs[buf].lastkey=NULL;
	return(0);
}

int free_buffer(int buf)
{
	if(bufs[buf].live)
	{
		add_to_buffer(buf, ERR, NORMAL, 0, false, "Buffer is still live!", "free_buffer:");
		return(1);
	}
	else
	{
		free(bufs[buf].bname);
		free(bufs[buf].serverloc);
		free(bufs[buf].realsname);
		n_free(bufs[buf].nlist);
		bufs[buf].nlist=NULL;
		n_free(bufs[buf].ilist);
		bufs[buf].ilist=NULL;
		free(bufs[buf].nick);
		free(bufs[buf].topic);
		if(bufs[buf].logf)
			fclose(bufs[buf].logf);
		free(bufs[buf].lm);
		free(bufs[buf].lq);
		free(bufs[buf].lp);
		free(bufs[buf].ls);
		int l;
		if(bufs[buf].lt)
		{
			for(l=0;l<bufs[buf].nlines;l++)
				free(bufs[buf].lt[l]);
			free(bufs[buf].lt);
		}
		if(bufs[buf].ltag)
		{
			for(l=0;l<bufs[buf].nlines;l++)
				free(bufs[buf].ltag[l]);
			free(bufs[buf].ltag);
		}
		if(bufs[buf].lpt)
		{
			for(l=0;l<bufs[buf].nlines;l++)
			{
				if(bufs[buf].lpt[l])
				{
					if(bufs[buf].lpl)
					{
						int p;
						for(p=0;p<bufs[buf].lpl[l];p++)
						{
							free(bufs[buf].lpt[l][p]);
						}
					}
					free(bufs[buf].lpt[l]);
				}
			}
			free(bufs[buf].lpt);
		}
		free(bufs[buf].lpl);
		free(bufs[buf].lpc);
		free(bufs[buf].ts);
		freeibuf(&bufs[buf].input);
		free(bufs[buf].prefixes);
		free(bufs[buf].key);
		free(bufs[buf].lastkey);
		if(cbuf>=buf)
			cbuf--;
		nbufs--;
		int b;
		for(b=buf;b<nbufs;b++)
		{
			bufs[b]=bufs[b+1];
		}
		for(b=0;b<nbufs;b++)
		{
			if(bufs[b].server==buf)
			{
				bufs[b].server=0; // orphaned; should not happen
				bufs[b].live=false;
				bufs[b].handle=0; // just in case
			}
			else if(bufs[b].server>buf)
			{
				bufs[b].server--;
			}
		}
		if(nbufs) redraw_buffer();
		return(0);
	}
}

int add_to_buffer(int buf, mtype lm, prio lq, char lp, bool ls, const char *lt, const char *ltag)
{
	if(buf>=nbufs)
	{
		if(bufs&&buf)
		{
			add_to_buffer(0, ERR, NORMAL, 0, false, "Line was written to bad buffer!  Contents below.", "add_to_buffer(): ");
			add_to_buffer(0, lm, NORMAL, lp, ls, lt, ltag);
		}
		return(1);
	}
	if(!debug&&(lq==DEBUG))
	{
		if(!d_buf.nlines)
		{
			init_ring(&d_buf);
			d_buf.loop=true;
		}
		return(add_to_ring(&d_buf, lm, lt, ltag));
	}
	int optr=bufs[buf].ptr;
	bool scrollisptr=(bufs[buf].scroll==bufs[buf].ptr)&&(bufs[buf].ascroll==0);
	bufs[buf].lm[bufs[buf].ptr]=lm;
	bufs[buf].lq[bufs[buf].ptr]=lq;
	bufs[buf].lp[bufs[buf].ptr]=lp;
	bufs[buf].ls[bufs[buf].ptr]=ls;
	free(bufs[buf].lt[bufs[buf].ptr]);
	bufs[buf].lt[bufs[buf].ptr]=strdup(lt);
	free(bufs[buf].ltag[bufs[buf].ptr]);
	bufs[buf].ltag[bufs[buf].ptr]=strdup(ltag);
	time_t ts=bufs[buf].ts[bufs[buf].ptr]=time(NULL);
	bufs[buf].ptr=(bufs[buf].ptr+1)%bufs[buf].nlines;
	if(scrollisptr)
	{
		bufs[buf].scroll=bufs[buf].ptr;
		bufs[buf].ascroll=0;
	}
	if(bufs[buf].ptr==0)
		bufs[buf].filled=true;
	render_line(buf, optr);
	if(buf==cbuf)
	{
		int e=redraw_buffer();
		if(e) return(e);
	}
	else
	{
		if(!(
			(bufs[buf].conf&&((lm==JOIN)||(lm==PART)||(lm==NICK)||(lm==MODE)||(lm==QUIT)))
			||
				(quiet&&(lq==QUIET))
			||
				(!debug&&(lq==DEBUG))
			))
		bufs[buf].alert=true;
	}
	if(bufs[buf].logf)
	{
		int e=log_add(bufs[buf].logf, bufs[buf].logt, lm, lq, lp, ls, lt, ltag, ts);
		if(e) return(e);
	}
	return(0);
}

int redraw_buffer(void)
{
	if(bufs[cbuf].dirty)
	{
		int e=render_buffer(cbuf);
		if(e) return(e);
		if(bufs[cbuf].dirty) return(1);
	}
	int uline=bufs[cbuf].scroll;
	int pline=bufs[cbuf].ascroll;
	while(pline<0)
	{
		uline--;
		if((bufs[cbuf].filled)&&(uline==bufs[cbuf].ptr))
		{
			uline++;
			pline=0;
			break;
		}
		if(uline<0)
		{
			if(bufs[cbuf].filled)
				uline+=bufs[cbuf].nlines;
			else
			{
				uline=0;
				pline=0;
				break;
			}
		}
		pline+=bufs[cbuf].lpl[uline];
	}
	if(uline==bufs[cbuf].ptr)
	{
		pline=0;
	}
	while(pline>=bufs[cbuf].lpl[uline])
	{
		pline-=bufs[cbuf].lpl[uline];
		if(bufs[cbuf].filled)
		{
			if(uline==bufs[cbuf].ptr)
			{
				pline=0;
				break;
			}
			uline=(uline+1)%bufs[cbuf].nlines;
		}
		else
		{
			if(uline>=bufs[cbuf].ptr)
			{
				uline=bufs[cbuf].ptr;
				pline=0;
				break;
			}
			uline++;
		}
	}
	bufs[cbuf].scroll=uline;
	bufs[cbuf].ascroll=pline;
	int row=height-2;
	//setcolour(bufs[cbuf].lpc[uline]);
	while(row>(tsb?1:0))
	{
		bool breakit=false;
		pline--;
		while(pline<0)
		{
			uline--;
			if(uline<0)
			{
				if(bufs[cbuf].filled)
					uline+=bufs[cbuf].nlines;
				else
				{
					breakit=true;
					pline=0;
					break;
				}
			}
			if(uline==bufs[cbuf].ptr)
			{
				breakit=true;
				break;
			}
			pline+=bufs[cbuf].lpl[uline];
		}
		if(breakit) break;
		locate(row, 0);
		fputs(bufs[cbuf].lpt[uline][pline], stdout);
		if(!full_width_colour) resetcol();
		clr();
		row--;
	}
	resetcol();
	while(row>(tsb?1:0))
	{
		locate(row--, 0);
		clr();
	}
	switch(bufs[cbuf].type)
	{
		case STATUS:
			settitle("quIRC - status");
		break;
		case SERVER: // have to scope it for the cstr 'variably modified type'
			{
				char cstr[16+strlen(bufs[cbuf].bname)];
				sprintf(cstr, "quIRC - %s", bufs[cbuf].bname);
				settitle(cstr);
			}
		break;
		case CHANNEL: // have to scope it for the cstr 'variably modified type'
			{
				char cstr[16+strlen(bufs[cbuf].bname)+strlen(SERVER(cbuf).bname)];
				sprintf(cstr, "quIRC - %s on %s", bufs[cbuf].bname, SERVER(cbuf).bname);
				settitle(cstr);
			}
		break;
		case PRIVATE: // have to scope it for the cstr 'variably modified type'
			{
				char cstr[16+strlen(bufs[cbuf].bname)+strlen(SERVER(cbuf).bname)];
				sprintf(cstr, "quIRC - <%s> on %s", bufs[cbuf].bname, SERVER(cbuf).bname);
				settitle(cstr);
			}
		break;
		default:
			settitle("quIRC");
		break;
	}
	if(tsb)
		titlebar();
	bufs[cbuf].alert=false;
	return(0);
}

int mark_buffer_dirty(int buf)
{
	bufs[buf].dirty=true;
	return(0);
}