Annotation of libwww/Library/src/HTNewsRq.c, revision 2.3
2.1 frystyk 1: /* HTNewsRq.c
2: ** NNTP MESSAGE GENERATION
3: **
4: ** This module implements the output stream for MIME used for sending
5: ** requests with or without a entity body to HTTP, NEWS, etc.
6: **
7: ** History:
8: ** Jan 95 HFN Written
9: */
10:
11: /* Library Includes */
12: #include "tcp.h"
13: #include "HTUtils.h"
14: #include "HTString.h"
15: #include "HTParse.h"
16: #include "HTTCP.h"
17: #include "HTWriter.h"
18: #include "HTReqMan.h"
19: #include "HTChunk.h"
20: #include "HTMIMERq.h"
21: #include "HTNewsRq.h" /* Implements */
22:
23: #define PUTBLOCK(b, l) (*me->target->isa->put_block)(me->target, b, l)
24:
25: struct _HTStream {
26: CONST HTStreamClass * isa;
27: HTStream * target;
28: HTRequest * request;
29: SOCKFD sockfd;
30: HTChunk * buffer;
31: int version;
32: BOOL transparent;
33: };
34:
35: /* ------------------------------------------------------------------------- */
36: /* News Output Post Stream */
37: /* ------------------------------------------------------------------------- */
38:
39: /* NewsPost_start
40: ** --------------
41: ** NNTP needs two extra headers: "From" and "Newsgroups".
42: ** Take the newsgroups from the Postweb model as destinations for this
43: ** anchor.
44: ** Return YES if OK else NO
45: */
46: PRIVATE BOOL NewsPost_start (HTStream * me, HTRequest * request)
47: {
48: char linebuf[128]; /* @@@ */
49: HTChunk *header = me->buffer;
50: CONST char *mailaddress = HTGetMailAddress();
51: if (mailaddress) {
52: sprintf(linebuf, "From: %s%c%c", mailaddress, CR, LF);
53: HTChunkPuts(header, linebuf);
54: }
55:
56: /*
57: ** Find all the newsgroups we are posting to by looking at all the
58: ** destinations from the source of this request.
59: ** First the main link and then the sub links
60: */
61: HTChunkPuts(header, "Newsgroups :");
62: if (HTRequest_isDestination(request)) {
63: HTRequest *src_req = HTRequest_source(request);
64: HTParentAnchor *src_anchor = HTRequest_anchor(src_req);
65: HTLink *link = HTAnchor_findMainLink(src_anchor);
66: HTAnchor *dest = HTAnchor_linkDest(link);
67: HTMethod method = HTAnchor_linkMethod(link);
68: if (link && method == METHOD_POST &&
69: HTAnchor_linkResult(link) == HT_LINK_NONE) {
70: char *desturl = HTAnchor_physical((HTParentAnchor *) dest);
71: char *access = HTParse(desturl, "", PARSE_ACCESS);
72: if (!strcasecomp(access, "news") || !strcasecomp(access, "nntp")) {
73: char *newsgroup = HTParse(desturl, "", PARSE_PATH);
74: HTUnEscape(newsgroup);
75: HTCleanTelnetString(newsgroup);
76: HTChunkPuts(header, newsgroup);
77: free(newsgroup);
78: }
79: free(access);
80: }
81:
82: /* DO FOR ALL SUB ANCHOR DESTINATION S AS WELL */
83:
84: }
2.2 frystyk 85: if (PROT_TRACE) TTYPrint(TDEST, "News Tx..... %s", HTChunkData(header));
2.1 frystyk 86: return YES;
87: }
88:
89: /* NewsPost_end
90: ** ------------
91: ** End the posting by CRLF.CRLF
92: ** returns whatever PUT_BLOCK returns
93: */
94: PRIVATE int NewsPost_end (HTStream * me)
95: {
96: char buf[6];
97: *buf = CR;
98: *(buf+1) = LF;
99: *(buf+2) = '.';
100: *(buf+3) = CR;
101: *(buf+4) = LF;
102: *(buf+5) = '\0';
103: return PUTBLOCK(buf, 5);
104: }
105:
106: PRIVATE int NewsPost_put_block (HTStream * me, CONST char* b, int l)
107: {
108: if (!me->target) {
109: return HT_WOULD_BLOCK;
110: } else if (me->transparent)
111: return b ? PUTBLOCK(b, l) : HT_OK;
112: else {
113: int status;
114: NewsPost_start(me, me->request);
115: if ((status = PUTBLOCK(HTChunkData(me->buffer),
116: HTChunkSize(me->buffer))) == HT_OK) {
117: me->transparent = YES;
118: return b ? PUTBLOCK(b, l) : HT_OK;
119: }
120: return status;
121: }
122: }
123:
124: PRIVATE int NewsPost_put_character (HTStream * me, char c)
125: {
126: return NewsPost_put_block(me, &c, 1);
127: }
128:
129: PRIVATE int NewsPost_put_string (HTStream * me, CONST char * s)
130: {
131: return NewsPost_put_block(me, s, strlen(s));
132: }
133:
134: /*
135: ** Flushes header but doesn't free stream object
136: */
137: PRIVATE int NewsPost_flush (HTStream * me)
138: {
139: return NewsPost_put_block(me, NULL, 0);
140: }
141:
142: /*
143: ** Flushes data and frees stream object
144: */
145: PRIVATE int NewsPost_free (HTStream * me)
146: {
147: int status;
148: if ((status = NewsPost_flush(me)) != HT_OK ||
149: (status = NewsPost_end(me)) != HT_OK ||
150: (status = (*me->target->isa->_free)(me->target)) != HT_OK)
151: return status;
152: HTChunkFree(me->buffer);
153: free(me);
154: return status;
155: }
156:
2.3 ! frystyk 157: PRIVATE int NewsPost_abort (HTStream * me, HTList * e)
2.1 frystyk 158: {
159: if (me->target) (*me->target->isa->abort)(me->target, e);
160: HTChunkFree(me->buffer);
161: free(me);
2.2 frystyk 162: if (PROT_TRACE) TTYPrint(TDEST, "NewsPost.... ABORTING...\n");
2.1 frystyk 163: return HT_ERROR;
164: }
165:
166: /* NewsPost Stream
167: ** -----------------
168: */
169: PRIVATE CONST HTStreamClass NewsPostClass =
170: {
171: "NewsPost",
172: NewsPost_flush,
173: NewsPost_free,
174: NewsPost_abort,
175: NewsPost_put_character,
176: NewsPost_put_string,
177: NewsPost_put_block
178: };
179:
180: PUBLIC HTStream * HTNewsPost_new (HTRequest * request, HTStream * target)
181: {
182: HTStream * me = (HTStream *) calloc(1, sizeof(HTStream));
183: if (!me) outofmem(__FILE__, "NewsPost_new");
184: me->isa = &NewsPostClass;
185: me->target = target;
186: me->request = request;
187: me->buffer = HTChunkCreate(256);
188: me->transparent = NO;
189: return HTMIMERequest_new(request, me); /* @@@ */
190: }
Webmaster